From ac69f1f2e49c410c72dc9aaa0a87e89be847e6bb Mon Sep 17 00:00:00 2001 From: Mara Nikola Kiefer <8320933+mnkiefer@users.noreply.github.com> Date: Fri, 23 Oct 2026 17:47:43 +0200 Subject: [PATCH 1/5] Expose truthful Value collection health and isolate bounded local computation Keep recurring remote acquisition deferred until shared per-request budgets are enforceable. Publish registration and decision facts independently of retained evidence, preserve clocks across storage profiles, and keep optional local computation and imports off the Activity acquisition path. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: e45b84aa-0ee5-49c3-8eea-a54a5eb80b03 --- .github/skills/add-operational-value/SKILL.md | 13 +- .../templates/campaign-operational-value.mjs | 11 +- .github/workflows/cao-activity.yml | 80 +++-- .github/workflows/cao-value-local.yml | 74 +++++ .github/workflows/shared/materialize-cao.mjs | 3 + ARCHITECTURE.md | 26 +- CODEBASE.yml | 9 +- activity/README.md | 29 +- activity/aw.yml | 1 + activity/cli-usage.mjs | 3 +- activity/cli/cache.mjs | 11 +- activity/cli/options.mjs | 2 +- activity/cli/payloads.mjs | 5 + activity/commands/operational-value.mjs | 3 +- activity/local-values.mjs | 117 ++++++++ activity/normalized-phase.mjs | 2 +- activity/operational-value.mjs | 61 +++- activity/workflow-value-status.mjs | 118 ++++++++ activity/workflow-values.mjs | 107 ++++--- .../dashboard-fragments/workflow-value.json | 85 +++++- dashboard/site/dashboard.json | 19 ++ .../site/src/agent/catalog.generated.json | 100 ++++++- .../site/src/agent/queries.generated.json | 2 +- .../site/src/data/adapters/gh-aw-logs.js | 22 ++ dashboard/site/src/data/ingest/coordinator.js | 5 +- .../ingest/expressions/gh-aw-logs-v2.json | 5 + dashboard/site/src/data/model/schema.js | 8 +- .../data/model/workflow-value-collection.js | 90 ++++++ dashboard/site/src/data/normalize/index.js | 7 +- dashboard/site/src/data/queries/database.js | 2 +- dashboard/site/src/data/queries/database.json | 19 ++ dashboard/site/src/data/storage/indexeddb.js | 9 +- dashboard/site/src/data/storage/retention.js | 14 +- dashboard/site/src/data/storage/shards.js | 9 + dashboard/site/src/specification.js | 5 + .../site/test/e2e/canonical-data.spec.js | 3 +- .../site/test/e2e/workflow-value.spec.js | 44 ++- .../fixtures/workflow-value-collection.jsonl | 1 + .../workflow-value-view-contract.json | 4 + .../site/test/unit/data-indexeddb.test.js | 3 + .../unit/workflow-value-collection.test.js | 52 ++++ .../unit/workflow-value-view-contract.test.js | 61 +++- dependabot/operational-value.mjs | 11 +- docs/cao-cli.md | 10 +- docs/dashboard-data-model.md | 3 +- docs/operational-value-how-to.md | 7 +- docs/operational-value.md | 60 ++-- internal/dashboardquery/snapshot.go | 2 +- optimization/operational-value.mjs | 11 +- .../optimization-token-optimizer.mjs | 4 + server/README.md | 16 +- server/internal/collect/lake_values.go | 5 +- server/internal/collect/projector.go | 94 +----- .../collect/projector_local_value_test.go | 93 ++++++ .../collect/projector_workflow_values.go | 278 +++++++++++------- .../collect/projector_workflow_values_test.go | 49 ++- .../collect/withdrawal_values_test.go | 6 +- server/internal/collect/worker.go | 28 +- server/internal/model/model.go | 2 +- server/internal/operationalvalue/collector.go | 14 + server/internal/operationalvalue/local.go | 90 ++++++ .../internal/operationalvalue/local_test.go | 101 +++++++ server/internal/operationalvalue/retained.go | 27 +- server/internal/postgresx/native.go | 13 + server/internal/postgresx/schema.gen.go | 18 ++ server/internal/postgresx/schema.sql | 37 ++- server/internal/postgresx/sql_plan.go | 7 + .../postgresx/workflow_value_collection.go | 134 +++++++++ .../workflow_value_collection_test.go | 162 ++++++++++ server/internal/sqlitex/diagnostics.go | 2 + .../operational_value_evidence_test.go | 50 ++++ server/internal/testutil/sqlite.go | 2 +- server/postgres/canonical-grants.sql | 2 +- server/spec/storage.test.mjs | 5 +- server/spec/storage.tsp | 22 ++ specs/dashboard-data.md | 84 +++++- .../unit/activity-partial-collection.test.mjs | 8 +- .../cao-operational-value-evidence.test.mjs | 38 ++- tests/unit/cao-operational-value.test.mjs | 118 +++++++- ...kflow-contract-dashboard-delivery.test.mjs | 18 +- tests/unit/workflow-values-recurring.test.mjs | 151 +++++++++- 81 files changed, 2610 insertions(+), 416 deletions(-) create mode 100644 .github/workflows/cao-value-local.yml create mode 100644 activity/local-values.mjs create mode 100644 activity/workflow-value-status.mjs create mode 100644 dashboard/site/src/data/model/workflow-value-collection.js create mode 100644 dashboard/site/test/fixtures/workflow-value-collection.jsonl create mode 100644 dashboard/site/test/unit/workflow-value-collection.test.js create mode 100644 server/internal/collect/projector_local_value_test.go create mode 100644 server/internal/operationalvalue/local.go create mode 100644 server/internal/operationalvalue/local_test.go create mode 100644 server/internal/postgresx/workflow_value_collection.go create mode 100644 server/internal/postgresx/workflow_value_collection_test.go diff --git a/.github/skills/add-operational-value/SKILL.md b/.github/skills/add-operational-value/SKILL.md index 8c7ba42b3..2b3984928 100644 --- a/.github/skills/add-operational-value/SKILL.md +++ b/.github/skills/add-operational-value/SKILL.md @@ -232,8 +232,12 @@ Use `/add-operational-value OWNER/REPO` to list repository workflows or `/add-op and validation. The automatic registration in step 6 records only the selected pair; function files alone are not runtime authority. Have the policy and collector reviewed, committed and deployed together. Do not widen Activity - scope or enable the measured workflow. Existing collection cycles invoke - registered collectors at their frozen cadence; a failed refresh must retain + scope or enable the measured workflow. Recurring remote acquisition remains + deferred until enforceable shared API budgets protect ordinary Activity. + Registration is visible as enabled-but-deferred, not a promise of fresh + measurements. Bounded local-only computations run independently on eligible + published snapshots; they do not bypass fast, public-only or API-limit gates. + An admitted collector must honor the frozen cadence; a failed refresh must retain the prior accepted evidence and timestamps. `value disable` revokes future collection without removing history and persists an explicit disable that automatic registration must respect. Re-enabling requires explicit @@ -465,3 +469,8 @@ proof, not a target for fresh collections. - It may emit provisional pre-maturity values, but must include their interim maturity status and workflow adoption timestamp so consumers can mark them dubious and place adoption in temporal plots. - It emits no record for unsupported repositories and fails closed on malformed requests, inaccessible evidence, or invalid collection results. - Historical evaluation and CAO collection must import the same shared module so evidence and scoring cannot drift. +- A module may export `localCollection = true` only when `collectBatch` can use + the supplied canonical database or local immutable evidence without remote + calls or download fallbacks. Automatic local-only execution admits the reviewed + standard adapter by source digest; keep its template and package copies equal + and update that reviewed digest with adapter changes. Other adapters defer. diff --git a/.github/skills/add-operational-value/templates/campaign-operational-value.mjs b/.github/skills/add-operational-value/templates/campaign-operational-value.mjs index 3818cfdda..5ea60793c 100755 --- a/.github/skills/add-operational-value/templates/campaign-operational-value.mjs +++ b/.github/skills/add-operational-value/templates/campaign-operational-value.mjs @@ -27,6 +27,7 @@ try { } if ( request?.schemaVersion !== 1 + || (request.localOnly !== undefined && typeof request.localOnly !== "boolean") || typeof request.timestamp !== "string" || Number.isNaN(Date.parse(request.timestamp)) || !Array.isArray(request.repositories) @@ -93,11 +94,13 @@ for (const moduleFile of moduleFiles) { valueIds: definition.metrics.map((metric) => `${definition.slug}.${metric.id}`), ...(valueModule.historyBatch === true ? { historyBatch: true } : {}), })); + if (request.localOnly && request.disabledWorkflows?.includes(definition.slug)) continue; const supported = new Set( definition.evidence.repositories.map((repository) => String(repository).toLowerCase()), ); - const repositories = request.repositories.filter((repository) => supported.has(repository.toLowerCase())); + const repositories = request.repositories.filter((repository) => supported.has(repository.toLowerCase()) + && !(request.localOnly && request.disabledCollections?.includes(`${repository.toLowerCase()}:${definition.slug}`))); if (repositories.length === 0) continue; const { durationDays, maturationDays } = definition.evidence.window; @@ -176,10 +179,16 @@ for (const moduleFile of moduleFiles) { } } + if (request.localOnly && valueModule.localCollection !== true) { + console.log(JSON.stringify({ kind: "operational_value_deferred", workflowSlug: definition.slug, + reason: "Remote acquisition requires enforceable shared API admission; retained evidence is unchanged." })); + continue; + } let collections; try { collections = await collectBatch(windows, { database: request.database, + ...(request.localOnly ? { localOnly: true } : {}), ...(history ? { history: true } : {}), }); } catch (error) { diff --git a/.github/workflows/cao-activity.yml b/.github/workflows/cao-activity.yml index 4656e5a57..606a1a152 100644 --- a/.github/workflows/cao-activity.yml +++ b/.github/workflows/cao-activity.yml @@ -29,6 +29,7 @@ on: paths: - .github/workflows/cao.json - .github/workflows/cao-activity.yml + - .github/workflows/cao-value-local.yml - .github/workflows/cao-dashboard.yml - ".github/value-collectors/**" - ".github/skills/add-operational-value/**" @@ -350,15 +351,18 @@ jobs: --graphql-cost-budget 25 \ --graphql-min-remaining 500 - - name: Compute owner-scoped operational value + - name: Retain Value evidence and publish collection health + id: value-health + timeout-minutes: 1 + continue-on-error: true env: REPORT_PUBLIC_ONLY: ${{ matrix.publicOnly == true }} ACTIVITY_ARTIFACT: ${{ matrix.artifact }} ACTIVITY_DATABASE: ${{ runner.temp }}/cao-activity/collection.sqlite ACTIVITY_OWNER: ${{ matrix.owner }} - CAO_OPERATIONAL_VALUE_GH_TOKEN: ${{ steps.activity-credential.outputs.token }} - GH_TOKEN: ${{ steps.activity-credential.outputs.token }} - REPORT_MAX_GITHUB_API_RATE_LIMIT: ${{ (vars.GH_AW_GITHUB_AUTH_MODE == '' || vars.GH_AW_GITHUB_AUTH_MODE == 'workflow-token') && '-100' || '-2000' }} + CAO_OPERATIONAL_VALUE_GH_TOKEN: "" + GH_TOKEN: "" + REPORT_TARGET_REPOSITORIES_JSON: ${{ toJSON(matrix.repositories) }} REPORT_GH_AW_LOGS_SHARDS: ${{ runner.temp }}/cao-activity-partial/${{ matrix.artifact }}/gh-aw-logs-shards REPORT_INVENTORY_SOURCES: ${{ runner.temp }}/cao-activity-partial/${{ matrix.artifact }}/inventory-sources.json REPORT_VALUE_SEED_SHARDS: ${{ runner.temp }}/cao-activity/gh-aw-logs-shards @@ -368,6 +372,9 @@ jobs: rich_seed="$REPORT_VALUE_SEED_SHARDS/workflow-values-$ACTIVITY_ARTIFACT.jsonl" rich_output="$REPORT_GH_AW_LOGS_SHARDS/workflow-values-$ACTIVITY_ARTIFACT.jsonl" if [[ -f "$rich_seed" ]]; then cp "$rich_seed" "$rich_output"; fi + health_seed="$REPORT_VALUE_SEED_SHARDS/workflow-values-$ACTIVITY_ARTIFACT-collections.jsonl" + health_output="$REPORT_GH_AW_LOGS_SHARDS/workflow-values-$ACTIVITY_ARTIFACT-collections.jsonl" + if [[ -f "$health_seed" ]]; then cp "$health_seed" "$health_output"; fi proof_seed="$RUNNER_TEMP/cao-activity/workflow-value-workspaces/$ACTIVITY_ARTIFACT" proof_output="$RUNNER_TEMP/cao-activity-partial/$ACTIVITY_ARTIFACT/workflow-value-workspaces/$ACTIVITY_ARTIFACT" mkdir -p "$proof_output" @@ -376,39 +383,26 @@ jobs: value_output="$REPORT_GH_AW_LOGS_SHARDS/operational-values-$ACTIVITY_ARTIFACT.jsonl" if [[ -f "$retained_values" ]]; then cp "$retained_values" "$value_output" - node activity/cao.mjs ingest-jsonl \ - --database "$ACTIVITY_DATABASE" \ - --input "$value_output" \ - --retention-days 30 \ - --run-retention-days 30 - fi - if [[ "$REPORT_FAST_MODE" == "true" || "$REPORT_RATE_LIMITED" == "true" || "$REPORT_PUBLIC_ONLY" == "true" ]]; then - echo "Fast, public-only, or limited API mode: retained operational-value history; skipping new computation." - exit 0 fi + reason=shared-budget-unavailable + if [[ "$REPORT_FAST_MODE" == "true" ]]; then reason=fast-mode; fi + if [[ "$REPORT_PUBLIC_ONLY" == "true" ]]; then reason=public-only; fi + if [[ "$REPORT_RATE_LIMITED" == "true" ]]; then reason=api-budget; fi repository_args=() while IFS= read -r target_repository; do repository_args+=(--repository "$target_repository") - done < <(jq -r --arg owner "$ACTIVITY_OWNER" \ - '.repositories.rows[] - | select((.organization | ascii_downcase) == ($owner | ascii_downcase)) - | "\(.organization)/\(.repository)"' \ - "$REPORT_INVENTORY_SOURCES") - if ! node activity/cao.mjs operational-value \ - --database "$ACTIVITY_DATABASE" \ - --root . \ - --output "$REPORT_GH_AW_LOGS_SHARDS/operational-values-$ACTIVITY_ARTIFACT.jsonl" \ - --retention-days 365 \ - "${repository_args[@]}" \ - --max-github-api-rate-limit "$REPORT_MAX_GITHUB_API_RATE_LIMIT"; then - echo "::warning::Operational value collection failed for $ACTIVITY_OWNER; continuing activity indexing." - fi - if ! node activity/workflow-values.mjs \ + done < <(jq -r --arg owner "$ACTIVITY_OWNER" '.[] | "\($owner)/\(.)"' <<< "$REPORT_TARGET_REPOSITORIES_JSON") + node activity/workflow-values.mjs \ --root . --policy .github/workflows/cao.json \ --database "$ACTIVITY_DATABASE" --output "$rich_output" \ - --workspace "$proof_output" "${repository_args[@]}"; then - echo "::warning::Opted-in workflow Value collection failed; retaining accepted history." - fi + --healthOutput "$health_output" --inventory "$REPORT_INVENTORY_SOURCES" \ + --defer "$reason" --workspace "$proof_output" "${repository_args[@]}" \ + --localRequest "$REPORT_GH_AW_LOGS_SHARDS/workflow-value-local.json" \ + --snapshot "$GITHUB_RUN_ID-$GITHUB_RUN_ATTEMPT" + + - name: Report collection-health publication failure + if: ${{ steps.value-health.outcome == 'failure' }} + run: echo "::warning::Value health could not be refreshed; retained evidence and its original dates are unchanged. Activity publication continues." - name: Recheck public-only repository boundary before publication if: ${{ matrix.publicOnly == true }} @@ -555,6 +549,30 @@ jobs: --input-dir "$RUNNER_TEMP/cao-activity/gh-aw-logs-shards" \ --retention-days 30 --max-bytes "$REPORT_MAX_CACHE_BYTES" + - name: Restore previously completed local Value computation + if: ${{ inputs.recycle-only != true }} + timeout-minutes: 1 + continue-on-error: true + uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: ${{ runner.temp }}/cao-local-value/operational-values.jsonl + key: cao-value-local-v1-lookup-${{ github.run_id }}-${{ github.run_attempt }} + restore-keys: cao-value-local-v1- + + - name: Retain completed local values within reviewed scope + id: local-value-import + if: ${{ inputs.recycle-only != true }} + timeout-minutes: 1 + continue-on-error: true + run: | + node activity/local-values.mjs retain --policy .github/workflows/cao.json \ + --input "$RUNNER_TEMP/cao-local-value/operational-values.jsonl" \ + --output "$RUNNER_TEMP/cao-activity/gh-aw-logs-shards/operational-values-local.jsonl" + + - name: Report optional local Value import failure + if: ${{ steps.local-value-import.outcome == 'failure' }} + run: echo "::warning::Completed local Value results could not be imported; accepted evidence is unchanged. Activity publication continues." + - name: Rebuild recycled snapshot projection from retained evidence if: ${{ inputs.recycle-only == true }} run: node activity/recycle-snapshot.mjs reset "$RUNNER_TEMP/cao-activity" diff --git a/.github/workflows/cao-value-local.yml b/.github/workflows/cao-value-local.yml new file mode 100644 index 000000000..3a6bca2e9 --- /dev/null +++ b/.github/workflows/cao-value-local.yml @@ -0,0 +1,74 @@ +name: CAO Local Value + +on: + workflow_run: # zizmor: ignore[dangerous-triggers] - Only successful default-branch Activity snapshots are read; code and policy come from the trusted workflow revision. + workflows: [CAO Activity] + types: [completed] + +permissions: + contents: read + actions: read + +concurrency: + group: central-agentic-ops-local-value + cancel-in-progress: false + +jobs: + compute: + if: >- + github.event.workflow_run.conclusion == 'success' + && github.event.workflow_run.head_branch == github.event.repository.default_branch + && github.event.workflow_run.head_repository.id == github.event.repository.id + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - name: Checkout trusted Value source + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + ref: ${{ github.workflow_sha }} + persist-credentials: false + + - name: Set up CAO activity runtime + uses: ./.github/actions/setup-cao-runtime # zizmor: ignore[self-repository] - local action is checked out at github.workflow_sha. + with: + bundle: activity + + - name: Set up Node.js + uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 + with: + node-version: 24 + + - name: Download the already-published Activity snapshot + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 + with: + name: cao-activity-index + path: ${{ runner.temp }}/cao-activity + repository: ${{ github.repository }} + github-token: ${{ github.token }} + run-id: ${{ github.event.workflow_run.id }} + + - name: Restore retained local Value history + uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: ${{ runner.temp }}/cao-local-value/operational-values.jsonl + key: cao-value-local-v1-${{ github.event.workflow_run.id }}-${{ github.event.workflow_run.run_attempt }} + restore-keys: cao-value-local-v1- + + - name: Compute bounded local values without target credentials + timeout-minutes: 3 + env: + ACTIVITY_SNAPSHOT: ${{ github.event.workflow_run.id }}-${{ github.event.workflow_run.run_attempt }} + GH_TOKEN: "" + GITHUB_TOKEN: "" + CAO_OPERATIONAL_VALUE_GH_TOKEN: "" + run: | + node activity/local-values.mjs compute \ + --root . --policy .github/workflows/cao.json \ + --snapshot "$RUNNER_TEMP/cao-activity" --snapshotKey "$ACTIVITY_SNAPSHOT" \ + --output "$RUNNER_TEMP/cao-local-value/operational-values.jsonl" + + - name: Cache completed values for a later Activity snapshot + uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: ${{ runner.temp }}/cao-local-value/operational-values.jsonl + key: cao-value-local-v1-${{ github.event.workflow_run.id }}-${{ github.event.workflow_run.run_attempt }} diff --git a/.github/workflows/shared/materialize-cao.mjs b/.github/workflows/shared/materialize-cao.mjs index 1aae7b3ad..0924b4da0 100644 --- a/.github/workflows/shared/materialize-cao.mjs +++ b/.github/workflows/shared/materialize-cao.mjs @@ -520,7 +520,10 @@ export function verifyCaoRuntime(bundle, repositoryRoot = process.cwd()) { activity: [ 'activity/cao.mjs', 'activity/workflow-values.mjs', + 'activity/workflow-value-status.mjs', + 'activity/local-values.mjs', 'dashboard/site/src/data/model/operational-value-evidence.js', + 'dashboard/site/src/data/model/workflow-value-collection.js', 'activity/cli/activity-stats.mjs', 'activity/cli/cache.mjs', 'activity/cli/dashboard.mjs', diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index e771e4891..07e6c350f 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -277,7 +277,7 @@ deduplicates GitHub webhooks, and atomically replaces the current Postgres sources and state. `server/spec/storage.tsp` owns the fresh-only physical Postgres contract. Its emitter generates the standalone `server/internal/postgresx/schema.sql` and matching Go column bindings. -Nineteen canonical collections map one-to-one to entity tables containing only +Canonical collections map one-to-one to entity tables containing only query-consumed fields and identity/storage keys. Scalars use native SQL types; required structured fields use entity-owned relational child values, not JSON, JSONB, or serialized row documents. Scalar entity rows are never duplicated @@ -294,6 +294,12 @@ source metadata without asserting complete coverage or current freshness. Counts, comparisons, movement and report presentation remain declarative queries; importing evidence grants no target authority and navigation never acquires evidence. +Separate `workflowValueCollections` records retain reviewed registrations and +bounded collection decisions through the same producer, normalization and +browser/SQLite/PostgreSQL paths. Decisions do not advance actual-attempt, +accepted-capture or evidence-cutoff clocks. Declarative Value queries expose +enabled, disabled and unconfigured health before a first report; stale/conflicting +decisions and regressed attempt history fail closed. Explicit `gh cao value publish` writes one validated original packet through administrator-only `POST /api/v1/value` into PostgreSQL. The namespace writer lock serializes publication with snapshot replacement; typed ownership metadata @@ -731,9 +737,21 @@ Successful-Run value computations keep produced safe outputs, native operational-grader measurements, and efficiency evidence separate; they do not turn runtime success or output creation into accepted value. Package-level `operational-value.mjs` programs compute repository-scoped metric -records through `cao operational-value`. Activity appends those timestamped -records to authoritative JSONL before the canonical Operational Value collection -is rebuilt in SQLite, IndexedDB, and the hosted Postgres entity store. +records through `cao operational-value`. Automatic remote acquisition remains +deferred until shared per-request API admission can protect ordinary Activity +against concurrent credential consumers; separate workers are not separate quota. +Activity publishes health and retains accepted packets/proof without remote +Value acquisition. Bounded cache-only/local computation remains independent: +Actions runs it only after a successful eligible Activity snapshot, while the +hosted worker uses its own single-owner lease and verified private snapshot. +Both use the reviewed local-only standard adapter, explicit local-capability +modules or exact versioned cache reuse, no target credentials or automatic +backfill, and a two-minute batch/thirty-second adapter budget. Scope, explicit +disables, fast, public-only and API-limited gates remain enforced. A later +ordinary snapshot imports completed results; optional work does not acquire +the projection lease, hold a long core evidence lock, or initiate a +compute/publication retry loop. Normalized timestamped records then rebuild +the canonical Operational Value collection in every storage profile. Package-level `problem-clustering.mjs` programs read a private Activity SQLite snapshot and emit bounded problem records with actionable fix prompts through `cao cluster-problems`. diff --git a/CODEBASE.yml b/CODEBASE.yml index 927769bbb..a48a999da 100644 --- a/CODEBASE.yml +++ b/CODEBASE.yml @@ -283,7 +283,10 @@ components: responsibility: authenticate explicit administrator publication of original bounded evidence through POST /api/v1/value, with PostgreSQL namespace-locked atomic packet/fact ownership preserved across snapshot replacement, idempotent exact retries, frozen contracts and immutable historical measurements; never register or execute uploaded code workflow_value_collection: path: activity/workflow-values.mjs - responsibility: refresh exact repository/workflow registrations from reviewed local source on existing Activity and hosted collection cycles; the skill stages registration after frozen function and bounded collector verification, preserving existing selections and explicit disables; intersect effective collection scope, preserve frozen cadence and reusable proof, retain prior capture on failure and history on disable + responsibility: publish reviewed exact-registration collection health through the canonical browser/SQLite/PostgreSQL pipeline independently of accepted evidence; preserve actual-attempt and capture/cutoff clocks, explicit disables, scope and proof; defer recurring remote acquisition pending enforceable shared per-request budgets rather than spending ordinary Activity headroom + local_value_computation: + path: activity/local-values.mjs + responsibility: compute bounded local values only after eligible policy-matched Activity publication, using the reviewed local-only standard adapter, explicit local-capability modules or exact versioned cache reuse; no target credentials or automatic backfill; two-minute batch and thirty-second adapter limits; hosted work owns a separate lease and verified snapshot without the projection lease or long evidence lock; a later ordinary snapshot publishes results without a compute/publication retry loop package_problem_clustering: path: /problem-clustering.mjs responsibility: compute bounded package problem rows from a private Activity SQLite snapshot through the cao cluster-problems command @@ -425,6 +428,9 @@ dependencies: - computations -> cao_cli - package_operational_value -> cao_cli - package_operational_value -> activity_jsonl_shards + - workflow_value_collection -> activity_jsonl_shards + - local_value_computation -> package_operational_value + - local_value_computation -> activity_jsonl_shards - sqlite_projection -> package_problem_clustering - package_problem_clustering -> cao_cli - activity_jsonl_shards -> indexeddb_projection @@ -622,6 +628,7 @@ invariants: - "Browsers and external clients MUST NOT receive Redis or Postgres endpoints, credentials, keys, or storage-specific representations." - "Computations MUST consume canonical evidence, preserve evidence quality and provenance, and emit bounded, versioned results." - "Operational Value evidence MUST retain one bounded current packet per target repository, workflow and frozen contribution metric/version, with acquired contract, output, acceptance, lineage, independent snapshot, quality and coverage facts as typed relational children. Atomic packet replacement MUST preserve one coherent evidence revision independently of seven-day Run-detail retention. Retained source identity MUST materialize observed Repository and Workflow parents without inferring registration or activation. Packet cutoff/capture provenance MUST supply metadata without asserting complete coverage or current freshness. The operational-value-evidence logical source MUST only normalize facts; counts, comparisons, movement and report presentation belong to declarative queries. Import MUST NOT grant target authority and navigation MUST NOT acquire evidence." + - "Workflow Value collection decisions MUST remain separate canonical facts, visible before a report and without inventing attempts or capture/cutoff freshness. Stale/conflicting decisions and regressed attempt history MUST fail closed. Recurring remote acquisition MUST defer until enforceable shared per-request admission protects core Activity; a separate worker is not separate quota. Bounded local-only work MUST remain independent of ordinary publication, preserve scope, disables and existing fast/public-only/API-limited gates, and retain accepted evidence on failure." - "Direct value publication MUST require PostgreSQL, existing observed parents, hosted administrator step-up and CSRF or local loopback bearer. Publication MUST atomically preserve owned packet/fact rows and required structural parents across Activity replacement, reject stale/conflicting captures, frozen-contract drift and immutable-history rewrites, and leave exact retries revision-neutral. No uploaded evaluator code, PAT fallback, enrollment or implicit collection is permitted." - "Recurring workflow-value collection MUST require exact reviewed opt-in under control-plane.campaigns.activity.workflow-values and a confined local collector deployed with policy. Existing Activity and hosted collection cycles MUST intersect effective collection scope and frozen cadence; failed refreshes MUST retain the original accepted capture without invented freshness or zeros. Disable MUST stop future collection without deleting history. Navigation, upload and discovery MUST NOT enable collection or introduce a new schedule or model call." - "Computation results MUST NOT grant authority or turn runtime success into verification, accepted outcomes, or operational value." diff --git a/activity/README.md b/activity/README.md index 9c079c361..907180159 100644 --- a/activity/README.md +++ b/activity/README.md @@ -30,7 +30,7 @@ For a fresh installation whose exact `allowed-repositories` scope contains only the control repository, Activity uses the job's `GITHUB_TOKEN` without any additional secrets or variables. An unset `GH_AW_GITHUB_AUTH_MODE` or an explicit `workflow-token` selects this repository-local path. It reserves -100 core API requests for both log and operational-value collection, fitting +100 core API requests for ordinary log collection, fitting the standard workflow-token quota. A repository with no agentic runs still publishes an explicit empty snapshot. Broader repository or owner-wide scopes require explicit `app` or `pat` authentication; missing credentials in those @@ -342,9 +342,34 @@ records by `organization` and `repository`, and left-joins those query results in the data Web Worker. Activity collection and browser components do not reconstruct those relationships. +## Health-first Value collection + +Activity publishes `workflow_value_collection` JSONL alongside retained evidence. +The Value page and workflow Value tab show reviewed enabled/disabled registrations +before any report exists, with actual deferral reasons and separate decision, +attempt, accepted capture and cutoff dates. Missing reports do not establish an +unconfigured collector. Deferrals and failures preserve accepted packets and proof. + +Recurring remote acquisition remains deferred pending enforceable shared-budget +admission; a separate process does not isolate API quota. Ordinary Activity only +performs bounded, credential-free health publication and retained-data import. +Actual API exhaustion, fast and public-only modes preserve their existing gates. +Recycle-only maintenance does not create a new eligible local-computation request. + +The separate `cao-value-local.yml` runs after successful default-branch Activity +publication. It validates the snapshot identity and current policy digest, admits +only the reviewed local-only standard adapter, and permits local-capable modules +or exact versioned cache reuse without target API calls or automatic backfill. +The job is capped at five minutes, its compute batch at two minutes and each +adapter at thirty seconds. Completed results use a separate cache and are +validated and scope-filtered into a later ordinary Activity snapshot. +Activity and Dashboard do not wait for this optional job. Disabled registrations, +campaigns and workflows stay disabled; malformed, missing or oversized optional +results leave accepted history unchanged. + ## Campaign problem clustering -After canonical ingestion and operational-value collection, Activity runs +After canonical ingestion and retained-value import, Activity runs `cao cluster-problems`. The command discovers one optional `/problem-clustering.mjs` file in each installed top-level campaign. This lets campaigns contribute deterministic problem computations without diff --git a/activity/aw.yml b/activity/aw.yml index 5b2739971..1443faf3c 100644 --- a/activity/aw.yml +++ b/activity/aw.yml @@ -5,3 +5,4 @@ min-version: v0.93.1 experimental: true includes: - .github/workflows/cao-activity.yml + - .github/workflows/cao-value-local.yml diff --git a/activity/cli-usage.mjs b/activity/cli-usage.mjs index aa28fd296..261f3fcc8 100644 --- a/activity/cli-usage.mjs +++ b/activity/cli-usage.mjs @@ -17,6 +17,7 @@ export const ENTITY_COLLECTIONS = [ 'issues', 'operationalValues', 'operationalValueEvidence', + 'workflowValueCollections', 'experiments', 'experimentAssignments', 'graders', @@ -53,7 +54,7 @@ export const USAGE = `Usage: cao mcp [--database FILE] [--dashboard FILE] [--host HOST] [--port PORT] cao computation intelligence [--database FILE] [--inventory FILE] [--campaign SLUG] [--previous FILE] [--feedback FILE] cao computation runtime-health [--database FILE] [--inventory FILE] [--campaign SLUG] [--diagnose] - cao operational-value [--database FILE] [--root DIRECTORY] [--output FILE] [--timestamp TIME] [--repository OWNER/REPO] [--campaign SLUG] [--retention-days DAYS|all] [--history-campaign SLUG] [--max-github-api-rate-limit LIMIT] + cao operational-value [--database FILE] [--root DIRECTORY] [--output FILE] [--timestamp TIME] [--repository OWNER/REPO] [--campaign SLUG] [--retention-days DAYS|all] [--history-campaign SLUG] [--max-github-api-rate-limit LIMIT] [--local-only] cao cluster-problems [--database FILE] [--root DIRECTORY] [--timestamp TIME] cao repair-database [--database FILE] [--ttl-days DAYS|all] [--run-ttl-days DAYS|all] Mutates SQLite: backs up before repairs and prunes expired/orphaned records, even without corruption. diff --git a/activity/cli/cache.mjs b/activity/cli/cache.mjs index 7e83c7125..48571180f 100644 --- a/activity/cli/cache.mjs +++ b/activity/cli/cache.mjs @@ -227,8 +227,16 @@ export async function mergeActivityFragments(fragmentDirectory, outputDirectory) if (roots.length === 0) throw new Error('No owner-scoped activity fragments were downloaded'); const inventories = []; const incoming = new Map(); + const localValueRequests = []; for (const fragment of roots) { inventories.push(JSON.parse(await readFile(path.join(fragment, 'inventory-sources.json'), 'utf8'))); + try { + const requests = JSON.parse(await readFile(path.join(fragment, 'gh-aw-logs-shards', 'workflow-value-local.json'), 'utf8')); + if (!Array.isArray(requests)) throw new Error('Invalid owner-scoped local Value requests'); + localValueRequests.push(...requests); + } catch (error) { + if (error.code !== 'ENOENT') throw error; + } const proofs = path.join(fragment, 'workflow-value-workspaces'); try { if ((await lstat(proofs)).isSymbolicLink()) throw new Error('Workflow evidence workspaces must not be symlinks'); @@ -254,9 +262,10 @@ export async function mergeActivityFragments(fragmentDirectory, outputDirectory) const destination = path.join(outputDirectory, 'gh-aw-logs-shards'); // Each successful collection fragment already includes its retained seed data. for (const file of await shardPaths(destination)) { - if (!incoming.has(path.basename(file))) await rm(file); + if (!incoming.has(path.basename(file)) && path.basename(file) !== 'operational-values-local.jsonl') await rm(file); } for (const [name, file] of incoming) await rename(file, path.join(destination, name)); await writeFile(path.join(outputDirectory, 'inventory-sources.json'), `${JSON.stringify(inventory, null, 2)}\n`); + await writeFile(path.join(destination, 'workflow-value-local.json'), `${JSON.stringify(localValueRequests)}\n`); return { fragments: roots.length, shards: incoming.size }; } diff --git a/activity/cli/options.mjs b/activity/cli/options.mjs index e9012a409..a4c5b71ef 100644 --- a/activity/cli/options.mjs +++ b/activity/cli/options.mjs @@ -13,7 +13,7 @@ export function parseOptions(arguments_) { const name = aliases[argument] ?? argument.slice(2); if (name === 'help' || name === 'stdin' || name === 'json' || name === 'keep' || name === 'diagnose' || name === 'dry-run' || name === 'no-open' || name === 'keep-existing' || name === 'replace-existing' - || name === 'strict-warnings' || name === 'offline') { + || name === 'strict-warnings' || name === 'offline' || name === 'local-only') { options[name] = 'true'; continue; } diff --git a/activity/cli/payloads.mjs b/activity/cli/payloads.mjs index ad7211b1f..5c4b7f623 100644 --- a/activity/cli/payloads.mjs +++ b/activity/cli/payloads.mjs @@ -9,6 +9,7 @@ import { adaptCachedGhAwJsonlStream } from '../../dashboard/site/src/data/adapte import { GH_AW_JSONL_INGESTION_VERSION, NORMALIZED_JSONL_INGESTION_VERSION } from '../../dashboard/site/src/data/ingest/coordinator.js'; import { normalize } from '../../dashboard/site/src/data/normalize/index.js'; import { mergeOperationalValueEvidence } from '../../dashboard/site/src/data/model/operational-value-evidence.js'; +import { mergeWorkflowValueCollection } from '../../dashboard/site/src/data/model/workflow-value-collection.js'; import { CANONICAL_SCHEMA_VERSION, mergeEvidenceDefinition } from '../../dashboard/site/src/data/model/schema.js'; import { mergeActivityStructuralRecord } from '../../dashboard/site/src/data/storage/retention.js'; import { NORMALIZED_COLLECTIONS } from '../cli-usage.mjs'; @@ -100,6 +101,10 @@ async function consolidatePhasePayloads( records.set(id, mergeOperationalValueEvidence(existing, record)); continue; } + if (entry.collection === 'workflowValueCollections') { + records.set(id, mergeWorkflowValueCollection(existing, record)); + continue; + } // Mirrors canonical ingestion precedence: discovery owns repository and // workflow inventory fields, every other collection is last-observation-wins. if (existing && (entry.collection === 'repositories' || entry.collection === 'workflows')) { diff --git a/activity/commands/operational-value.mjs b/activity/commands/operational-value.mjs index 5ef2cefd5..ab44fa746 100644 --- a/activity/commands/operational-value.mjs +++ b/activity/commands/operational-value.mjs @@ -13,7 +13,7 @@ export function runOperationalValueCommand({ rejectUnknownOptions, UsageError, }) { - rejectUnknownOptions(options, ["database", "root", "output", "timestamp", "repository", "retention-days", "max-github-api-rate-limit", "campaign", "history-campaign"]); + rejectUnknownOptions(options, ["database", "root", "output", "timestamp", "repository", "retention-days", "max-github-api-rate-limit", "campaign", "history-campaign", "local-only"]); const repositories = options.repository === undefined ? [] : Array.isArray(options.repository) ? options.repository : [options.repository]; @@ -47,6 +47,7 @@ export function runOperationalValueCommand({ timestamp: option(options, "timestamp", false) || new Date().toISOString(), repositories, rateLimitReserve: operationalValueReserve(option(options, "max-github-api-rate-limit", false), UsageError), + localOnly: options["local-only"] === "true", retentionWindow: retentionWindow ?? OPERATIONAL_VALUE_RETENTION_MS, signal, }); diff --git a/activity/local-values.mjs b/activity/local-values.mjs new file mode 100644 index 000000000..139ad803a --- /dev/null +++ b/activity/local-values.mjs @@ -0,0 +1,117 @@ +import { readFile, stat } from 'node:fs/promises'; +import path from 'node:path'; +import { pathToFileURL } from 'node:url'; +import { loadPolicyFile } from '../.github/workflows/shared/policy.mjs'; +import { MAX_LOCAL_VALUE_BYTES as MAX_BYTES, runOperationalValue } from './operational-value.mjs'; +import { adaptCachedGhAwJsonl } from '../dashboard/site/src/data/adapters/gh-aw-logs.js'; +import { readValueEnvelopes, valuePolicyDigest, valueRepositoryInScope, writeValueEnvelopes } from './workflow-value-status.mjs'; + +export async function localValuePlan({ policy, snapshot, snapshotKey }) { + const document = loadPolicyFile(policy); + const filename = path.join(snapshot, 'gh-aw-logs-shards', 'workflow-value-local.json'); + let requests; + try { + if ((await stat(filename)).size > MAX_BYTES) throw new Error('Local Value requests exceed their byte budget'); + requests = JSON.parse(await readFile(filename, 'utf8')); + } catch (error) { + if (error.code !== 'ENOENT') throw error; + console.warn('Local Value deferred: no eligible Activity snapshot request is available'); + return { repositories: [], disabledCampaigns: [], disabledWorkflows: [], disabledCollections: [] }; + } + if (!Array.isArray(requests) || requests.length > 1000) throw new Error('Invalid local Value requests'); + const repositories = new Set(); + for (const request of requests) { + if (request.schemaVersion !== 1 || typeof request.eligible !== 'boolean' + || !Array.isArray(request.repositories) || request.repositories.length > 10000 + || request.repositories.some(repository => typeof repository !== 'string')) { + throw new Error('Invalid local Value request'); + } + if (!request.eligible || request.snapshot !== snapshotKey || request.policyDigest !== valuePolicyDigest(document)) continue; + for (const repository of request.repositories) { + if (valueRepositoryInScope(document, request.repositories, repository, true)) repositories.add(repository.toLowerCase()); + } + } + const control = document['control-plane']; + return { + repositories: control.campaigns?.activity?.enabled === false ? [] : [...repositories].sort(), + disabledCampaigns: Object.entries(control.campaigns ?? {}).filter(([, value]) => value.enabled === false).map(([name]) => name), + disabledWorkflows: Object.entries(control.workflows ?? {}).filter(([, value]) => value.enabled === false).map(([name]) => name), + disabledCollections: (control.campaigns?.activity?.['workflow-values'] ?? []).filter(entry => entry.enabled === false) + .map(entry => `${entry.repository.toLowerCase()}:${entry.workflow}`), + }; +} + +export async function computeLocalValues(options) { + const plan = await localValuePlan(options); + if (plan.repositories.length === 0) { + console.warn('Local Value deferred: the snapshot is ineligible or its reviewed policy has changed'); + return { values: [], warnings: [{ message: 'The snapshot is ineligible or its reviewed policy has changed' }] }; + } + return runOperationalValue({ + ...plan, root: options.root, outputPath: options.output, + databasePath: options.database ?? path.join(options.snapshot, 'gh-aw-logs.sqlite'), + localOnly: true, retentionWindow: 365 * 86400000, + signal: options.signal ?? AbortSignal.timeout(120000), workerTimeoutMs: 30000, + }); +} + +export async function retainLocalValues({ policy, input, output }) { + const document = loadPolicyFile(policy); + const readValues = async filename => { + try { + if ((await stat(filename)).size > MAX_BYTES) throw new Error('Local Value output exceeds its byte budget'); + } catch (error) { + if (error.code === 'ENOENT') return []; + throw error; + } + const envelopes = await readValueEnvelopes(filename); + if (envelopes.some(envelope => envelope.schema_version !== 2 || envelope.kind !== 'operational_value')) { + throw new Error('Invalid completed local Value envelope'); + } + adaptCachedGhAwJsonl(envelopes.map(envelope => JSON.stringify(envelope)).join('\n')); + return envelopes; + }; + const retained = await readValues(output); + let incoming = []; + try { + incoming = await readValues(input); + } catch (error) { + console.warn(`Local Value import deferred: ${error.message}; retained evidence is unchanged`); + incoming = []; + } + const accepted = new Map(); + for (const envelope of [...retained, ...incoming]) { + const value = envelope.operational_value; + if (!valueRepositoryInScope(document, [value.repository], value.repository, true)) continue; + accepted.set(JSON.stringify([value.campaign, value.repository.toLowerCase(), value.value_id, value.timestamp]), envelope); + } + const envelopes = [...accepted.values()]; + if (Buffer.byteLength(envelopes.map(envelope => JSON.stringify(envelope)).join('\n')) + envelopes.length > MAX_BYTES) { + throw new Error('Combined local Value output exceeds its byte budget; retained evidence is unchanged'); + } + await writeValueEnvelopes(output, envelopes); +} + +if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) { + try { + const [operation, ...args] = process.argv.slice(2); + const options = {}; + for (let index = 0; index < args.length; index += 2) { + const key = args[index].replace(/^--/, ''); + if (!['root', 'policy', 'snapshot', 'snapshotKey', 'database', 'input', 'output'].includes(key) || !args[index + 1]) { + throw new Error('Invalid local-values option'); + } + options[key] = args[index + 1]; + } + if (operation === 'retain') await retainLocalValues(options); + else if (operation === 'compute') { + const result = await computeLocalValues(options); + console.log(JSON.stringify({ ...result, values: result.values.length })); + } + else if (operation === 'plan') console.log(JSON.stringify(await localValuePlan(options))); + else throw new Error('Expected local-values compute, retain, or plan'); + } catch (error) { + console.error(`Local Value failed: ${error.message}`); + process.exitCode = 1; + } +} diff --git a/activity/normalized-phase.mjs b/activity/normalized-phase.mjs index 8fdd3d0bc..b7beba791 100644 --- a/activity/normalized-phase.mjs +++ b/activity/normalized-phase.mjs @@ -3,7 +3,7 @@ import { NORMALIZED_COLLECTIONS } from './cli-usage.mjs'; const RUN_COLLECTIONS = new Set([ 'campaigns', 'repositories', 'workflows', 'runs', 'experiments', 'experimentAssignments' ]); -const STRUCTURAL_COLLECTIONS = new Set(['campaigns', 'repositories', 'workflows', 'experiments', 'graders', 'evals', 'operationalValueEvidence']); +const STRUCTURAL_COLLECTIONS = new Set(['campaigns', 'repositories', 'workflows', 'experiments', 'graders', 'evals', 'operationalValueEvidence', 'workflowValueCollections']); export const STRUCTURAL_CONSOLIDATION_BUCKET = '0000-00-00'; const TIMESTAMP_FIELDS = ['startedAt', 'observedAt', 'timestamp', 'completedAt', 'createdAt', 'updatedAt']; diff --git a/activity/operational-value.mjs b/activity/operational-value.mjs index e4a0c2d87..ed63b1a99 100644 --- a/activity/operational-value.mjs +++ b/activity/operational-value.mjs @@ -1,4 +1,5 @@ import { spawn, spawnSync } from 'node:child_process'; +import { createHash } from 'node:crypto'; import { readFile, readdir, mkdir, rename, rm, stat, writeFile } from 'node:fs/promises'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; @@ -13,6 +14,9 @@ const BASELINE_OBSERVATIONS = 3; const MAX_HISTORY_OBSERVATIONS = 366; const WORKER_TIMEOUT_MS = 2 * 60 * 1000; const RATE_LIMIT_TIMEOUT_MS = 30 * 1000; +// Older/custom adapters may ignore localOnly. Admit only the reviewed standard adapter. +export const LOCAL_VALUE_ADAPTER_DIGEST = '771ab1363f035e771684fc334c38dfeeee1855d691758055d4637373d3617416'; +export const MAX_LOCAL_VALUE_BYTES = 16 * 1024 * 1024; const WORKER_ENVIRONMENT = [ 'CI', 'HOME', @@ -71,11 +75,11 @@ async function githubApiRemaining(env, signal) { return remaining; } -function operationalValueWorkerEnvironment(databasePath, observedAt, rateLimitReserve) { +function operationalValueWorkerEnvironment(databasePath, observedAt, rateLimitReserve, localOnly) { const env = Object.fromEntries(WORKER_ENVIRONMENT.flatMap((name) => ( process.env[name] === undefined ? [] : [[name, process.env[name]]] ))); - const token = process.env.CAO_OPERATIONAL_VALUE_GH_TOKEN || process.env.GH_TOKEN; + const token = localOnly ? undefined : process.env.CAO_OPERATIONAL_VALUE_GH_TOKEN || process.env.GH_TOKEN; if (token) env.GH_TOKEN = token; env.CAO_DATABASE = path.resolve(databasePath); env.CAO_ACTIVITY_CLI = fileURLToPath(new URL('./cao.mjs', import.meta.url)); @@ -152,7 +156,7 @@ function runChildProcess(command, args, { : timeoutSignal; return new Promise((resolve) => { const child = spawn(command, args, { - detached: process.platform !== 'win32', + detached: process.platform !== 'win32' && process.env.CAO_VALUE_SHARED_PROCESS_GROUP !== '1', env, stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true @@ -224,6 +228,7 @@ export function operationalValueReserve(value, UsageError = Error) { function parseOperationalValueOutput(content, source, repositories) { const allowedRepositories = new Set(repositories.map((repository) => repository.toLowerCase())); const definitions = []; + const deferred = []; const definedIds = new Set(); const values = String(content).split(/\r?\n/).flatMap((line, index) => { if (!line.trim()) return []; @@ -236,6 +241,12 @@ function parseOperationalValueOutput(content, source, repositories) { if (!record || typeof record !== 'object' || Array.isArray(record)) { throw new Error(`${source}:${index + 1} must emit a JSON object`); } + if (record.kind === 'operational_value_deferred') { + if (!OPERATIONAL_VALUE_SLUG.test(record.workflowSlug ?? '') || typeof record.reason !== 'string' + || !record.reason.trim() || record.reason.length > 1024) throw new Error('Invalid operational value deferral'); + deferred.push(`${record.workflowSlug}: ${record.reason}`); + return []; + } if (record.kind === 'operational_value_definition') { const workflowSlug = String(record.workflowSlug ?? ''); const evaluationMode = record.evaluationMode; @@ -383,7 +394,7 @@ function parseOperationalValueOutput(content, source, repositories) { ...(hasRollupNumerator ? { rollupNumerator, rollupDenominator } : {}) }]; }); - return { definitions, values }; + return { definitions, values, deferred }; } function historicalObservationTimes(definition, observedAt, retentionWindow) { @@ -472,6 +483,10 @@ export async function runOperationalValue({ timestamp = new Date().toISOString(), repositories = [], rateLimitReserve, + localOnly = false, + disabledCampaigns = [], + disabledWorkflows = [], + disabledCollections = [], retentionWindow, signal, workerTimeoutMs = WORKER_TIMEOUT_MS @@ -493,9 +508,9 @@ export async function runOperationalValue({ throw new Error('Operational value requires at least one repository in the dashboard database or --repository'); } const discoveredScripts = await discoverOperationalValueScripts(root); - const scripts = campaign + const scripts = (campaign ? discoveredScripts.filter((entry) => entry.package === campaign) - : discoveredScripts; + : discoveredScripts).filter(entry => !disabledCampaigns.includes(entry.package)); if (campaign && scripts.length === 0) { throw new Error(`Operational value campaign not found: ${campaign}`); } @@ -503,6 +518,13 @@ export async function runOperationalValue({ throw new Error(`Operational value history campaign not found: ${historyCampaign}`); } const output = outputPath ? path.resolve(outputPath) : undefined; + if (localOnly && output) { + try { + if ((await stat(output)).size > MAX_LOCAL_VALUE_BYTES) throw new Error('Retained local Value exceeds its byte budget'); + } catch (error) { + if (error.code !== 'ENOENT') throw error; + } + } const cutoff = retentionWindow === undefined ? Number.NEGATIVE_INFINITY : Date.parse(observedAt) - retentionWindow; @@ -517,14 +539,16 @@ export async function runOperationalValue({ schemaVersion: 1, timestamp: observedAt, repositories: uniqueRepositories, - database: path.resolve(databasePath) + database: path.resolve(databasePath), + ...(localOnly ? { localOnly: true, disabledWorkflows, disabledCollections } : {}) })}\n`; const values = []; const warnings = []; const activeValueIds = new Map(); const cadenceDefinitions = new Map(); let historyValues = 0; - const worker = operationalValueWorkerEnvironment(databasePath, observedAt, rateLimitReserve); + let localOutputBytes = 0; + const worker = operationalValueWorkerEnvironment(databasePath, observedAt, rateLimitReserve, localOnly); const warn = (entry, error) => { const message = redactToken(error instanceof Error ? error.message : error, worker.token); const warning = { package: entry?.package ?? null, message }; @@ -534,14 +558,21 @@ export async function runOperationalValue({ for (const entry of scripts) { try { signal?.throwIfAborted(); - if (rateLimitReserve !== undefined && await githubApiRemaining(worker.env, signal) <= rateLimitReserve) { + if (localOnly && createHash('sha256').update(await readFile(entry.script)).digest('hex') !== LOCAL_VALUE_ADAPTER_DIGEST) { + throw new Error(`${entry.package}: local computation deferred because the adapter has no reviewed local-only boundary`); + } + if (!localOnly && rateLimitReserve !== undefined && await githubApiRemaining(worker.env, signal) <= rateLimitReserve) { throw new Error(`GitHub API core remaining is at or below the reserved ${rateLimitReserve} requests`); } const workerOutput = await runOperationalValueWorker(entry, request, worker.env, { signal, timeoutMs: workerTimeoutMs }); + if (localOnly && (localOutputBytes += Buffer.byteLength(workerOutput)) > MAX_LOCAL_VALUE_BYTES) { + throw new Error('Local Value batch exceeded its output budget; accepted evidence retained'); + } const parsed = parseOperationalValueOutput(workerOutput, entry.script, uniqueRepositories); + for (const reason of parsed.deferred) warn(entry, reason); values.push(...parsed.values.map((record) => ({ ...record, campaign: entry.package }))); if (parsed.definitions.length > 0) { activeValueIds.set(entry.package, new Set( @@ -594,7 +625,8 @@ export async function runOperationalValue({ timestamp: batch.at(-1), ...(definition.historyBatch ? { historyTimestamps: batch } : {}), repositories: supportedRepositories, - database: path.resolve(databasePath) + database: path.resolve(databasePath), + ...(localOnly ? { localOnly: true, disabledWorkflows, disabledCollections } : {}) })}\n`; const historyOutput = await runOperationalValueWorker( entry, @@ -602,6 +634,9 @@ export async function runOperationalValue({ historyEnvironment, { signal, timeoutMs: workerTimeoutMs } ); + if (localOnly && (localOutputBytes += Buffer.byteLength(historyOutput)) > MAX_LOCAL_VALUE_BYTES) { + throw new Error('Local Value batch exceeded its output budget; accepted evidence retained'); + } const historyParsed = parseOperationalValueOutput( historyOutput, entry.script, @@ -642,11 +677,12 @@ export async function runOperationalValue({ } } catch (error) { signal?.throwIfAborted(); + if (localOnly && localOutputBytes > MAX_LOCAL_VALUE_BYTES) throw error; warn(entry, error); } } signal?.throwIfAborted(); - if (rateLimitReserve !== undefined) { + if (!localOnly && rateLimitReserve !== undefined) { try { if (await githubApiRemaining(worker.env, signal) < rateLimitReserve) { throw new Error(`Operational value crossed the reserved GitHub API floor of ${rateLimitReserve} requests`); @@ -714,6 +750,9 @@ export async function runOperationalValue({ } } const jsonl = [...merged.values()].map((envelope) => JSON.stringify(envelope)).join('\n'); + if (localOnly && Buffer.byteLength(jsonl) + 1 > MAX_LOCAL_VALUE_BYTES) { + throw new Error('Combined local Value exceeds its output budget; accepted evidence retained'); + } const temporary = `${output}.tmp-${process.pid}-${Date.now()}`; try { await writeFile(temporary, jsonl ? `${jsonl}\n` : '', { flag: 'wx' }); diff --git a/activity/workflow-value-status.mjs b/activity/workflow-value-status.mjs new file mode 100644 index 000000000..ac0cefb40 --- /dev/null +++ b/activity/workflow-value-status.mjs @@ -0,0 +1,118 @@ +import { createHash } from 'node:crypto'; +import { mkdir, readFile, rename, writeFile } from 'node:fs/promises'; +import path from 'node:path'; +import { queryDashboardSourceObservations } from '../dashboard/site/src/data/queries/ingestion.js'; +import { + VALUE_COLLECTION_REASONS, validateWorkflowValueCollection, workflowValueCollectionId, +} from '../dashboard/site/src/data/model/workflow-value-collection.js'; + +const same = (a, b) => typeof a === 'string' && typeof b === 'string' && a.toLowerCase() === b.toLowerCase(); +export const VALUE_DEFERRALS = new Set(['api-budget', 'budget-unavailable', 'shared-budget-unavailable', + 'fast-mode', 'public-only', 'batch-budget']); +export const valuePolicyDigest = document => createHash('sha256').update(JSON.stringify(document)).digest('hex'); + +export function valueRepositoryInScope(document, repositories, repository, allowActivityFallback = false) { + const control = document['control-plane']; + if (!control) throw new Error('Control policy is required'); + const scope = control.scope ?? {}; + const enrolled = control.activity?.repositories + ?? (allowActivityFallback ? scope['allowed-repositories'] ?? [] : []); + return repositories.some(target => same(target, repository)) + && enrolled.some(target => same(target, repository)) + && (!scope['allowed-repositories'] || scope['allowed-repositories'].some(target => same(target, repository))) + && (!scope['allowed-owners'] || scope['allowed-owners'].some(owner => same(owner, repository.split('/')[0]))); +} + +export function workflowValueSelections(document, repositories) { + return (document['control-plane']?.campaigns?.activity?.['workflow-values'] ?? []) + .filter(entry => valueRepositoryInScope(document, repositories, entry.repository)); +} + +export async function readValueEnvelopes(filename) { + try { + return (await readFile(filename, 'utf8')).split('\n').filter(Boolean).map(line => JSON.parse(line)); + } catch (error) { + if (error.code === 'ENOENT') return []; + throw error; + } +} + +export async function writeValueEnvelopes(filename, envelopes) { + await mkdir(path.dirname(filename), { recursive: true }); + const pending = `${filename}.pending`; + await writeFile(pending, envelopes.map(value => JSON.stringify(value)).join('\n') + + (envelopes.length ? '\n' : ''), { mode: 0o600 }); + await rename(pending, filename); +} + +export async function workflowValueStatusContext(options, document, retained) { + const output = options.healthOutput ?? options.output.replace(/(?:\.jsonl)?$/, '-collections.jsonl'); + const previous = new Map((await readValueEnvelopes(output)).flatMap(envelope => { + if (envelope.schema_version !== 2 || envelope.kind !== 'workflow_value_collection') { + throw new Error('Invalid retained workflow Value collection envelope'); + } + const record = validateWorkflowValueCollection(envelope.workflow_value_collection); + return valueRepositoryInScope(document, options.repositories, record.repository) ? [[record.id, record]] : []; + })); + const registrations = workflowValueSelections(document, options.repositories); + const targets = new Map(); + const include = ({ repository, workflow }) => { + if (!valueRepositoryInScope(document, options.repositories, repository)) return; + targets.set(workflowValueCollectionId(repository, workflow), { repository, workflow }); + }; + for (const record of previous.values()) include(record); + for (const envelope of retained) include(envelope.operational_value_evidence); + if (options.inventory) { + const inventory = JSON.parse(await readFile(options.inventory, 'utf8')); + const sources = {}; + for (const name of ['repositories', 'workflows']) { + if (inventory[name]?.metadata?.availability === 'unavailable') { + console.warn(`Workflow Value inventory unavailable: ${name}; registration decisions still use reviewed policy`); + } else sources[name] = inventory[name]; + } + const { observations } = queryDashboardSourceObservations({ + ...sources, + }); + const repositories = new Map(observations.filter(value => value.kind === 'repository') + .map(value => [value.data.id, `${value.data.owner}/${value.data.name}`])); + for (const { data } of observations.filter(value => value.kind === 'workflow')) { + const workflow = /^\.github\/workflows\/([a-z0-9]+(?:-[a-z0-9]+)*)\.md$/.exec(String(data.path))?.[1]; + const repository = repositories.get(data.repositoryId); + if (workflow && repository) include({ repository, workflow }); + } + } + for (const entry of registrations) targets.set(workflowValueCollectionId(entry.repository, entry.workflow), entry); + if (targets.size > 10000) throw new Error('Workflow Value collection inventory exceeds its row budget'); + return { + output, previous, targets: [...targets.values()], + policyDigest: valuePolicyDigest(document), + activityDisabled: document['control-plane']?.campaigns?.activity?.enabled === false, + }; +} + +export function valueCollectionDecision(context, entry, { + state, reasonCode, observedAt, lastAttemptAt, lastAttemptOutcome, +}) { + const id = workflowValueCollectionId(entry.repository, entry.workflow); + const previous = context.previous.get(id); + const record = validateWorkflowValueCollection({ + schemaVersion: 1, id, repository: entry.repository.toLowerCase(), workflow: entry.workflow, + sourcePath: `.github/workflows/${entry.workflow}.md`, + policyDigest: context.policyDigest, observedAt, + registration: entry.enabled === false ? 'disabled' : entry.collector ? 'enabled' : 'unconfigured', + ...(entry.collector ? { collector: entry.collector } : {}), + state, reasonCode, reason: VALUE_COLLECTION_REASONS[reasonCode], + ...(lastAttemptAt || previous?.lastAttemptAt ? { + lastAttemptAt: lastAttemptAt ?? previous.lastAttemptAt, + lastAttemptOutcome: lastAttemptOutcome ?? previous.lastAttemptOutcome, + } : {}), + }); + context.previous.set(id, record); + return record; +} + +export async function saveValueCollectionDecisions(context) { + await writeValueEnvelopes(context.output, [...context.previous.values()] + .sort((left, right) => left.id.localeCompare(right.id)) + .map(record => ({ schema_version: 2, kind: 'workflow_value_collection', workflow_value_collection: record }))); +} diff --git a/activity/workflow-values.mjs b/activity/workflow-values.mjs index 05027a6e2..41535a63a 100644 --- a/activity/workflow-values.mjs +++ b/activity/workflow-values.mjs @@ -4,12 +4,17 @@ // The return value is the original schema-v2 operational_value_evidence envelope. import { spawn, spawnSync } from 'node:child_process'; import { createHash } from 'node:crypto'; -import { lstat, mkdir, mkdtemp, readFile, readdir, rename, rm, writeFile } from 'node:fs/promises'; +import { lstat, mkdir, mkdtemp, readdir, rm, writeFile } from 'node:fs/promises'; import path from 'node:path'; import { pathToFileURL } from 'node:url'; import { loadPolicyFile } from '../.github/workflows/shared/policy.mjs'; import { validateOperationalValueEvidence } from '../dashboard/site/src/data/model/operational-value-evidence.js'; import { assertValueHistory } from './workflow-value-history.mjs'; +import { + readValueEnvelopes, saveValueCollectionDecisions, valueCollectionDecision, VALUE_DEFERRALS, + workflowValueSelections, workflowValueStatusContext, writeValueEnvelopes, + valueRepositoryInScope, +} from './workflow-value-status.mjs'; export { assertValueHistory } from './workflow-value-history.mjs'; @@ -38,14 +43,7 @@ export function workflowValueRegistrations(document, repositories) { if (!control) throw new Error('Control policy is required'); const activity = control.campaigns?.activity; if (activity?.enabled === false) return []; - const enrolled = control.activity?.repositories ?? []; - const scope = control.scope ?? {}; - return (activity?.['workflow-values'] ?? []).filter((entry) => - entry.enabled !== false - && repositories.some((repository) => same(repository, entry.repository)) - && enrolled.some((repository) => same(repository, entry.repository)) - && (!scope['allowed-repositories'] || scope['allowed-repositories'].some((repository) => same(repository, entry.repository))) - && (!scope['allowed-owners'] || scope['allowed-owners'].some((owner) => same(owner, entry.repository.split('/')[0])))); + return workflowValueSelections(document, repositories).filter(entry => entry.enabled !== false); } export async function collectWorkflowValue(request) { @@ -102,15 +100,6 @@ export async function collectWorkflowValue(request) { } } -async function readPrevious(filename) { - try { - return (await readFile(filename, 'utf8')).split('\n').filter(Boolean).map((line) => JSON.parse(line)); - } catch (error) { - if (error.code === 'ENOENT') return []; - throw error; - } -} - async function executeCollector(request, timeout) { return new Promise((resolve) => { // Hosted Go owns the encompassing process group; Actions owns this worker's @@ -120,7 +109,7 @@ async function executeCollector(request, timeout) { detached, stdio: ['pipe', 'pipe', 'pipe'], env: process.env, }); const chunks = []; - let bytes = 0, errors = 0, failed = false; + let bytes = 0, errors = 0, failed = false, timedOut = false; const terminate = () => { try { if (child.pid) process.kill(detached ? -child.pid : child.pid, 'SIGKILL'); @@ -128,7 +117,7 @@ async function executeCollector(request, timeout) { if (error.code !== 'ESRCH') failed = true; } }; - const timer = setTimeout(() => { failed = true; terminate(); }, timeout); + const timer = setTimeout(() => { failed = true; timedOut = true; terminate(); }, timeout); child.stdout.on('data', (chunk) => { bytes += chunk.length; if (bytes > MAX_BYTES) { failed = true; terminate(); } @@ -142,7 +131,7 @@ async function executeCollector(request, timeout) { child.on('close', (status) => { clearTimeout(timer); terminate(); - resolve({ status: failed ? -1 : status, stdout: Buffer.concat(chunks).toString('utf8') }); + resolve({ status: failed ? -1 : status, timedOut, stdout: Buffer.concat(chunks).toString('utf8') }); }); child.stdin.on('error', () => {}); child.stdin.end(JSON.stringify(request)); @@ -150,13 +139,50 @@ async function executeCollector(request, timeout) { } export async function runWorkflowValues(options) { + const now = options.now ?? (() => new Date().toISOString()); const policy = loadPolicyFile(options.policy); - const entries = workflowValueRegistrations(policy, options.repositories); - const retained = await readPrevious(options.previous ?? options.output); - const result = { collected: 0, skipped: 0, warnings: [] }; + if (options.defer && !VALUE_DEFERRALS.has(options.defer)) throw new Error('Invalid Value deferral reason'); + const previousEnvelopes = await readValueEnvelopes(options.previous ?? options.output); + for (const envelope of previousEnvelopes) { + if (envelope.schema_version !== 2 || envelope.kind !== 'operational_value_evidence') { + throw new Error('Invalid retained workflow Value evidence envelope'); + } + validateOperationalValueEvidence(envelope.operational_value_evidence); + } + const retained = previousEnvelopes.filter(envelope => + valueRepositoryInScope(policy, options.repositories, envelope.operational_value_evidence.repository)); + const health = await workflowValueStatusContext(options, policy, retained); + if (options.localRequest) { + if (!options.snapshot) throw new Error('Local Value request requires a snapshot identity'); + await mkdir(path.dirname(options.localRequest), { recursive: true }); + await writeFile(options.localRequest, JSON.stringify([{ + schemaVersion: 1, snapshot: options.snapshot, policyDigest: health.policyDigest, + eligible: !health.activityDisabled && options.defer === 'shared-budget-unavailable', + reason: health.activityDisabled ? 'activity-disabled' : options.defer, + repositories: options.repositories.filter(repository => valueRepositoryInScope(policy, options.repositories, repository, true)), + }]) + '\n', { mode: 0o600 }); + } + const result = { collected: 0, skipped: 0, deferred: 0, failed: 0, warnings: [] }; const fresh = []; let freshBytes = 0; - for (const entry of entries) { + const startedAt = Date.now(); + const batchTimeout = options.batchTimeout ?? Infinity; + for (const entry of health.targets) { + const checkedAt = now(); + const decision = (state, reasonCode, attempt = {}) => + valueCollectionDecision(health, entry, { state, reasonCode, observedAt: checkedAt, ...attempt }); + if (!entry.collector || entry.enabled === false || health.activityDisabled) { + const disabled = entry.enabled === false || Boolean(entry.collector) && health.activityDisabled; + decision(disabled ? 'disabled' : 'unconfigured', + entry.enabled === false ? 'disabled' : disabled ? 'activity-disabled' : 'unconfigured'); + continue; + } + const defer = options.defer || (Date.now() - startedAt >= batchTimeout ? 'batch-budget' : ''); + if (defer) { + decision('deferred', defer); + result.deferred++; + continue; + } const reserve = Number(process.env.CAO_GITHUB_API_MIN_REMAINING ?? Math.abs(Number(process.env.REPORT_MAX_GITHUB_API_RATE_LIMIT ?? 0))); if (reserve > 0) { @@ -165,6 +191,9 @@ export async function runWorkflowValues(options) { }); const remaining = Number(budget.stdout?.trim()); if (budget.status !== 0 || !budget.stdout?.trim() || !Number.isSafeInteger(remaining) || remaining <= reserve) { + decision('deferred', budget.status === 0 && budget.stdout?.trim() && Number.isSafeInteger(remaining) + ? 'api-budget' : 'budget-unavailable'); + result.deferred++; result.warnings.push(`${entry.repository}/${entry.workflow}: API budget unavailable or exhausted; previous evidence retained`); continue; } @@ -180,7 +209,10 @@ export async function runWorkflowValues(options) { observedAt: options.observedAt ?? new Date().toISOString(), database: options.database, workspace: path.resolve(options.workspace, identity), }; - const child = await executeCollector(request, options.timeout ?? 600000); + const attemptAt = now(); + const child = await executeCollector(request, Math.min(options.timeout ?? 600000, + Math.max(1, batchTimeout - (Date.now() - startedAt)))); + const attempt = { observedAt: now(), lastAttemptAt: attemptAt }; try { for (const entry of await readdir(request.workspace)) { if (entry.startsWith('.scratch-')) await rm(path.join(request.workspace, entry), { recursive: true, force: true }); @@ -189,6 +221,8 @@ export async function runWorkflowValues(options) { if (error.code !== 'ENOENT') throw error; } if (child.status !== 0 || child.error) { + decision('failed', child.timedOut ? 'timeout' : 'collector-failed', { ...attempt, lastAttemptOutcome: 'failed' }); + result.failed++; result.warnings.push(`${entry.repository}/${entry.workflow}: collector failed, incomplete or budget exhausted; previous evidence retained`); continue; } @@ -198,18 +232,26 @@ export async function runWorkflowValues(options) { validateOperationalValueEvidence(envelope.operational_value_evidence); freshBytes += Buffer.byteLength(child.stdout); if (freshBytes > MAX_BATCH_BYTES) { + decision('failed', 'batch-budget', { ...attempt, lastAttemptOutcome: 'failed' }); result.warnings.push('Workflow Value batch evidence budget exhausted; remaining accepted evidence retained'); - break; + result.failed++; + continue; } fresh.push(envelope); result.collected++; } else result.skipped++; + decision('available', envelope ? 'captured' : 'not-due', { ...attempt, lastAttemptOutcome: 'available' }); } catch { + decision('failed', 'invalid-evidence', { ...attempt, lastAttemptOutcome: 'failed' }); + result.failed++; result.warnings.push(`${entry.repository}/${entry.workflow}: invalid collector output; previous evidence retained`); } } - if (!fresh.length && !options.previous) return result; - await mkdir(path.dirname(options.output), { recursive: true }); + if (!fresh.length && !options.previous) { + if (retained.length !== previousEnvelopes.length) await writeValueEnvelopes(options.output, retained); + await saveValueCollectionDecisions(health); + return result; + } // Packets are cumulative: compact superseded captures, never accepted facts. const latest = new Map(); for (const envelope of [...retained, ...fresh]) { @@ -218,9 +260,8 @@ export async function runWorkflowValues(options) { if (!previous || Date.parse(previous.observedAt) <= Date.parse(envelope.operational_value_evidence.observedAt)) latest.set(key, envelope); } const output = options.previous ? fresh : [...latest.values()]; - const staged = `${options.output}.pending`; - await writeFile(staged, output.map((value) => JSON.stringify(value)).join('\n') + (output.length ? '\n' : ''), { mode: 0o600 }); - await rename(staged, options.output); + await writeValueEnvelopes(options.output, output); + await saveValueCollectionDecisions(health); return result; } @@ -241,7 +282,7 @@ if (process.argv[1] && pathToFileURL(path.resolve(process.argv[1])).href === imp const options = { repositories: [] }; for (let i = 2; i < process.argv.length; i += 2) { const key = process.argv[i].slice(2), value = process.argv[i + 1]; - if (!value || !['root', 'policy', 'database', 'output', 'workspace', 'repository', 'previous', 'observedAt'].includes(key)) throw new Error('Invalid workflow-values option'); + if (!value || !['root', 'policy', 'database', 'output', 'workspace', 'repository', 'previous', 'observedAt', 'defer', 'inventory', 'healthOutput', 'localRequest', 'snapshot'].includes(key)) throw new Error('Invalid workflow-values option'); if (key === 'repository') options.repositories.push(value); else options[key] = value; } diff --git a/dashboard/site/dashboard-fragments/workflow-value.json b/dashboard/site/dashboard-fragments/workflow-value.json index a64042eec..c2002cb0b 100644 --- a/dashboard/site/dashboard-fragments/workflow-value.json +++ b/dashboard/site/dashboard-fragments/workflow-value.json @@ -25,6 +25,55 @@ "order-by": [{ "field": "window-end", "direction": "desc" }, { "field": "observed-at", "direction": "desc" }, { "field": "report-id", "direction": "desc" }] }] }, + { + "name": "value-capture-order", + "subject": "Actual captures across the retained measures of each workflow.", + "objective": "Expose the last accepted capture independently of collection decisions.", + "acceptance": "Select by original capture time. A deferred or failed check cannot advance evidence clocks.", + "from": "value-contracts", + "window": [{ + "operation": "change", "field": "report-marker", "as": "later-capture", "mode": "absolute", + "groupby": ["organization", "repository", "workflow"], + "order-by": [{ "field": "observed-at", "direction": "desc" }, { "field": "report-id", "direction": "desc" }] + }] + }, + { + "name": "value-latest-capture", + "subject": "One last accepted capture per workflow, not a freshness claim.", + "objective": "Join capture and cutoff without multiplying collection registrations.", + "acceptance": "Missing packets remain unavailable, never zero or an inferred successful collection.", + "from": "value-capture-order", + "filter": { "predicates": [{ "field": "later-capture", "equals": "unknown" }] } + }, + { + "name": "value-collection-health", + "subject": "Reviewed registration and authoritative collection decisions, with independently retained evidence.", + "objective": "Explain disabled, unconfigured, deferred, failed and not-yet-captured workflows.", + "acceptance": "Use published collector facts, not missing result cards. Preserve decision, attempt, capture and cutoff as distinct clocks.", + "from": "workflow-value-collections", + "time": { "range": "all" }, + "joins": [{ + "source": "value-latest-capture", "type": "left", + "on": [{ "left": "organization", "right": "organization" }, { "left": "repository", "right": "repository" }, { "left": "workflow", "right": "workflow" }], + "fields": [{ "field": "observed-at", "as": "captured-at" }, { "field": "window-end", "as": "evidence-cutoff" }] + }], + "compute": [ + { "as": "workflow-route", "function": "concat", "args": [{ "field": "organization" }, { "value": "/" }, { "field": "repository" }, { "value": ":" }, { "field": "workflow-path" }] }, + { "as": "workflow-context", "function": "concat", "args": [{ "field": "workflow" }, { "value": " · " }, { "field": "organization" }, { "value": "/" }, { "field": "repository" }] }, + { "as": "capture-missing", "function": "equals-any", "args": [{ "field": "captured-at" }, { "value": null }] }, + { "as": "evidence-state", "function": "if", "args": [{ "field": "capture-missing" }, { "value": "No retained capture" }, { "value": "Retained evidence available" }] } + ], + "order-by": [{ "field": "organization", "direction": "asc" }, { "field": "repository", "direction": "asc" }, { "field": "workflow", "direction": "asc" }] + }, + { + "name": "value-registered-collections", + "subject": "Reviewed Value registrations, including explicit disables and registrations with no report.", + "objective": "Make collection health visible before the first accepted packet.", + "acceptance": "Registration is independent of measured outcomes. No enrollment or acquisition follows from navigation.", + "from": "value-collection-health", + "filter": { "predicates": [{ "field": "registration", "in": ["enabled", "disabled"] }] }, + "limit": 1000 + }, { "name": "value-snapshots", "subject": "Independent repository-state observations and exact item drill-downs.", @@ -329,6 +378,15 @@ { "id": "runs", "label": "Runs", "icon": "play", "page": "workflow-runs" } ] }, "views": [{ + "id": "workflow-value-collection-health", "title": "Collection health", + "subject": "The selected workflow's published registration and collection decision.", + "objective": "Separate acquisition health from retained repository outcomes.", + "acceptance": "Show actual reasons and separate clocks. Absent collection facts are unknown, not proof of absent registration.", + "data": { "source": "value-collection-health", "arguments": [{ "name": "workflow", "field": "workflow-route" }], "query-context": false, "time": { "range": "all" } }, + "mark": "list", "list": { "style": "entity-cards", "card": "workflow-value-collection", "icon": "pulse" }, + "encoding": { "columns": [{ "field": "workflow-context", "type": "nominal", "title": "Workflow" }] }, + "layout": "full", "empty-message": "Collection status has not been published for this workflow. Missing status does not prove that collection is unconfigured." + }, { "id": "workflow-value-cards", "title": "Repository outcomes", "subject": "Direction-aware native changes for this workflow's measured repository problems.", "objective": "Open the evidence behind one compact result card.", @@ -338,7 +396,7 @@ "list": { "style": "entity-cards", "card": "workflow-value-result", "icon": "trophy", "drill": { "type": "query", "page": "value-report", "query": "value-report-summary", "title-field": "snapshot-name", "arguments": [{ "name": "report", "field": "report-id" }] } }, "encoding": { "columns": [{ "field": "change-label", "type": "nominal", "title": "Observed change" }] }, - "layout": "full", "empty-message": "No value evidence has been published for this workflow. Configure a frozen measurement with /add-operational-value; missing evidence is not zero value." + "layout": "full", "empty-message": "No accepted Value evidence is retained for this workflow. See collection health above; missing evidence is not zero value." }] }, { @@ -371,23 +429,36 @@ }, { "id": "value", "kind": "custom", "title": "Value", "icon": "trophy", - "description": "Review measured results and follow the evidence behind each workflow's contribution.", - "intent": "Start with repository outcomes, then inspect the workflow evidence behind a result.", - "subject": "Latest published workflow value reports across repositories.", - "objective": "Find a measured result and open its native evidence report.", + "description": "Inspect collection health, then review retained results at their actual capture and cutoff dates.", + "intent": "Distinguish collection availability from measured repository outcomes.", + "subject": "Reviewed Value registrations and latest retained workflow reports.", + "objective": "Explain missing or delayed evidence and open the native evidence that is available.", "acceptance": "Keep native units, direction, repository, workflow, dates and unknowns visible. No alert score, causal credit or GitHub acquisition.", "views": [{ + "id": "value-collection-health", "title": "Collection health", + "description": "Optional acquisition must leave capacity for Activity. A recent status check does not make retained measurements fresh.", + "subject": "Reviewed registrations and their real collection status before or after a report exists.", + "objective": "Explain deferrals and failures without discarding accepted evidence.", + "acceptance": "Never infer opt-in, successful capture or zero value from missing reports.", + "data": { "source": "value-registered-collections", "query-context": false, "time": { "range": "all" } }, + "mark": "list", + "list": { "style": "entity-cards", "card": "workflow-value-collection", "icon": "pulse", + "drill": { "type": "query", "page": "workflow-value", "query": "value-collection-health", "title-field": "workflow-context", "arguments": [{ "name": "workflow", "field": "workflow-route" }] } }, + "encoding": { "columns": [{ "field": "workflow-context", "type": "nominal", "title": "Workflow" }] }, + "layout": "full", + "empty-message": "No reviewed Value registrations are present in the published collection inventory. If that inventory is unavailable, configuration is unknown." + }, { "id": "value-results", "title": "Workflow results", "show-title": false, "subject": "Direction-aware results from published frozen evidence packets.", "objective": "Open a result's intent, output, acceptance and independent measurement trail.", - "acceptance": "Use the same latest-packet selector and reusable card as the workflow shortcut. Missing reports are unconfigured, never zero value or healthy.", + "acceptance": "Use the same latest-packet selector and reusable card as the workflow shortcut. Missing reports do not imply missing registration, zero value or healthy outcomes.", "data": { "source": "value-workflow-results", "query-context": false, "time": { "range": "all" } }, "mark": "list", "list": { "style": "entity-cards", "card": "workflow-value-result", "icon": "trophy", "drill": { "type": "query", "page": "value-report", "query": "value-report-summary", "title-field": "workflow-name", "arguments": [{ "name": "report", "field": "report-id" }] } }, "encoding": { "columns": [{ "field": "change-label", "type": "nominal", "title": "Observed change" }] }, "layout": "full", - "empty-message": "No workflow value reports have been published. Use /add-operational-value to define a frozen measure and publish evidence." + "empty-message": "No accepted workflow Value reports are retained. See collection health above; a registered collector may be deferred before its first capture." }] } ] diff --git a/dashboard/site/dashboard.json b/dashboard/site/dashboard.json index 6b0fd856b..3ca988d4f 100644 --- a/dashboard/site/dashboard.json +++ b/dashboard/site/dashboard.json @@ -48,6 +48,25 @@ { "field": "last-ping-at", "title": "Last signed ping", "type": "temporal", "format": "human-friendly-timestamp", "icon": "clock" } ] }, + { + "id": "workflow-value-collection", + "icon": "pulse", + "title": { "field": "workflow-context", "title": "Workflow" }, + "status": { "field": "collection-state", "title": "Collection" }, + "detail-labels": "visible", + "labels": [{ "field": "registration", "title": "Registration" }, { "field": "evidence-state", "title": "Evidence" }], + "details": [ + { "field": "reason", "title": "Reason" }, + { "field": "collector", "title": "Reviewed collector" }, + { "field": "last-attempt-outcome", "title": "Last attempt outcome" } + ], + "timing": [ + { "field": "checked-at", "type": "temporal", "format": "human-friendly-timestamp", "title": "Collection checked", "icon": "clock" }, + { "field": "last-attempt-at", "type": "temporal", "format": "human-friendly-timestamp", "title": "Last collector attempt", "icon": "history" }, + { "field": "captured-at", "type": "temporal", "format": "human-friendly-timestamp", "title": "Evidence captured", "icon": "clock" }, + { "field": "evidence-cutoff", "type": "temporal", "format": "human-friendly-timestamp", "title": "Evidence through", "icon": "calendar" } + ] + }, { "id": "workflow-value-result", "icon": "trophy", diff --git a/dashboard/site/src/agent/catalog.generated.json b/dashboard/site/src/agent/catalog.generated.json index c0512d455..59c8c2cd3 100644 --- a/dashboard/site/src/agent/catalog.generated.json +++ b/dashboard/site/src/agent/catalog.generated.json @@ -443,6 +443,7 @@ } ], "queries": [ + "value-collection-health", "value-report-summary", "value-workflow-results" ] @@ -508,14 +509,16 @@ { "id": "value", "title": "Value", - "description": "Review measured results and follow the evidence behind each workflow's contribution.", - "intent": "Start with repository outcomes, then inspect the workflow evidence behind a result.", - "subject": "Latest published workflow value reports across repositories.", - "objective": "Find a measured result and open its native evidence report.", + "description": "Inspect collection health, then review retained results at their actual capture and cutoff dates.", + "intent": "Distinguish collection availability from measured repository outcomes.", + "subject": "Reviewed Value registrations and latest retained workflow reports.", + "objective": "Explain missing or delayed evidence and open the native evidence that is available.", "acceptance": "Keep native units, direction, repository, workflow, dates and unknowns visible. No alert score, causal credit or GitHub acquisition.", "experimental": false, "parameters": [], "queries": [ + "value-collection-health", + "value-registered-collections", "value-report-summary", "value-workflow-results" ] @@ -3387,6 +3390,95 @@ ] } }, + { + "id": "value-capture-order", + "subject": "Actual captures across the retained measures of each workflow.", + "objective": "Expose the last accepted capture independently of collection decisions.", + "acceptance": "Select by original capture time. A deferred or failed check cannot advance evidence clocks.", + "description": "", + "parameters": [], + "sources": [ + "value-contracts" + ], + "used-by-pages": [], + "execution": { + "local": true, + "backend": "sqlite", + "requirements": [ + "operational-value-evidence" + ] + } + }, + { + "id": "value-latest-capture", + "subject": "One last accepted capture per workflow, not a freshness claim.", + "objective": "Join capture and cutoff without multiplying collection registrations.", + "acceptance": "Missing packets remain unavailable, never zero or an inferred successful collection.", + "description": "", + "parameters": [], + "sources": [ + "value-capture-order" + ], + "used-by-pages": [], + "execution": { + "local": true, + "backend": "sqlite", + "requirements": [ + "operational-value-evidence" + ] + } + }, + { + "id": "value-collection-health", + "subject": "Reviewed registration and authoritative collection decisions, with independently retained evidence.", + "objective": "Explain disabled, unconfigured, deferred, failed and not-yet-captured workflows.", + "acceptance": "Use published collector facts, not missing result cards. Preserve decision, attempt, capture and cutoff as distinct clocks.", + "description": "", + "parameters": [ + { + "name": "workflow", + "field": "workflow-route" + } + ], + "sources": [ + "value-latest-capture", + "workflow-value-collections" + ], + "used-by-pages": [ + "value", + "workflow-value" + ], + "execution": { + "local": true, + "backend": "sqlite", + "requirements": [ + "operational-value-evidence", + "workflow-value-collections" + ] + } + }, + { + "id": "value-registered-collections", + "subject": "Reviewed Value registrations, including explicit disables and registrations with no report.", + "objective": "Make collection health visible before the first accepted packet.", + "acceptance": "Registration is independent of measured outcomes. No enrollment or acquisition follows from navigation.", + "description": "", + "parameters": [], + "sources": [ + "value-collection-health" + ], + "used-by-pages": [ + "value" + ], + "execution": { + "local": true, + "backend": "sqlite", + "requirements": [ + "operational-value-evidence", + "workflow-value-collections" + ] + } + }, { "id": "value-snapshots", "subject": "Independent repository-state observations and exact item drill-downs.", diff --git a/dashboard/site/src/agent/queries.generated.json b/dashboard/site/src/agent/queries.generated.json index e71ef48cd..8c5664c58 100644 --- a/dashboard/site/src/agent/queries.generated.json +++ b/dashboard/site/src/agent/queries.generated.json @@ -1 +1 @@ -[{"name":"command-queue","subject":"Show the durable local CLI command queue.","objective":"Inspect command lifecycle and reconnect to output without rerunning work.","acceptance":"Preserve persistent command IDs and all six server states; closing output never cancels execution. Unavailable local authority is not an empty queue.","from":"cli-commands","compute":[{"as":"command-action","function":"coalesce","args":[{"field":"actionId"},{"value":""}]},{"as":"command-title","function":"coalesce","args":[{"field":"command"},{"field":"actionId"}]},{"as":"command-target","function":"coalesce","args":[{"field":"repository"},{"field":"campaign"},{"field":"package-source"},{"value":"Local control repository"}]},{"as":"command-created-at","function":"coalesce","args":[{"field":"createdAt"},{"value":null}]},{"as":"command-href","function":"concat","args":[{"value":"#page-command?command="},{"field":"id"}]},{"as":"command-dashboard-link","function":"dashboard-link","args":[{"value":""},{"field":"command-href"},{"field":"command-title"},{"field":"id"}]}]},{"name":"event-base","subject":"Project shared event fields before combining run-owned records.","objective":"Provide the narrow retained event evidence needed for inspection and run import-coverage analysis.","acceptance":"The result unions retained audit, domain, tool, and issue records with their available run identity; an empty or unavailable preview cannot establish zero source activity or complete import coverage.","from":"audits","union":["domains","tools","issues"],"select":[{"field":"organization"},{"field":"repository"},{"field":"workflow"},{"field":"run"},{"field":"run-attempt"},{"field":"event"},{"field":"event-source"},{"field":"event-type"},{"field":"event-summary"},{"field":"event-status"},{"field":"github-entity-type"},{"field":"safe-output-type"},{"field":"safe-output-url"},{"field":"correlation-id"},{"field":"implementation-pull-request-url"},{"field":"event-timestamp"},{"field":"run-link"}]},{"name":"audit-event-runs","subject":"Count imported audit records per run before combining event sources.","objective":"Bound audit evidence for run import-coverage analysis.","acceptance":"Count only retained audit records with event identity by run attempt; missing evidence does not establish zero activity.","from":"audits","aggregate":{"by":["organization","repository","workflow","run","run-attempt"],"values":[{"field":"event","as":"events","reducer":"count"}]}},{"name":"domain-event-runs","subject":"Count imported domain records per run before combining event sources.","objective":"Bound domain evidence for run import-coverage analysis.","acceptance":"Count only retained domain records with event identity by run attempt; missing evidence does not establish zero activity.","from":"domains","aggregate":{"by":["organization","repository","workflow","run","run-attempt"],"values":[{"field":"event","as":"events","reducer":"count"}]}},{"name":"tool-event-runs","subject":"Count imported tool records per run before combining event sources.","objective":"Bound tool evidence for run import-coverage analysis.","acceptance":"Count only retained tool records with event identity by run attempt; missing evidence does not establish zero activity.","from":"tools","aggregate":{"by":["organization","repository","workflow","run","run-attempt"],"values":[{"field":"event","as":"events","reducer":"count"}]}},{"name":"issue-event-runs","subject":"Count imported issue records per run before combining event sources.","objective":"Bound issue evidence for run import-coverage analysis.","acceptance":"Count only retained issue records with event identity by run attempt; missing evidence does not establish zero activity.","from":"issues","aggregate":{"by":["organization","repository","workflow","run","run-attempt"],"values":[{"field":"event","as":"events","reducer":"count"}]}},{"name":"event-runs","subject":"Identify each workflow run that has one or more imported run-owned records.","objective":"Identify run attempts with retained imported records so their presence can be compared with observed runs.","acceptance":"One row per organization, repository, workflow, run, and attempt contains events, the count of matching retained records; no row in an available result does not prove that no event was produced.","description":"Distinct workflow runs represented by imported domain, tool, audit, or issue records.","from":"audit-event-runs","union":["domain-event-runs","tool-event-runs","issue-event-runs"],"aggregate":{"by":["organization","repository","workflow","run","run-attempt"],"values":[{"field":"events","as":"events","reducer":"sum"}]}},{"name":"run-import-status","subject":"Identify observed runs that have one or more imported run-owned records.","objective":"Compare observed run attempts with retained run-owned event evidence to locate import-coverage gaps for investigation.","acceptance":"Keep each observed run and its run-attempt identity; imported-event-count is zero and imported is false without a matching retained event, but missing events alone do not establish an ingestion failure.","description":"Observed runs enriched with imported-record status.","from":"runs","joins":[{"source":"event-runs","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"},{"left":"run","right":"run"},{"left":"run-attempt","right":"run-attempt"}],"fields":[{"field":"events","as":"imported-events"}]}],"compute":[{"as":"imported-event-count","function":"coalesce","args":[{"field":"imported-events"},{"value":0}]},{"as":"imported","function":"greater-than","args":[{"field":"imported-event-count"},{"value":0}]}]},{"name":"workflow-run-totals","subject":"Summarize observed run counts and imported runs by declared workflow.","objective":"Compare observed run attempts, conclusions, and imported-record coverage for each workflow.","acceptance":"Group by organization, repository, and workflow; report distinct run-attempt totals, successful and failed conclusion counts, and imported-run totals only from retained evidence. Missing run records cannot establish zero execution.","description":"Observed run and imported-run totals for each declared workflow.","from":"run-import-status","compute":[{"as":"run-attempt-identity","function":"concat","args":[{"field":"run"},{"value":":"},{"field":"run-attempt"}]}],"aggregate":{"by":["organization","repository","workflow"],"values":[{"field":"run-attempt-identity","as":"runs","reducer":"distinct-count"},{"field":"run-conclusion","as":"successful-runs","reducer":"count","filter":{"predicates":[{"field":"run-conclusion","equals":"success"}]}},{"field":"run-conclusion","as":"failed-runs","reducer":"count","filter":{"predicates":[{"field":"run-conclusion","in":["failure","startup-failure","stale","timed-out"]}]}},{"field":"imported","as":"imported-runs","reducer":"sum"}]}},{"name":"workflow-aic-run-totals","subject":"Summarize observed run attempts and AI Credits for workflow cost comparison.","objective":"Count retained run attempts and recorded AI Credits without loading imported-event coverage.","acceptance":"Count all distinct retained run attempts, but include only positive recorded AIC in cost totals and cost denominators; zero and missing telemetry cannot skew cost averages.","from":"runs","compute":[{"as":"run-attempt-identity","function":"concat","args":[{"field":"run"},{"value":":"},{"field":"run-attempt"}]},{"as":"positive-aic","function":"greater-than","args":[{"field":"aic-total"},{"value":0}]}],"aggregate":{"by":["organization","repository","workflow"],"values":[{"field":"run-attempt-identity","as":"runs","reducer":"distinct-count"},{"field":"run-attempt-identity","as":"aic-runs","reducer":"distinct-count","filter":{"predicates":[{"field":"positive-aic","equals":true}]}},{"field":"aic-total","as":"aic","reducer":"sum","filter":{"predicates":[{"field":"positive-aic","equals":true}]}}]}},{"name":"workflow-aic-totals","subject":"Summarize observed AI Credit usage by declared workflow.","objective":"Expose retained AI Credit consumption per workflow for bounded cost review alongside observed execution.","acceptance":"Sum only positive recorded aic-total by organization, repository, and workflow; exclude zero and missing costs rather than treating them as free execution.","description":"Observed AI Credit totals for each declared workflow.","from":"workflow-aic-run-totals","filter":{"predicates":[{"field":"aic-runs","gte":1}]},"select":[{"field":"organization"},{"field":"repository"},{"field":"workflow"},{"field":"aic"},{"field":"aic-runs"}]},{"name":"mcp-tool-workflow-totals","subject":"Summarize observed MCP calls by tool and workflow before the tool inventory is materialized.","objective":"Keep MCP inventory intermediates bounded without dropping calls or changing byte totals.","acceptance":"Count retained observation identities and sum request and response bytes per server, tool, and workflow; retain safe-output-server classification for downstream exclusion.","from":"mcp-calls","compute":[{"as":"safe-output-server","function":"equals-any","args":[{"field":"mcp-server"},{"value":"safe_outputs"},{"value":"safeoutputs"}]},{"as":"mcp-tool-label","function":"concat","args":[{"field":"mcp-server"},{"value":"/"},{"field":"mcp-tool"}]},{"as":"workflow-key","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"},{"value":":"},{"field":"workflow"}]}],"aggregate":{"by":["safe-output-server","mcp-tool-label","mcp-server","mcp-tool","workflow-key"],"values":[{"field":"mcp-observation","as":"calls","reducer":"count"},{"field":"request-bytes","as":"request-bytes","reducer":"sum"},{"field":"response-bytes","as":"response-bytes","reducer":"sum"}]}},{"name":"mcp-tool-calls","subject":"Prepare MCP tool calls for aggregation with safe-output-server calls identified for downstream exclusion.","objective":"Identify retained MCP call labels and safe-output-server classification for downstream tool-use investigation.","acceptance":"Preserve each retained call with its workflow key and tool label and mark safe-output-server calls explicitly; downstream exclusion must not be mistaken for absence of those calls or complete tool telemetry.","description":"Observed MCP tool calls labeled with whether they belong to the internal safe outputs server.","from":"mcp-calls","compute":[{"as":"safe-output-server","function":"equals-any","args":[{"field":"mcp-server"},{"value":"safe_outputs"},{"value":"safeoutputs"}]},{"as":"mcp-tool-label","function":"concat","args":[{"field":"mcp-server"},{"value":"/"},{"field":"mcp-tool"}]},{"as":"workflow-key","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"},{"value":":"},{"field":"workflow"}]}]},{"name":"issue-safe-outputs","subject":"List retained GitHub issue safe outputs.","objective":"Inspect retained issue safe outputs and their observed closure state before deciding which items need follow-up.","acceptance":"Include only safe_output.result issue records, not pull requests; preserve issue and run links, timestamps, state, and status detail. Unknown or unobserved closure state must not be presented as closed.","description":"Issue-only projection of retained safe-output items.","from":"issues","filter":{"predicates":[{"field":"event-type","equals":"safe_output.result"},{"field":"is-pull-request","equals":false}]},"joins":[{"source":"runs","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"},{"left":"run","right":"run"},{"left":"run-attempt","right":"run-attempt"}],"fields":[{"field":"run-link","as":"linked-run"}]}],"compute":[{"as":"_issue-state-open","function":"equals-any","args":[{"field":"issue-state"},{"value":"OPEN"}]},{"as":"_issue-state-closed","function":"equals-any","args":[{"field":"issue-state"},{"value":"CLOSED"}]},{"as":"_issue-open-status","function":"if","args":[{"field":"_issue-state-open"},{"value":"Open"},{"value":"Unknown"}]},{"as":"issue-status","function":"if","args":[{"field":"_issue-state-closed"},{"value":"Closed"},{"field":"_issue-open-status"}]},{"as":"_issue-closing-reason","function":"coalesce","args":[{"field":"issue-state-reason"},{"value":"unknown"}]},{"as":"_issue-closing-reason-normalized","function":"lower","args":[{"field":"_issue-closing-reason"}]},{"as":"issue-closing-status","function":"title-case","args":[{"field":"_issue-closing-reason-normalized"}]},{"as":"_issue-closed-status-detail","function":"concat","args":[{"value":"Closed: "},{"field":"issue-closing-status"}]},{"as":"issue-status-detail","function":"if","args":[{"field":"_issue-state-closed"},{"field":"_issue-closed-status-detail"},{"field":"issue-status"}]}],"select":[{"field":"event-timestamp","as":"observed-at"},{"field":"github-entity-type"},{"field":"is-pull-request"},{"field":"safe-output-type"},{"field":"issue-state"},{"field":"issue-closed"},{"field":"issue-state-reason"},{"field":"issue-status"},{"field":"issue-closing-status"},{"field":"issue-status-detail"},{"field":"issue-closed-at"},{"field":"issue-status-observed-at"},{"field":"event-summary"},{"field":"correlation-id","as":"entity-url"},{"field":"organization"},{"field":"repository"},{"field":"workflow"},{"field":"run"},{"field":"linked-run","as":"run-link"}],"order-by":[{"field":"observed-at","direction":"desc"},{"field":"entity-url","direction":"asc"}]},{"name":"issue-safe-output-label-options","subject":"List observed safe-output badges for the issue list Labels filter.","objective":"Choose retained safe-output types without scanning or filtering presented cards.","acceptance":"Return distinct observed badge values in ascending order; missing evidence is not an empty label inventory.","from":"issue-safe-outputs","aggregate":{"by":["safe-output-type"],"values":[{"field":"entity-url","as":"items","reducer":"count"}]},"order-by":[{"field":"safe-output-type","direction":"asc"}]},{"name":"issue-status-label-options","subject":"List observed status badges for the issue list Status filter.","objective":"Choose retained issue states and closing reasons without inferring resolution.","acceptance":"Return distinct observed status details in ascending order; Unknown remains distinct from Open and Closed.","from":"issue-safe-outputs","aggregate":{"by":["issue-status-detail"],"values":[{"field":"entity-url","as":"items","reducer":"count"}]},"order-by":[{"field":"issue-status-detail","direction":"asc"}]},{"name":"issue-repository-totals","subject":"Rank the ten repositories with the most retained GitHub issue safe outputs.","objective":"Locate repositories with the largest observed issue-safe-output volume for a bounded review of linked records.","acceptance":"Return at most ten repository coordinates ordered by retained issue-record count; ties or missing issue evidence must not imply a complete fleet ranking or unique issue count.","description":"Top repositories by retained issue safe-output count.","from":"issue-safe-outputs","compute":[{"as":"repository-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]}],"aggregate":{"by":["repository-coordinate"],"values":[{"field":"entity-url","as":"issues","reducer":"count"}]},"order-by":[{"field":"issues","direction":"desc"},{"field":"repository-coordinate","direction":"asc"}],"limit":10},{"name":"campaign-import-audit-count","subject":"Count retained audit identities for campaign inventory source quality.","objective":"Retain audit provenance without reconstructing run coverage.","acceptance":"Count canonical audit IDs; missing evidence stays unavailable and the count is not displayed as import coverage.","from":"audits","aggregate":{"values":[{"field":"id","as":"records","reducer":"count"}]}},{"name":"campaign-import-domain-count","subject":"Count retained domain identities for campaign inventory source quality.","objective":"Retain domain provenance without reconstructing run coverage.","acceptance":"Count canonical domain IDs; missing evidence stays unavailable and the count is not displayed as import coverage.","from":"domains","aggregate":{"values":[{"field":"id","as":"records","reducer":"count"}]}},{"name":"campaign-import-tool-count","subject":"Count retained tool identities for campaign inventory source quality.","objective":"Retain tool provenance without reconstructing run coverage.","acceptance":"Count canonical tool IDs; missing evidence stays unavailable and the count is not displayed as import coverage.","from":"tools","aggregate":{"values":[{"field":"id","as":"records","reducer":"count"}]}},{"name":"campaign-import-issue-count","subject":"Count retained issue identities for campaign inventory source quality.","objective":"Retain issue provenance without reconstructing run coverage.","acceptance":"Count canonical issue IDs; missing evidence stays unavailable and the count is not displayed as import coverage.","from":"issues","aggregate":{"values":[{"field":"id","as":"records","reducer":"count"}]}},{"name":"campaign-workflow-import-evidence","subject":"Compose retained import-source quality for campaign workflow execution totals.","objective":"Preserve all four import dependencies without counting unused per-run or per-workflow coverage.","acceptance":"Compose audit, domain, tool, and issue availability, freshness, and completeness exactly as event-runs. The retained-record count carries source quality only; it is not displayed or used as horizon-specific import coverage, executions, or outcomes. Run and AI Credit totals retain their selected horizon.","from":"campaign-import-audit-count","union":["campaign-import-domain-count","campaign-import-tool-count","campaign-import-issue-count"],"time":{"range":"all"},"compute":[{"as":"import-scope","function":"literal","args":[{"value":"retained"}]}],"aggregate":{"by":["import-scope"],"values":[{"field":"records","as":"events","reducer":"sum"}]}},{"name":"campaign-workflow-execution-base","subject":"Summarize retained run attempts and AI Credits before campaign workflow enrichment.","objective":"Read run identity and recorded AI Credits together instead of enriching every run with import status.","acceptance":"Count distinct run-attempt identities and sum aic-total per organization, repository, and workflow; missing retained evidence is not proof of no execution or cost.","from":"runs","compute":[{"as":"import-scope","function":"literal","args":[{"value":"retained"}]},{"as":"run-attempt-identity","function":"concat","args":[{"field":"run"},{"value":":"},{"field":"run-attempt"}]},{"as":"positive-aic","function":"greater-than","args":[{"field":"aic-total"},{"value":0}]}],"aggregate":{"by":["organization","repository","workflow","import-scope"],"values":[{"field":"run-attempt-identity","as":"runs","reducer":"distinct-count"},{"field":"aic-total","as":"aic","reducer":"sum","filter":{"predicates":[{"field":"positive-aic","equals":true}]}}]}},{"name":"campaign-workflow-execution-totals","subject":"Attach retained import-evidence quality to compact workflow execution totals.","objective":"Preserve the public inventory's run and import availability composition after aggregating run evidence.","acceptance":"Keep runs and AI Credits unchanged; unavailable run evidence fails closed and optional import evidence degrades quality exactly as in run-import-status.","description":"Only source quality is consumed from import evidence. Join its compact retained-source summary after run aggregation; do not build unused run-level import coverage or change horizon-specific execution totals.","from":"campaign-workflow-execution-base","joins":[{"source":"campaign-workflow-import-evidence","type":"left","on":[{"left":"import-scope","right":"import-scope"}],"fields":[{"field":"events","as":"imported-events"}]}],"select":[{"field":"organization"},{"field":"repository"},{"field":"workflow"},{"field":"runs"},{"field":"aic"}]},{"name":"campaign-workflow-declarations","subject":"Project reusable campaign workflow declarations without execution evidence.","objective":"Share declaration display fields between structural topology and execution inventory without joining runs or import evidence.","acceptance":"Preserve raw organization, repository, workflow and declaration fields for joins. Select orchestrator and worker roles once, retaining inactive and unknown declarations; only list consumers select active entries. Display defaults and repository links do not establish execution, enrollment or authority.","from":"workflows","filter":{"predicates":[{"field":"workflow-role","in":["orchestrator","worker"]}]},"compute":[{"as":"repository-slug","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"declared-mode","function":"coalesce","args":[{"field":"rollout-mode"},{"value":"unknown"}]},{"as":"declared-registration","function":"coalesce","args":[{"field":"workflow-active"},{"value":"unknown"}]},{"as":"campaign-title","function":"title-case","args":[{"field":"campaign"}]},{"as":"campaign-display-name","function":"coalesce","args":[{"field":"campaign-name"},{"field":"campaign-title"},{"value":"Repository-owned"}]},{"as":"workflow-display-name","function":"coalesce","args":[{"field":"workflow-name"},{"field":"workflow"}]},{"as":"encoded-repository","function":"url-encode","args":[{"field":"repository-slug"}]},{"as":"repository-dashboard-href","function":"concat","args":[{"value":"#page-repository-detail?repository="},{"field":"encoded-repository"}]},{"as":"repository-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"repository-slug"},{"value":" repository dashboard"}]},{"as":"repository-dashboard-link","function":"dashboard-link","args":[{"field":"repository-link"},{"field":"repository-dashboard-href"},{"field":"repository-dashboard-label"},{"field":"repository-slug"}]}],"select":[{"field":"organization"},{"field":"repository"},{"field":"workflow"},{"field":"campaign"},{"field":"campaign-name"},{"field":"workflow-name"},{"field":"workflow-role"},{"field":"rollout-mode"},{"field":"workflow-active"},{"field":"repository-link"},{"field":"workflow-link"},{"field":"repository-slug"},{"field":"declared-mode"},{"field":"declared-registration"},{"field":"campaign-display-name"},{"field":"workflow-display-name"},{"field":"repository-dashboard-link"}]},{"name":"campaign-workflow-inventory","subject":"Project declared campaign workflows with lean execution and configuration evidence.","objective":"Provide campaign totals and lists from shared declarations with separate execution and import-quality evidence.","acceptance":"Keep all declared orchestrators and workers, including inactive and unobserved entries; preserve inventory ordering, configuration defaults, execution totals, and import-evidence quality.","description":"Lean campaign inventory with execution totals that retain the public workflow inventory's evidence-quality dependencies.","from":"campaign-workflow-declarations","joins":[{"source":"campaign-workflow-execution-totals","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"}],"fields":[{"field":"runs","as":"observed-runs"},{"field":"aic","as":"observed-aic"}]}],"compute":[{"as":"total-runs","function":"coalesce","args":[{"field":"observed-runs"},{"value":0}]},{"as":"total-aic","function":"coalesce","args":[{"field":"observed-aic"},{"value":0}]}],"select":[{"field":"campaign"},{"field":"campaign-name"},{"field":"organization"},{"field":"repository-slug","as":"repository"},{"field":"workflow"},{"field":"workflow-name"},{"field":"workflow-role"},{"field":"declared-mode","as":"rollout-mode"},{"field":"declared-registration","as":"workflow-active"},{"field":"total-runs","as":"runs"},{"field":"total-aic","as":"aic"},{"field":"repository-link"},{"field":"workflow-link"},{"field":"campaign-display-name"},{"field":"workflow-display-name"},{"field":"repository-dashboard-link"}],"order-by":[{"field":"repository","direction":"asc"},{"field":"workflow","direction":"asc"}]},{"name":"workflow-inventory","subject":"List declared workflows with their campaign, repository, configuration, and observed execution totals.","objective":"Compare declared workflow configuration with retained run, import-coverage, and AI Credit evidence to select a workflow for closer inspection.","acceptance":"Keep one row per declared workflow with identity, role, mode, registration, links, observed totals, and ingestion indicator; zero joined totals and missing evidence must not be treated as proof of no execution or complete ingestion.","description":"Central campaign and repository-owned workflow inventory with observed execution totals.","from":"workflows","joins":[{"source":"workflow-run-totals","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"}],"fields":[{"field":"runs","as":"observed-runs"},{"field":"successful-runs","as":"observed-successful-runs"},{"field":"failed-runs","as":"observed-failed-runs"},{"field":"imported-runs","as":"observed-imported-runs"}]},{"source":"workflow-aic-totals","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"}],"fields":[{"field":"aic","as":"observed-aic"},{"field":"aic-runs","as":"observed-aic-runs"}]}],"compute":[{"as":"campaign-title","function":"title-case","args":[{"field":"campaign"}]},{"as":"campaign-display-name","function":"coalesce","args":[{"field":"campaign-name"},{"field":"campaign-title"},{"value":"Repository-owned"}]},{"as":"repository-slug","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"workflow-display-name","function":"coalesce","args":[{"field":"workflow-name"},{"field":"workflow"}]},{"as":"declared-role","function":"coalesce","args":[{"field":"workflow-role"},{"value":"standalone"}]},{"as":"declared-mode","function":"coalesce","args":[{"field":"rollout-mode"},{"value":"unknown"}]},{"as":"declared-registration","function":"coalesce","args":[{"field":"workflow-active"},{"value":"unknown"}]},{"as":"total-runs","function":"coalesce","args":[{"field":"observed-runs"},{"value":0}]},{"as":"total-successful-runs","function":"coalesce","args":[{"field":"observed-successful-runs"},{"value":0}]},{"as":"has-observed-runs","function":"greater-than","args":[{"field":"total-runs"},{"value":0}]},{"as":"total-failed-runs","function":"coalesce","args":[{"field":"observed-failed-runs"},{"value":0}]},{"as":"total-aic","function":"coalesce","args":[{"field":"observed-aic"},{"value":0}]},{"as":"aic-per-run","function":"quotient","args":[{"field":"total-aic"},{"field":"observed-aic-runs"}]},{"as":"total-imported-runs","function":"coalesce","args":[{"field":"observed-imported-runs"},{"value":0}]},{"as":"ingestion-rate","function":"quotient","args":[{"field":"total-imported-runs"},{"field":"total-runs"}]},{"as":"ingestion","function":"format-percent","args":[{"field":"ingestion-rate"}]},{"as":"encoded-campaign","function":"url-encode","args":[{"field":"campaign"}]},{"as":"campaign-dashboard-href","function":"concat","args":[{"value":"#page-campaign-insights?campaign="},{"field":"encoded-campaign"}]},{"as":"campaign-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"campaign-display-name"},{"value":" campaign dashboard"}]},{"as":"campaign-dashboard-link","function":"dashboard-link","args":[{"field":"repository-link"},{"field":"campaign-dashboard-href"},{"field":"campaign-dashboard-label"},{"field":"campaign"}]},{"as":"encoded-repository","function":"url-encode","args":[{"field":"repository-slug"}]},{"as":"repository-dashboard-href","function":"concat","args":[{"value":"#page-repository-detail?repository="},{"field":"encoded-repository"}]},{"as":"repository-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"repository-slug"},{"value":" repository dashboard"}]},{"as":"repository-dashboard-link","function":"dashboard-link","args":[{"field":"repository-link"},{"field":"repository-dashboard-href"},{"field":"repository-dashboard-label"},{"field":"repository-slug"}]},{"as":"workflow-identity","function":"concat","args":[{"field":"repository-slug"},{"value":":"},{"field":"workflow"}]},{"as":"encoded-workflow","function":"url-encode","args":[{"field":"workflow-identity"}]},{"as":"workflow-dashboard-href","function":"concat","args":[{"value":"#page-workflow-runtime?workflow="},{"field":"encoded-workflow"}]},{"as":"workflow-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"workflow-display-name"},{"value":" workflow dashboard"}]},{"as":"workflow-dashboard-link","function":"dashboard-link","args":[{"field":"workflow-link"},{"field":"workflow-dashboard-href"},{"field":"workflow-dashboard-label"},{"field":"workflow-identity"}]}],"select":[{"field":"campaign"},{"field":"campaign-display-name","as":"campaign-name"},{"field":"organization"},{"field":"repository-slug","as":"repository"},{"field":"workflow"},{"field":"workflow-display-name","as":"workflow-name"},{"field":"workflow-identity","as":"workflow-label"},{"field":"declared-role","as":"workflow-role"},{"field":"declared-mode","as":"rollout-mode"},{"field":"declared-registration","as":"workflow-active"},{"field":"total-aic","as":"aic"},{"field":"total-runs","as":"runs"},{"field":"total-successful-runs","as":"successful-runs"},{"field":"total-failed-runs","as":"failed-runs"},{"field":"aic-per-run"},{"field":"has-observed-runs"},{"field":"ingestion"},{"field":"campaign-dashboard-link","as":"campaign-link"},{"field":"repository-dashboard-link","as":"repository-link"},{"field":"workflow-dashboard-link","as":"workflow-link"}],"order-by":[{"field":"repository","direction":"asc"},{"field":"workflow","direction":"asc"}]},{"name":"repository-run-statistics","subject":"Reduce run counts, conclusions, and positive AI Credits before repository enrichment.","objective":"Share one row-local run aggregate between repository execution and cost summaries.","acceptance":"Keep organization/repository grain, distinct run IDs, existing failure and approval counts, and positive recorded AIC. Reduce before joins; missing evidence is not zero activity or free execution.","from":"runs","compute":[{"as":"positive-aic","function":"greater-than","args":[{"field":"aic-total"},{"value":0}]}],"aggregate":{"by":["organization","repository"],"values":[{"field":"run","as":"runs","reducer":"distinct-count"},{"field":"run-conclusion","as":"failed","reducer":"count","filter":{"predicates":[{"field":"run-conclusion","in":["failure","startup-failure","timed-out"]}]}},{"field":"run-conclusion","as":"action-required","reducer":"count","filter":{"predicates":[{"field":"run-conclusion","equals":"action-required"}]}},{"field":"run","as":"aic-runs","reducer":"count","filter":{"predicates":[{"field":"positive-aic","equals":true}]}},{"field":"aic-total","as":"aic","reducer":"sum","filter":{"predicates":[{"field":"positive-aic","equals":true}]}}]}},{"name":"repository-aic-totals","subject":"Summarize observed AI Credit usage by repository.","objective":"Provide repository-level retained AI Credit totals for comparing observed usage with run activity.","acceptance":"Sum only positive recorded aic-total by organization and repository; exclude zero and missing costs rather than treating them as free execution.","description":"Observed AI Credit totals for each repository.","from":"repository-run-statistics","filter":{"predicates":[{"field":"aic-runs","gte":1}]},"select":[{"field":"organization"},{"field":"repository"},{"field":"aic"}]},{"name":"maintenance-repository-versions","subject":"Group installed and current gh-aw compiler versions and upgrade evidence by repository.","objective":"Identify repositories with declared Markdown workflows whose retained compiler-version evidence warrants upgrade review.","acceptance":"Group Markdown workflow declarations by repository coordinate and return distinct recorded installed/current version lists plus upgrade-required and unknown flags; inspect absent or mixed version evidence rather than inferring a repository-wide installed version.","from":"workflows","filter":{"predicates":[{"field":"workflow","includes":".md"}]},"compute":[{"as":"repository-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"update-available","function":"equals-any","args":[{"field":"gh-aw-update-state"},{"value":"update-available"}]},{"as":"upgrade-state-unknown","function":"equals-any","args":[{"field":"gh-aw-update-state"},{"value":"unknown"}]},{"as":"upgrade-state-unknown-value","function":"if","args":[{"field":"upgrade-state-unknown"},{"value":1},{"value":0}]},{"as":"upgrade-required-value","function":"if","args":[{"field":"update-available"},{"value":1},{"value":0}]}],"aggregate":{"by":["repository-coordinate"],"values":[{"field":"gh-aw-version","as":"gh-aw-version","reducer":"distinct-list"},{"field":"gh-aw-current-version","as":"gh-aw-current-version","reducer":"distinct-list"},{"field":"upgrade-required-value","as":"upgrade-required","reducer":"max"},{"field":"upgrade-state-unknown-value","as":"upgrade-state-unknown","reducer":"max"}]}},{"name":"maintenance-repositories","subject":"List each repository with recorded compiler versions and computed upgrade state.","objective":"Expose recorded compiler versions and computed upgrade state per repository, with its GitHub home URL for inspection.","acceptance":"Return repository, repository-url, version lists, upgrade-required, upgrade-state, and upgrade-action-visible. Show Upgrade for outdated or unknown evidence; hide it for known-current repositories. Visibility grants no rollout authority.","from":"maintenance-repository-versions","compute":[{"as":"repository-url","function":"concat","args":[{"value":"https://github.com/"},{"field":"repository-coordinate"}]},{"as":"should-upgrade","function":"equals-any","args":[{"field":"upgrade-required"},{"value":1}]},{"as":"installed-version-unavailable","function":"equals-any","args":[{"field":"gh-aw-version"},{"value":""},{"value":"unknown"}]},{"as":"compiler-versions-match","function":"equals-any","args":[{"field":"gh-aw-version"},{"field":"gh-aw-current-version"}]},{"as":"known-current-versions","function":"if","args":[{"field":"installed-version-unavailable"},{"value":false},{"field":"compiler-versions-match"}]},{"as":"upgrade-status-unavailable","function":"if","args":[{"field":"known-current-versions"},{"value":false},{"value":true}]},{"as":"current-or-unavailable","function":"if","args":[{"field":"upgrade-status-unavailable"},{"value":"Upgrade status unavailable"},{"value":"Current"}]},{"as":"upgrade-action-visible","function":"if","args":[{"field":"should-upgrade"},{"value":true},{"field":"upgrade-status-unavailable"}]},{"as":"upgrade-state","function":"if","args":[{"field":"should-upgrade"},{"value":"Upgrade recommended"},{"field":"current-or-unavailable"}]}],"select":[{"field":"repository-coordinate","as":"repository"},{"field":"repository-url"},{"field":"gh-aw-version"},{"field":"gh-aw-current-version"},{"field":"upgrade-required"},{"field":"upgrade-action-visible"},{"field":"upgrade-state"}],"order-by":[{"field":"repository","direction":"asc"}]},{"name":"maintenance-campaign-updates","subject":"Expose at most one CAO package update row for the Updates navigation indicator.","objective":"Determine whether retained campaign metadata contains an update-available signal for the Updates indicator.","acceptance":"Return zero or one campaign-update-state row only when it equals update-available; an empty result means no matching retained signal, not that every campaign is current.","from":"campaigns","filter":{"predicates":[{"field":"campaign-update-state","equals":"update-available"}]},"select":[{"field":"campaign-update-state"}],"limit":1},{"name":"maintenance-repository-upgrades","subject":"Expose at most one gh-aw compiler upgrade row for the Updates navigation indicator.","objective":"Determine whether repository compiler metadata contains an upgrade-required signal for the Updates indicator.","acceptance":"Return zero or one upgrade-required row only when the retained value is 1; no row does not establish that all repositories are current when version data is missing.","from":"maintenance-repositories","filter":{"predicates":[{"field":"upgrade-required","equals":1}]},"select":[{"field":"upgrade-required"}],"limit":1},{"name":"run-incomplete-outcomes","subject":"Project retained report-incomplete terminal outcomes as concise run diagnoses.","objective":"Find recorded report_incomplete terminal outcomes that can explain a specific run's incomplete reporting.","acceptance":"Include only runs with a recorded report_incomplete terminal outcome, preserving run-attempt identity, outcome kind, and recorded diagnosis; absence is not proof that reporting completed.","description":"One retained incomplete-evidence diagnosis per workflow Run when the agent explicitly reported that required evidence or access was unavailable.","from":"runs","filter":{"predicates":[{"field":"terminal-outcome","equals":"report_incomplete"}]},"select":[{"field":"organization"},{"field":"repository"},{"field":"workflow"},{"field":"run"},{"field":"run-attempt"},{"field":"terminal-outcome","as":"outcome-kind"},{"field":"terminal-outcome-detail","as":"outcome-diagnosis"}]},{"name":"campaign-runs","subject":"Project workflow runs with campaign attribution and retained failure evidence.","objective":"Connect retained run status and failure details to declared campaign/workflow identity for run-level diagnosis.","acceptance":"Expose run and attempt identity, declared attribution, runtime and target repositories, status, failure and incomplete-outcome evidence, timestamps, and drill-down links; do not infer an outcome from runtime success or missing details.","description":"Canonical workflow runs joined to their declared campaign and workflow identity.","from":"runs","joins":[{"source":"workflows","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"}],"fields":[{"field":"campaign","as":"declared-campaign"},{"field":"campaign-name","as":"declared-campaign-name"},{"field":"workflow-name","as":"declared-workflow-name"},{"field":"workflow-role","as":"declared-workflow-role"},{"field":"workflow-link","as":"declared-workflow-link"}]},{"source":"run-incomplete-outcomes","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"},{"left":"run","right":"run"},{"left":"run-attempt","right":"run-attempt"}],"fields":[{"field":"outcome-kind","as":"outcome-kind"},{"field":"outcome-diagnosis","as":"outcome-diagnosis"}]}],"compute":[{"as":"status","function":"coalesce","args":[{"field":"run-conclusion"},{"field":"run-status"},{"value":"unknown"}]},{"as":"effective-outcome-kind","function":"coalesce","args":[{"field":"outcome-kind"},{"field":"terminal-outcome"},{"value":""}]},{"as":"is-incomplete-outcome","function":"equals-any","args":[{"field":"effective-outcome-kind"},{"value":"report_incomplete"}]},{"as":"diagnosis-kind","function":"if","args":[{"field":"is-incomplete-outcome"},{"value":"incomplete_evidence"},{"value":""}]},{"as":"error-signature","function":"coalesce","args":[{"field":"diagnosis-kind"},{"field":"failure-kind"},{"field":"classification"},{"field":"status"}]},{"as":"_error-signature-default-label","function":"title-case","args":[{"field":"error-signature"}]},{"as":"_is-driver-exit","function":"equals-any","args":[{"field":"error-signature"},{"value":"driver_exit"},{"value":"driver-exit"}]},{"as":"error-signature-label","function":"if","args":[{"field":"_is-driver-exit"},{"value":"Agent process exited unexpectedly"},{"field":"_error-signature-default-label"}]},{"as":"status-detail","function":"coalesce","args":[{"field":"outcome-diagnosis"},{"field":"terminal-outcome-detail"},{"field":"failure-detail"},{"field":"failure-message"},{"field":"failure-step"},{"field":"admission-reason"},{"value":""}]},{"as":"runtime-repository","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"is-worker","function":"equals-any","args":[{"field":"declared-workflow-role"},{"value":"worker"}]},{"as":"is-orchestrator","function":"equals-any","args":[{"field":"declared-workflow-role"},{"value":"orchestrator"}]},{"as":"root-dispatch-type","function":"if","args":[{"field":"is-orchestrator"},{"value":"Campaign orchestrator"},{"value":"Standalone workflow"}]},{"as":"dispatch-type","function":"if","args":[{"field":"is-worker"},{"value":"Campaign worker"},{"field":"root-dispatch-type"}]},{"as":"campaign-display-name","function":"coalesce","args":[{"field":"declared-campaign-name"},{"field":"declared-campaign"}]},{"as":"workflow-display-name","function":"coalesce","args":[{"field":"declared-workflow-name"},{"field":"workflow"}]},{"as":"encoded-campaign","function":"url-encode","args":[{"field":"declared-campaign"}]},{"as":"campaign-dashboard-href","function":"concat","args":[{"value":"#page-campaign-insights?campaign="},{"field":"encoded-campaign"}]},{"as":"campaign-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"campaign-display-name"},{"value":" campaign dashboard"}]},{"as":"campaign-dashboard-link","function":"dashboard-link","args":[{"field":"repository-link"},{"field":"campaign-dashboard-href"},{"field":"campaign-dashboard-label"},{"field":"declared-campaign"}]},{"as":"encoded-repository","function":"url-encode","args":[{"field":"runtime-repository"}]},{"as":"repository-dashboard-href","function":"concat","args":[{"value":"#page-repository-detail?repository="},{"field":"encoded-repository"}]},{"as":"repository-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"runtime-repository"},{"value":" repository dashboard"}]},{"as":"repository-dashboard-link","function":"dashboard-link","args":[{"field":"repository-link"},{"field":"repository-dashboard-href"},{"field":"repository-dashboard-label"},{"field":"runtime-repository"}]},{"as":"workflow-identity","function":"concat","args":[{"field":"runtime-repository"},{"value":":"},{"field":"workflow"}]},{"as":"encoded-workflow","function":"url-encode","args":[{"field":"workflow-identity"}]},{"as":"workflow-dashboard-href","function":"concat","args":[{"value":"#page-workflow-runtime?workflow="},{"field":"encoded-workflow"}]},{"as":"workflow-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"workflow-display-name"},{"value":" workflow dashboard"}]},{"as":"workflow-dashboard-link","function":"dashboard-link","args":[{"field":"workflow-link"},{"field":"workflow-dashboard-href"},{"field":"workflow-dashboard-label"},{"field":"workflow-identity"}]}],"select":[{"field":"started-at"},{"field":"dispatch-type"},{"field":"declared-campaign","as":"campaign"},{"field":"declared-campaign-name","as":"campaign-name"},{"field":"declared-workflow-name","as":"workflow-name"},{"field":"run"},{"field":"run-attempt"},{"field":"run-title"},{"field":"event"},{"field":"runtime-repository"},{"field":"target-repository"},{"field":"rollout-mode"},{"field":"status"},{"field":"run-status"},{"field":"error-signature"},{"field":"error-signature-label"},{"field":"status-detail"},{"field":"outcome-kind"},{"field":"outcome-diagnosis"},{"field":"declared-workflow-role","as":"workflow-role"},{"field":"failure-job"},{"field":"failure-message"},{"field":"failure-step"},{"field":"failure-log"},{"field":"engine"},{"field":"engine-version"},{"field":"gh-aw-version"},{"field":"requested-model"},{"field":"resolved-model"},{"field":"aic-total"},{"field":"safe-items-count"},{"field":"resource-reset-at","as":"status-detail-at"},{"field":"organization"},{"field":"repository"},{"field":"workflow"},{"field":"declared-workflow-link","as":"workflow-source-link"},{"field":"run-link"},{"field":"campaign-dashboard-link","as":"campaign-link"},{"field":"repository-dashboard-link","as":"repository-link"},{"field":"workflow-dashboard-link","as":"workflow-link"}],"order-by":[{"field":"started-at","direction":"desc"}]},{"name":"campaign-runtime-health-runs","subject":"Project only the run and workflow fields required to classify current campaign runtime health.","objective":"Provide the retained run identity, timing, role, dispatch type, repository, and status needed to assess campaign runtime-health groups.","acceptance":"Project the selected fields from overview-runs without converting missing statuses or unattributed workflows into failures; unavailable run history leaves health assessment incomplete.","description":"A bounded runtime-health input that excludes audit outcomes and presentation-only campaign run fields.","from":"overview-runs","compute":[{"as":"status","function":"coalesce","args":[{"field":"run-conclusion"},{"field":"run-status"},{"value":"unknown"}]},{"as":"runtime-repository","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"is-worker","function":"equals-any","args":[{"field":"workflow-role"},{"value":"worker"}]},{"as":"is-orchestrator","function":"equals-any","args":[{"field":"workflow-role"},{"value":"orchestrator"}]},{"as":"root-dispatch-type","function":"if","args":[{"field":"is-orchestrator"},{"value":"Campaign orchestrator"},{"value":"Standalone workflow"}]},{"as":"dispatch-type","function":"if","args":[{"field":"is-worker"},{"value":"Campaign worker"},{"field":"root-dispatch-type"}]}],"select":[{"field":"started-at"},{"field":"campaign"},{"field":"campaign-name"},{"field":"workflow"},{"field":"workflow-name"},{"field":"workflow-role"},{"field":"dispatch-type"},{"field":"runtime-repository"},{"field":"run"},{"field":"run-status"},{"field":"status"}]},{"name":"campaign-runtime-health-groups","subject":"Compute each campaign workflow and runtime repository's latest consecutive failure streak in the selected horizon.","objective":"Locate campaign workflow/runtime-repository groups whose most recent retained completed runs have consecutive runtime failures.","acceptance":"Group completed runs by campaign, workflow, role, dispatch type, and runtime repository; failure-count is the latest retained failure streak, not a rate or a claim about runs outside the available horizon.","description":"Current retained failure streaks grouped by campaign workflow and runtime repository, considering only concluded Runs so an in-flight retry cannot mask an active failure streak.","from":"campaign-runtime-health-runs","filter":{"predicates":[{"field":"run-status","equals":"completed"}]},"compute":[{"as":"is-runtime-failure","function":"equals-any","args":[{"field":"status"},{"value":"failure"},{"value":"startup-failure"},{"value":"stale"},{"value":"timed-out"}]},{"as":"runtime-failure-streak-point","function":"failure-streak-point","args":[{"field":"started-at"},{"field":"run"},{"field":"is-runtime-failure"}]}],"aggregate":{"by":["campaign","campaign-name","workflow","workflow-name","workflow-role","dispatch-type","runtime-repository"],"values":[{"field":"runtime-failure-streak-point","as":"failure-count","reducer":"latest-failure-streak"}]}},{"name":"workflow-run-observation-counts","subject":"Count retained Runs for each workflow identity in the selected horizon.","objective":"Measure retained run presence by workflow identity to compare with active orchestrator declarations.","acceptance":"Count overview-runs by organization, repository, and workflow; a missing group indicates no retained matching run in the available horizon, not proof of no executions.","description":"One row per organization, repository, and workflow with retained Run counts, safe to join without row multiplication.","from":"overview-runs","aggregate":{"by":["organization","repository","workflow"],"values":[{"field":"run","as":"observed-run-count","reducer":"count"}]}},{"name":"campaign-active-orchestrator-run-presence","subject":"Count retained Runs for each active campaign orchestrator in the selected horizon.","objective":"Compare active orchestrator declarations with retained run observations to identify missing visibility.","acceptance":"Keep only workflows declared active with orchestrator role and expose their identity, runtime repository, and observed-run-count; a zero joined count means no retained match, not necessarily a stopped schedule.","description":"Active campaign orchestrators annotated with retained Run presence.","from":"workflows","joins":[{"source":"workflow-run-observation-counts","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"}],"fields":[{"field":"observed-run-count","as":"joined-observed-run-count"}]}],"filter":{"predicates":[{"field":"workflow-role","equals":"orchestrator"},{"field":"workflow-active","equals":"true"}]},"compute":[{"as":"runtime-repository","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"observed-run-count","function":"coalesce","args":[{"field":"joined-observed-run-count"},{"value":0}]}],"select":[{"field":"campaign"},{"field":"campaign-name"},{"field":"workflow"},{"field":"workflow-name"},{"field":"workflow-role"},{"field":"runtime-repository"},{"field":"observed-run-count"}]},{"name":"campaign-unobserved-orchestrator-candidates","subject":"Mark active campaign orchestrators with no retained Runs in the selected horizon.","objective":"Mark active orchestrators lacking retained run evidence for bounded telemetry or schedule review.","acceptance":"Preserve active orchestrator identity and observed-run-count; is-unobserved marks zero retained matches and must not be interpreted as a runtime failure or evidence that dispatch was expected.","description":"Active orchestrators annotated with whether runtime evidence is absent.","from":"campaign-active-orchestrator-run-presence","compute":[{"as":"is-unobserved","function":"equals-any","args":[{"field":"observed-run-count"},{"value":0}]},{"as":"failure-count","function":"sum","args":[{"value":0},{"value":0}]},{"as":"dispatch-type","function":"coalesce","args":[{"value":"Campaign orchestrator"},{"value":"Campaign orchestrator"}]},{"as":"problem-kind","function":"coalesce","args":[{"value":"not-observed"},{"value":"not-observed"}]}]},{"name":"campaign-unobserved-orchestrators","subject":"Show active campaign orchestrators with no retained Runs in the selected horizon.","objective":"List active orchestrator declarations with no retained run observations for follow-up on evidence availability.","acceptance":"Return only is-unobserved candidates with their workflow and repository identity; an empty result does not certify run completeness or scheduler health.","description":"Active campaign orchestrators whose runtime state cannot be established from retained evidence.","from":"campaign-unobserved-orchestrator-candidates","filter":{"predicates":[{"field":"is-unobserved","equals":true}]}},{"name":"dispatches","subject":"Select workflow-dispatch runs from campaign-attributed workflow run evidence.","objective":"Inspect retained workflow_dispatch runs attributed to campaigns before comparing campaign dispatch activity.","acceptance":"Include only campaign-runs with event workflow_dispatch and preserve run, attempt, attribution, status, and time; absence does not establish that no dispatch occurred beyond retained evidence.","description":"Canonical workflow runs whose authoritative trigger is workflow_dispatch.","from":"campaign-runs","filter":{"predicates":[{"field":"event","equals":"workflow_dispatch"}]},"order-by":[{"field":"started-at","direction":"desc"}]},{"name":"campaign-dispatch-inventory","subject":"Project retained dispatch identity and campaign attribution before campaign counting.","objective":"Count dispatches without materializing run diagnoses and presentation links.","acceptance":"Keep workflow_dispatch runs in timestamp order with declared campaign attribution; preserve workflow and incomplete-outcome join quality and duplicate-key failure behavior.","description":"Lean dispatch-count input; the incomplete-outcome join preserves the full campaign run source's evidence quality and fail-closed validation.","from":"runs","joins":[{"source":"workflows","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"}],"fields":[{"field":"campaign","as":"declared-campaign"}]},{"source":"run-incomplete-outcomes","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"},{"left":"run","right":"run"},{"left":"run-attempt","right":"run-attempt"}],"fields":[{"field":"outcome-kind","as":"outcome-kind"}]}],"filter":{"predicates":[{"field":"event","equals":"workflow_dispatch"}]},"select":[{"field":"declared-campaign","as":"campaign"},{"field":"run"},{"field":"started-at"}],"order-by":[{"field":"started-at","direction":"desc"}]},{"name":"campaign-dispatch-totals","subject":"Summarize observed workflow dispatches for each centrally managed campaign.","objective":"Compare retained workflow_dispatch run counts across attributed campaigns.","acceptance":"Count distinct run identifiers per campaign from dispatches; do not treat missing campaign attribution or unretained dispatches as zero actual activity.","description":"Observed workflow-dispatch run totals grouped by campaign.","from":"campaign-dispatch-inventory","aggregate":{"by":["campaign"],"values":[{"field":"run","as":"dispatches","reducer":"distinct-count"}]}},{"name":"campaign-workflow-totals","subject":"Summarize observed workflow and execution totals for each centrally managed campaign.","objective":"Compare declared orchestrator/worker composition, rollout registration, observed runs, and AI Credit usage by campaign.","acceptance":"Group only orchestrator and worker workflow-inventory rows by campaign; retain workflow count, distinct roles/modes/registration and summed observed runs and AIC, without inferring successful outcomes.","description":"Observed workflow, rollout, run, and AI Credit totals grouped by campaign.","from":"campaign-workflow-inventory","aggregate":{"by":["campaign"],"values":[{"field":"workflow","as":"workflows","reducer":"count"},{"field":"workflow-role","as":"roles","reducer":"distinct-list"},{"field":"rollout-mode","as":"modes","reducer":"distinct-list"},{"field":"workflow-active","as":"registration","reducer":"distinct-list"},{"field":"runs","as":"runs","reducer":"sum"},{"field":"aic","as":"aic","reducer":"sum"}]}},{"name":"campaign-repository-coverage","subject":"Count distinct registered target repositories reached by successful worker dispatches for each campaign.","objective":"Estimate observed campaign target reach from successful worker workflow_dispatch runs joined to registered repositories.","acceptance":"Count distinct matched target-repository values per campaign only for successful worker dispatches; this is observed reach, not verified target outcomes or complete fleet coverage.","description":"Campaign repository coverage derived from successful worker dispatch runs in the selected horizon.","from":"runs","joins":[{"source":"workflows","type":"inner","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"}],"fields":[{"field":"campaign","as":"campaign"},{"field":"workflow-role","as":"workflow-role"}]},{"source":"repositories","type":"inner","on":[{"left":"target-repository","right":"repository-coordinate"}],"fields":[{"field":"repository-coordinate","as":"registered-target-repository"}]}],"filter":{"predicates":[{"field":"event","equals":"workflow_dispatch"},{"field":"run-conclusion","equals":"success"},{"field":"workflow-role","equals":"worker"}]},"aggregate":{"by":["campaign"],"values":[{"field":"target-repository","as":"covered-repositories","reducer":"distinct-count"}]}},{"name":"campaign-inventory-preview","subject":"Show declared campaigns before execution evidence is evaluated.","objective":"Expose campaign identities and navigation links while observed totals remain pending.","acceptance":"Preserve every declared campaign and its dashboard link without reporting missing execution totals as zero.","from":"campaigns","compute":[{"as":"encoded-campaign","function":"url-encode","args":[{"field":"campaign"}]},{"as":"campaign-dashboard-href","function":"concat","args":[{"value":"#page-campaign-insights?campaign="},{"field":"encoded-campaign"}]},{"as":"campaign-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"campaign-name"},{"value":" campaign dashboard"}]},{"as":"campaign-dashboard-link","function":"dashboard-link","args":[{"value":""},{"field":"campaign-dashboard-href"},{"field":"campaign-dashboard-label"},{"field":"campaign"}]}],"select":[{"field":"campaign"},{"field":"campaign-name"},{"field":"campaign-dashboard-link"}],"order-by":[{"field":"campaign-name","direction":"asc"}]},{"name":"campaign-inventory","subject":"List centrally managed campaigns with their observed workflow and execution totals.","objective":"Compare declared campaigns with retained workflow composition, dispatches, target reach, runs, and AIC to choose an evidence-backed drill-down.","acceptance":"Keep declared campaigns with campaign identity and link plus joined totals; defaulted zero values mean no matching retained evidence and cannot certify no activity, complete coverage, or successful outcomes.","description":"Canonical campaign inventory enriched with observed workflow, rollout, run, repository coverage, and AI Credit totals.","from":"campaigns","joins":[{"source":"campaign-workflow-totals","type":"left","on":[{"left":"campaign","right":"campaign"}],"fields":[{"field":"workflows","as":"observed-workflows"},{"field":"roles","as":"observed-roles"},{"field":"modes","as":"observed-modes"},{"field":"registration","as":"observed-registration"},{"field":"runs","as":"observed-runs"},{"field":"aic","as":"observed-aic"}]},{"source":"campaign-dispatch-totals","type":"left","on":[{"left":"campaign","right":"campaign"}],"fields":[{"field":"dispatches","as":"observed-dispatches"}]},{"source":"campaign-repository-coverage","type":"left","on":[{"left":"campaign","right":"campaign"}],"fields":[{"field":"covered-repositories","as":"observed-covered-repositories"}]}],"compute":[{"as":"workflows","function":"coalesce","args":[{"field":"observed-workflows"},{"value":0}]},{"as":"roles","function":"coalesce","args":[{"field":"observed-roles"},{"value":""}]},{"as":"modes","function":"coalesce","args":[{"field":"observed-modes"},{"field":"campaign-mode"}]},{"as":"registration","function":"coalesce","args":[{"field":"observed-registration"},{"field":"campaign-registration"}]},{"as":"runs","function":"coalesce","args":[{"field":"observed-runs"},{"value":0}]},{"as":"dispatches","function":"coalesce","args":[{"field":"observed-dispatches"},{"value":0}]},{"as":"covered-repositories","function":"coalesce","args":[{"field":"observed-covered-repositories"},{"value":0}]},{"as":"aic","function":"coalesce","args":[{"field":"observed-aic"},{"value":0}]},{"as":"encoded-campaign","function":"url-encode","args":[{"field":"campaign"}]},{"as":"campaign-dashboard-href","function":"concat","args":[{"value":"#page-campaign-insights?campaign="},{"field":"encoded-campaign"}]},{"as":"campaign-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"campaign-name"},{"value":" campaign dashboard"}]},{"as":"campaign-dashboard-link","function":"dashboard-link","args":[{"value":""},{"field":"campaign-dashboard-href"},{"field":"campaign-dashboard-label"},{"field":"campaign"}]}],"select":[{"field":"campaign"},{"field":"campaign-name"},{"field":"campaign-dashboard-link"},{"field":"workflows"},{"field":"roles"},{"field":"modes"},{"field":"registration"},{"field":"runs"},{"field":"dispatches"},{"field":"covered-repositories"},{"field":"aic"}],"order-by":[{"field":"campaign-name","direction":"asc"}]},{"name":"firewall-domain-totals","subject":"Show each observed firewall domain with the number of runs and total accepted and blocked requests.","objective":"Identify domains with observed denied requests for a closer review of firewall evidence.","acceptance":"Report distinct observed runs and native accepted and blocked request totals by domain; a denied request alone does not justify allowing egress, and no row does not prove no requests occurred.","description":"Distinct runs and accepted and blocked request totals by firewall domain.","from":"firewall-observations","filter":{"predicates":[{"field":"decision","in":["allowed","denied"]}]},"aggregate":{"by":["domain"],"values":[{"field":"run","as":"run","reducer":"distinct-count"},{"field":"request-count","as":"accepted","reducer":"sum","filter":{"predicates":[{"field":"decision","equals":"allowed"}]}},{"field":"request-count","as":"blocked","reducer":"sum","filter":{"predicates":[{"field":"decision","equals":"denied"}]}}]},"order-by":[{"field":"blocked","direction":"desc"},{"field":"accepted","direction":"desc"},{"field":"domain","direction":"asc"}]},{"name":"firewall-most-blocked-domains","subject":"Highlight the domains with the most blocked firewall requests.","objective":"Prioritize up to ten observed domains by blocked request total for investigation.","acceptance":"Rank by observed blocked totals and inspect underlying domain/workflow evidence before deciding whether a block needs attention; the ranking is not a policy authorization or an incidence rate.","description":"The ten domains with the highest observed blocked request totals.","from":"firewall-domain-totals","order-by":[{"field":"blocked","direction":"desc"},{"field":"domain","direction":"asc"}],"limit":10},{"name":"firewall-domain-workflows","subject":"Show workflows that allowed or blocked requests to each observed firewall domain.","objective":"Locate which observed workflows contributed accepted or denied requests for a domain.","acceptance":"Preserve workflow scope, source link, distinct runs, and native accepted and blocked totals; investigate the run and egress context rather than assuming a denied request is a failure or grounds for wider access.","description":"Workflow-level accepted and blocked request totals by firewall domain.","from":"firewall-observations","filter":{"predicates":[{"field":"decision","in":["allowed","denied"]}]},"compute":[{"as":"workflow-source-url","function":"link-href","args":[{"field":"workflow-link"}]}],"aggregate":{"by":["domain","organization","repository","workflow","workflow-source-url"],"values":[{"field":"run","as":"runs","reducer":"distinct-count"},{"field":"request-count","as":"accepted","reducer":"sum","filter":{"predicates":[{"field":"decision","equals":"allowed"}]}},{"field":"request-count","as":"blocked","reducer":"sum","filter":{"predicates":[{"field":"decision","equals":"denied"}]}}]},"order-by":[{"field":"blocked","direction":"desc"},{"field":"accepted","direction":"desc"},{"field":"repository","direction":"asc"},{"field":"workflow","direction":"asc"}]},{"name":"mcp-tool-totals","subject":"Group observed MCP activity by tool and count calls and calling workflows, excluding the internal safe outputs server.","objective":"Expose tool-level call, workflow, and byte totals to investigate observed MCP usage.","acceptance":"Group only observed non-safe-output-server calls by server and tool, preserving counts and byte totals; lack of calls does not establish no access, and call volume does not establish value or permission.","description":"Observed MCP tool-call totals grouped by MCP server and tool, with the number of distinct calling workflows.","from":"mcp-tool-workflow-totals","filter":{"predicates":[{"field":"safe-output-server","equals":false}]},"aggregate":{"by":["mcp-tool-label","mcp-server","mcp-tool"],"values":[{"field":"calls","as":"calls","reducer":"sum"},{"field":"workflow-key","as":"workflows","reducer":"distinct-count"},{"field":"request-bytes","as":"request-bytes","reducer":"sum"},{"field":"response-bytes","as":"response-bytes","reducer":"sum"}]},"select":[{"field":"mcp-tool-label"},{"field":"mcp-tool"},{"field":"mcp-server"},{"field":"calls"},{"field":"workflows"},{"field":"request-bytes"},{"field":"response-bytes"}],"order-by":[{"field":"calls","direction":"desc"},{"field":"mcp-tool-label","direction":"asc"}]},{"name":"mcp-top-tools","subject":"Show the ten most frequently called MCP tools.","objective":"Identify up to ten tools with the highest observed non-safe-output-server call counts for inspection.","acceptance":"Rank observed calls by tool label and inspect grouped tool evidence before drawing conclusions; do not treat popularity as effectiveness or authority to add tools.","description":"The ten MCP tools with the most observed calls, excluding the internal safe outputs server.","from":"mcp-tool-totals","order-by":[{"field":"calls","direction":"desc"},{"field":"mcp-tool-label","direction":"asc"}],"limit":10},{"name":"steering-events","subject":"Prepare observed gateway steering warnings for aggregation by steering type and workflow.","objective":"Expose warning identity, run context, type, and timestamp for downstream steering diagnostics.","acceptance":"Project recorded gateway steering events with workflow and run attribution where available; a warning is not a completed budget overrun, failure, or reason to increase limits.","description":"Gateway steering warnings emitted when a run approaches its AI Credit budget, time limit, or another declared limit, labelled with a readable steering type.","from":"audits","filter":{"predicates":[{"field":"event-type","equals":"firewall.steering"}]},"joins":[{"source":"workflows","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"}],"fields":[{"field":"campaign","as":"campaign"},{"field":"workflow-name","as":"workflow-name"}]}],"compute":[{"as":"steering-code","function":"coalesce","args":[{"field":"code"},{"field":"event-status"},{"value":"unknown"}]},{"as":"_token-steering","function":"equals-any","args":[{"field":"steering-code"},{"value":"token_steering"}]},{"as":"_timeout-steering","function":"equals-any","args":[{"field":"steering-code"},{"value":"timeout_steering"}]},{"as":"_turn-steering","function":"equals-any","args":[{"field":"steering-code"},{"value":"turn_steering"},{"value":"max_turns_steering"}]},{"as":"_turn-steering-type","function":"if","args":[{"field":"_turn-steering"},{"value":"Running out of turns"},{"field":"steering-code"}]},{"as":"_timeout-steering-type","function":"if","args":[{"field":"_timeout-steering"},{"value":"Running out of time"},{"field":"_turn-steering-type"}]},{"as":"steering-type","function":"if","args":[{"field":"_token-steering"},{"value":"Running out of tokens"},{"field":"_timeout-steering-type"}]},{"as":"workflow-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"},{"value":":"},{"field":"workflow"}]},{"as":"workflow-label","function":"coalesce","args":[{"field":"workflow-name"},{"field":"workflow-coordinate"}]}],"select":[{"field":"id"},{"field":"organization"},{"field":"repository"},{"field":"workflow"},{"field":"workflow-name"},{"field":"workflow-coordinate"},{"field":"workflow-label"},{"field":"campaign"},{"field":"run"},{"field":"run-link"},{"field":"steering-code"},{"field":"steering-type"},{"field":"event-summary"},{"field":"observed-at"}]},{"name":"steering-type-totals","subject":"Show how often each kind of steering warning occurred.","objective":"Identify steering warning categories to inspect in their run context.","acceptance":"Report observed event totals and distinct runs and workflows by type; confirm underlying warnings before interpreting frequency, and do not infer actual limit breaches.","description":"Observed gateway steering warnings grouped by steering type with the number of affected runs and workflows.","from":"steering-events","aggregate":{"by":["steering-type","steering-code"],"values":[{"field":"id","as":"events","reducer":"count"},{"field":"run","as":"runs","reducer":"distinct-count"},{"field":"workflow-coordinate","as":"workflows","reducer":"distinct-count"}]},"select":[{"field":"steering-type"},{"field":"steering-code"},{"field":"events"},{"field":"runs"},{"field":"workflows"}],"order-by":[{"field":"events","direction":"desc"},{"field":"steering-type","direction":"asc"}]},{"name":"steering-workflow-totals","subject":"Count steering warnings for each workflow.","objective":"Expose workflow-level warning totals and token/time warning breakdowns for downstream review.","acceptance":"Count recorded events and distinct runs by workflow, retaining the declared token/time categories; other types remain in total events and no warning alone establishes a failure.","description":"Gateway steering warnings grouped by workflow, split into token-budget and time-limit warnings.","from":"steering-events","aggregate":{"by":["workflow-coordinate","organization","repository","workflow","workflow-label","campaign"],"values":[{"field":"id","as":"events","reducer":"count"},{"field":"run","as":"runs","reducer":"distinct-count"},{"field":"id","as":"token-events","reducer":"count","filter":{"predicates":[{"field":"steering-code","equals":"token_steering"}]}},{"field":"id","as":"time-events","reducer":"count","filter":{"predicates":[{"field":"steering-code","equals":"timeout_steering"}]}},{"field":"steering-type","as":"steering-types","reducer":"distinct-count"}]},"order-by":[{"field":"events","direction":"desc"},{"field":"workflow-coordinate","direction":"asc"}]},{"name":"steering-workflows","subject":"Present workflow steering totals with a link to each workflow dashboard.","objective":"Show observed workflow steering totals with navigation to the affected run context.","acceptance":"Keep workflow identity, link, events, runs, and warning breakdowns tied to their grouped evidence; use drill-through before recommending changes, not warning counts as a basis to widen budgets.","description":"Workflow steering totals labelled with a link to the workflow runtime page.","from":"steering-workflow-totals","compute":[{"as":"encoded-workflow","function":"url-encode","args":[{"field":"workflow-coordinate"}]},{"as":"workflow-dashboard-href","function":"concat","args":[{"value":"#page-workflow-runtime?workflow="},{"field":"encoded-workflow"}]},{"as":"workflow-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"workflow-coordinate"},{"value":" workflow dashboard"}]},{"as":"workflow-dashboard-link","function":"dashboard-link","args":[{"value":""},{"field":"workflow-dashboard-href"},{"field":"workflow-dashboard-label"},{"field":"workflow-label"}]}],"select":[{"field":"workflow-coordinate"},{"field":"workflow-label"},{"field":"workflow-dashboard-link"},{"field":"organization"},{"field":"repository"},{"field":"campaign"},{"field":"events"},{"field":"runs"},{"field":"token-events"},{"field":"time-events"},{"field":"steering-types"}],"order-by":[{"field":"events","direction":"desc"},{"field":"workflow-coordinate","direction":"asc"}]},{"name":"steering-top-workflows","subject":"Highlight the workflows with the most steering warnings.","objective":"Prioritize up to ten workflows by observed warning count for investigation.","acceptance":"Rank recorded warning totals with workflow context, checking underlying events and telemetry coverage; a high rank neither proves overrun nor justifies a limit change.","description":"The ten workflows with the highest observed gateway steering warning totals.","from":"steering-workflows","order-by":[{"field":"events","direction":"desc"},{"field":"workflow-coordinate","direction":"asc"}],"limit":10},{"name":"entity-workflow-run-totals","subject":"Summarize run outcomes and AI Credit consumption for reusable workflow cards.","objective":"Compare retained run-attempt activity, recorded conclusions, and AI Credit usage per workflow card.","acceptance":"Group by organization, repository, and workflow; expose distinct run-attempt count, success/failure conclusion counts, and sum of recorded AIC, without treating missing run history as zero actual activity.","from":"runs","compute":[{"as":"run-attempt-identity","function":"concat","args":[{"field":"run"},{"value":":"},{"field":"run-attempt"}]},{"as":"positive-aic","function":"greater-than","args":[{"field":"aic-total"},{"value":0}]}],"aggregate":{"by":["organization","repository","workflow"],"values":[{"field":"run-attempt-identity","as":"runs","reducer":"distinct-count"},{"field":"run-attempt-identity","as":"aic-runs","reducer":"distinct-count","filter":{"predicates":[{"field":"positive-aic","equals":true}]}},{"field":"run-conclusion","as":"successful-runs","reducer":"count","filter":{"predicates":[{"field":"run-conclusion","equals":"success"}]}},{"field":"run-conclusion","as":"failed-runs","reducer":"count","filter":{"predicates":[{"field":"run-conclusion","in":["failure","startup-failure","stale","timed-out"]}]}},{"field":"aic-total","as":"aic","reducer":"sum","filter":{"predicates":[{"field":"positive-aic","equals":true}]}}]}},{"name":"entity-workflows","subject":"Project workflow entities for reusable workflow cards and repository drill-down.","objective":"Relate declared workflows to observed run and AIC totals for workflow-level drill-down.","acceptance":"Keep declared workflow identity, role, registration, campaign, link, and joined totals; a missing run match defaults to displayed zeros but does not establish no executions or outcomes.","from":"workflows","joins":[{"source":"entity-workflow-run-totals","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"}],"fields":[{"field":"runs","as":"observed-runs"},{"field":"successful-runs","as":"observed-successful-runs"},{"field":"failed-runs","as":"observed-failed-runs"},{"field":"aic","as":"observed-aic"},{"field":"aic-runs","as":"observed-aic-runs"}]}],"compute":[{"as":"runs","function":"coalesce","args":[{"field":"observed-runs"},{"value":0}]},{"as":"successful-runs","function":"coalesce","args":[{"field":"observed-successful-runs"},{"value":0}]},{"as":"failed-runs","function":"coalesce","args":[{"field":"observed-failed-runs"},{"value":0}]},{"as":"aic","function":"coalesce","args":[{"field":"observed-aic"},{"value":0}]},{"as":"aic-per-run","function":"quotient","args":[{"field":"aic"},{"field":"observed-aic-runs"}]}],"select":[{"field":"organization"},{"field":"repository"},{"field":"workflow"},{"field":"workflow-name"},{"field":"workflow-role"},{"field":"workflow-active"},{"field":"campaign-name"},{"field":"observed-at"},{"field":"runs"},{"field":"successful-runs"},{"field":"failed-runs"},{"field":"aic-per-run"},{"field":"workflow-link"}],"order-by":[{"field":"repository","direction":"asc"},{"field":"workflow","direction":"asc"}]},{"name":"repository-runs","subject":"Project canonical runs into repository-addressable run evidence.","objective":"Expose retained run chronology and status for a selected repository's drill-down.","acceptance":"Retain repository coordinate, workflow, run identity, title, event, start time, conclusion, mode, AIC, and run link; absent details or runs do not establish a healthy or idle repository.","description":"Workflow runs with a stable repository route key.","from":"runs","compute":[{"as":"repository-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]}],"select":[{"field":"repository-coordinate"},{"field":"workflow"},{"field":"run"},{"field":"run-title"},{"field":"event"},{"field":"started-at"},{"field":"run-status"},{"field":"run-conclusion"},{"field":"rollout-mode"},{"field":"aic-total"},{"field":"run-link"}],"order-by":[{"field":"started-at","direction":"desc"},{"field":"run","direction":"desc"}]},{"name":"repository-workflow-totals","subject":"Summarize declared and disabled workflow counts by repository.","objective":"Compare declared and disabled workflow counts for each repository in the retained workflow inventory.","acceptance":"Count declared workflows and workflow-active=false entries by organization and repository; missing declarations must not be interpreted as a complete zero-workflow inventory.","description":"Declared and disabled workflow totals for each repository.","from":"workflows","aggregate":{"by":["organization","repository"],"values":[{"field":"workflow","as":"workflows","reducer":"count"},{"field":"workflow","as":"disabled","reducer":"count","filter":{"predicates":[{"field":"workflow-active","equals":"false"}]}}]}},{"name":"repository-report-totals","subject":"Summarize published outcome report counts by repository.","objective":"Show retained outcome-report volume per repository for comparison with observed execution.","acceptance":"Count retained outcome rows by organization and repository; a missing aggregate does not prove no reports were published or that reported outcomes succeeded.","description":"Published report totals for each repository.","from":"outcomes","aggregate":{"by":["organization","repository"],"values":[{"field":"repository","as":"reports","reducer":"count"}]}},{"name":"repository-run-identities","subject":"Project the run-attempt identities needed to match imported evidence.","objective":"Keep import-coverage joins narrow without carrying run details, links, or costs.","acceptance":"Preserve each selected run attempt and its organization, repository, workflow, run, and attempt keys. Do not deduplicate attempts or change selected-horizon semantics.","from":"runs","select":[{"field":"organization"},{"field":"repository"},{"field":"workflow"},{"field":"run"},{"field":"run-attempt"}]},{"name":"repository-import-totals","subject":"Count selected run attempts with matching retained imported records.","objective":"Join compact run identities to already reduced event evidence, then reduce import coverage by repository.","acceptance":"Match all five run-attempt keys and count each selected run row once when events are positive. Preserve optional-evidence quality and horizon filters; records for unselected runs do not establish coverage.","from":"repository-run-identities","joins":[{"source":"event-runs","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"},{"left":"run","right":"run"},{"left":"run-attempt","right":"run-attempt"}],"fields":[{"field":"events","as":"imported-events"}]}],"compute":[{"as":"imported","function":"greater-than","args":[{"field":"imported-events"},{"value":0}]}],"aggregate":{"by":["organization","repository"],"values":[{"field":"imported","as":"imported-runs","reducer":"sum"}]}},{"name":"repository-run-totals","subject":"Summarize distinct runs, failures, and approval-required runs by repository.","objective":"Join already reduced run statistics and import coverage at repository grain.","acceptance":"Group by organization and repository; preserve distinct run IDs, configured failure/action-required conclusion counts, and imported-run sums. Missing enrichment or run history must not be treated as complete coverage.","description":"Distinct run and conclusion totals for each repository.","from":"repository-run-statistics","joins":[{"source":"repository-import-totals","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"}],"fields":[{"field":"imported-runs","as":"imported-runs"}]}],"select":[{"field":"organization"},{"field":"repository"},{"field":"runs"},{"field":"failed"},{"field":"action-required"},{"field":"imported-runs"}]},{"name":"repository-activity-preview","subject":"List repository identities before execution metrics are computed.","objective":"Show retained repository identities and drill links while activity metrics are pending.","acceptance":"List repositories by organization with repository drill links; this preview does not establish activity totals or outcomes.","description":"Fast repository inventory with drill links; activity fields remain pending.","from":"repositories","compute":[{"as":"repository-slug","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"encoded-repository","function":"url-encode","args":[{"field":"repository-slug"}]},{"as":"repository-dashboard-href","function":"concat","args":[{"value":"#page-repository-detail?repository="},{"field":"encoded-repository"}]},{"as":"repository-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"repository-slug"},{"value":" repository dashboard"}]},{"as":"repository-dashboard-link","function":"dashboard-link","args":[{"field":"repository-link"},{"field":"repository-dashboard-href"},{"field":"repository-dashboard-label"},{"field":"repository-slug"}]}],"select":[{"field":"organization"},{"field":"repository-slug","as":"repository"},{"field":"repository-dashboard-link","as":"repository-link"}],"order-by":[{"field":"repository","direction":"asc"}]},{"name":"repository-activity-core","subject":"Join each repository with its workflow, report, and run totals.","objective":"Attach retained workflow, report, and run aggregates to each repository for bounded inventory review.","acceptance":"Preserve each repository and the available joined aggregates by organization and repository; unmatched metrics remain missing evidence, not confirmed zero activity or evaluated outcomes.","description":"Repository inventory joined with workflow, report, evaluation, and run totals.","from":"repositories","joins":[{"source":"repository-workflow-totals","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"}],"fields":[{"field":"workflows","as":"observed-workflows"},{"field":"disabled","as":"observed-disabled"}]},{"source":"repository-report-totals","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"}],"fields":[{"field":"reports","as":"observed-reports"}]},{"source":"repository-run-totals","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"}],"fields":[{"field":"runs","as":"observed-runs"},{"field":"failed","as":"observed-failed"},{"field":"action-required","as":"observed-action-required"},{"field":"imported-runs","as":"observed-imported-runs"}]}]},{"name":"repository-activity","subject":"Show repository-level execution health, outcome activity, and AI Credit usage in an actionable inventory.","objective":"Prioritize repository drill-down using declared workflows, observed runs, reports, failures, import coverage, and AIC.","acceptance":"Return repository identity and link with retained counts, ingestion indicator, failure summary, AIC, and computed status; statuses describe retained evidence only, and an empty or unavailable preview cannot verify health, outcomes, or zero activity.","description":"Repository-local execution health and attributed outcome totals.","from":"repository-activity-core","joins":[{"source":"repository-aic-totals","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"}],"fields":[{"field":"aic","as":"observed-aic"}]}],"compute":[{"as":"repository-slug","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"workflows","function":"coalesce","args":[{"field":"observed-workflows"},{"value":0}]},{"as":"disabled","function":"coalesce","args":[{"field":"observed-disabled"},{"value":0}]},{"as":"runs","function":"coalesce","args":[{"field":"observed-runs"},{"value":0}]},{"as":"failed","function":"coalesce","args":[{"field":"observed-failed"},{"value":0}]},{"as":"imported-runs","function":"coalesce","args":[{"field":"observed-imported-runs"},{"value":0}]},{"as":"ingestion-rate","function":"quotient","args":[{"field":"imported-runs"},{"field":"runs"}]},{"as":"ingestion","function":"format-percent","args":[{"field":"ingestion-rate"}]},{"as":"action-required","function":"coalesce","args":[{"field":"observed-action-required"},{"value":0}]},{"as":"aic","function":"coalesce","args":[{"field":"observed-aic"},{"value":0}]},{"as":"has-failures","function":"greater-than","args":[{"field":"failed"},{"value":0}]},{"as":"has-action-required","function":"greater-than","args":[{"field":"action-required"},{"value":0}]},{"as":"has-runs","function":"greater-than","args":[{"field":"runs"},{"value":0}]},{"as":"has-disabled","function":"greater-than","args":[{"field":"disabled"},{"value":0}]},{"as":"outcomes-observed","function":"coalesce","args":[{"field":"observed-reports"},{"value":0}]},{"as":"has-outcomes","function":"greater-than","args":[{"field":"outcomes-observed"},{"value":0}]},{"as":"failure-rate","function":"quotient","args":[{"field":"failed"},{"field":"runs"}]},{"as":"failure-percent","function":"format-percent","args":[{"field":"failure-rate"}]},{"as":"failure-count","function":"format-count","args":[{"field":"failed"}]},{"as":"observed-failure-summary","function":"concat","args":[{"field":"failure-percent"},{"value":" · "},{"field":"failure-count"},{"value":" failed"}]},{"as":"failure-summary","function":"if","args":[{"field":"has-runs"},{"field":"observed-failure-summary"},{"value":"—"}]},{"as":"outcome-status","function":"if","args":[{"field":"has-outcomes"},{"value":"Outcomes observed"},{"value":"No recent activity"}]},{"as":"disabled-status","function":"if","args":[{"field":"has-disabled"},{"value":"Disabled workflows"},{"field":"outcome-status"}]},{"as":"run-status","function":"if","args":[{"field":"has-runs"},{"value":"No failures observed"},{"field":"disabled-status"}]},{"as":"action-status","function":"if","args":[{"field":"has-action-required"},{"value":"Approval required"},{"field":"run-status"}]},{"as":"status","function":"if","args":[{"field":"has-failures"},{"value":"Needs attention"},{"field":"action-status"}]},{"as":"encoded-repository","function":"url-encode","args":[{"field":"repository-slug"}]},{"as":"repository-dashboard-href","function":"concat","args":[{"value":"#page-repository-detail?repository="},{"field":"encoded-repository"}]},{"as":"repository-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"repository-slug"},{"value":" repository dashboard"}]},{"as":"repository-dashboard-link","function":"dashboard-link","args":[{"field":"repository-link"},{"field":"repository-dashboard-href"},{"field":"repository-dashboard-label"},{"field":"repository-slug"}]}],"select":[{"field":"organization"},{"field":"repository","as":"repository-name"},{"field":"repository-slug","as":"repository"},{"field":"workflows"},{"field":"observed-reports","as":"reports"},{"field":"runs"},{"field":"ingestion"},{"field":"failure-summary"},{"field":"aic"},{"field":"status"},{"field":"repository-dashboard-link","as":"repository-link"},{"field":"failed"}],"order-by":[{"field":"failed","direction":"desc"},{"field":"runs","direction":"desc"},{"field":"repository","direction":"asc"}]},{"name":"repository-observed-run-counts","subject":"Count distinct retained run IDs by repository without importing event evidence.","objective":"Supply the run-volume chart without computing activity health, ingestion coverage, or workflow costs.","acceptance":"Group by organization and repository coordinate and count distinct retained run IDs, not attempts; missing runs remain missing evidence and global scope and time filters still apply.","from":"runs","compute":[{"as":"repository-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]}],"aggregate":{"by":["organization","repository-coordinate"],"values":[{"field":"run","as":"runs","reducer":"distinct-count"}]}},{"name":"repository-run-inventory","subject":"Registered repositories and distinct retained workflow run IDs in the selected horizon.","objective":"Compare repository execution volume and choose repositories for drill-down.","acceptance":"Keep up to 100 repository identities and drill links, ordered by run count descending with repository tie-breaks. Zero means no retained runs, not proof of inactivity; preserve unavailable and partial evidence. The Table view retains the full inventory.","from":"repository-activity-preview","joins":[{"source":"repository-observed-run-counts","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository-coordinate"}],"fields":[{"field":"runs","as":"observed-runs"}]}],"compute":[{"as":"runs","function":"coalesce","args":[{"field":"observed-runs"},{"value":0}]}],"select":[{"field":"organization"},{"field":"repository"},{"field":"runs"},{"field":"repository-link"}],"order-by":[{"field":"runs","direction":"desc"},{"field":"repository","direction":"asc"}],"limit":100},{"name":"workflow-route-record","subject":"Project the selected workflow's identity and registration for its route shell.","objective":"Identify the workflow and its recorded campaign registration before inspecting route-specific evidence.","acceptance":"Preserve organization, repository, workflow identity, recorded role, activation, campaign, rollout mode, and source link; absent registration is not inferred from runs, and displayed activation does not grant execution authority.","from":"workflows","select":[{"field":"organization"},{"field":"repository"},{"field":"workflow"},{"field":"workflow-name"},{"field":"workflow-role"},{"field":"workflow-active"},{"field":"campaign"},{"field":"campaign-name"},{"field":"rollout-mode"},{"field":"workflow-link"}]},{"name":"workflow-runtime-health-summary","subject":"Count mutually exclusive runtime conclusion classes for the selected workflow.","objective":"Identify workflows whose retained run conclusions or pending execution warrant investigation.","acceptance":"Within each organization, repository, and workflow, successful, failed, approval, pending, and other counts sum to the retained run total; missing or unrecognized conclusions are not treated as success, and runtime success is not a verified outcome.","from":"runs","compute":[{"as":"successful","function":"equals-any","args":[{"field":"run-conclusion"},{"value":"success"}]},{"as":"failed","function":"equals-any","args":[{"field":"run-conclusion"},{"value":"failure"},{"value":"startup-failure"},{"value":"stale"},{"value":"timed-out"}]},{"as":"approval","function":"equals-any","args":[{"field":"run-conclusion"},{"value":"action-required"}]},{"as":"classified","function":"equals-any","args":[{"field":"run-conclusion"},{"value":"success"},{"value":"failure"},{"value":"startup-failure"},{"value":"stale"},{"value":"timed-out"},{"value":"action-required"}]},{"as":"status","function":"concat","args":[{"field":"run-status"},{"value":""}]},{"as":"terminal-or-missing","function":"equals-any","args":[{"field":"status"},{"value":"completed"},{"value":""}]}],"aggregate":{"by":["organization","repository","workflow"],"values":[{"field":"run","as":"total","reducer":"count"},{"field":"run","as":"successful","reducer":"count","filter":{"predicates":[{"field":"successful","equals":true}]}},{"field":"run","as":"failed","reducer":"count","filter":{"predicates":[{"field":"failed","equals":true}]}},{"field":"run","as":"approval","reducer":"count","filter":{"predicates":[{"field":"approval","equals":true}]}},{"field":"run","as":"pending","reducer":"count","filter":{"predicates":[{"field":"classified","equals":false},{"field":"terminal-or-missing","equals":false}]}},{"field":"run","as":"other","reducer":"count","filter":{"predicates":[{"field":"classified","equals":false},{"field":"terminal-or-missing","equals":true}]}}]}},{"name":"workflow-runtime-usage-summary","subject":"Sum retained AI Credits and count telemetry rows for the selected workflow without transferring runs.","objective":"Inspect a workflow's observed AI Credit consumption together with the amount of retained usage telemetry.","acceptance":"AI Credits sum the retained aic values within each organization, repository, and workflow, and telemetry-count counts its usage records; absent telemetry does not establish zero cost or complete run coverage.","from":"usage","compute":[{"as":"positive-aic","function":"greater-than","args":[{"field":"aic"},{"value":0}]}],"aggregate":{"by":["organization","repository","workflow"],"values":[{"field":"aic","as":"aic","reducer":"sum","filter":{"predicates":[{"field":"positive-aic","equals":true}]}},{"field":"run","as":"telemetry-count","reducer":"count"}]}},{"name":"outcome-route-record","subject":"Project the selected safe-output record for the outcome route and its sections.","objective":"Inspect a retained safe output's recorded disposition and follow its durable evidence links.","acceptance":"Preserve safe-output and run identity, title, category, disposition, summary, timestamps, rollout mode, workflow context, and retained links; missing fields stay unknown and a recorded disposition is not independently verified operational impact.","from":"outcomes","select":[{"field":"safe-output"},{"field":"run"},{"field":"outcome-title"},{"field":"outcome-number"},{"field":"outcome-category"},{"field":"outcome-status"},{"field":"outcome-state"},{"field":"outcome-summary"},{"field":"published-at"},{"field":"observed-at"},{"field":"rollout-mode"},{"field":"workflow"},{"field":"workflow-name"},{"field":"workflow-link"},{"field":"external-link"},{"field":"issue-link"},{"field":"pull-request-link"},{"field":"run-link"}]},{"name":"entity-runs","subject":"Project run entities for reusable run cards and workflow drill-down.","objective":"Expose retained run-attempt identity, execution timing, conclusion, and link for a bounded workflow-run inspection.","acceptance":"Keep organization, repository, workflow, run and attempt with status, conclusion, event, branch, duration, timestamps, and run link; missing timing or conclusion remains unknown rather than inferred success.","from":"runs","select":[{"field":"organization"},{"field":"repository"},{"field":"workflow"},{"field":"target-repository"},{"field":"run"},{"field":"run-attempt"},{"field":"run-title"},{"field":"run-status"},{"field":"run-conclusion"},{"field":"event"},{"field":"branch"},{"field":"duration"},{"field":"started-at"},{"field":"ended-at"},{"field":"run-link"}],"order-by":[{"field":"started-at","direction":"desc"}]},{"name":"workflow-runs","subject":"Project canonical runs into route-addressable workflow run evidence.","objective":"Trace retained runs and recorded failure evidence for a selected workflow route.","acceptance":"Preserve workflow route, run identity, start/end, status, conclusion, failure fields, mode, engine/model metadata, and run link; missing failure details do not prove success or rule out incomplete import.","description":"Workflow runs with a stable repository and workflow route key.","from":"runs","compute":[{"as":"repository-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"workflow-route","function":"concat","args":[{"field":"repository-coordinate"},{"value":":"},{"field":"workflow"}]}],"select":[{"field":"workflow-route"},{"field":"organization"},{"field":"repository"},{"field":"workflow"},{"field":"run"},{"field":"run-title"},{"field":"event"},{"field":"started-at"},{"field":"ended-at"},{"field":"run-status"},{"field":"run-conclusion"},{"field":"failure-job"},{"field":"failure-message"},{"field":"failure-step"},{"field":"failure-log"},{"field":"rollout-mode"},{"field":"engine"},{"field":"engine-version"},{"field":"gh-aw-version"},{"field":"requested-model"},{"field":"resolved-model"},{"field":"run-link"}],"order-by":[{"field":"started-at","direction":"desc"},{"field":"run","direction":"desc"}]},{"name":"workflow-failure-trend","subject":"Show recent failure counts and their change for each workflow.","objective":"Spot a change in observed workflow failure activity without treating unknown conclusions as failures.","acceptance":"Each observed failure counts once within its own workflow; the first change is undefined and the seven-observation window is not a seven-day calendar interval.","from":"workflow-runs","compute":[{"as":"is-failure","function":"equals-any","args":[{"field":"run-conclusion"},{"value":"failure"},{"value":"timed_out"}]},{"as":"failure-count","function":"if","args":[{"field":"is-failure"},{"value":1},{"value":0}]}],"window":[{"operation":"rolling","field":"failure-count","as":"recent-failure-count","frame":7,"reducer":"sum","order-by":[{"field":"started-at","direction":"asc"},{"field":"run","direction":"asc"}],"groupby":["workflow-route"]},{"operation":"change","field":"recent-failure-count","as":"failure-count-change","mode":"absolute","order-by":[{"field":"started-at","direction":"asc"},{"field":"run","direction":"asc"}],"groupby":["workflow-route"]}]},{"name":"workflow-reports","subject":"Project retained outcomes into route-addressable workflow reports.","objective":"Review retained workflow outcome reports separately from execution status before interpreting operational results.","acceptance":"Keep route, safe output, report title and summary, recorded status, category, observation time, metadata, and external link; missing reports or status do not imply success or no work.","description":"Workflow outcome reports with stable route keys and disposition fields.","from":"outcomes","compute":[{"as":"report-repository","function":"coalesce","args":[{"field":"runtime-repository"},{"field":"repository"}]},{"as":"workflow-route","function":"concat","args":[{"field":"report-repository"},{"value":":"},{"field":"workflow"}]},{"as":"report-status","function":"coalesce","args":[{"field":"outcome-status"},{"field":"outcome-state"},{"value":"unknown"}]}],"select":[{"field":"workflow-route"},{"field":"safe-output"},{"field":"outcome-title"},{"field":"outcome-summary"},{"field":"report-status","as":"outcome-status"},{"field":"rollout-mode"},{"field":"engine"},{"field":"engine-version"},{"field":"requested-model"},{"field":"resolved-model"},{"field":"outcome-category"},{"field":"observed-at"},{"field":"external-link"}],"order-by":[{"field":"observed-at","direction":"desc"},{"field":"outcome-title","direction":"asc"}]},{"name":"value-evidence-facts","subject":"Published original evidence for frozen workflow value contracts.","objective":"Keep report identity, target repository, workflow and capture together.","acceptance":"Read canonical evidence only. No GitHub acquisition, HTML loading or fabricated evidence on navigation.","from":"operational-value-evidence","time":{"range":"all"},"compute":[{"as":"workflow-route","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"},{"value":":"},{"field":"workflow-path"}]}]},{"name":"value-contracts","subject":"Latest retained report contract per repository, workflow and native measure.","objective":"Prevent old reports or versions from masking newer evidence.","acceptance":"Select the latest cutoff then capture before evaluating missing or incomplete evidence. Preserve separate measures.","from":"value-evidence-facts","filter":{"predicates":[{"field":"fact-kind","equals":"contract"}]},"compute":[{"as":"report-marker","function":"literal","args":[{"value":1}]}],"window":[{"operation":"change","field":"report-marker","as":"older-report","mode":"absolute","groupby":["organization","repository","workflow","metric-id"],"order-by":[{"field":"window-end","direction":"desc"},{"field":"observed-at","direction":"desc"},{"field":"report-id","direction":"desc"}]}]},{"name":"value-snapshots","subject":"Independent repository-state observations and exact item drill-downs.","objective":"Keep everyone's changes separate from workflow-linked delivery.","acceptance":"Retain observed native values, dates and immutable references. Do not invent intermediate observations.","from":"value-evidence-facts","filter":{"predicates":[{"field":"fact-kind","equals":"snapshot"}]},"compute":[{"as":"snapshot-marker","function":"literal","args":[{"value":1}]},{"as":"snapshot-route","function":"concat","args":[{"field":"report-id"},{"value":"|"},{"field":"fact-id"}]},{"as":"encoded-snapshot","function":"url-encode","args":[{"field":"snapshot-route"}]},{"as":"snapshot-href","function":"concat","args":[{"value":"#page-value-snapshot?snapshot="},{"field":"encoded-snapshot"}]}],"order-by":[{"field":"at","direction":"asc"},{"field":"fact-id","direction":"asc"}]},{"name":"value-first-snapshot-order","subject":"First independently observed repository state.","objective":"Name the actual first-snapshot reference rather than an invented baseline.","acceptance":"Strictly use retained snapshot time. A post-adoption snapshot is not a pre-adoption baseline.","from":"value-snapshots","window":[{"operation":"change","field":"snapshot-marker","as":"earlier-snapshot","mode":"absolute","groupby":["report-id"],"order-by":[{"field":"at","direction":"asc"}]}]},{"name":"value-first-snapshot","subject":"First retained snapshot per report.","objective":"Provide the explicit reference value and date.","acceptance":"No retained reference means no comparison.","from":"value-first-snapshot-order","filter":{"predicates":[{"field":"earlier-snapshot","equals":"unknown"}]}},{"name":"value-last-snapshot-order","subject":"Latest independently observed repository state.","objective":"Show the actual last measurement rather than an extrapolation.","acceptance":"Preserve the latest retained snapshot even if unchanged.","from":"value-snapshots","window":[{"operation":"change","field":"snapshot-marker","as":"later-snapshot","mode":"absolute","groupby":["report-id"],"order-by":[{"field":"at","direction":"desc"}]}]},{"name":"value-last-snapshot","subject":"Last retained snapshot per report.","objective":"Provide the current native observation.","acceptance":"One snapshot establishes state, not movement.","from":"value-last-snapshot-order","filter":{"predicates":[{"field":"later-snapshot","equals":"unknown"}]}},{"name":"value-output-counts","subject":"Retained safe outputs and applied creation receipts.","objective":"Describe output activity without treating it as accepted value.","acceptance":"Count distinct validated output facts. Tracking corroboration is not an applied receipt.","from":"value-evidence-facts","filter":{"predicates":[{"field":"fact-kind","equals":"output"}]},"aggregate":{"by":["report-id"],"values":[{"field":"fact-id","as":"retained-outputs","reducer":"count"},{"field":"fact-id","as":"receipt-outputs","reducer":"count","filter":{"predicates":[{"field":"origin","equals":"receipt-verified"}]}}]}},{"name":"value-implementation-counts","subject":"Distinct accepted implementations and their measured native effects.","objective":"Count each accepted implementation once, including zero and negative effects.","acceptance":"Validated implementation identities are unique; many-to-many output edges must not multiply value. Complete coverage is checked separately.","from":"value-evidence-facts","filter":{"predicates":[{"field":"fact-kind","equals":"implementation"}]},"compute":[{"as":"accepted-ms","function":"timestamp","args":[{"field":"at"}]},{"as":"cutoff-ms","function":"timestamp","args":[{"field":"window-end"}]},{"as":"current-start","function":"difference","args":[{"field":"cutoff-ms"},{"value":2419200000}]},{"as":"previous-start","function":"difference","args":[{"field":"cutoff-ms"},{"value":4838400000}]},{"as":"before-current","function":"greater-than","args":[{"field":"current-start"},{"field":"accepted-ms"}]},{"as":"before-previous","function":"greater-than","args":[{"field":"previous-start"},{"field":"accepted-ms"}]},{"as":"current-effect","function":"if","args":[{"field":"before-current"},{"value":0},{"field":"value"}]},{"as":"previous-candidate","function":"if","args":[{"field":"before-previous"},{"value":0},{"field":"value"}]},{"as":"previous-effect","function":"if","args":[{"field":"before-current"},{"field":"previous-candidate"},{"value":0}]}],"aggregate":{"by":["report-id"],"values":[{"field":"fact-id","as":"accepted-implementations","reducer":"count"},{"field":"value","as":"known-result","reducer":"sum"},{"field":"current-effect","as":"known-recent","reducer":"sum"},{"field":"previous-effect","as":"known-previous","reducer":"sum"}]}},{"name":"value-covered-durations","subject":"Explicit complete evidence durations in the report and adjacent 28-day delivery periods.","objective":"Distinguish known zero from gaps or incomplete evidence.","acceptance":"The producer validates non-overlapping bounded coverage. Count only complete intervals, clipped to each exact half-open period.","from":"value-evidence-facts","filter":{"predicates":[{"field":"fact-kind","equals":"coverage"},{"field":"coverage-status","equals":"complete"}]},"compute":[{"as":"left-ms","function":"timestamp","args":[{"field":"at"}]},{"as":"right-ms","function":"timestamp","args":[{"field":"end-at"}]},{"as":"cutoff-ms","function":"timestamp","args":[{"field":"window-end"}]},{"as":"current-start","function":"difference","args":[{"field":"cutoff-ms"},{"value":2419200000}]},{"as":"previous-start","function":"difference","args":[{"field":"cutoff-ms"},{"value":4838400000}]},{"as":"after-current","function":"greater-than","args":[{"field":"left-ms"},{"field":"current-start"}]},{"as":"after-previous","function":"greater-than","args":[{"field":"left-ms"},{"field":"previous-start"}]},{"as":"before-current-end","function":"greater-than","args":[{"field":"current-start"},{"field":"right-ms"}]},{"as":"current-left","function":"if","args":[{"field":"after-current"},{"field":"left-ms"},{"field":"current-start"}]},{"as":"previous-left","function":"if","args":[{"field":"after-previous"},{"field":"left-ms"},{"field":"previous-start"}]},{"as":"previous-right","function":"if","args":[{"field":"before-current-end"},{"field":"right-ms"},{"field":"current-start"}]},{"as":"duration","function":"difference","args":[{"field":"right-ms"},{"field":"left-ms"}]},{"as":"current-duration","function":"difference","args":[{"field":"right-ms"},{"field":"current-left"}]},{"as":"previous-duration","function":"difference","args":[{"field":"previous-right"},{"field":"previous-left"}]},{"as":"positive-current","function":"greater-than","args":[{"field":"current-duration"},{"value":0}]},{"as":"positive-previous","function":"greater-than","args":[{"field":"previous-duration"},{"value":0}]},{"as":"covered-current","function":"if","args":[{"field":"positive-current"},{"field":"current-duration"},{"value":0}]},{"as":"covered-previous","function":"if","args":[{"field":"positive-previous"},{"field":"previous-duration"},{"value":0}]}],"aggregate":{"by":["report-id"],"values":[{"field":"duration","as":"covered-duration","reducer":"sum"},{"field":"covered-current","as":"covered-current","reducer":"sum"},{"field":"covered-previous","as":"covered-previous","reducer":"sum"}]}},{"name":"value-report-delivery","subject":"Evidence-qualified output and accepted-contribution totals.","objective":"Keep populations and native units separate without an implied conversion rate.","acceptance":"Absent output context is unknown. Missing coverage withholds complete totals and recent zero, retaining labelled known subtotals.","from":"value-contracts","joins":[{"source":"value-output-counts","type":"left","on":[{"left":"report-id","right":"report-id"}],"fields":[{"field":"retained-outputs","as":"retained-outputs"},{"field":"receipt-outputs","as":"retained-receipts"}]},{"source":"value-implementation-counts","type":"left","on":[{"left":"report-id","right":"report-id"}],"fields":[{"field":"accepted-implementations","as":"retained-implementations"},{"field":"known-result","as":"known-result"},{"field":"known-recent","as":"known-recent"},{"field":"known-previous","as":"known-previous"}]},{"source":"value-covered-durations","type":"left","on":[{"left":"report-id","right":"report-id"}],"fields":[{"field":"covered-duration","as":"covered-duration"},{"field":"covered-current","as":"covered-current"},{"field":"covered-previous","as":"covered-previous"}]}],"compute":[{"as":"start-ms","function":"timestamp","args":[{"field":"window-start"}]},{"as":"end-ms","function":"timestamp","args":[{"field":"window-end"}]},{"as":"report-duration","function":"difference","args":[{"field":"end-ms"},{"field":"start-ms"}]},{"as":"complete-report","function":"equals-any","args":[{"field":"covered-duration"},{"field":"report-duration"}]},{"as":"complete-current","function":"equals-any","args":[{"field":"covered-current"},{"value":2419200000}]},{"as":"complete-previous","function":"equals-any","args":[{"field":"covered-previous"},{"value":2419200000}]},{"as":"show-workflow-trail","function":"equals-any","args":[{"field":"measurement-basis"},{"value":"workflow-contribution"}]},{"as":"known-output-count","function":"coalesce","args":[{"field":"retained-outputs"},{"value":0}]},{"as":"known-receipt-count","function":"coalesce","args":[{"field":"retained-receipts"},{"value":0}]},{"as":"receipt-outputs","function":"if","args":[{"field":"outputs-available"},{"field":"known-receipt-count"},{"value":null}]},{"as":"accepted-implementations","function":"coalesce","args":[{"field":"retained-implementations"},{"value":0}]},{"as":"output-count","function":"if","args":[{"field":"outputs-available"},{"field":"known-output-count"},{"value":null}]},{"as":"native-result","function":"coalesce","args":[{"field":"known-result"},{"value":0}]},{"as":"current-subtotal","function":"coalesce","args":[{"field":"known-recent"},{"value":0}]},{"as":"previous-subtotal","function":"coalesce","args":[{"field":"known-previous"},{"value":0}]},{"as":"recent-result","function":"if","args":[{"field":"complete-current"},{"field":"current-subtotal"},{"value":null}]},{"as":"previous-result","function":"if","args":[{"field":"complete-previous"},{"field":"previous-subtotal"},{"value":null}]}]},{"name":"value-report-summary","subject":"Shared native card and report comparison against the first retained snapshot.","objective":"Show signed repository-wide movement, the goal direction and the exact comparison dates.","acceptance":"This first/last snapshot comparison is not the adjacent-period alert policy, a pre-adoption baseline or causal workflow credit. One snapshot is not zero change.","from":"value-report-delivery","joins":[{"source":"value-first-snapshot","type":"left","on":[{"left":"report-id","right":"report-id"}],"fields":[{"field":"value","as":"reference-value"},{"field":"at","as":"reference-at"}]},{"source":"value-last-snapshot","type":"left","on":[{"left":"report-id","right":"report-id"}],"fields":[{"field":"value","as":"current-value"},{"field":"at","as":"current-at"},{"field":"snapshot-href","as":"current-snapshot-href"}]}],"compute":[{"as":"same-snapshot","function":"equals-any","args":[{"field":"reference-at"},{"field":"current-at"}]},{"as":"raw-change","function":"difference","args":[{"field":"current-value"},{"field":"reference-value"}]},{"as":"native-change","function":"if","args":[{"field":"same-snapshot"},{"value":null},{"field":"raw-change"}]},{"as":"change-missing","function":"equals-any","args":[{"field":"native-change"},{"value":null}]},{"as":"rising","function":"greater-than","args":[{"field":"native-change"},{"value":0}]},{"as":"falling","function":"greater-than","args":[{"value":0},{"field":"native-change"}]},{"as":"unchanged","function":"equals-any","args":[{"field":"native-change"},{"value":0}]},{"as":"decrease-goal","function":"equals-any","args":[{"field":"snapshot-direction"},{"value":"decrease"}]},{"as":"increase-goal","function":"equals-any","args":[{"field":"snapshot-direction"},{"value":"increase"}]},{"as":"increase-movement","function":"if","args":[{"field":"rising"},{"value":"Better"},{"value":"Worse"}]},{"as":"decrease-movement","function":"if","args":[{"field":"falling"},{"value":"Better"},{"value":"Worse"}]},{"as":"directed-movement","function":"if","args":[{"field":"decrease-goal"},{"field":"decrease-movement"},{"field":"increase-movement"}]},{"as":"known-movement","function":"if","args":[{"field":"unchanged"},{"value":"Unchanged"},{"field":"directed-movement"}]},{"as":"movement","function":"if","args":[{"field":"change-missing"},{"value":"Comparison unavailable"},{"field":"known-movement"}]},{"as":"increase-direction-label","function":"if","args":[{"field":"increase-goal"},{"value":"↑ Higher is better"},{"value":"Direction not retained"}]},{"as":"direction-label","function":"if","args":[{"field":"decrease-goal"},{"value":"↓ Lower is better"},{"field":"increase-direction-label"}]},{"as":"change-arrow","function":"if","args":[{"field":"rising"},{"value":"↑ +"},{"value":"↓ "}]},{"as":"change-number","function":"format-count","args":[{"field":"native-change"}]},{"as":"directional-delta","function":"concat","args":[{"field":"change-arrow"},{"field":"change-number"},{"value":" "},{"field":"snapshot-unit"}]},{"as":"known-delta","function":"if","args":[{"field":"unchanged"},{"value":"Unchanged"},{"field":"directional-delta"}]},{"as":"delta-label","function":"if","args":[{"field":"change-missing"},{"value":"Comparison unavailable"},{"field":"known-delta"}]},{"as":"signed-change","function":"concat","args":[{"field":"change-arrow"},{"field":"change-number"},{"value":" "},{"field":"snapshot-unit"},{"value":" · "},{"field":"movement"}]},{"as":"unchanged-change","function":"if","args":[{"field":"unchanged"},{"value":"Unchanged"},{"field":"signed-change"}]},{"as":"change-label","function":"if","args":[{"field":"change-missing"},{"value":"Comparison unavailable"},{"field":"unchanged-change"}]},{"as":"reference-day","function":"date-day","args":[{"field":"reference-at"}]},{"as":"known-comparison-label","function":"concat","args":[{"value":"Since "},{"field":"reference-day"},{"value":" · Everyone's work"}]},{"as":"comparison-label","function":"if","args":[{"field":"change-missing"},{"value":"No earlier snapshot for comparison"},{"field":"known-comparison-label"}]},{"as":"workflow-label","function":"coalesce","args":[{"field":"workflow-name"},{"field":"workflow"}]},{"as":"workflow-context","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"},{"value":" · "},{"field":"workflow-label"}]},{"as":"encoded-workflow","function":"url-encode","args":[{"field":"workflow-route"}]},{"as":"workflow-value-href","function":"concat","args":[{"value":"#page-workflow-value?workflow="},{"field":"encoded-workflow"}]},{"as":"encoded-report","function":"url-encode","args":[{"field":"report-id"}]},{"as":"report-href","function":"concat","args":[{"value":"#page-value-report?report="},{"field":"encoded-report"}]}]},{"name":"value-workflow-results","subject":"Current published report results per native measure.","objective":"Expose the latest coherent packet on the workflow Value tab.","acceptance":"Never replace missing facts with an older measured version. Explicit report links retain their own version.","from":"value-report-summary","filter":{"predicates":[{"field":"older-report","equals":"unknown"}]}},{"name":"value-intent-sources","subject":"Immutable extracted workflow intent sources.","objective":"Let readers inspect the original goal and requirements.","acceptance":"Only retained HTTPS evidence is linked; workflow text remains untrusted.","from":"value-evidence-facts","filter":{"predicates":[{"field":"fact-kind","equals":"intent-source"}]}},{"name":"value-requirements","subject":"Original full acceptance requirements.","objective":"Distinguish the measured structural facet from all workflow safeguards.","acceptance":"Requirements are source text, not proof they passed.","from":"value-evidence-facts","filter":{"predicates":[{"field":"fact-kind","equals":"requirement"}]}},{"name":"value-outputs","subject":"Retained safe-output lifecycle facts.","objective":"Show receipts, current-at-cutoff state and originating evidence.","acceptance":"A closed output is not automatically an accepted implementation; absence of a link is unknown.","from":"value-evidence-facts","filter":{"predicates":[{"field":"fact-kind","equals":"output"}]},"order-by":[{"field":"at","direction":"desc"},{"field":"fact-id","direction":"asc"}]},{"name":"value-output-origin-evidence","subject":"Retained producer and applied safe-output evidence.","objective":"Let readers distinguish receipt-confirmed creation from corroborated tracking.","acceptance":"Tracking identities locate outputs but do not establish accepted value. Keep unavailable producer evidence explicit.","from":"value-evidence-facts","filter":{"predicates":[{"field":"fact-kind","equals":"output-evidence"}]},"joins":[{"source":"value-outputs","type":"inner","on":[{"left":"report-id","right":"report-id"},{"left":"parent-id","right":"fact-id"}],"fields":[{"field":"label","as":"output-label"},{"field":"url","as":"output-url"}]}]},{"name":"value-implementations","subject":"Accepted implementations and native before/after effects.","objective":"Expose delivery time and immutable acceptance evidence.","acceptance":"Do not equate acceptance with full quality verification or omit negative effects.","from":"value-evidence-facts","filter":{"predicates":[{"field":"fact-kind","equals":"implementation"}]},"order-by":[{"field":"at","direction":"desc"},{"field":"fact-id","direction":"asc"}]},{"name":"value-output-trails","subject":"Explicit output-to-implementation edges.","objective":"Make the trail from a proposal to an accepted measured change inspectable.","acceptance":"Use retained dated edges only. Many-to-many links do not duplicate headline counts or values.","from":"value-evidence-facts","filter":{"predicates":[{"field":"fact-kind","equals":"output-implementation"}]},"joins":[{"source":"value-outputs","type":"inner","on":[{"left":"report-id","right":"report-id"},{"left":"parent-id","right":"fact-id"}],"fields":[{"field":"label","as":"output-label"},{"field":"url","as":"output-url"}]},{"source":"value-implementations","type":"inner","on":[{"left":"report-id","right":"report-id"},{"left":"related-id","right":"fact-id"}],"fields":[{"field":"label","as":"implementation-label"},{"field":"url","as":"implementation-url"},{"field":"value","as":"implementation-value"},{"field":"at","as":"trail-accepted-at"}]}]},{"name":"value-implementation-files","subject":"Measured implementation files and retained lineage sources.","objective":"Link to exact Git facts rather than only a repository tree.","acceptance":"No URL is reconstructed from an unrelated revision. Preserve before, after and replacement file evidence.","from":"value-evidence-facts","filter":{"predicates":[{"field":"fact-kind","in":["implementation-evidence","implementation-lineage"]}]},"joins":[{"source":"value-implementations","type":"inner","on":[{"left":"report-id","right":"report-id"},{"left":"parent-id","right":"fact-id"}],"fields":[{"field":"label","as":"implementation-label"},{"field":"url","as":"implementation-url"}]}]},{"name":"value-quality-checks","subject":"Explicit independent verification checks.","objective":"Keep unverified behavior, tests and other safeguards visible.","acceptance":"Missing or not-verified is not a passing check.","from":"value-evidence-facts","filter":{"predicates":[{"field":"fact-kind","equals":"quality-check"}]}},{"name":"value-limitations","subject":"Retained evidence and attribution limitations.","objective":"Qualify claims without inventing completeness.","acceptance":"Treat source limitations as untrusted text and never suppress them.","from":"value-evidence-facts","filter":{"predicates":[{"field":"fact-kind","equals":"limitation"}]}},{"name":"value-snapshot-items","subject":"Actual counted items at an independent immutable snapshot.","objective":"Open exact per-item evidence from the plotted observation.","acceptance":"Only retained items are shown. Missing item evidence must not look like an empty measured population.","from":"value-evidence-facts","filter":{"predicates":[{"field":"fact-kind","equals":"snapshot-item"}]},"joins":[{"source":"value-snapshots","type":"inner","on":[{"left":"report-id","right":"report-id"},{"left":"parent-id","right":"fact-id"}],"fields":[{"field":"snapshot-route","as":"snapshot-route"},{"field":"at","as":"snapshot-at"}]}]},{"name":"audit-event-summary-buckets","subject":"Aggregate high- and medium-severity audit events with the same severity and summary by workflow.","objective":"Select recurring high- or medium-severity audit summaries for run-level investigation.","acceptance":"Each bucket's event count is traceable to retained audit or tool observations with the same campaign, severity, workflow, and summary; missing workflow attribution stays unknown, and a count alone does not verify impact.","description":"High- and medium-severity audit event counts grouped by severity, workflow, and shared summary.","from":"audits","union":["tools"],"filter":{"predicates":[{"field":"event-type","in":["audit.finding","audit.observability","audit.recommendation","audit.missing_tool","audit.missing_data","audit.noop","audit.mcp_failure","skill.invoked"]},{"field":"event-status","in":["high","medium"]}]},"joins":[{"source":"workflows","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"}],"fields":[{"field":"campaign","as":"campaign"}]}],"aggregate":{"by":["campaign","event-status","workflow","event-summary"],"values":[{"field":"event","as":"events","reducer":"count"}]},"select":[{"field":"campaign"},{"field":"event-status"},{"field":"workflow"},{"field":"event-summary"},{"field":"events"}],"order-by":[{"field":"event-status","direction":"asc"},{"field":"events","direction":"desc"},{"field":"workflow","direction":"asc"},{"field":"event-summary","direction":"asc"}]},{"name":"campaign-workflows","subject":"List campaign-owned orchestrator and worker workflows with database-backed execution totals.","objective":"Choose an active campaign workflow whose observed execution warrants inspection.","acceptance":"Listed workflows match active declared orchestrator or worker inventory entries; runs and AI Credits agree with the selected-horizon inventory, and absence is not evidence of disabled authority or no executions. Rollout mode is context, not permission to change policy.","description":"Campaign workflows projected from lean canonical inventory, with shared declaration names and active-only workflow drill-down links.","from":"campaign-workflow-inventory","filter":{"predicates":[{"field":"workflow-active","equals":"true"}]},"compute":[{"as":"workflow-identity","function":"concat","args":[{"field":"repository"},{"value":":"},{"field":"workflow"}]},{"as":"encoded-workflow","function":"url-encode","args":[{"field":"workflow-identity"}]},{"as":"workflow-dashboard-href","function":"concat","args":[{"value":"#page-workflow-runtime?workflow="},{"field":"encoded-workflow"}]},{"as":"workflow-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"workflow-display-name"},{"value":" workflow dashboard"}]},{"as":"workflow-dashboard-link","function":"dashboard-link","args":[{"field":"workflow-link"},{"field":"workflow-dashboard-href"},{"field":"workflow-dashboard-label"},{"field":"workflow-identity"}]}],"select":[{"field":"campaign"},{"field":"campaign-display-name","as":"campaign-name"},{"field":"organization"},{"field":"repository"},{"field":"workflow"},{"field":"workflow-display-name","as":"workflow-name"},{"field":"workflow-role"},{"field":"rollout-mode"},{"field":"workflow-active"},{"field":"runs"},{"field":"aic"},{"field":"repository-dashboard-link","as":"repository-link"},{"field":"workflow-dashboard-link","as":"workflow-link"}],"order-by":[{"field":"campaign-name","direction":"asc"},{"field":"workflow-role","direction":"asc"},{"field":"workflow-name","direction":"asc"}]},{"name":"campaign-repository-declarations","subject":"List active declared campaign workflows and their owning repositories without execution evidence.","objective":"Inspect campaign repository topology without computing unused run totals or import coverage.","acceptance":"Preserve active orchestrator and worker identities, display names, rollout context, links, and ordering. Declaration counts are not target enrollment, dispatch coverage, or execution totals. Empty inventory and unavailable workflow evidence remain distinct.","description":"Declaration-only repository topology. Run totals and import-evidence quality belong to execution views, not this inventory.","from":"campaign-workflow-declarations","filter":{"predicates":[{"field":"workflow-active","equals":"true"}]},"select":[{"field":"campaign"},{"field":"campaign-display-name","as":"campaign-name"},{"field":"organization"},{"field":"repository-slug","as":"repository"},{"field":"workflow"},{"field":"workflow-display-name","as":"workflow-name"},{"field":"workflow-role"},{"field":"declared-mode","as":"rollout-mode"},{"field":"workflow-active"},{"field":"repository-dashboard-link","as":"repository-link"}],"order-by":[{"field":"repository","direction":"asc"},{"field":"workflow","direction":"asc"}]},{"name":"campaign-repository-inventory","subject":"Present declared campaign repository topology in workflow display order.","objective":"Filter and search projected repository coordinates and workflow names without time-filtering structural declarations.","acceptance":"Preserve the campaign workflow list's stable ordering and declaration-only evidence quality; runtime horizons must not remove declared workflows.","from":"campaign-repository-declarations","order-by":[{"field":"campaign-name","direction":"asc"},{"field":"workflow-role","direction":"asc"},{"field":"workflow-name","direction":"asc"}]},{"name":"campaign-reports","subject":"Project retained outcomes into campaign-addressable report evidence.","objective":"Identify a campaign report whose durable outcome record needs follow-up.","acceptance":"Each report's campaign, title, source link, observation time, and disposition match its retained outcome; missing status is labeled unknown rather than accepted or resolved, and report production is not verified impact.","description":"Campaign outcome reports with database-backed disposition fields.","from":"outcomes","compute":[{"as":"report-status","function":"coalesce","args":[{"field":"outcome-status"},{"field":"outcome-state"},{"value":"unknown"}]}],"select":[{"field":"campaign"},{"field":"safe-output"},{"field":"outcome-title"},{"field":"outcome-summary"},{"field":"report-status","as":"outcome-status"},{"field":"rollout-mode"},{"field":"engine"},{"field":"engine-version"},{"field":"requested-model"},{"field":"resolved-model"},{"field":"outcome-category"},{"field":"observed-at"},{"field":"external-link"}],"order-by":[{"field":"observed-at","direction":"desc"},{"field":"outcome-title","direction":"asc"}]},{"name":"campaign-worker-issues","subject":"Project issue outcomes created by campaign worker workflows.","objective":"Choose a campaign worker issue whose current recorded disposition needs review.","acceptance":"Include only issues whose producing run joins declared worker inventory on organization, repository, and workflow, even when the issue lands elsewhere. Preserve campaign and role across Activity imports. Retain run and status evidence; missing closure details stay unknown and closure is not proof of resolution.","description":"Campaign-addressable issue outcomes restricted to declared worker workflows.","from":"outcomes","joins":[{"source":"workflows","type":"inner","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"}],"fields":[{"field":"workflow-role","as":"declared-workflow-role"}]}],"filter":{"predicates":[{"field":"outcome-category","equals":"issue"},{"field":"declared-workflow-role","equals":"worker"}]},"select":[{"field":"campaign"},{"field":"organization"},{"field":"repository"},{"field":"safe-output"},{"field":"outcome-number"},{"field":"outcome-title","as":"event-summary"},{"field":"outcome-title"},{"field":"outcome-summary"},{"field":"outcome-status"},{"field":"outcome-state"},{"field":"issue-state"},{"field":"issue-closed"},{"field":"issue-state-reason"},{"field":"issue-status"},{"field":"issue-closing-status"},{"field":"issue-status-detail"},{"field":"issue-closed-at"},{"field":"issue-status-observed-at"},{"field":"outcome-category","as":"safe-output-type"},{"field":"workflow"},{"field":"workflow-name"},{"field":"run"},{"field":"observed-at"},{"field":"issue-link"},{"field":"external-link"},{"field":"run-link"}],"order-by":[{"field":"observed-at","direction":"desc"}]},{"name":"campaign-issue-tab-counts","subject":"Count the retained worker issues available for each campaign Reports tab.","objective":"Decide whether a campaign has retained worker issue reports to inspect.","acceptance":"For each returned campaign, items equals the number of rows in campaign-worker-issues for that campaign in the same horizon; missing campaigns are not treated as zero issues or verified resolution.","description":"One campaign row with the number of retained issue outcomes produced by campaign workers.","from":"campaign-worker-issues","aggregate":{"by":["campaign"],"values":[{"field":"campaign","as":"items","reducer":"count"}]}},{"name":"campaign-readme-orchestrators","subject":"Resolve one repository link for each campaign README from its declared orchestrator workflow.","objective":"Locate the declared orchestrator repository to contextualize a campaign README.","acceptance":"Each returned campaign and repository link traces to a declared orchestrator workflow; missing or multiple declarations are reported as uncertain rather than inventing a canonical repository.","from":"workflows","filter":{"predicates":[{"field":"workflow-role","equals":"orchestrator"}]},"select":[{"field":"campaign"},{"field":"repository-link"}]},{"name":"campaign-readme-details","subject":"Present retained campaign README content with its repository-relative link context.","objective":"Open the campaign's retained README in its declared repository context before relying on its guidance.","acceptance":"The README text and path match the campaign record and any repository link resolves through a declared orchestrator; absent content or repository linkage remains unavailable, not inferred.","from":"campaigns","joins":[{"source":"campaign-readme-orchestrators","type":"left","on":[{"left":"campaign","right":"campaign"}],"fields":[{"field":"repository-link","as":"repository-link"}]}],"select":[{"field":"campaign"},{"field":"campaign-readme"},{"field":"campaign-readme-path"},{"field":"repository-link"}]},{"name":"campaign-memory-campaigns","subject":"Provide the registered campaigns whose repository memory can be browsed together.","objective":"Choose a registered campaign for repository-memory inspection.","acceptance":"Each campaign identity and display name matches the retained campaign registry in the selected scope; listing a campaign does not establish that memory observations exist or are complete.","description":"Registered campaigns ordered for the all-campaign repository-memory browser.","from":"campaigns","select":[{"field":"campaign"},{"field":"campaign-name"}],"order-by":[{"field":"campaign-name","direction":"asc"}]},{"name":"campaign-performance-baseline-totals","subject":"Establish a selected-horizon campaign baseline from concluded run attempts while keeping reliability, unverified production, and efficiency as separate facts.","objective":"Select campaigns whose retained run reliability, output production, or AI Credit efficiency merits closer examination.","acceptance":"Concluded and successful attempts, outputs, and mean AI Credits reconcile to filtered retained runs; absent denominators or costs stay unknown. Produced outputs are unverified, not operational value.","description":"Canonical campaign run attempts aggregated into bounded selected-horizon baseline totals without treating runtime success or produced outputs as operational value.","from":"campaign-runs","compute":[{"as":"run-attempt-identity","function":"concat","args":[{"field":"run"},{"value":":"},{"field":"run-attempt"}]},{"as":"positive-aic","function":"greater-than","args":[{"field":"aic-total"},{"value":0}]}],"aggregate":{"by":["campaign"],"values":[{"field":"run-attempt-identity","as":"concluded-runs","reducer":"count","filter":{"predicates":[{"field":"status","in":["success","failure","cancelled","timed-out","action-required","neutral","skipped","stale","startup-failure"]}]}},{"field":"run-attempt-identity","as":"successful-runs","reducer":"count","filter":{"predicates":[{"field":"status","equals":"success"}]}},{"field":"safe-items-count","as":"runs-with-output-evidence","reducer":"count","filter":{"predicates":[{"field":"status","equals":"success"}]}},{"field":"safe-items-count","as":"produced-outputs","reducer":"sum","filter":{"predicates":[{"field":"status","equals":"success"}]}},{"field":"aic-total","as":"aic-per-successful-run","reducer":"mean","filter":{"predicates":[{"field":"status","equals":"success"},{"field":"positive-aic","equals":true}]}}]}},{"name":"campaign-performance-baseline","subject":"Turn each campaign's selected-horizon baseline totals into deterministic reliability and production signals with an explicit successful-run efficiency fact.","objective":"Decide which campaign baseline signal needs run- or output-level verification next.","acceptance":"Success-rate and signal labels follow the retained totals and their explicit denominators; no concluded attempts or output evidence is distinguished from zero verified impact, and AI Credits per successful run remain a separate cost fact rather than a value score.","description":"A bounded, explainable baseline that distinguishes runtime reliability, unverified output production, and AI Credit efficiency.","from":"campaign-performance-baseline-totals","compute":[{"as":"success-rate","function":"quotient","args":[{"field":"successful-runs"},{"field":"concluded-runs"}]},{"as":"success-rate-display","function":"format-percent","args":[{"field":"success-rate"}]},{"as":"success-rate-percent","function":"product","args":[{"field":"success-rate"},{"value":100}]},{"as":"has-concluded-runs","function":"greater-than","args":[{"field":"concluded-runs"},{"value":0}]},{"as":"has-unsuccessful-runs","function":"greater-than","args":[{"field":"concluded-runs"},{"field":"successful-runs"}]},{"as":"observed-reliability-signal","function":"if","args":[{"field":"has-unsuccessful-runs"},{"value":"Unsuccessful runs observed"},{"value":"No unsuccessful runs observed"}]},{"as":"reliability-signal","function":"if","args":[{"field":"has-concluded-runs"},{"field":"observed-reliability-signal"},{"value":"No concluded runs observed"}]},{"as":"has-output-evidence","function":"greater-than","args":[{"field":"runs-with-output-evidence"},{"value":0}]},{"as":"has-produced-outputs","function":"greater-than","args":[{"field":"produced-outputs"},{"value":0}]},{"as":"observed-production-signal","function":"if","args":[{"field":"has-produced-outputs"},{"value":"Outputs produced; acceptance unverified"},{"value":"No outputs observed"}]},{"as":"production-signal","function":"if","args":[{"field":"has-output-evidence"},{"field":"observed-production-signal"},{"value":"Output evidence unavailable"}]}],"select":[{"field":"campaign"},{"field":"concluded-runs"},{"field":"successful-runs"},{"field":"success-rate"},{"field":"success-rate-display"},{"field":"success-rate-percent"},{"field":"reliability-signal"},{"field":"produced-outputs"},{"field":"production-signal"},{"field":"aic-per-successful-run"}]},{"name":"campaign-problem-runs","subject":"List retained failed runs for campaign problem investigation.","objective":"Choose a recent failed campaign run to investigate with its diagnostic evidence.","acceptance":"Each row corresponds to a retained campaign run with a declared failure, startup-failure, stale, or timed-out status; campaign-problem-run-evidence orders matching rows newest first. Absence is not proof of healthy execution or complete ingestion.","description":"Private failed-run input with retained diagnostic metadata; the evidence consumer orders only runs matching current runtime problems.","from":"campaign-runs","filter":{"predicates":[{"field":"status","in":["failure","startup-failure","stale","timed-out"]}]}},{"name":"campaign-problem-runtime-failures","subject":"Select current failing runtime partitions without presentation ordering.","objective":"Retain the exact current-failure eligibility needed by the problem evidence join.","acceptance":"A latest failure streak is a nonnegative integer, so failure-count at least one is equivalent to has-current-failure; missing or incomplete runtime evidence remains unknown.","description":"Private unsorted failure partitions for problem evidence; ordering is supplied by the retained failed runs.","from":"campaign-runtime-health-groups","filter":{"predicates":[{"field":"failure-count","gte":1}]},"compute":[{"as":"problem-kind","function":"coalesce","args":[{"value":"failure"},{"value":"failure"}]}]},{"name":"campaign-problem-runtime-partitions","subject":"Project current runtime problem keys and diagnoses for the failed-run evidence join.","objective":"Avoid sorting and retaining unused runtime problem presentation fields.","acceptance":"Retain both current failures and unobserved orchestrators, including their metadata and duplicate-key failure semantics; this projection does not establish health or root cause.","description":"Private compact equivalent of campaign-runtime-problems for equality enrichment, not presentation.","from":"campaign-problem-runtime-failures","union":["campaign-unobserved-orchestrators"],"select":[{"field":"campaign"},{"field":"workflow"},{"field":"runtime-repository"},{"field":"failure-count"},{"field":"problem-kind"}]},{"name":"campaign-problem-run-evidence","subject":"Attach the current campaign runtime problem summary to each retained failed Run for that partition.","objective":"Inspect the failure count and problem kind alongside a failed run without inferring its root cause.","acceptance":"Each returned row joins a retained failed run to a runtime problem on campaign, workflow, and runtime repository; the inner join drops unmatched runs, so compare with campaign-problem-runs before interpreting absence as no problem.","description":"Failed campaign runs annotated with the failure-count and problem-kind of their active runtime problem, one row per retained failed Run.","from":"campaign-problem-runs","joins":[{"source":"campaign-problem-runtime-partitions","type":"inner","on":[{"left":"campaign","right":"campaign"},{"left":"workflow","right":"workflow"},{"left":"runtime-repository","right":"runtime-repository"}],"fields":[{"field":"failure-count","as":"failure-count"},{"field":"problem-kind","as":"problem-kind"}]}],"order-by":[{"field":"started-at","direction":"desc"},{"field":"run","direction":"desc"}]},{"name":"campaign-problem-latest-target-runs","subject":"Identify the most recent retained failed Run for each campaign workflow target repository.","objective":"Select the latest retained failed run identity for each campaign workflow and target partition.","acceptance":"For every returned campaign, workflow, runtime repository, and target repository, latest-target-run agrees with the maximum retained failed run identity in that partition; a missing partition is not a healthy target.","description":"One row per campaign workflow and target repository with its most recent retained failed Run identity.","from":"campaign-problem-run-evidence","aggregate":{"by":["campaign","workflow","runtime-repository","target-repository"],"values":[{"field":"run","as":"latest-target-run","reducer":"max"}]}},{"name":"campaign-problem-error-groups","subject":"Cluster retained failed Run evidence by workflow, runtime repository, target repository, and error signature so repeated identical failures for one target collapse into one diagnosable group.","objective":"Rank repeated target-specific error signatures for investigation without merging unrelated failures.","acceptance":"Occurrence-count and latest-run match retained failed runs grouped by campaign, workflow, repositories, problem kind, and signature; unknown signatures may group together. Counts do not prove a root cause.","description":"One row per distinct target repository and error signature within a campaign runtime problem partition, with an occurrence count and the most recent matching Run identity for follow-up.","from":"campaign-problem-run-evidence","aggregate":{"by":["campaign","campaign-name","workflow","workflow-name","workflow-role","runtime-repository","target-repository","rollout-mode","failure-count","problem-kind","error-signature","error-signature-label"],"values":[{"field":"run","as":"occurrence-count","reducer":"count"},{"field":"run","as":"latest-run","reducer":"max"}]}},{"name":"campaign-current-problem-error-groups","subject":"Keep only the newest error signature for each campaign workflow target repository.","objective":"Focus investigation on the signature associated with the latest retained failed run per target.","acceptance":"Each returned group joins campaign-problem-latest-target-runs on campaign, workflow, runtime repository, and latest run ID; target repository is not a join key, so verify target identity against underlying runs before claiming one current signature per target.","description":"Current target-specific error groups whose representative Run is the target repository's most recent retained failed Run.","from":"campaign-problem-error-groups","joins":[{"source":"campaign-problem-latest-target-runs","type":"inner","on":[{"left":"campaign","right":"campaign"},{"left":"workflow","right":"workflow"},{"left":"runtime-repository","right":"runtime-repository"},{"left":"latest-run","right":"latest-target-run"}],"fields":[{"field":"latest-target-run","as":"current-target-run"}]}]},{"name":"campaign-problem-items","subject":"Attach the most recent representative Run evidence to each distinct campaign runtime problem error signature.","objective":"Open the representative failed run and target for each current campaign problem group.","acceptance":"Check joined run-link, run ID, campaign, workflow, and runtime repository; verify target against run evidence (not a join key). Unobserved orchestrators need inventory review. Missing evidence remains unknown; rollout mode does not authorize policy changes.","description":"Current campaign runtime problems represented by the newest error signature for each target repository, with its effective rollout mode, an occurrence count, the most recent matching failed Run, and a repair prompt.","from":"campaign-current-problem-error-groups","joins":[{"source":"campaign-problem-run-evidence","type":"inner","on":[{"left":"campaign","right":"campaign"},{"left":"workflow","right":"workflow"},{"left":"runtime-repository","right":"runtime-repository"},{"left":"latest-run","right":"run"}],"fields":[{"field":"started-at","as":"started-at"},{"field":"run","as":"run"},{"field":"status","as":"status"},{"field":"status-detail","as":"status-detail"},{"field":"failure-job","as":"failure-job"},{"field":"failure-message","as":"failure-message"},{"field":"failure-step","as":"failure-step"},{"field":"failure-log","as":"failure-log"},{"field":"gh-aw-version","as":"gh-aw-version"},{"field":"engine","as":"engine"},{"field":"engine-version","as":"engine-version"},{"field":"requested-model","as":"requested-model"},{"field":"resolved-model","as":"resolved-model"},{"field":"run-link","as":"run-link"},{"field":"repository-link","as":"repository-link"},{"field":"workflow-link","as":"workflow-link"},{"field":"workflow-source-link","as":"workflow-source-link"}]}],"union":["campaign-unobserved-orchestrators"],"compute":[{"as":"problem-title","function":"coalesce","args":[{"field":"failure-message"},{"field":"status-detail"},{"field":"error-signature-label"},{"field":"workflow-name"}]},{"as":"_runtime-repository-encoded","function":"url-encode","args":[{"field":"runtime-repository"}]},{"as":"_runtime-repository-href","function":"concat","args":[{"value":"#page-repository-detail?repository="},{"field":"_runtime-repository-encoded"}]},{"as":"runtime-repository-link","function":"dashboard-link","args":[{"field":"repository-link"},{"field":"_runtime-repository-href"},{"field":"runtime-repository"},{"field":"runtime-repository"}]},{"as":"_target-repository-encoded","function":"url-encode","args":[{"field":"target-repository"}]},{"as":"_target-repository-href","function":"concat","args":[{"value":"#page-repository-detail?repository="},{"field":"_target-repository-encoded"}]},{"as":"target-repository-link","function":"dashboard-link","args":[{"field":"target-repository"},{"field":"_target-repository-href"},{"field":"target-repository"}]}],"order-by":[{"field":"workflow-name","direction":"asc"},{"field":"runtime-repository","direction":"asc"},{"field":"occurrence-count","direction":"desc"},{"field":"started-at","direction":"desc"}]},{"name":"campaign-problem-tab-counts","subject":"Count the current runtime problem items available for each campaign Problems tab.","objective":"Determine whether the campaign has current retained failure groups requiring review.","acceptance":"For every returned campaign, items equals the number of campaign-problem-items rows in the same horizon; a missing count does not establish zero failures or healthy execution.","description":"One campaign row with the number of current runtime problem groups.","from":"campaign-problem-items","aggregate":{"by":["campaign"],"values":[{"field":"campaign","as":"items","reducer":"count"}]}},{"name":"campaign-baseline-successful-runs","subject":"Project successful concluded attempts from the selected-horizon campaign baseline.","objective":"Show the successful share of concluded runs without implying verified impact.","acceptance":"Counts reconcile to campaign-performance-baseline-totals; missing campaigns do not imply zero runs.","from":"campaign-performance-baseline-totals","compute":[{"as":"outcome","function":"concat","args":[{"value":"Successful attempts"},{"value":""}]}],"select":[{"field":"campaign"},{"field":"outcome"},{"field":"successful-runs","as":"runs"}]},{"name":"campaign-baseline-other-runs","subject":"Project non-successful concluded attempts from the selected-horizon campaign baseline.","objective":"Show the remaining concluded runs for reliability review.","acceptance":"Runs equal concluded-runs minus successful-runs; the category includes every other concluded status, not just failures.","from":"campaign-performance-baseline-totals","compute":[{"as":"outcome","function":"concat","args":[{"value":"Other concluded attempts"},{"value":""}]},{"as":"other-runs","function":"difference","args":[{"field":"concluded-runs"},{"field":"successful-runs"}]}],"select":[{"field":"campaign"},{"field":"outcome"},{"field":"other-runs","as":"runs"}]},{"name":"campaign-baseline-outcome-distribution","subject":"Compare successful and other concluded attempts in the selected horizon.","objective":"Spot campaign run reliability that needs inspection.","acceptance":"Successful and other counts sum to concluded attempts; neither runtime result nor output production establishes operational value.","from":"campaign-baseline-successful-runs","union":["campaign-baseline-other-runs"]},{"name":"campaign-audit-summary-plot-inventory","subject":"Describe the rendered audit-summary chart using the shared campaign Insights plot contract.","objective":"Find campaigns with retained high- or medium-severity audit summaries worth reviewing.","acceptance":"Each campaign's bucket count equals its retained audit-event-summary-buckets rows; the count describes displayed groups, not distinct incidents or confirmed harm, and missing buckets are not proof of safety.","description":"One plot-inventory row per campaign when its high- and medium-severity audit summary chart has data.","from":"audit-event-summary-buckets","aggregate":{"by":["campaign"],"values":[{"field":"event-summary","as":"buckets","reducer":"count"}]}},{"name":"campaign-insight-plot-inventory","subject":"Inventory every plot rendered on each campaign Insights page through one reusable plot contract.","objective":"Choose an available campaign Insights plot to inspect its underlying evidence.","acceptance":"Each plot entry is supplied by the audit summary plot inventory for the same campaign; experimental operational-value evidence is excluded, no plot count is treated as outcome quality, and unavailable evidence is not synthesized into a plot.","description":"One campaign row per rendered Insights plot, independent of the plot's data source or renderer.","from":"campaign-audit-summary-plot-inventory"},{"name":"campaign-insight-tab-counts","subject":"Count the plots declared by the shared campaign Insights plot inventory.","objective":"Determine whether a campaign has evidence-backed Insights plots to inspect.","acceptance":"For every returned campaign, items equals its rows in campaign-insight-plot-inventory for the same horizon; absent rows do not establish absent value, and plot counts do not measure impact.","description":"One campaign row with the number of rendered Insights plots, independent of plot type.","from":"campaign-insight-plot-inventory","aggregate":{"by":["campaign"],"values":[{"field":"campaign","as":"items","reducer":"count"}]}},{"name":"workflow-ordered-runs","subject":"Order retained run attempts within each workflow by their observed start time.","objective":"Identify each workflow's latest execution without importing event coverage or outcome totals.","acceptance":"The first chronological attempt in each workflow partition has no preceding run delta; break timestamp ties by run ID and attempt, and use creation time for queued runs.","from":"runs","compute":[{"as":"latest-run-at","function":"coalesce","args":[{"field":"started-at"},{"field":"created-at"}]}],"window":[{"operation":"change","field":"run","as":"preceding-run-delta","mode":"absolute","groupby":["organization","repository","workflow"],"order-by":[{"field":"latest-run-at","direction":"desc"},{"field":"run","direction":"desc"},{"field":"run-attempt","direction":"desc"}]}],"select":[{"field":"organization"},{"field":"repository"},{"field":"workflow"},{"field":"run"},{"field":"run-attempt"},{"field":"latest-run-at"},{"field":"run-status"},{"field":"run-conclusion"},{"field":"preceding-run-delta"},{"field":"run-link"}]},{"name":"workflow-latest-runs","subject":"Project the latest retained run attempt for each workflow.","objective":"Expose each workflow's latest observed execution state without implying aggregate outcomes.","acceptance":"Select only the first chronologically ordered attempt per workflow; preserve queued and in-progress states instead of treating unknown conclusions as failures.","from":"workflow-ordered-runs","filter":{"predicates":[{"field":"preceding-run-delta","equals":"unknown"}]},"compute":[{"as":"observed-conclusion","function":"coalesce","args":[{"field":"run-conclusion"},{"value":"unknown"}]},{"as":"completed","function":"equals-any","args":[{"field":"run-status"},{"value":"completed"}]},{"as":"latest-run-status","function":"if","args":[{"field":"completed"},{"field":"observed-conclusion"},{"field":"run-status"}]}],"select":[{"field":"organization"},{"field":"repository"},{"field":"workflow"},{"field":"run"},{"field":"run-attempt"},{"field":"latest-run-at"},{"field":"latest-run-status"},{"field":"run-link"}]},{"name":"workflow-list-preview","subject":"Show workflow declarations while latest-run evidence is still loading.","objective":"Make workflow identities and drill links available before retained runs are evaluated.","acceptance":"Preserve every declared workflow and its drill link; leave latest-run fields absent until the complete projection arrives.","from":"workflows","compute":[{"as":"repository-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"workflow-label","function":"concat","args":[{"field":"repository-coordinate"},{"value":":"},{"field":"workflow"}]},{"as":"workflow-display-name","function":"coalesce","args":[{"field":"workflow-name"},{"field":"workflow"}]},{"as":"declared-role","function":"coalesce","args":[{"field":"workflow-role"},{"value":"standalone"}]},{"as":"declared-mode","function":"coalesce","args":[{"field":"rollout-mode"},{"value":"unknown"}]},{"as":"declared-registration","function":"coalesce","args":[{"field":"workflow-active"},{"value":"unknown"}]},{"as":"encoded-workflow","function":"url-encode","args":[{"field":"workflow-label"}]},{"as":"workflow-dashboard-href","function":"concat","args":[{"value":"#page-workflow-runtime?workflow="},{"field":"encoded-workflow"}]},{"as":"workflow-dashboard-link","function":"dashboard-link","args":[{"field":"workflow-link"},{"field":"workflow-dashboard-href"},{"field":"workflow-display-name"},{"field":"workflow-label"}]}],"select":[{"field":"organization"},{"field":"repository-coordinate","as":"repository"},{"field":"workflow"},{"field":"workflow-display-name","as":"workflow-name"},{"field":"workflow-label"},{"field":"campaign-name"},{"field":"declared-role","as":"workflow-role"},{"field":"declared-mode","as":"rollout-mode"},{"field":"declared-registration","as":"workflow-active"},{"field":"repository-link"},{"field":"workflow-dashboard-link","as":"workflow-link"}],"order-by":[{"field":"repository","direction":"asc"},{"field":"workflow","direction":"asc"}]},{"name":"workflow-list","subject":"List declared workflows in latest observed run order.","objective":"Open a dedicated workflow page from a lightweight inventory with its latest execution status.","acceptance":"Preserve textual run identities and keep unobserved workflows last with an explicit missing-run state; use only workflow declarations and retained runs, not event coverage or aggregate success/failure counters.","from":"workflows","joins":[{"source":"workflow-latest-runs","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"}],"fields":[{"field":"run","as":"latest-run"},{"field":"latest-run-at","as":"latest-run-at"},{"field":"latest-run-status","as":"observed-run-status"},{"field":"run-link","as":"run-link"}]}],"compute":[{"as":"repository-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"workflow-label","function":"concat","args":[{"field":"repository-coordinate"},{"value":":"},{"field":"workflow"}]},{"as":"workflow-display-name","function":"coalesce","args":[{"field":"workflow-name"},{"field":"workflow"}]},{"as":"declared-role","function":"coalesce","args":[{"field":"workflow-role"},{"value":"standalone"}]},{"as":"declared-mode","function":"coalesce","args":[{"field":"rollout-mode"},{"value":"unknown"}]},{"as":"declared-registration","function":"coalesce","args":[{"field":"workflow-active"},{"value":"unknown"}]},{"as":"observed-run-id","function":"coalesce","args":[{"field":"latest-run"},{"value":"0"}]},{"as":"has-observed-run","function":"greater-than","args":[{"field":"observed-run-id"},{"value":0}]},{"as":"latest-run-status","function":"coalesce","args":[{"field":"observed-run-status"},{"value":"No observed run"}]},{"as":"encoded-workflow","function":"url-encode","args":[{"field":"workflow-label"}]},{"as":"workflow-dashboard-href","function":"concat","args":[{"value":"#page-workflow-runtime?workflow="},{"field":"encoded-workflow"}]},{"as":"workflow-dashboard-link","function":"dashboard-link","args":[{"field":"workflow-link"},{"field":"workflow-dashboard-href"},{"field":"workflow-display-name"},{"field":"workflow-label"}]}],"select":[{"field":"organization"},{"field":"repository-coordinate","as":"repository"},{"field":"workflow"},{"field":"workflow-display-name","as":"workflow-name"},{"field":"workflow-label"},{"field":"campaign-name"},{"field":"declared-role","as":"workflow-role"},{"field":"declared-mode","as":"rollout-mode"},{"field":"declared-registration","as":"workflow-active"},{"field":"latest-run"},{"field":"latest-run-at"},{"field":"latest-run-status"},{"field":"has-observed-run"},{"field":"repository-link"},{"field":"workflow-dashboard-link","as":"workflow-link"},{"field":"run-link"}],"order-by":[{"field":"has-observed-run","direction":"desc"},{"field":"latest-run-at","direction":"desc"},{"field":"repository","direction":"asc"},{"field":"workflow","direction":"asc"}]},{"name":"runs-daily-conclusions","subject":"Aggregate workflow run conclusions by UTC day for the Runs stacked area graph.","objective":"Expose changes in observed run conclusions by day for investigation.","acceptance":"Count retained runs by started-at UTC day and recorded conclusion; an empty day or missing conclusion is not evidence of healthy execution or absence of activity.","from":"runs","compute":[{"as":"day","function":"date-day","args":[{"field":"started-at"}]}],"aggregate":{"by":["day","run-conclusion"],"values":[{"field":"run","as":"runs","reducer":"count"}]}},{"name":"entity-events","subject":"Project all run-owned records for reusable cards and run drill-down.","objective":"Expose run-owned event identity, status, provenance, timestamp, and available navigation links for inspection.","acceptance":"Projected event fields and fallback URL trace to the source record; a missing link or event is not proof of no output, and event status alone does not verify downstream impact.","from":"event-base","compute":[{"as":"event-url","function":"coalesce","args":[{"field":"safe-output-url"},{"field":"correlation-id"},{"field":"implementation-pull-request-url"}]}],"select":[{"field":"organization"},{"field":"repository"},{"field":"workflow"},{"field":"run"},{"field":"run-attempt"},{"field":"event"},{"field":"event-source"},{"field":"event-type"},{"field":"event-summary"},{"field":"event-status"},{"field":"github-entity-type"},{"field":"safe-output-type"},{"field":"event-url"},{"field":"event-timestamp","as":"observed-at"},{"field":"run-link"}],"order-by":[{"field":"observed-at","direction":"desc"},{"field":"event","direction":"asc"}]},{"name":"runs-table","subject":"Show observed workflow runs in a table with execution, repository, workflow, engine, model, and navigation details.","objective":"Locate observed runs whose recorded status or conclusion needs closer inspection.","acceptance":"Show recorded run identity, status, conclusion, scope, execution metadata, and source links in newest-first order; absent runs require a freshness and coverage check, and a successful run is not proof of accepted outcomes.","description":"Observed workflow runs ordered from newest to oldest.","from":"runs","compute":[{"as":"repository-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]}],"select":[{"field":"run"},{"field":"run-status"},{"field":"run-conclusion"},{"field":"repository-coordinate"},{"field":"workflow"},{"field":"rollout-mode"},{"field":"engine"},{"field":"engine-version"},{"field":"gh-aw-version"},{"field":"requested-model"},{"field":"resolved-model"},{"field":"started-at"},{"field":"repository-link"},{"field":"workflow-link"},{"field":"run-link"}],"order-by":[{"field":"started-at","direction":"desc"}]},{"name":"workflow-aic-per-run","subject":"List declared workflows with recorded positive AI Credit costs and their average cost per run.","objective":"Identify workflows with observed run AIC averages worth investigating alongside run evidence.","acceptance":"Include only declared workflows with at least one run attempt reporting positive AIC; exclude zero and missing telemetry from the average and ranking, without interpreting missing telemetry as free execution.","description":"Workflow AI Credit averages limited to run attempts with recorded positive AIC.","from":"workflows","joins":[{"source":"workflow-aic-run-totals","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"}],"fields":[{"field":"runs","as":"observed-runs"},{"field":"aic-runs","as":"observed-aic-runs"},{"field":"aic","as":"observed-aic"}]}],"compute":[{"as":"repository-slug","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"workflow-display-name","function":"coalesce","args":[{"field":"workflow-name"},{"field":"workflow"}]},{"as":"workflow-identity","function":"concat","args":[{"field":"repository-slug"},{"value":":"},{"field":"workflow"}]},{"as":"encoded-workflow","function":"url-encode","args":[{"field":"workflow-identity"}]},{"as":"workflow-dashboard-href","function":"concat","args":[{"value":"#page-workflow-runtime?workflow="},{"field":"encoded-workflow"}]},{"as":"workflow-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"workflow-display-name"},{"value":" workflow dashboard"}]},{"as":"workflow-dashboard-link","function":"dashboard-link","args":[{"field":"workflow-link"},{"field":"workflow-dashboard-href"},{"field":"workflow-dashboard-label"},{"field":"workflow-identity"}]},{"as":"aic-per-run","function":"quotient","args":[{"field":"observed-aic"},{"field":"observed-aic-runs"}]}],"filter":{"predicates":[{"field":"observed-aic-runs","gte":1}]},"select":[{"field":"workflow-identity","as":"workflow-label"},{"field":"workflow-dashboard-link","as":"workflow-link"},{"field":"aic-per-run"}],"order-by":[{"field":"aic-per-run","direction":"desc"}],"limit":10},{"name":"dashboard-ingestion-health","subject":"Expose the current collection state for the global ingestion indicator.","objective":"Distinguish reported ingestion failure or recovery from the age of retained workflow evidence.","acceptance":"Use the authorized server collection-health classification, not cumulative failures or browser refresh time. Missing or unauthorized health remains unknown and static dashboards do not request this source.","from":"collection-health","select":[{"field":"configured"},{"field":"health"}],"limit":1},{"name":"dashboard-data-freshness","subject":"Find the newest workflow activity timestamp in retained canonical data.","objective":"Warn globally when the ingested workflow evidence has not advanced for 24 hours.","acceptance":"Use upstream updated-at, falling back to created-at, never browser import or refresh time. Missing or invalid timestamps remain unknown; inactivity alone does not prove an ingestion failure.","from":"runs","compute":[{"as":"data-at","function":"coalesce","args":[{"field":"updated-at"},{"field":"created-at"}]},{"as":"data-at-ms","function":"timestamp","args":[{"field":"data-at"}]}],"aggregate":{"values":[{"field":"data-at-ms","as":"latest-data-at","reducer":"max"}]}},{"name":"indexing-shards","subject":"List retained Activity shard import receipts.","objective":"Inspect which shards were ingested, when, and how many records they committed.","acceptance":"Show shard scope, phase, import status, import timestamp, counts and payload identity from retained receipts. Import time is not upstream freshness and missing receipts do not prove complete coverage.","from":"transactions","filter":{"predicates":[{"field":"kind","in":["ingest-normalized-jsonl","ingest-jsonl","ingest-jsonl-failed","runs","records"]}]},"select":[{"field":"id"},{"field":"payloadScope","as":"shard"},{"field":"kind"},{"field":"activity-status","as":"status"},{"field":"createdAt","as":"ingested-at"},{"field":"committedRecords","as":"committed-records"},{"field":"rawRuns","as":"workflow-runs"},{"field":"payloadHash","as":"payload-hash"}],"order-by":[{"field":"ingested-at","direction":"desc"}]},{"name":"ingestion-queued","subject":"Label the shared collection task queue depth for the administrator queue chart.","objective":"Identify total ready and scheduled collection work, including backfill tasks.","acceptance":"Show the observed shared queue depth only when collection is configured; missing or unauthorized health data is not zero pending work.","from":"collection-health","filter":{"predicates":[{"field":"configured","equals":true}]},"compute":[{"as":"queue","function":"coalesce","args":[{"value":"Ready and scheduled"},{"value":"Ready and scheduled"}]}],"select":[{"field":"queue"},{"field":"queue-depth","as":"tasks"}]},{"name":"ingestion-inflight","subject":"Label current in-flight collection tasks for the administrator queue chart.","objective":"Distinguish leased collection tasks from work awaiting collection.","acceptance":"Show the observed pending task count only when collection is configured; do not infer a count from an unavailable source.","from":"collection-health","filter":{"predicates":[{"field":"configured","equals":true}]},"compute":[{"as":"queue","function":"coalesce","args":[{"value":"In flight"},{"value":"In flight"}]}],"select":[{"field":"queue"},{"field":"pending-tasks","as":"tasks"}]},{"name":"ingestion-backfill","subject":"Label cumulative backfill run admissions for the administrator ingestion chart.","objective":"Compare historically admitted run tasks with current outstanding work without treating admissions as a live backlog.","acceptance":"Show the cumulative run task admissions only when collection is configured; this value does not decrease as tasks complete and missing health data does not imply completed backfill.","from":"collection-health","filter":{"predicates":[{"field":"configured","equals":true}]},"compute":[{"as":"queue","function":"coalesce","args":[{"value":"Backfill admitted (total)"},{"value":"Backfill admitted (total)"}]}],"select":[{"field":"queue"},{"field":"backfill-queued-run-tasks","as":"tasks"}]},{"name":"ingestion-queue-sizes","subject":"Compare current shared queue pressure, in-flight tasks, and cumulative historical backfill admissions from the administrator-only server snapshot.","objective":"Spot a growing backlog without treating past backfill admissions as outstanding work.","acceptance":"Current queue sizes and cumulative admissions come only from an authorized collection-health snapshot; unavailable state is not zero.","from":"ingestion-queued","union":["ingestion-inflight","ingestion-backfill"],"select":[{"field":"queue"},{"field":"tasks"}]},{"name":"ingestion-webhook-status","subject":"Inspect live webhook delivery counters for the current server process.","objective":"Distinguish signature validation, acknowledgements, rejections and failures without polling GitHub.","acceptance":"Show only authorized process-local counters, including in-flight requests, duplicate acknowledgements and signed pings. Counters reset on restart, are not replica totals, and do not establish GitHub-side webhook registration or completed collection. Refresh the active subscription even without canonical data changes.","from":"webhook-status","compute":[{"as":"configuration","function":"if","args":[{"field":"configured"},{"value":"Configured"},{"value":"Not configured"}]}],"limit":1},{"name":"ingestion-health","subject":"Show the current Redis-backed webhook and collection health snapshot.","objective":"Determine whether the reported collection, webhook, queue, and backfill state warrants inspecting ingestion diagnostics.","acceptance":"Report the observed health, queue, failure, success, and projection timestamps together; verify freshness and configuration before calling collection healthy, and treat missing state as unknown rather than zero.","from":"collection-health","select":[{"field":"configured"},{"field":"health"},{"field":"queue-depth"},{"field":"pending-tasks"},{"field":"dead-letters"},{"field":"oldest-pending-age"},{"field":"backfill"},{"field":"backfill-failures"},{"field":"backfill-queued-run-tasks"},{"field":"webhook-load"},{"field":"collection-load"},{"field":"failure-load"},{"field":"last-projected"},{"field":"last-webhook-at"},{"field":"last-failure-at"},{"field":"last-failure-code"},{"field":"last-success-at"},{"field":"webhook-received"},{"field":"webhook-duplicate"},{"field":"webhook-admission-failed"},{"field":"task-queued"},{"field":"task-coalesced"},{"field":"collection-succeeded"},{"field":"collection-failed"},{"field":"collection-retried"},{"field":"collection-dead-lettered"}]},{"name":"github-api-usage","subject":"Show retained GitHub API quota usage per bucket and in aggregate over the last 24 hours.","objective":"Determine whether any GitHub App installation or the CAO fleet as a whole is approaching its GitHub API rate limit.","acceptance":"Report peak usage percentages with their limits, used, and reserved counts; treat a slot without observations as unknown rather than idle, and never infer credentials from bucket identity.","from":"github-quota-usage","select":[{"field":"observed-at"},{"field":"scope"},{"field":"bucket"},{"field":"app"},{"field":"installation"},{"field":"resource"},{"field":"buckets"},{"field":"limit"},{"field":"used"},{"field":"reserved"},{"field":"usage-percent"}]},{"name":"marketplace-directory","subject":"Browse packages from configured marketplace registries.","objective":"Present a stable alphabetical directory that can be loaded in bounded pages.","acceptance":"Preserve resolver-produced provenance and package metadata. Order by package name and immutable source so continuation pages neither skip nor duplicate entries; discovery grants no installation authority.","from":"marketplace-packages","order-by":[{"field":"package-name","direction":"asc"},{"field":"package-source","direction":"asc"}]},{"name":"marketplace-package-detail","subject":"Expose normalized marketplace package records for source-coordinate lookup by the detail view.","objective":"Locate the resolver-produced package record for a source coordinate supplied by the consuming view.","acceptance":"Use the returned package-source, registry, ref, and resolved-commit fields when inspecting a matching record; the query itself does not filter by coordinate, and an absent match is not proof of package nonexistence or approval.","from":"marketplace-packages"},{"name":"friction-by-workflow","subject":"Rank workflows by observed gh-aw audit friction AI Credit totals for investigation.","objective":"Identify which repository and workflow combinations have the largest measured friction totals in retained observations.","acceptance":"Compare friction-aic and distinct runs with the underlying measurement states and attribution evidence; do not equate a ranking with avoidable cost or a validated saving.","description":"Total gh-aw audit friction cost grouped by repository and workflow.","from":"friction","compute":[{"as":"positive-aic","function":"greater-than","args":[{"field":"aic"},{"value":0}]},{"as":"repository-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"workflow-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"},{"value":":"},{"field":"workflow"}]}],"aggregate":{"by":["workflow-coordinate","repository-coordinate","workflow"],"values":[{"field":"aic","as":"friction-aic","reducer":"sum","filter":{"predicates":[{"field":"positive-aic","equals":true}]}},{"field":"run","as":"runs","reducer":"distinct-count"}]},"order-by":[{"field":"friction-aic","direction":"desc"},{"field":"workflow-coordinate","direction":"asc"}]},{"name":"friction-observations","subject":"List retained gh-aw audit friction measurements with their run context and attribution totals.","objective":"Trace each reported friction measurement to a run and distinguish counted, suppressed, and unattributed occurrences.","acceptance":"Preserve native AIC, total-run AIC, measurement state, timestamps, links, and occurrence counts; missing or unattributed evidence remains uncertain, not a verified opportunity for savings.","description":"Newest friction measurements first, preserving the native audit values and uncertainty state.","from":"friction","compute":[{"as":"repository-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"friction-percent","function":"format-percent","args":[{"field":"friction-ratio"}]}],"select":[{"field":"event-timestamp","as":"observed-at"},{"field":"repository-coordinate"},{"field":"workflow"},{"field":"run"},{"field":"run-link"},{"field":"measurement-state"},{"field":"aic"},{"field":"total-run-aic"},{"field":"friction-percent"},{"field":"counted-occurrences"},{"field":"suppressed-occurrences"},{"field":"unattributed-occurrences"}],"order-by":[{"field":"observed-at","direction":"desc"},{"field":"run","direction":"desc"}]},{"name":"indexing-shard-dates","subject":"Read the activity date encoded in each retained transaction's shard filename.","objective":"Separate source shard dates from ingestion timestamps.","acceptance":"Keep every transaction and leave absent, invalid, or structural shard dates unknown; never substitute import time.","from":"transactions","compute":[{"as":"shard-day","function":"activity-shard-day","args":[{"field":"payloadScope"}]},{"as":"missing-shard-day","function":"equals-any","args":[{"field":"shard-day"},{"value":null}]}]},{"name":"indexing-ingestion-runs","subject":"Show retained ingestion transactions at the activity date encoded in their shard filename.","objective":"Compare reported run counts by source shard activity date, independently of import time.","acceptance":"Preserve every dated transaction, including coincident dates, all kinds, and zero counts, without grouping, limits, or page filters. Omit missing or invalid shard dates; never substitute import time. Missing counts use labeled zero-position placeholders, not measured zeroes.","from":"indexing-shard-dates","filter":{"predicates":[{"field":"missing-shard-day","equals":false}]},"compute":[{"as":"workflow-runs","function":"coalesce","args":[{"field":"rawRuns"},{"value":0}]},{"as":"missing-run-count","function":"equals-any","args":[{"field":"rawRuns"},{"value":null}]},{"as":"run-count-status","function":"if","args":[{"field":"missing-run-count"},{"value":"Run count unavailable (shown at 0)"},{"value":"Reported run count"}]}],"select":[{"field":"id"},{"field":"kind"},{"field":"createdAt"},{"field":"shard-day"},{"field":"rawRuns"},{"field":"workflow-runs"},{"field":"run-count-status"}],"order-by":[{"field":"shard-day","direction":"asc"},{"field":"id","direction":"asc"}]},{"name":"indexing-campaigns-table-count","subject":"Count retained campaigns rows in the dashboard database.","objective":"Provide the retained campaigns row count for the table-count diagnostic.","acceptance":"Label the result campaigns and count campaign rows in the current database; absence or zero does not establish completeness or expected campaign coverage.","from":"campaigns","compute":[{"as":"table","function":"literal","args":[{"value":"campaigns"}]}],"aggregate":{"by":["table"],"values":[{"field":"campaign","as":"records","reducer":"count"}]}},{"name":"indexing-repositories-table-count","subject":"Count retained repositories rows in the dashboard database.","objective":"Provide the retained repositories row count for the table-count diagnostic.","acceptance":"Label the result repositories and count repository rows in the current database; absence or zero does not establish completeness or expected repository coverage.","from":"repositories","compute":[{"as":"table","function":"literal","args":[{"value":"repositories"}]}],"aggregate":{"by":["table"],"values":[{"field":"repository","as":"records","reducer":"count"}]}},{"name":"indexing-workflows-table-count","subject":"Count retained workflows rows in the dashboard database.","objective":"Provide the retained workflows row count for the table-count diagnostic.","acceptance":"Label the result workflows and count workflow rows in the current database; absence or zero does not establish completeness or expected workflow coverage.","from":"workflows","compute":[{"as":"table","function":"literal","args":[{"value":"workflows"}]}],"aggregate":{"by":["table"],"values":[{"field":"workflow","as":"records","reducer":"count"}]}},{"name":"indexing-runs-table-count","subject":"Count retained workflow runs rows in the dashboard database.","objective":"Provide the retained workflow runs row count for the table-count diagnostic.","acceptance":"Label the result workflow runs and count run rows in the current database; absence or zero does not establish completeness or expected execution volume.","from":"runs","compute":[{"as":"table","function":"literal","args":[{"value":"runs"}]}],"aggregate":{"by":["table"],"values":[{"field":"run","as":"records","reducer":"count"}]}},{"name":"indexing-domains-table-count","subject":"Count retained network domains rows in the dashboard database.","objective":"Provide the retained network domains row count for the table-count diagnostic.","acceptance":"Label the result network domains and count domain event rows in the current database; absence or zero does not prove no network activity.","from":"domains","compute":[{"as":"table","function":"literal","args":[{"value":"domains"}]}],"aggregate":{"by":["table"],"values":[{"field":"event","as":"records","reducer":"count"}]}},{"name":"indexing-tools-table-count","subject":"Count retained tool events rows in the dashboard database.","objective":"Provide the retained tool events row count for the table-count diagnostic.","acceptance":"Label the result tool events and count tool event rows in the current database; absence or zero does not prove no tool use.","from":"tools","compute":[{"as":"table","function":"literal","args":[{"value":"tools"}]}],"aggregate":{"by":["table"],"values":[{"field":"table","as":"records","reducer":"count"}]}},{"name":"indexing-audits-table-count","subject":"Count retained audit events rows in the dashboard database.","objective":"Provide the retained audit events row count for the table-count diagnostic.","acceptance":"Label the result audit events and count audit event rows in the current database; absence or zero does not prove no audit findings.","from":"audits","compute":[{"as":"table","function":"literal","args":[{"value":"audits"}]}],"aggregate":{"by":["table"],"values":[{"field":"event","as":"records","reducer":"count"}]}},{"name":"indexing-issues-table-count","subject":"Count retained issue events rows in the dashboard database.","objective":"Provide the retained issue events row count for the table-count diagnostic.","acceptance":"Label the result issue events and count issue event rows in the current database; absence or zero does not prove no issues exist.","from":"issues","compute":[{"as":"table","function":"literal","args":[{"value":"issues"}]}],"aggregate":{"by":["table"],"values":[{"field":"event","as":"records","reducer":"count"}]}},{"name":"indexing-operational-values-table-count","subject":"Count retained operational values rows in the dashboard database.","objective":"Provide the retained operational values row count for the table-count diagnostic.","acceptance":"Label the result operational values and count operational-value rows in the current database; absence or zero does not imply zero value or an evaluated outcome.","from":"operational-values","compute":[{"as":"table","function":"literal","args":[{"value":"operationalValues"}]}],"aggregate":{"by":["table"],"values":[{"field":"operational-value","as":"records","reducer":"count"}]}},{"name":"indexing-transactions-table-count","subject":"Count retained ingestion transactions rows in the dashboard database.","objective":"Provide the retained ingestion transactions row count for the table-count diagnostic.","acceptance":"Label the result ingestion transactions and count transaction IDs in the current database; absence or zero does not establish whether upstream ingestion ran.","from":"transactions","compute":[{"as":"table","function":"literal","args":[{"value":"transactions"}]}],"aggregate":{"by":["table"],"values":[{"field":"id","as":"records","reducer":"count"}]}},{"name":"indexing-database-table-counts","subject":"Count retained canonical dashboard database rows by table.","objective":"Compare the retained table row counts to identify tables needing further ingestion or coverage investigation.","acceptance":"Union the named table-count projections and report their table labels and counts; check source availability, retention, and separate transaction evidence before interpreting an empty or small table as an ingestion defect.","from":"indexing-campaigns-table-count","union":["indexing-repositories-table-count","indexing-workflows-table-count","indexing-runs-table-count","indexing-domains-table-count","indexing-tools-table-count","indexing-audits-table-count","indexing-issues-table-count","indexing-operational-values-table-count","indexing-transactions-table-count"],"order-by":[{"field":"records","direction":"desc"},{"field":"table","direction":"asc"}]},{"name":"indexing-transactions","subject":"Prepare retained ingestion transactions for card presentation.","objective":"Expose transaction identity, kind, timestamp, committed-record count, and payload hash for ingestion traceability.","acceptance":"Projected fields match retained transactions without implying successful upstream coverage from a committed count or hash alone; missing transactions require a freshness and availability check.","from":"transactions","select":[{"field":"id"},{"field":"kind"},{"field":"createdAt","as":"created-at"},{"field":"committedRecords","as":"committed-records"},{"field":"payloadHash","as":"payload-hash"}]},{"name":"engines-models-usage","subject":"Summarize run-level AIC and token usage by agent and model identifiers without treating unavailable telemetry as zero.","objective":"Locate agent and model combinations whose observed per-run AIC or token usage merits checking against individual runs.","acceptance":"Report run counts and native minimum, mean, and maximum values only for reported metrics; inspect underlying runs for per-metric telemetry coverage and context before comparing combinations, and infer neither efficiency nor outcome value from usage alone.","description":"Observed workflow runs grouped by agent ID and model ID. AIC statistics use only positive-AIC runs; token statistics use runs that reported each token metric.","from":"runs","compute":[{"as":"summary","function":"concat","args":[{"field":"agent-id"},{"value":" / "},{"field":"model-id"}]},{"as":"positive-aic","function":"greater-than","args":[{"field":"aic-total"},{"value":0}]}],"aggregate":{"by":["summary"],"values":[{"field":"run","as":"runs","reducer":"count"},{"field":"aic-total","as":"minimum-aic-per-run","reducer":"min","filter":{"predicates":[{"field":"positive-aic","equals":true}]}},{"field":"aic-total","as":"average-aic-per-run","reducer":"mean","filter":{"predicates":[{"field":"positive-aic","equals":true}]}},{"field":"aic-total","as":"maximum-aic-per-run","reducer":"max","filter":{"predicates":[{"field":"positive-aic","equals":true}]}},{"field":"input-tokens","as":"minimum-input-tokens-per-run","reducer":"min"},{"field":"input-tokens","as":"average-input-tokens-per-run","reducer":"mean"},{"field":"input-tokens","as":"maximum-input-tokens-per-run","reducer":"max"},{"field":"output-tokens","as":"minimum-output-tokens-per-run","reducer":"min"},{"field":"output-tokens","as":"average-output-tokens-per-run","reducer":"mean"},{"field":"output-tokens","as":"maximum-output-tokens-per-run","reducer":"max"},{"field":"cache-read-tokens","as":"minimum-cache-read-tokens-per-run","reducer":"min"},{"field":"cache-read-tokens","as":"average-cache-read-tokens-per-run","reducer":"mean"},{"field":"cache-read-tokens","as":"maximum-cache-read-tokens-per-run","reducer":"max"},{"field":"cache-write-tokens","as":"minimum-cache-write-tokens-per-run","reducer":"min"},{"field":"cache-write-tokens","as":"average-cache-write-tokens-per-run","reducer":"mean"},{"field":"cache-write-tokens","as":"maximum-cache-write-tokens-per-run","reducer":"max"},{"field":"reasoning-tokens","as":"minimum-reasoning-tokens-per-run","reducer":"min"},{"field":"reasoning-tokens","as":"average-reasoning-tokens-per-run","reducer":"mean"},{"field":"reasoning-tokens","as":"maximum-reasoning-tokens-per-run","reducer":"max"}]},"select":[{"field":"summary"},{"field":"runs"},{"field":"average-aic-per-run"},{"field":"minimum-aic-per-run"},{"field":"maximum-aic-per-run"},{"field":"minimum-input-tokens-per-run"},{"field":"average-input-tokens-per-run"},{"field":"maximum-input-tokens-per-run"},{"field":"minimum-output-tokens-per-run"},{"field":"average-output-tokens-per-run"},{"field":"maximum-output-tokens-per-run"},{"field":"minimum-cache-read-tokens-per-run"},{"field":"average-cache-read-tokens-per-run"},{"field":"maximum-cache-read-tokens-per-run"},{"field":"minimum-cache-write-tokens-per-run"},{"field":"average-cache-write-tokens-per-run"},{"field":"maximum-cache-write-tokens-per-run"},{"field":"minimum-reasoning-tokens-per-run"},{"field":"average-reasoning-tokens-per-run"},{"field":"maximum-reasoning-tokens-per-run"}],"order-by":[{"field":"runs","direction":"desc"},{"field":"summary","direction":"asc"}]},{"name":"skill-invocations","subject":"Select observed skill invocations for skill usage analytics.","objective":"Expose skill event identity, scope, invocation counts, and failed counts for downstream usage analysis.","acceptance":"Keep each observed event and its repository/workflow attribution with native counts; missing records or failed counts alone do not establish whether a skill was useful or available.","from":"skills","select":[{"field":"event","as":"id"},{"field":"name","as":"skill"},{"field":"organization"},{"field":"repository"},{"field":"workflow"},{"field":"invocation-count"},{"field":"failed-count"}]},{"name":"skill-invocations-by-skill","subject":"Rank skills by their observed invocation count.","objective":"Identify skills with the highest observed invocation totals for follow-up inspection.","acceptance":"Sum observed invocation counts by skill and retain the rank as a usage description; do not equate popularity with effectiveness or infer unobserved invocations.","from":"skill-invocations","aggregate":{"by":["skill"],"values":[{"field":"invocation-count","as":"invocations","reducer":"sum"}]},"order-by":[{"field":"invocations","direction":"desc"},{"field":"skill","direction":"asc"}]},{"name":"skill-invocations-by-workflow-totals","subject":"Rank workflows by their observed skill invocation count.","objective":"Produce repository-scoped workflow invocation totals for downstream skill-usage comparison.","acceptance":"Sum observed invocation counts by organization, repository, and workflow; totals describe recorded usage only, not success or expected adoption.","from":"skill-invocations","aggregate":{"by":["organization","repository","workflow"],"values":[{"field":"invocation-count","as":"invocations","reducer":"sum"}]}},{"name":"skill-invocations-by-workflow","subject":"Present workflow skill invocation totals with drill-through navigation to the workflow dashboard.","objective":"Expose observed workflow skill invocation totals with a link to inspect each workflow.","acceptance":"Each projected workflow coordinate, link, and invocation total traces to the grouped source; using a link to investigate does not establish that usage caused an outcome.","from":"skill-invocations-by-workflow-totals","compute":[{"as":"workflow-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"},{"value":":"},{"field":"workflow"}]},{"as":"encoded-workflow","function":"url-encode","args":[{"field":"workflow-coordinate"}]},{"as":"workflow-dashboard-href","function":"concat","args":[{"value":"#page-workflow-runtime?workflow="},{"field":"encoded-workflow"}]},{"as":"workflow-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"workflow-coordinate"},{"value":" workflow dashboard"}]},{"as":"workflow-link","function":"dashboard-link","args":[{"value":""},{"field":"workflow-dashboard-href"},{"field":"workflow-dashboard-label"},{"field":"workflow-coordinate"}]}],"select":[{"field":"workflow-coordinate"},{"field":"workflow-link"},{"field":"invocations"}],"order-by":[{"field":"invocations","direction":"desc"},{"field":"workflow-coordinate","direction":"asc"}]},{"name":"skill-workflow-totals","subject":"Count observed invocations for each skill and workflow.","objective":"Produce skill-by-workflow invocation totals for the downstream inventory.","acceptance":"Sum observed invocation counts by skill, organization, repository, and workflow; missing combinations are not evidence that a skill could not run.","from":"skill-invocations","aggregate":{"by":["skill","organization","repository","workflow"],"values":[{"field":"invocation-count","as":"invocations","reducer":"sum"}]}},{"name":"skill-workflow-inventory","subject":"List observed skills by workflow with drill-through navigation to the workflow dashboard.","objective":"Identify observed skill/workflow combinations and provide a workflow link for inspecting their runs.","acceptance":"Show the repository, workflow, skill, link, and observed invocation total from the grouped evidence; an absent row does not prove non-use, and a high count does not prove effectiveness.","from":"skill-workflow-totals","compute":[{"as":"repository-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"workflow-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"},{"value":":"},{"field":"workflow"}]},{"as":"encoded-workflow","function":"url-encode","args":[{"field":"workflow-coordinate"}]},{"as":"workflow-dashboard-href","function":"concat","args":[{"value":"#page-workflow-runtime?workflow="},{"field":"encoded-workflow"}]},{"as":"workflow-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"workflow-coordinate"},{"value":" workflow dashboard"}]},{"as":"workflow-link","function":"dashboard-link","args":[{"value":""},{"field":"workflow-dashboard-href"},{"field":"workflow-dashboard-label"},{"field":"workflow-coordinate"}]}],"select":[{"field":"skill"},{"field":"repository-coordinate"},{"field":"workflow"},{"field":"workflow-link"},{"field":"invocations"}],"order-by":[{"field":"invocations","direction":"desc"},{"field":"skill","direction":"asc"},{"field":"workflow","direction":"asc"}]},{"name":"experiment-assignment-coverage","subject":"Count observed run assignments for each experiment and workflow without inferring a completion target.","objective":"Expose assignment counts by experiment and workflow for investigating observed experiment coverage.","acceptance":"Count retained assignment rows in each experiment/workflow group, not distinct runs; do not invent a target, infer missing assignments from absent groups, or treat assignments as eval or grader outcomes.","from":"experiment-assignments","compute":[{"as":"workflow-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"},{"value":":"},{"field":"workflow"}]}],"aggregate":{"by":["workflow-coordinate","experiment"],"values":[{"field":"run","as":"assignments","reducer":"count"}]}},{"name":"eval-status-ledger","subject":"Inspect every explicitly classified eval answer, including UNKNOWN.","objective":"Expose retained eval observations with their workflow, run evidence and observation time.","acceptance":"Keep recorded YES, NO and UNKNOWN answers distinct; unknown or absent evidence must not imply success or failure, and historical answers are not current verdicts or validated operational outcomes.","from":"eval-observations","compute":[{"as":"_recorded-run-href","function":"link-href","args":[{"field":"evidence-link"}]},{"as":"_eval-run-href","function":"coalesce","args":[{"field":"_recorded-run-href"},{"field":"evidence-link"}]},{"as":"run-link","function":"link","args":[{"field":"_eval-run-href"},{"field":"run"}]}],"filter":{"predicates":[{"field":"eval-result","in":["YES","NO","UNKNOWN"]}]}},{"name":"eval-answer-counts","subject":"Count recorded YES, NO and UNKNOWN answers for each workflow-scoped eval.","objective":"Provide complete answer denominators before expanding each eval into three bars.","acceptance":"Keep canonical eval identities separate and count only explicitly classified observations. Select at most 33 complete eval groups, never truncate an answer group.","from":"eval-status-ledger","aggregate":{"by":["organization","repository","workflow","eval"],"values":[{"field":"eval-result","as":"answers","reducer":"count"},{"field":"eval-result","as":"yes","reducer":"count","filter":{"predicates":[{"field":"eval-result","equals":"YES"}]}},{"field":"eval-result","as":"no","reducer":"count","filter":{"predicates":[{"field":"eval-result","equals":"NO"}]}},{"field":"eval-result","as":"unknown","reducer":"count","filter":{"predicates":[{"field":"eval-result","equals":"UNKNOWN"}]}}]},"order-by":[{"field":"eval","direction":"asc"},{"field":"organization","direction":"asc"},{"field":"repository","direction":"asc"},{"field":"workflow","direction":"asc"}],"limit":33},{"name":"eval-yes-shares","subject":"Compute the YES share of each eval's recorded answers.","objective":"Expose recorded YES proportions for comparing answer categories without inferring verified operational outcomes.","acceptance":"Emit one YES row per retained canonical eval group, including zero YES counts; answer-share is yes / answers across recorded YES, NO and UNKNOWN observations. Do not count absent observations.","from":"eval-answer-counts","compute":[{"as":"eval-result","function":"literal","args":[{"value":"YES"}]},{"as":"answer-order","function":"literal","args":[{"value":0}]},{"as":"answer-share","function":"quotient","args":[{"field":"yes"},{"field":"answers"}]}]},{"name":"eval-no-shares","subject":"Compute the NO share of each eval's recorded answers.","objective":"Expose recorded NO proportions for comparing answer categories without treating historical answers as current verdicts.","acceptance":"Emit one NO row per retained canonical eval group, including zero NO counts; answer-share is no / answers across recorded YES, NO and UNKNOWN observations. Do not count absent observations.","from":"eval-answer-counts","compute":[{"as":"eval-result","function":"literal","args":[{"value":"NO"}]},{"as":"answer-order","function":"literal","args":[{"value":1}]},{"as":"answer-share","function":"quotient","args":[{"field":"no"},{"field":"answers"}]}]},{"name":"eval-unknown-shares","subject":"Compute the explicit UNKNOWN share of each eval's recorded answers.","objective":"Expose explicitly recorded UNKNOWN proportions without conflating absent observations with classified uncertainty.","acceptance":"Emit one UNKNOWN row per retained canonical eval group, including zero UNKNOWN counts; answer-share is unknown / answers across recorded YES, NO and UNKNOWN observations. Missing observations are not UNKNOWN answers.","from":"eval-answer-counts","compute":[{"as":"eval-result","function":"literal","args":[{"value":"UNKNOWN"}]},{"as":"answer-order","function":"literal","args":[{"value":2}]},{"as":"answer-share","function":"quotient","args":[{"field":"unknown"},{"field":"answers"}]}]},{"name":"eval-answer-distribution","subject":"Compare YES, NO and UNKNOWN percentages within each eval.","objective":"Show three horizontal bars per eval that together account for all recorded answers.","acceptance":"Emit all three answer categories, including zero shares; percentages sum to 100 per canonical eval. Missing observations are not UNKNOWN answers. Preserve workflow and repository attribution.","from":"eval-yes-shares","union":["eval-no-shares","eval-unknown-shares"],"compute":[{"as":"answer-percent","function":"product","args":[{"field":"answer-share"},{"value":100}]},{"as":"eval-label","function":"concat","args":[{"field":"eval"},{"value":" | "},{"field":"organization"},{"value":"/"},{"field":"repository"},{"value":":"},{"field":"workflow"}]}],"order-by":[{"field":"eval-label","direction":"asc"},{"field":"answer-order","direction":"asc"}]},{"name":"grader-observed-maxima","subject":"Find each workflow-scoped grader's maximum retained value in the selected data.","objective":"Provide an observed normalization denominator without mixing grader identities or claiming a theoretical maximum.","acceptance":"Group by canonical grader identity, not display name; ignore missing values and preserve zero or negative maxima without substituting a denominator.","from":"grader-observations","aggregate":{"by":["grader-id"],"values":[{"field":"value","as":"max-grader-value","reducer":"max"}]}},{"name":"grader-normalized-observations","subject":"Normalize each grader observation by that grader's observed maximum.","objective":"Compare relative grader values over time while preserving native measurements and run provenance.","acceptance":"Compute value / max-grader-value without clamping or inverting lower-is-better measures; zero or missing denominators produce null, never a fabricated zero or infinity.","from":"grader-observations","joins":[{"source":"grader-observed-maxima","type":"left","on":[{"left":"grader-id","right":"grader-id"}],"fields":[{"field":"max-grader-value","as":"max-grader-value"}]}],"compute":[{"as":"normalized-value","function":"quotient","args":[{"field":"value"},{"field":"max-grader-value"}]},{"as":"_observation-time","function":"timestamp","args":[{"field":"observed-at"}]},{"as":"_unplottable-value","function":"equals-any","args":[{"field":"normalized-value"},{"value":null}]},{"as":"_unplottable-time","function":"equals-any","args":[{"field":"_observation-time"},{"value":null}]},{"as":"grader-series","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"},{"value":" / "},{"field":"workflow"},{"value":" / "},{"field":"grader"}]}]},{"name":"grader-value-scatter","subject":"Plot timed grader observations with a defined value-to-observed-maximum ratio.","objective":"Show relative grader measurements at their recorded observation times.","acceptance":"Keep each eligible observation and its run link; omit missing ratios or observation times from the plot while retaining those records in the native-value ledger. Ratios are not eval answers or evidence of improvement.","from":"grader-normalized-observations","filter":{"predicates":[{"field":"_unplottable-value","equals":false},{"field":"_unplottable-time","equals":false}]},"order-by":[{"field":"observed-at","direction":"asc"}]},{"name":"grader-status-ledger","subject":"Report grader measurements, units and explicit statuses without confusing them with binary eval answers.","objective":"Preserve numeric grader evidence and distinguish explicit per-observation pass and fail verdicts from unknown statuses.","acceptance":"Retain native grader values, units and statuses. Map only pass/passed to YES and fail/failed to NO in the auxiliary verdict field, leaving all other statuses unknown; never infer an eval answer, current success, causation or policy authority from a grader score.","from":"grader-observations","compute":[{"as":"is-pass","function":"equals-any","args":[{"field":"status"},{"value":"pass"},{"value":"passed"}]},{"as":"is-fail","function":"equals-any","args":[{"field":"status"},{"value":"fail"},{"value":"failed"}]},{"as":"non-pass-verdict","function":"if","args":[{"field":"is-fail"},{"value":"NO"},{"value":"unknown"}]},{"as":"verdict","function":"if","args":[{"field":"is-pass"},{"value":"YES"},{"field":"non-pass-verdict"}]}]},{"name":"routing-session-observations","subject":"Read metadata-only unified-session routing evidence.","objective":"Keep routing analytics independent of native logs and inferred run totals.","acceptance":"Only recognized session events contribute; event clocks remain absent when unrecorded.","from":"audits","filter":{"predicates":[{"field":"event-type","in":["session.format","workflow.info","workflow.job_result","agent.execution","firewall.model_routing","firewall.token_usage","usage.report","firewall.steering","firewall.upstream_error","model.config","model.baseline_estimate","model.resolution","model_routing.outcome","model_endpoint.mismatch","session.collection","session.collection_warning","subagent.request","subagent.started","subagent.configured","subagent.completed","subagent.failed","subagent.model_unavailable"]}]},"compute":[{"as":"record-clock","function":"timestamp","args":[{"field":"event-timestamp"}]},{"as":"event-clock","function":"coalesce","args":[{"field":"routing-session-clock"},{"field":"record-clock"}]},{"as":"routing-run-key","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"},{"value":":"},{"field":"run"}]},{"as":"agent-phase","function":"equals-any","args":[{"field":"phase"},{"value":"agent"}]},{"as":"proxy-selection","function":"equals-any","args":[{"field":"routing-stage"},{"value":"selection"}]},{"as":"proxy-failure","function":"equals-any","args":[{"field":"routing-stage"},{"value":"failure"}]},{"as":"has-agent-name","function":"greater-than","args":[{"field":"routing-agent-name"},{"value":""}]}]},{"name":"routing-session-attempts","from":"routing-session-observations","subject":"Identify available session files and their earliest recorded clocks.","objective":"Keep rerun attempts from multiplying routing denominators.","acceptance":"Attempt order is only a tie-breaker after the recorded session clock.","aggregate":{"by":["routing-run-key","run-attempt"],"values":[{"field":"event-clock","as":"session-clock","reducer":"min"}]}},{"name":"routing-session-order","from":"routing-session-attempts","subject":"Order duplicate run sessions by run time and attempt.","objective":"Keep the latest file for each repository/run identity.","acceptance":"Only one attempt contributes to routing facts.","window":[{"operation":"row-number","field":"run-attempt","as":"session-position","groupby":["routing-run-key"],"order-by":[{"field":"session-clock","direction":"desc"},{"field":"run-attempt","direction":"desc"}]}]},{"name":"routing-latest-sessions","from":"routing-session-order","subject":"Retain one authoritative session attempt per run.","objective":"Avoid mixing picks or accounting from reruns.","acceptance":"Duplicate attempts remain available in session coverage.","filter":{"predicates":[{"field":"session-position","equals":1}]}},{"name":"routing-session-events","from":"routing-session-observations","subject":"Read routing metadata from the latest session file per run.","objective":"Deduplicate rerun attempts before any metric.","acceptance":"Earlier attempts never add cost or change the selected pick.","joins":[{"source":"routing-latest-sessions","type":"inner","on":[{"left":"routing-run-key","right":"routing-run-key"},{"left":"run-attempt","right":"run-attempt"}],"fields":[{"field":"session-clock","as":"session-clock"}]}]},{"name":"routing-run-facts","subject":"Collect per-session source facts without interpreting absence as success.","objective":"Resolve routing states and coverage from runner and proxy evidence.","acceptance":"Agent-phase proxy selection wins over failure and harness status; untimed observations keep unknown time.","from":"routing-session-events","aggregate":{"by":["routing-run-key","organization","repository","workflow","run"],"values":[{"field":"event-clock","as":"run-clock","reducer":"min"},{"field":"run-link","as":"run-link","reducer":"unique"},{"field":"engine","as":"engine","reducer":"unique"},{"field":"event","as":"workflow-info-count","reducer":"count","filter":{"predicates":[{"field":"event-type","equals":"workflow.info"},{"field":"required","equals":true}]}},{"field":"event-status","as":"session-format","reducer":"unique","filter":{"predicates":[{"field":"event-type","equals":"session.format"}]}},{"field":"event","as":"selection-count","reducer":"count","filter":{"predicates":[{"field":"event-type","equals":"firewall.model_routing"},{"field":"routing-stage","equals":"selection"},{"field":"phase","equals":"agent"}]}},{"field":"event","as":"failure-count","reducer":"count","filter":{"predicates":[{"field":"event-type","equals":"firewall.model_routing"},{"field":"routing-stage","equals":"failure"},{"field":"phase","equals":"agent"}]}},{"field":"event","as":"local-effort-failures","reducer":"count","filter":{"predicates":[{"field":"event-type","equals":"firewall.model_routing"},{"field":"routing-stage","equals":"failure"},{"field":"code","equals":"unsupported_reasoning_effort"}]}},{"field":"event","as":"proxy-record-count","reducer":"count","filter":{"predicates":[{"field":"event-type","equals":"firewall.model_routing"},{"field":"phase","equals":"agent"}]}},{"field":"event","as":"agent-accounting-count","reducer":"count","filter":{"predicates":[{"field":"event-type","equals":"firewall.token_usage"},{"field":"phase","equals":"agent"}]}},{"field":"event","as":"subagent-count","reducer":"count","filter":{"predicates":[{"field":"event-type","in":["subagent.started","subagent.request","subagent.configured","subagent.completed","subagent.failed","subagent.model_unavailable"]}]}},{"field":"routing-status","as":"harness-status","reducer":"unique","filter":{"predicates":[{"field":"event-type","equals":"workflow.info"}]}},{"field":"routing-enabled","as":"configured-enabled","reducer":"unique","filter":{"predicates":[{"field":"event-type","equals":"model.config"}]}},{"field":"routing-selected-model","as":"harness-model","reducer":"unique","filter":{"predicates":[{"field":"event-type","equals":"workflow.info"}]}},{"field":"telemetry-model","as":"workflow-model","reducer":"unique","filter":{"predicates":[{"field":"event-type","equals":"workflow.info"}]}},{"field":"routing-selected-effort","as":"harness-effort","reducer":"unique","filter":{"predicates":[{"field":"event-type","equals":"workflow.info"}]}},{"field":"routing-mode","as":"harness-mode","reducer":"unique","filter":{"predicates":[{"field":"event-type","equals":"workflow.info"}]}},{"field":"routing-awf-version","as":"session-awf-version","reducer":"unique","filter":{"predicates":[{"field":"event-type","equals":"workflow.info"}]}},{"field":"routing-goal","as":"configured-goal","reducer":"unique","filter":{"predicates":[{"field":"event-type","equals":"model.config"}]}},{"field":"routing-configured-mode","as":"configured-routing-mode","reducer":"unique","filter":{"predicates":[{"field":"event-type","equals":"model.config"}]}},{"field":"routing-max-credits","as":"configured-max-credits","reducer":"unique","filter":{"predicates":[{"field":"event-type","equals":"model.config"}]}},{"field":"event-status","as":"agent-result","reducer":"unique","filter":{"predicates":[{"field":"event-type","equals":"workflow.job_result"},{"field":"name","equals":"agent"},{"field":"event-status","in":["success","failure","cancelled","skipped"]}]}},{"field":"event","as":"warnings","reducer":"count","filter":{"predicates":[{"field":"event-type","equals":"session.collection_warning"}]}}]}},{"name":"routing-ordered-selections","subject":"Order proxy selections within each session.","objective":"Use the last selection by normalized clock and file order.","acceptance":"Harness and advisory picks never override proxy selections.","from":"routing-session-events","filter":{"predicates":[{"field":"event-type","equals":"firewall.model_routing"},{"field":"routing-stage","equals":"selection"},{"field":"phase","equals":"agent"}]},"window":[{"operation":"row-number","field":"source-sequence","as":"selection-position","groupby":["routing-run-key"],"order-by":[{"field":"event-timestamp","direction":"desc"},{"field":"source-sequence","direction":"desc"}]}]},{"name":"routing-selections","subject":"Retain one authoritative proxy pick per run.","objective":"Avoid multiplying requests or run counts after re-selection.","acceptance":"One row per identified run uses the final proxy selection.","from":"routing-ordered-selections","filter":{"predicates":[{"field":"selection-position","equals":1}]}},{"name":"routing-resolved-runs","subject":"Resolve routing state, pick and label cells from unified sessions.","objective":"Distinguish selected, failed, harness-only, configured, inferred and unknown evidence.","acceptance":"Proxy evidence wins; configuration conflicts are visible; missing picks and time remain unknown.","from":"routing-run-facts","joins":[{"source":"routing-selections","type":"left","on":[{"left":"routing-run-key","right":"routing-run-key"}],"fields":[{"field":"routing-selected-model","as":"proxy-model"},{"field":"routing-selected-effort","as":"proxy-effort"},{"field":"routing-goal","as":"proxy-goal"},{"field":"routing-mode","as":"proxy-mode"},{"field":"routing-configured-mode","as":"proxy-configured-mode"},{"field":"routing-task-type","as":"routing-task-type"},{"field":"routing-scope","as":"routing-scope"},{"field":"routing-complexity","as":"routing-complexity"},{"field":"routing-latency-ms","as":"routing-latency-ms"},{"field":"routing-degraded","as":"routing-degraded"},{"field":"routing-classifier-attempts","as":"routing-classifier-attempts"},{"field":"routing-classifier-model","as":"routing-classifier-model"},{"field":"routing-classifier-effort","as":"routing-classifier-effort"},{"field":"routing-schema","as":"routing-schema"},{"field":"routing-awf-version","as":"proxy-awf-version"},{"field":"routing-router-version","as":"routing-router-version"}]}],"compute":[{"as":"observed-at","function":"iso-timestamp","args":[{"field":"run-clock"}]},{"as":"routing-awf-version","function":"coalesce","args":[{"field":"session-awf-version"},{"field":"proxy-awf-version"}]},{"as":"routing-mode","function":"coalesce","args":[{"field":"proxy-mode"},{"field":"harness-mode"}]},{"as":"routing-goal","function":"coalesce","args":[{"field":"proxy-goal"},{"field":"configured-goal"}]},{"as":"routing-configured-mode","function":"coalesce","args":[{"field":"proxy-configured-mode"},{"field":"configured-routing-mode"}]},{"as":"has-selection","function":"greater-than","args":[{"field":"selection-count"},{"value":0}]},{"as":"has-failure","function":"greater-than","args":[{"field":"failure-count"},{"value":0}]},{"as":"has-harness","function":"equals-any","args":[{"field":"harness-status"},{"value":null}]},{"as":"has-usage","function":"greater-than","args":[{"field":"agent-accounting-count"},{"value":0}]},{"as":"no-proxy","function":"equals-any","args":[{"field":"proxy-record-count"},{"value":0}]},{"as":"usage-state","function":"if","args":[{"field":"has-usage"},{"value":"unrouted_inferred"},{"value":"unknown"}]},{"as":"inferred-state","function":"if","args":[{"field":"no-proxy"},{"field":"usage-state"},{"value":"unknown"}]},{"as":"enabled","function":"equals-any","args":[{"field":"configured-enabled"},{"value":true}]},{"as":"disabled","function":"equals-any","args":[{"field":"configured-enabled"},{"value":false}]},{"as":"enabled-state","function":"if","args":[{"field":"enabled"},{"value":"configured_unrecorded"},{"field":"inferred-state"}]},{"as":"configured-state","function":"if","args":[{"field":"disabled"},{"value":"unrouted"},{"field":"enabled-state"}]},{"as":"reported-state","function":"if","args":[{"field":"has-harness"},{"field":"configured-state"},{"value":"harness_reported"}]},{"as":"failure-state","function":"if","args":[{"field":"has-failure"},{"value":"selection_failed"},{"field":"reported-state"}]},{"as":"routing-state","function":"if","args":[{"field":"has-selection"},{"value":"selected"},{"field":"failure-state"}]},{"as":"observed-pick-model","function":"if","args":[{"field":"has-selection"},{"field":"proxy-model"},{"field":"harness-model"}]},{"as":"observed-pick-effort","function":"if","args":[{"field":"has-selection"},{"field":"proxy-effort"},{"field":"harness-effort"}]},{"as":"pick-model","function":"coalesce","args":[{"field":"observed-pick-model"},{"value":"unknown"}]},{"as":"pick-effort","function":"coalesce","args":[{"field":"observed-pick-effort"},{"value":"unknown"}]},{"as":"pick","function":"concat","args":[{"field":"pick-model"},{"value":" / "},{"field":"pick-effort"}]},{"as":"has-proxy-decision","function":"if","args":[{"field":"has-selection"},{"value":true},{"field":"has-failure"}]},{"as":"has-decision","function":"if","args":[{"field":"has-harness"},{"field":"has-proxy-decision"},{"value":true}]},{"as":"configuration-conflict","function":"if","args":[{"field":"disabled"},{"field":"has-decision"},{"value":false}]},{"as":"unknown-pick-model","function":"equals-any","args":[{"field":"pick-model"},{"value":"unknown"}]},{"as":"unknown-pick-effort","function":"equals-any","args":[{"field":"pick-effort"},{"value":"unknown"}]},{"as":"unknown-pick","function":"if","args":[{"field":"unknown-pick-model"},{"value":true},{"field":"unknown-pick-effort"}]},{"as":"routing-key-encoded","function":"url-encode","args":[{"field":"routing-run-key"}]},{"as":"routing-href","function":"concat","args":[{"value":"#page-routing-run?routing-run="},{"field":"routing-key-encoded"}]},{"as":"routing-dashboard-link","function":"dashboard-link","args":[{"field":"run-link"},{"field":"routing-href"},{"field":"run"}]}],"filter":{"predicates":[{"field":"workflow-info-count","gte":1}]}},{"name":"routing-filter-candidates","from":"routing-aggregates","subject":"Apply one run-level scope before every routing metric and event join.","objective":"Filter complete sessions, never fragments of their evidence.","acceptance":"Unknown run time is excluded from a bounded range; blank filters retain all known values.","parameters":[{"name":"routing-filter-workflow","type":"string"},{"name":"routing-filter-repository","type":"string"},{"name":"routing-filter-engine","type":"string"},{"name":"routing-filter-state","type":"string"},{"name":"routing-filter-goal","type":"string"},{"name":"routing-filter-mode","type":"string"},{"name":"routing-filter-awf","type":"string"},{"name":"routing-filter-start","type":"string"},{"name":"routing-filter-end","type":"string"}],"compute":[{"as":"full-repository","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"all-workflows","function":"equals-any","args":[{"parameter":"routing-filter-workflow"},{"value":""}]},{"as":"same-workflow","function":"equals-any","args":[{"field":"workflow"},{"parameter":"routing-filter-workflow"}]},{"as":"include-workflow","function":"if","args":[{"field":"all-workflows"},{"value":true},{"field":"same-workflow"}]},{"as":"all-repositories","function":"equals-any","args":[{"parameter":"routing-filter-repository"},{"value":""}]},{"as":"same-repository","function":"equals-any","args":[{"field":"full-repository"},{"parameter":"routing-filter-repository"}]},{"as":"include-repository","function":"if","args":[{"field":"all-repositories"},{"value":true},{"field":"same-repository"}]},{"as":"all-engines","function":"equals-any","args":[{"parameter":"routing-filter-engine"},{"value":""}]},{"as":"same-engine","function":"equals-any","args":[{"field":"engine"},{"parameter":"routing-filter-engine"}]},{"as":"include-engine","function":"if","args":[{"field":"all-engines"},{"value":true},{"field":"same-engine"}]},{"as":"all-states","function":"equals-any","args":[{"parameter":"routing-filter-state"},{"value":""}]},{"as":"same-state","function":"equals-any","args":[{"field":"routing-state"},{"parameter":"routing-filter-state"}]},{"as":"include-state","function":"if","args":[{"field":"all-states"},{"value":true},{"field":"same-state"}]},{"as":"all-goals","function":"equals-any","args":[{"parameter":"routing-filter-goal"},{"value":""}]},{"as":"same-goal","function":"equals-any","args":[{"field":"routing-goal"},{"parameter":"routing-filter-goal"}]},{"as":"include-goal","function":"if","args":[{"field":"all-goals"},{"value":true},{"field":"same-goal"}]},{"as":"all-modes","function":"equals-any","args":[{"parameter":"routing-filter-mode"},{"value":""}]},{"as":"same-mode","function":"equals-any","args":[{"field":"routing-mode"},{"parameter":"routing-filter-mode"}]},{"as":"include-mode","function":"if","args":[{"field":"all-modes"},{"value":true},{"field":"same-mode"}]},{"as":"all-awf","function":"equals-any","args":[{"parameter":"routing-filter-awf"},{"value":""}]},{"as":"same-awf","function":"equals-any","args":[{"field":"routing-awf-version"},{"parameter":"routing-filter-awf"}]},{"as":"include-awf","function":"if","args":[{"field":"all-awf"},{"value":true},{"field":"same-awf"}]},{"as":"all-starts","function":"equals-any","args":[{"parameter":"routing-filter-start"},{"value":""}]},{"as":"start-clock","function":"timestamp","args":[{"parameter":"routing-filter-start"}]},{"as":"start-before","function":"difference","args":[{"field":"start-clock"},{"value":1}]},{"as":"after-start","function":"greater-than","args":[{"field":"run-clock"},{"field":"start-before"}]},{"as":"include-start","function":"if","args":[{"field":"all-starts"},{"value":true},{"field":"after-start"}]},{"as":"all-ends","function":"equals-any","args":[{"parameter":"routing-filter-end"},{"value":""}]},{"as":"end-clock","function":"timestamp","args":[{"parameter":"routing-filter-end"}]},{"as":"before-end","function":"greater-than","args":[{"field":"end-clock"},{"field":"run-clock"}]},{"as":"include-end","function":"if","args":[{"field":"all-ends"},{"value":true},{"field":"before-end"}]}]},{"name":"routing-runs","from":"routing-filter-candidates","subject":"Retain identified runs matching every selected routing filter.","objective":"Use the same population for adoption, accounting and outcomes.","acceptance":"A time bound excludes untimed runs and does not remove individual events from retained sessions.","filter":{"predicates":[{"field":"include-workflow","equals":true},{"field":"include-repository","equals":true},{"field":"include-engine","equals":true},{"field":"include-state","equals":true},{"field":"include-goal","equals":true},{"field":"include-mode","equals":true},{"field":"include-awf","equals":true},{"field":"include-start","equals":true},{"field":"include-end","equals":true}]}},{"name":"routing-events","from":"routing-session-events","subject":"Retain all evidence belonging to scoped identified runs.","objective":"Filter event metrics by the resolved run rather than by individual event clocks.","acceptance":"State, pick and accounting are computed before the scope is applied.","joins":[{"source":"routing-runs","type":"inner","on":[{"left":"routing-run-key","right":"routing-run-key"}],"fields":[{"field":"routing-state","as":"run-routing-state"}]}]},{"name":"routing-phase-sources","subject":"Choose one nonoverlapping accounting source per run and phase.","objective":"Prefer proxy token usage over usage reports.","acceptance":"Snapshot totals and cumulative totalAic never enter additive cost.","from":"routing-events","aggregate":{"by":["routing-run-key","phase"],"values":[{"field":"event","as":"proxy-usage-count","reducer":"count","filter":{"predicates":[{"field":"event-type","equals":"firewall.token_usage"}]}},{"field":"event","as":"report-usage-count","reducer":"count","filter":{"predicates":[{"field":"event-type","equals":"usage.report"}]}},{"field":"event","as":"proxy-source-count","reducer":"count","filter":{"predicates":[{"field":"event-type","equals":"session.collection"},{"field":"name","equals":"token-usage.jsonl"},{"field":"event-status","equals":"collected"}]}},{"field":"event","as":"report-source-count","reducer":"count","filter":{"predicates":[{"field":"event-type","equals":"session.collection"},{"field":"name","in":["agent_usage.json","usage.json","usage.jsonl","usage-report.jsonl"]},{"field":"event-status","equals":"collected"}]}}]}},{"name":"routing-accounting-candidates","subject":"Read nonoverlapping per-response accounting records.","objective":"Expose recorded credits and token classes without repricing unknown usage.","acceptance":"Each phase uses proxy accounting when present and usage.report otherwise; absent AIC is counted.","from":"routing-events","joins":[{"source":"routing-phase-sources","type":"left","on":[{"left":"routing-run-key","right":"routing-run-key"},{"left":"phase","right":"phase"}],"fields":[{"field":"proxy-usage-count","as":"proxy-usage-count"}]}],"compute":[{"as":"has-proxy-accounting","function":"greater-than","args":[{"field":"proxy-usage-count"},{"value":0}]},{"as":"accounting-identity","function":"coalesce","args":[{"field":"correlation-id"},{"field":"event"}]},{"as":"accounting-source","function":"if","args":[{"field":"has-proxy-accounting"},{"value":"firewall.token_usage"},{"value":"usage.report"}]},{"as":"selected-accounting","function":"equals-any","args":[{"field":"event-type"},{"field":"accounting-source"}]},{"as":"unknown-aic","function":"equals-any","args":[{"field":"aic"},{"value":null}]},{"as":"unknown-aic-count","function":"if","args":[{"field":"unknown-aic"},{"value":1},{"value":0}]}],"window":[{"operation":"row-number","field":"source-sequence","as":"accounting-position","groupby":["routing-run-key","phase","event-type","accounting-identity"],"order-by":[{"field":"event-timestamp","direction":"desc"},{"field":"source-sequence","direction":"desc"}]}]},{"name":"routing-accounting","subject":"Select the authoritative accounting source for each phase.","objective":"Exclude overlapping usage reports and snapshots.","acceptance":"Every accounting row contributes at most once.","from":"routing-accounting-candidates","filter":{"predicates":[{"field":"selected-accounting","equals":true},{"field":"accounting-position","equals":1},{"field":"phase","in":["agent","detection","evals"]}]}},{"name":"routing-request-candidates","subject":"Keep per-request routing decisions separate from accounting.","objective":"Join routed outcomes by run, phase and request ID.","acceptance":"Rejected requests establish local zero cost; other unmatched requests retain unknown cost.","from":"routing-events","filter":{"predicates":[{"field":"event-type","equals":"firewall.model_routing"},{"field":"routing-stage","equals":"request"}]},"compute":[{"as":"request-identity","function":"coalesce","args":[{"field":"correlation-id"},{"field":"event"}]}],"window":[{"operation":"row-number","field":"source-sequence","as":"request-position","groupby":["routing-run-key","phase","request-identity"],"order-by":[{"field":"event-timestamp","direction":"desc"},{"field":"source-sequence","direction":"desc"}]}]},{"name":"routing-request-records","from":"routing-request-candidates","subject":"Retain the latest record for each request identity.","objective":"Avoid duplicate request joins and overlapping totals.","acceptance":"Requests without IDs remain independent, not falsely correlated.","filter":{"predicates":[{"field":"request-position","equals":1}]}},{"name":"routing-subagent-candidates","subject":"Read engine-reported sub-agent request ownership.","objective":"Use exact request-ID ownership before falling back to unsplit traffic.","acceptance":"Only request identities can assign exact ownership; advisory outcomes never assign credits.","from":"routing-events","filter":{"predicates":[{"field":"event-type","equals":"subagent.request"}]},"compute":[{"as":"subagent-identity","function":"coalesce","args":[{"field":"correlation-id"},{"field":"event"}]}],"window":[{"operation":"row-number","field":"source-sequence","as":"subagent-position","groupby":["routing-run-key","phase","subagent-identity"],"order-by":[{"field":"event-timestamp","direction":"desc"},{"field":"source-sequence","direction":"desc"}]}]},{"name":"routing-subagent-requests","from":"routing-subagent-candidates","subject":"Retain one sub-agent observation per request identity.","objective":"Keep exact ownership joins unique.","acceptance":"Missing identities do not match unrelated requests.","filter":{"predicates":[{"field":"subagent-position","equals":1}]}},{"name":"routing-exact-accounting","subject":"Attribute each accounting record to exactly one traffic bucket.","objective":"Keep detection, evals, classifier, exact sub-agent, main, unsplit and unattributed credits distinct.","acceptance":"Detection and evals use phase, missing purpose is never agent by default, and snapshot credits are excluded.","from":"routing-accounting","joins":[{"source":"routing-request-records","type":"left","on":[{"left":"routing-run-key","right":"routing-run-key"},{"left":"phase","right":"phase"},{"left":"correlation-id","right":"correlation-id"}],"fields":[{"field":"event","as":"request-event"},{"field":"routing-routed","as":"request-routed"},{"field":"routing-deviations","as":"request-deviations"},{"field":"routing-outcome","as":"request-outcome"},{"field":"routing-requested-model","as":"request-model"},{"field":"routing-requested-effort","as":"request-effort"}]},{"source":"routing-subagent-requests","type":"left","on":[{"left":"routing-run-key","right":"routing-run-key"},{"left":"phase","right":"phase"},{"left":"correlation-id","right":"correlation-id"}],"fields":[{"field":"routing-agent-name","as":"exact-agent-name"}]},{"source":"routing-run-facts","type":"left","on":[{"left":"routing-run-key","right":"routing-run-key"}],"fields":[{"field":"subagent-count","as":"subagent-count"}]}],"compute":[{"as":"exact-owner","function":"coalesce","args":[{"field":"routing-agent-name"},{"field":"exact-agent-name"}]},{"as":"no-exact-owner","function":"equals-any","args":[{"field":"exact-owner"},{"value":null}]}]},{"name":"routing-correlation-usage-candidates","from":"routing-exact-accounting","subject":"Find accounting records without exact sub-agent ownership.","objective":"Correlate only fully recorded token quartets in file order.","acceptance":"Missing token classes never match by model alone.","filter":{"predicates":[{"field":"phase","equals":"agent"},{"field":"no-exact-owner","equals":true}]},"compute":[{"as":"token-quartet","function":"sum","args":[{"field":"input-tokens"},{"field":"output-tokens"},{"field":"cache-read-tokens"},{"field":"cache-write-tokens"}]},{"as":"is-classifier","function":"equals-any","args":[{"field":"routing-purpose"},{"value":"routing_classification"}]}]},{"name":"routing-correlation-usage","from":"routing-correlation-usage-candidates","subject":"Order unmatched accounting within model and token quartet.","objective":"Match each engine-reported request at most once.","acceptance":"Classifier, incomplete and already-exact requests are excluded.","filter":{"predicates":[{"field":"token-quartet","gte":0},{"field":"is-classifier","equals":false}]},"window":[{"operation":"row-number","field":"source-sequence","as":"correlation-position","groupby":["routing-run-key","telemetry-model","input-tokens","output-tokens","cache-read-tokens","cache-write-tokens"],"order-by":[{"field":"source-sequence","direction":"asc"}]}]},{"name":"routing-correlation-subagent-candidates","from":"routing-subagent-requests","subject":"Exclude engine requests already matched by proxy request ID.","objective":"Prevent exact and correlated ownership from claiming the same request.","acceptance":"Only engine requests with a complete quartet and a definition name can correlate.","joins":[{"source":"routing-accounting","type":"left","on":[{"left":"routing-run-key","right":"routing-run-key"},{"left":"phase","right":"phase"},{"left":"correlation-id","right":"correlation-id"}],"fields":[{"field":"event","as":"exact-accounting-event"}]}],"compute":[{"as":"token-quartet","function":"sum","args":[{"field":"input-tokens"},{"field":"output-tokens"},{"field":"cache-read-tokens"},{"field":"cache-write-tokens"}]}]},{"name":"routing-correlation-subagents","from":"routing-correlation-subagent-candidates","subject":"Order unmatched engine requests within each model/token quartet.","objective":"Produce deterministic one-to-one correlated ownership.","acceptance":"Correlation is labelled separately from exact evidence.","filter":{"predicates":[{"field":"exact-accounting-event","equals":null},{"field":"token-quartet","gte":0},{"field":"phase","equals":"agent"}]},"window":[{"operation":"row-number","field":"source-sequence","as":"correlation-position","groupby":["routing-run-key","telemetry-model","input-tokens","output-tokens","cache-read-tokens","cache-write-tokens"],"order-by":[{"field":"source-sequence","direction":"asc"}]}]},{"name":"routing-correlated-accounting","from":"routing-correlation-usage","subject":"Join proxy usage with unmatched engine requests by model, quartet and occurrence.","objective":"Use the spec's correlated sub-agent attribution without duplicating credits.","acceptance":"Each engine request and accounting record participates at most once.","joins":[{"source":"routing-correlation-subagents","type":"left","on":[{"left":"routing-run-key","right":"routing-run-key"},{"left":"telemetry-model","right":"telemetry-model"},{"left":"input-tokens","right":"input-tokens"},{"left":"output-tokens","right":"output-tokens"},{"left":"cache-read-tokens","right":"cache-read-tokens"},{"left":"cache-write-tokens","right":"cache-write-tokens"},{"left":"correlation-position","right":"correlation-position"}],"fields":[{"field":"routing-agent-name","as":"correlated-owner"}]}],"select":[{"field":"routing-run-key"},{"field":"event"},{"field":"correlated-owner"}]},{"name":"routing-attributed-accounting","from":"routing-exact-accounting","subject":"Assign every accounting record to exactly one exclusive bucket.","objective":"Keep exact and correlated sub-agent ownership distinct.","acceptance":"Phase wins over purpose; missing ownership remains unsplit or unattributed.","joins":[{"source":"routing-correlated-accounting","type":"left","on":[{"left":"routing-run-key","right":"routing-run-key"},{"left":"event","right":"event"}],"fields":[{"field":"correlated-owner","as":"correlated-owner"}]}],"compute":[{"as":"agent-name","function":"coalesce","args":[{"field":"exact-owner"},{"field":"correlated-owner"}]},{"as":"unknown-agent","function":"equals-any","args":[{"field":"agent-name"},{"value":null}]},{"as":"unknown-request","function":"equals-any","args":[{"field":"request-event"},{"value":null}]},{"as":"has-subagents","function":"greater-than","args":[{"field":"subagent-count"},{"value":0}]},{"as":"is-subagent-purpose","function":"equals-any","args":[{"field":"routing-purpose"},{"value":"subagent"}]},{"as":"is-agent-purpose","function":"equals-any","args":[{"field":"routing-purpose"},{"value":"agent"}]},{"as":"matched-bucket","function":"if","args":[{"field":"has-subagents"},{"value":"agent_unsplit"},{"value":"main_agent"}]},{"as":"request-bucket","function":"if","args":[{"field":"unknown-request"},{"value":"unattributed"},{"field":"matched-bucket"}]},{"as":"subagent-bucket","function":"if","args":[{"field":"is-subagent-purpose"},{"value":"agent_unsplit"},{"field":"request-bucket"}]},{"as":"purpose-bucket","function":"if","args":[{"field":"is-agent-purpose"},{"value":"main_agent"},{"field":"subagent-bucket"}]},{"as":"subagent-attribution","function":"if","args":[{"field":"no-exact-owner"},{"value":"subagent_correlated"},{"value":"subagent_exact"}]},{"as":"ownership-bucket","function":"if","args":[{"field":"unknown-agent"},{"field":"purpose-bucket"},{"field":"subagent-attribution"}]},{"as":"classifier","function":"equals-any","args":[{"field":"routing-purpose"},{"value":"routing_classification"}]},{"as":"classifier-bucket","function":"if","args":[{"field":"classifier"},{"value":"classifier"},{"field":"ownership-bucket"}]},{"as":"evals","function":"equals-any","args":[{"field":"phase"},{"value":"evals"}]},{"as":"phase-bucket","function":"if","args":[{"field":"evals"},{"value":"evals"},{"field":"classifier-bucket"}]},{"as":"detection","function":"equals-any","args":[{"field":"phase"},{"value":"detection"}]},{"as":"bucket","function":"if","args":[{"field":"detection"},{"value":"detection"},{"field":"phase-bucket"}]}]},{"name":"routing-joined-requests","subject":"Inspect per-request deviations and outcomes against proxy picks.","objective":"Keep requests without accounting visible and never invent a deviation cause.","acceptance":"Unmatched requests have unknown cost; each request retains its own requested and selected model.","from":"routing-request-records","joins":[{"source":"routing-accounting","type":"left","on":[{"left":"routing-run-key","right":"routing-run-key"},{"left":"phase","right":"phase"},{"left":"correlation-id","right":"correlation-id"}],"fields":[{"field":"aic","as":"accounted-aic"},{"field":"event","as":"accounting-event"}]}],"compute":[{"as":"missing-accounting","function":"equals-any","args":[{"field":"accounting-event"},{"value":null}]},{"as":"failed-request","function":"equals-any","args":[{"field":"routing-outcome"},{"value":"failed"}]},{"as":"failed-unaccounted","function":"if","args":[{"field":"missing-accounting"},{"field":"failed-request"},{"value":false}]}],"order-by":[{"field":"event-timestamp","direction":"desc"}]},{"name":"routing-unaccounted-failures","from":"routing-joined-requests","subject":"Count failed requests lacking accounting per run.","objective":"Recognize only unambiguous AWF-local effort failures.","acceptance":"A run-level effort failure cannot assign zero to multiple failed requests.","aggregate":{"by":["routing-run-key"],"values":[{"field":"event","as":"failed-unaccounted-count","reducer":"count","filter":{"predicates":[{"field":"failed-unaccounted","equals":true}]}}]}},{"name":"routing-deviations","from":"routing-joined-requests","subject":"Resolve explicit local zero costs and preserve all other unknown request costs.","objective":"Avoid partial-cost comparisons based on missing accounting.","acceptance":"Only guard rejection or an unambiguous local effort failure establishes zero AIC.","joins":[{"source":"routing-unaccounted-failures","type":"left","on":[{"left":"routing-run-key","right":"routing-run-key"}],"fields":[{"field":"failed-unaccounted-count","as":"failed-unaccounted-count"}]},{"source":"routing-run-facts","type":"left","on":[{"left":"routing-run-key","right":"routing-run-key"}],"fields":[{"field":"local-effort-failures","as":"local-effort-failures"}]}],"compute":[{"as":"only-unaccounted-failure","function":"equals-any","args":[{"field":"failed-unaccounted-count"},{"value":1}]},{"as":"has-local-failure","function":"greater-than","args":[{"field":"local-effort-failures"},{"value":0}]},{"as":"unambiguous-local-failure","function":"if","args":[{"field":"only-unaccounted-failure"},{"field":"has-local-failure"},{"value":false}]},{"as":"local-code","function":"equals-any","args":[{"field":"code"},{"value":"unsupported_reasoning_effort"}]},{"as":"local-evidence","function":"if","args":[{"field":"local-code"},{"value":true},{"field":"unambiguous-local-failure"}]},{"as":"local-failure","function":"if","args":[{"field":"failed-request"},{"field":"local-evidence"},{"value":false}]},{"as":"guard-rejection","function":"equals-any","args":[{"field":"routing-outcome"},{"value":"rejected"}]},{"as":"zero-local-cost","function":"if","args":[{"field":"guard-rejection"},{"value":true},{"field":"local-failure"}]},{"as":"local-cost","function":"if","args":[{"field":"zero-local-cost"},{"value":0},{"value":null}]},{"as":"request-aic","function":"coalesce","args":[{"field":"accounted-aic"},{"field":"local-cost"}]},{"as":"unknown-request-cost","function":"equals-any","args":[{"field":"request-aic"},{"value":null}]},{"as":"unknown-request-count","function":"if","args":[{"field":"unknown-request-cost"},{"value":1},{"value":0}]}]},{"name":"routing-phase-usage","from":"routing-accounting","subject":"Sum nonoverlapping accounting per run and phase.","objective":"Establish complete costs only with known response values.","acceptance":"Unknown response costs remain counted.","aggregate":{"by":["routing-run-key","phase"],"values":[{"field":"aic","as":"recorded-aic","reducer":"sum"},{"field":"aic","as":"known-responses","reducer":"count"},{"field":"unknown-aic-count","as":"unknown-responses","reducer":"sum"}]}},{"name":"routing-request-coverage","from":"routing-deviations","subject":"Count requests whose cost remains unknown.","objective":"Exclude incomplete runs from distribution comparisons.","acceptance":"Unmatched nonlocal requests cannot be treated as free.","aggregate":{"by":["routing-run-key","phase"],"values":[{"field":"unknown-request-count","as":"unknown-requests","reducer":"sum"}]}},{"name":"routing-phase-costs","from":"routing-phase-sources","subject":"Evaluate accounting completeness using collected source receipts and request joins.","objective":"Exclude partial costs from medians and comparisons.","acceptance":"A complete phase has its selected accounting source, no missing AIC and no unaccounted nonlocal requests.","joins":[{"source":"routing-phase-usage","type":"left","on":[{"left":"routing-run-key","right":"routing-run-key"},{"left":"phase","right":"phase"}],"fields":[{"field":"recorded-aic","as":"recorded-aic"},{"field":"unknown-responses","as":"unknown-responses"},{"field":"known-responses","as":"known-responses"}]},{"source":"routing-request-coverage","type":"left","on":[{"left":"routing-run-key","right":"routing-run-key"},{"left":"phase","right":"phase"}],"fields":[{"field":"unknown-requests","as":"unknown-requests"}]}],"compute":[{"as":"has-proxy","function":"greater-than","args":[{"field":"proxy-usage-count"},{"value":0}]},{"as":"has-report","function":"greater-than","args":[{"field":"report-usage-count"},{"value":0}]},{"as":"any-source-count","function":"sum","args":[{"field":"proxy-source-count"},{"field":"report-source-count"}]},{"as":"report-or-empty-source","function":"if","args":[{"field":"has-report"},{"field":"report-source-count"},{"field":"any-source-count"}]},{"as":"accounting-source-count","function":"if","args":[{"field":"has-proxy"},{"field":"proxy-source-count"},{"field":"report-or-empty-source"}]},{"as":"source-present","function":"greater-than","args":[{"field":"accounting-source-count"},{"value":0}]},{"as":"missing-responses","function":"coalesce","args":[{"field":"unknown-responses"},{"value":0}]},{"as":"missing-requests","function":"coalesce","args":[{"field":"unknown-requests"},{"value":0}]},{"as":"missing-count","function":"sum","args":[{"field":"missing-responses"},{"field":"missing-requests"}]},{"as":"all-values-known","function":"equals-any","args":[{"field":"missing-count"},{"value":0}]},{"as":"complete","function":"if","args":[{"field":"source-present"},{"field":"all-values-known"},{"value":false}]},{"as":"known-sum","function":"coalesce","args":[{"field":"recorded-aic"},{"value":0}]},{"as":"complete-aic","function":"if","args":[{"field":"complete"},{"field":"known-sum"},{"value":null}]}]},{"name":"routing-agent-costs","from":"routing-phase-costs","subject":"Select complete or explicitly partial agent-phase costs.","objective":"Keep detection and evals out of agent-phase comparisons.","acceptance":"Classifier remains part of agent-phase cost.","filter":{"predicates":[{"field":"phase","equals":"agent"}]}},{"name":"routing-detection-costs","from":"routing-phase-costs","subject":"Retain detection-phase cost completeness separately.","objective":"Do not count detection as classifier or agent traffic.","acceptance":"Missing detection evidence remains unknown, not zero.","filter":{"predicates":[{"field":"phase","equals":"detection"}]}},{"name":"routing-cost-runs","from":"routing-resolved-runs","subject":"Attach accounting completeness to identified routing runs.","objective":"Provide comparable costs only for complete runs.","acceptance":"An absent cost stays unknown and never inherits aggregate run AIC.","joins":[{"source":"routing-runs","type":"inner","on":[{"left":"routing-run-key","right":"routing-run-key"}],"fields":[{"field":"main-aic","as":"main-aic"},{"field":"baseline-model","as":"baseline-model"},{"field":"baseline-aic","as":"baseline-aic"},{"field":"baseline-complete","as":"baseline-complete"}]},{"source":"routing-agent-costs","type":"left","on":[{"left":"routing-run-key","right":"routing-run-key"}],"fields":[{"field":"complete-aic","as":"complete-aic"},{"field":"complete","as":"cost-complete"},{"field":"missing-count","as":"missing-cost-records"}]},{"source":"routing-detection-costs","type":"left","on":[{"left":"routing-run-key","right":"routing-run-key"}],"fields":[{"field":"complete-aic","as":"detection-aic"},{"field":"complete","as":"detection-complete"}]}],"compute":[{"as":"run-cost-complete","function":"if","args":[{"field":"cost-complete"},{"field":"detection-complete"},{"value":false}]},{"as":"run-aic","function":"sum","args":[{"field":"complete-aic"},{"field":"detection-aic"}]},{"as":"budget-use","function":"quotient","args":[{"field":"run-aic"},{"field":"configured-max-credits"}]}]},{"name":"routing-weekly-cost-totals","from":"routing-runs","subject":"Summarize complete agent-phase costs by UTC ISO week and routing state.","objective":"Expose trends without including partial costs.","acceptance":"Untimed runs cannot enter time buckets.","filter":{"predicates":[{"field":"run-clock","gte":0}]},"compute":[{"as":"week","function":"date-bucket","args":[{"field":"observed-at"},{"value":"week"}]}],"aggregate":{"by":["week","routing-state"],"values":[{"field":"run","as":"runs","reducer":"count"},{"field":"complete-aic","as":"complete-runs","reducer":"count"},{"field":"complete-aic","as":"observed-median","reducer":"median"}]}},{"name":"routing-weekly-accounting-cost","from":"routing-weekly-cost-totals","subject":"Gate weekly medians by complete sample size.","objective":"Keep sparse weeks from implying meaningful cost trends.","acceptance":"Weeks below the configurable minimum display insufficient data.","parameters":[{"name":"minimum-sample","type":"number"}],"compute":[{"as":"cost-series","function":"concat","args":[{"value":"Agent-phase accounting: "},{"field":"routing-state"}]},{"as":"sample-floor","function":"difference","args":[{"parameter":"minimum-sample"},{"value":1}]},{"as":"enough-samples","function":"greater-than","args":[{"field":"complete-runs"},{"field":"sample-floor"}]},{"as":"median-aic","function":"if","args":[{"field":"enough-samples"},{"field":"observed-median"},{"value":null}]},{"as":"sample-status","function":"if","args":[{"field":"enough-samples"},{"value":"observational"},{"value":"insufficient data"}]}],"order-by":[{"field":"week","direction":"asc"}]},{"name":"routing-resolutions","from":"routing-session-events","subject":"Read runner-written configured-model resolutions for scoped routing runs.","objective":"Explain what each workflow role's configured model resolved to before the engine launched.","acceptance":"Only model.resolution facts from latest scoped attempts contribute; missing or unsafe values and failed null resolutions remain unknown.","joins":[{"source":"routing-runs","type":"inner","on":[{"left":"routing-run-key","right":"routing-run-key"}],"fields":[{"field":"run-clock","as":"run-clock"},{"field":"observed-at","as":"run-observed-at"},{"field":"full-repository","as":"full-repository"},{"field":"routing-dashboard-link","as":"routing-dashboard-link"},{"field":"routing-state","as":"run-routing-state"}]}],"filter":{"predicates":[{"field":"event-type","equals":"model.resolution"}]},"compute":[{"as":"resolution-engine","function":"coalesce","args":[{"field":"telemetry-engine"},{"value":"unknown"}]},{"as":"resolution-role-label","function":"coalesce","args":[{"field":"resolution-role"},{"value":"unknown"}]},{"as":"configured-model","function":"coalesce","args":[{"field":"resolution-configured-model"},{"value":"unknown"}]},{"as":"resolved-model-label","function":"coalesce","args":[{"field":"resolution-resolved-model"},{"value":"unknown"}]},{"as":"resolution-provider","function":"coalesce","args":[{"field":"provider"},{"value":"unknown"}]},{"as":"resolution-status","function":"coalesce","args":[{"field":"event-status"},{"value":"unknown"}]},{"as":"failed-resolution","function":"equals-any","args":[{"field":"event-status"},{"value":"failed"}]},{"as":"failure-cause","function":"coalesce","args":[{"field":"code"},{"value":"unknown"}]},{"as":"resolution-cause","function":"if","args":[{"field":"failed-resolution"},{"field":"failure-cause"},{"field":"code"}]},{"as":"unknown-resolved-model","function":"equals-any","args":[{"field":"resolution-resolved-model"},{"value":null}]},{"as":"untimed","function":"equals-any","args":[{"field":"run-clock"},{"value":null}]},{"as":"configured-to-resolved","function":"concat","args":[{"field":"configured-model"},{"value":" → "},{"field":"resolved-model-label"}]},{"as":"workflow-key","function":"concat","args":[{"field":"full-repository"},{"value":":"},{"field":"workflow"}]},{"as":"resolution-actor","function":"concat","args":[{"field":"resolution-engine"},{"value":"/"},{"field":"resolution-role-label"},{"value":"/"},{"field":"resolution-provider"}]},{"as":"resolution-series","function":"concat","args":[{"field":"workflow-key"},{"value":" | "},{"field":"resolution-actor"},{"value":" | "},{"field":"configured-model"}]}]},{"name":"routing-health-totals","from":"routing-runs","subject":"Count routed runs and their selection, failure, adherence, outcome and cost evidence per repository and workflow.","objective":"Answer whether routing is on and working from one row per routed workflow.","acceptance":"Only selected, selection_failed, harness_reported and configured_unrecorded runs contribute; runs without evidence stay out of each denominator.","filter":{"predicates":[{"field":"routing-state","in":["selected","selection_failed","harness_reported","configured_unrecorded"]}]},"compute":[{"as":"has-routing-failure","function":"greater-than","args":[{"field":"failure-count"},{"value":0}]},{"as":"failure-or-fallback","function":"if","args":[{"field":"has-routing-failure"},{"value":true},{"field":"routing-degraded"}]},{"as":"adherence-known","function":"greater-than","args":[{"field":"flagged-requests"},{"value":0}]},{"as":"no-deviation","function":"equals-any","args":[{"field":"deviated-requests"},{"value":0}]}],"aggregate":{"by":["full-repository","workflow","baseline-model"],"values":[{"field":"paired-main-aic","as":"paired-main-aic","reducer":"sum"},{"field":"paired-baseline-aic","as":"paired-baseline-aic","reducer":"sum"},{"field":"run","as":"routed-runs","reducer":"count"},{"field":"run","as":"selected-runs","reducer":"count","filter":{"predicates":[{"field":"routing-state","equals":"selected"}]}},{"field":"run","as":"failure-runs","reducer":"count","filter":{"predicates":[{"field":"failure-or-fallback","equals":true}]}},{"field":"run","as":"adherence-known-runs","reducer":"count","filter":{"predicates":[{"field":"adherence-known","equals":true}]}},{"field":"run","as":"followed-runs","reducer":"count","filter":{"predicates":[{"field":"adherence-known","equals":true},{"field":"no-deviation","equals":true}]}},{"field":"agent-result","as":"known-outcomes","reducer":"count"},{"field":"run","as":"successes","reducer":"count","filter":{"predicates":[{"field":"agent-result","equals":"success"}]}},{"field":"complete-aic","as":"complete-runs","reducer":"count"},{"field":"complete-aic","as":"median-aic","reducer":"median"}]}},{"name":"routing-health","subject":"Show routing health shares per repository and workflow.","objective":"Tell whether routing is on and working from selection, failure or fallback, pick adherence, known outcomes and complete cost.","acceptance":"A zero denominator or no complete cost is unknown, never zero; unknown job outcomes are excluded from the success rate.","from":"routing-health-totals","compute":[{"as":"estimated-cost-vs-baseline","function":"quotient","args":[{"field":"paired-main-aic"},{"field":"paired-baseline-aic"}]},{"as":"estimated-cost-percent","function":"format-percent","args":[{"field":"estimated-cost-vs-baseline"}]},{"as":"selected-share","function":"quotient","args":[{"field":"selected-runs"},{"field":"routed-runs"}]},{"as":"failure-share","function":"quotient","args":[{"field":"failure-runs"},{"field":"routed-runs"}]},{"as":"followed-share","function":"quotient","args":[{"field":"followed-runs"},{"field":"adherence-known-runs"}]},{"as":"success-rate","function":"quotient","args":[{"field":"successes"},{"field":"known-outcomes"}]},{"as":"selected-percent","function":"format-percent","args":[{"field":"selected-share"}]},{"as":"failure-percent","function":"format-percent","args":[{"field":"failure-share"}]},{"as":"followed-percent","function":"format-percent","args":[{"field":"followed-share"}]},{"as":"success-percent","function":"format-percent","args":[{"field":"success-rate"}]}],"order-by":[{"field":"routed-runs","direction":"desc"},{"field":"full-repository","direction":"asc"},{"field":"workflow","direction":"asc"}]},{"name":"routing-weekly-models","from":"routing-runs","subject":"Count proxy-selected runs by UTC ISO week and picked model.","objective":"Show what the router chooses over time.","acceptance":"Only selected runs with a known pick model and a recorded run clock contribute; an unrecorded effort does not exclude a run.","filter":{"predicates":[{"field":"routing-state","equals":"selected"},{"field":"unknown-pick-model","equals":false},{"field":"run-clock","gte":0}]},"compute":[{"as":"week","function":"date-bucket","args":[{"field":"observed-at"},{"value":"week"}]}],"aggregate":{"by":["week","pick-model"],"values":[{"field":"run","as":"runs","reducer":"count"}]},"order-by":[{"field":"week","direction":"asc"},{"field":"pick-model","direction":"asc"}]},{"name":"routing-weekly-paired-totals","from":"routing-runs","subject":"Weekly paired complete main-request costs by baseline model.","objective":"Compare routing cost trends with each named baseline using identical main-request populations.","acceptance":"Only timed runs with complete positive baseline estimates and matching known main-request costs contribute to both medians.","filter":{"predicates":[{"field":"paired","equals":true},{"field":"run-clock","gte":0}]},"compute":[{"as":"week","function":"date-bucket","args":[{"field":"observed-at"},{"value":"week"}]}],"aggregate":{"by":["week","baseline-model"],"values":[{"field":"run","as":"complete-runs","reducer":"count"},{"field":"paired-main-aic","as":"observed-main-median","reducer":"median"},{"field":"paired-baseline-aic","as":"baseline-estimate-median","reducer":"median"}]}},{"name":"routing-weekly-paired-cost","from":"routing-weekly-paired-totals","subject":"Paired main-request samples that meet the chosen evidence floor.","objective":"Avoid changing routing policy based on insufficient paired evidence.","acceptance":"Observed and estimated series share the same complete-run count and configurable minimum sample.","parameters":[{"name":"minimum-sample","type":"number"}],"compute":[{"as":"sample-floor","function":"difference","args":[{"parameter":"minimum-sample"},{"value":1}]},{"as":"enough-samples","function":"greater-than","args":[{"field":"complete-runs"},{"field":"sample-floor"}]}]},{"name":"routing-weekly-main-observed","from":"routing-weekly-paired-cost","subject":"Observed main-request AIC for the same eligible runs as each baseline.","objective":"Identify weeks when routed main-request costs exceed the matching baseline estimate.","acceptance":"Observed medians exclude classifier and sub-agent costs and remain unknown below the paired sample floor.","compute":[{"as":"cost-series","function":"concat","args":[{"value":"Main requests observed (baseline: "},{"field":"baseline-model"},{"value":")"}]},{"as":"median-aic","function":"if","args":[{"field":"enough-samples"},{"field":"observed-main-median"},{"value":null}]}]},{"name":"routing-weekly-baseline-estimate","from":"routing-weekly-paired-cost","subject":"Explicitly estimated baseline AIC for paired main-agent requests.","objective":"Show the named counterfactual against which owners can assess routing goal or mode.","acceptance":"The series is labelled estimated, separates baseline models and uses exactly the observed series' eligible runs.","compute":[{"as":"cost-series","function":"concat","args":[{"value":"Baseline estimate (estimated, main requests): "},{"field":"baseline-model"}]},{"as":"median-aic","function":"if","args":[{"field":"enough-samples"},{"field":"baseline-estimate-median"},{"value":null}]}]},{"name":"routing-weekly-cost","from":"routing-weekly-accounting-cost","union":["routing-weekly-main-observed","routing-weekly-baseline-estimate"],"subject":"Compare the same main-agent requests to an explicitly estimated baseline.","objective":"Change routing goal or mode when paired observed cost exceeds the named baseline.","acceptance":"Keep agent-phase accounting separate, baseline models distinct and sparse weeks as gaps.","order-by":[{"field":"week","direction":"asc"},{"field":"cost-series","direction":"asc"}]},{"name":"routing-failure-problems","from":"routing-runs","subject":"Runs whose routing failure codes require investigation.","objective":"Investigate routing configuration or execution failures before changing rollout.","acceptance":"Emit one row per run with recorded routing failure identifiers, excluding upstream errors handled by their own kind.","filter":{"predicates":[{"field":"routing-failure-codes","gte":""}]},"compute":[{"as":"problem-kind","function":"literal","args":[{"value":"routing failure"}]},{"as":"problem-cause","function":"coalesce","args":[{"field":"routing-failure-codes"},{"value":null}]}],"select":[{"field":"routing-run-key"},{"field":"problem-kind"},{"field":"problem-cause"}]},{"name":"routing-deviation-problems","from":"routing-runs","subject":"Runs whose requests deviated from the routing pick.","objective":"Investigate why requests did not follow the selected model or effort.","acceptance":"Emit one row per run with distinct recorded deviation causes, without inferring causes from model names.","filter":{"predicates":[{"field":"routing-deviation-codes","gte":""}]},"compute":[{"as":"problem-kind","function":"literal","args":[{"value":"deviation"}]},{"as":"problem-cause","function":"coalesce","args":[{"field":"routing-deviation-codes"},{"value":null}]}],"select":[{"field":"routing-run-key"},{"field":"problem-kind"},{"field":"problem-cause"}]},{"name":"routing-resolution-problems","from":"routing-runs","subject":"Runs whose configured models could not be resolved.","objective":"Correct model aliases or restore catalogue availability for failed resolutions.","acceptance":"Emit one row per run with recorded resolution failure causes, not absence of resolution evidence.","filter":{"predicates":[{"field":"routing-resolution-codes","gte":""}]},"compute":[{"as":"problem-kind","function":"literal","args":[{"value":"resolution failure"}]},{"as":"problem-cause","function":"coalesce","args":[{"field":"routing-resolution-codes"},{"value":null}]}],"select":[{"field":"routing-run-key"},{"field":"problem-kind"},{"field":"problem-cause"}]},{"name":"routing-upstream-problems","from":"routing-runs","subject":"Provider-rejected requests with distinct upstream error codes.","objective":"Correct model or effort settings rejected by the provider.","acceptance":"Emit one upstream-error row per run with distinct safe codes or unknown, never a duplicate generic routing failure.","filter":{"predicates":[{"field":"routing-upstream-codes","gte":""}]},"compute":[{"as":"problem-kind","function":"literal","args":[{"value":"upstream error"}]},{"as":"problem-cause","function":"coalesce","args":[{"field":"routing-upstream-codes"},{"value":null}]}],"select":[{"field":"routing-run-key"},{"field":"problem-kind"},{"field":"problem-cause"}]},{"name":"routing-candidate-problems","from":"routing-runs","subject":"Runs whose full eligible pool contains choices the router cannot rank.","objective":"Review allowed models when the router cannot rank the complete eligible pool.","acceptance":"Emit one row only when both pool counters are known and overlap is below eligibility, displaying the observed ratio.","filter":{"predicates":[{"field":"candidate-coverage","gte":""}]},"compute":[{"as":"problem-kind","function":"literal","args":[{"value":"candidates not rankable"}]},{"as":"problem-cause","function":"coalesce","args":[{"field":"candidate-coverage"},{"value":null}]}],"select":[{"field":"routing-run-key"},{"field":"problem-kind"},{"field":"problem-cause"}]},{"name":"routing-problems","from":"routing-failure-problems","union":["routing-deviation-problems","routing-resolution-problems","routing-upstream-problems","routing-candidate-problems"],"subject":"List routing failures, deviations and resolution failures with one row per run and kind.","objective":"Show what needs attention and link each problem to its run page.","acceptance":"Time is the run's recorded observation time and stays unknown without a run clock; untimed rows sort after timed rows.","joins":[{"source":"routing-runs","type":"inner","on":[{"left":"routing-run-key","right":"routing-run-key"}],"fields":[{"field":"run","as":"run"},{"field":"full-repository","as":"full-repository"},{"field":"workflow","as":"workflow"},{"field":"run-clock","as":"run-clock"},{"field":"observed-at","as":"observed-at"},{"field":"routing-dashboard-link","as":"routing-dashboard-link"}]}],"compute":[{"as":"untimed","function":"equals-any","args":[{"field":"run-clock"},{"value":null}]}],"order-by":[{"field":"untimed","direction":"asc"},{"field":"run-clock","direction":"desc"},{"field":"run","direction":"desc"},{"field":"problem-kind","direction":"asc"}]},{"name":"simulator-database-inputs","subject":"Model daily run volume and 30-day retained detail from user-supplied scenario inputs.","objective":"Compare hypothetical workload choices without treating results as observed activity.","acceptance":"Each simulated day uses the selected inputs; skipped runs retain summaries and detailed records have a 30-day lifetime.","description":"Each simulated day includes all accumulated run summaries; tools and issues belong only to non-skipped runs and expire after 30 days.","from":"simulation-days","parameters":[{"name":"repositories","type":"number"},{"name":"runs-per-day","type":"number"},{"name":"tools-per-run","type":"number"},{"name":"issues-per-run","type":"number"},{"name":"skip-rate","type":"number"}],"compute":[{"as":"runs-daily","function":"product","args":[{"parameter":"repositories"},{"parameter":"runs-per-day"}]},{"as":"skip-fraction","function":"quotient","args":[{"parameter":"skip-rate"},{"value":100}]},{"as":"active-fraction","function":"difference","args":[{"value":1},{"field":"skip-fraction"}]},{"as":"summary-runs","function":"product","args":[{"field":"day"},{"field":"runs-daily"}]},{"as":"past-ttl","function":"greater-than","args":[{"field":"day"},{"value":30}]},{"as":"detail-days","function":"if","args":[{"field":"past-ttl"},{"value":30},{"field":"day"}]},{"as":"detail-runs","function":"product","args":[{"field":"detail-days"},{"field":"runs-daily"},{"field":"active-fraction"}]},{"as":"tools-per-run","function":"literal","args":[{"parameter":"tools-per-run"}]},{"as":"issues-per-run","function":"literal","args":[{"parameter":"issues-per-run"}]}]},{"name":"simulator-run-size","subject":"Estimate retained run-summary table size at 512 bytes per run.","objective":"Show modeled accumulation of run summaries.","acceptance":"Summary size includes every simulated run at 512 bytes and is not presented as measured storage.","from":"simulator-database-inputs","compute":[{"as":"table","function":"literal","args":[{"value":"Run summaries"}]},{"as":"bytes","function":"product","args":[{"field":"summary-runs"},{"value":512}]}],"select":[{"field":"day"},{"field":"table"},{"field":"bytes"}]},{"name":"simulator-tool-size","subject":"Estimate retained tool table size at 256 bytes per tool on non-skipped runs.","objective":"Show modeled tool-record growth under the selected workload.","acceptance":"Tool size uses only non-skipped simulated runs and 256 bytes per tool over the retained period.","from":"simulator-database-inputs","compute":[{"as":"table","function":"literal","args":[{"value":"Tools (30-day TTL)"}]},{"as":"bytes","function":"product","args":[{"field":"detail-runs"},{"field":"tools-per-run"},{"value":256}]}],"select":[{"field":"day"},{"field":"table"},{"field":"bytes"}]},{"name":"simulator-issue-size","subject":"Estimate retained issue table size at 512 bytes per issue on non-skipped runs.","objective":"Show modeled issue-record growth under the selected workload.","acceptance":"Issue size uses only non-skipped simulated runs and 512 bytes per issue over the retained period.","from":"simulator-database-inputs","compute":[{"as":"table","function":"literal","args":[{"value":"Issues (30-day TTL)"}]},{"as":"bytes","function":"product","args":[{"field":"detail-runs"},{"field":"issues-per-run"},{"value":512}]}],"select":[{"field":"day"},{"field":"table"},{"field":"bytes"}]},{"name":"simulator-database-size","subject":"Show modeled run-summary, tool, and issue table bytes after 30 days.","objective":"Compare hypothetical database table sizes at the end of the retention horizon.","acceptance":"The model presents separate summary, tool, and issue estimates after 30 simulated days, never observed storage.","description":"Run summaries accumulate; detailed records have a 30-day TTL.","from":"simulator-run-size","union":["simulator-tool-size","simulator-issue-size"],"filter":{"predicates":[{"field":"day","equals":30}]},"select":[{"field":"table"},{"field":"bytes"}]},{"name":"simulator-database-total","subject":"Sum the modeled table sizes after 30 days.","objective":"Show the final estimated size of the modeled database tables.","acceptance":"The final value is the sum of the three modeled table sizes after 30 days.","from":"simulator-database-size","compute":[{"as":"total-label","function":"literal","args":[{"value":"Total"}]}],"aggregate":{"by":["total-label"],"values":[{"field":"bytes","as":"bytes","reducer":"sum"}]},"select":[{"field":"total-label","as":"table"},{"field":"bytes"}]},{"name":"simulator-database-summary","subject":"List modeled table sizes and their final total after 30 days.","objective":"Present the 30-day estimate in a compact table.","acceptance":"Three modeled table sizes and their summed final value are shown without a growth chart.","from":"simulator-database-size","union":["simulator-database-total"]},{"name":"overview-run-summary","subject":"Summarize successful, failed, and active runs with rollout-mode counts.","objective":"Expose observed success, failure, and active run counts, including active live and review modes, for the selected horizon.","acceptance":"Each count follows its declared conclusion, status, and rollout-mode filters; run success is not treated as a verified outcome, and incomplete or stale evidence is identified.","from":"overview-runs","aggregate":{"values":[{"field":"run-conclusion","as":"successful-runs","reducer":"count","filter":{"predicates":[{"field":"run-conclusion","equals":"success"}]}},{"field":"run-conclusion","as":"failed-runs","reducer":"count","filter":{"predicates":[{"field":"run-conclusion","in":["failure","startup-failure","stale","timed-out"]}]}},{"field":"run-status","as":"active-runs","reducer":"count","filter":{"predicates":[{"field":"run-status","in":["queued","in-progress","in_progress"]}]}},{"field":"run-status","as":"active-live","reducer":"count","filter":{"predicates":[{"field":"run-status","in":["queued","in-progress","in_progress"]},{"field":"rollout-mode","equals":"live"}]}},{"field":"run-status","as":"active-review","reducer":"count","filter":{"predicates":[{"field":"run-status","in":["queued","in-progress","in_progress"]},{"field":"rollout-mode","equals":"review"}]}}]}},{"name":"overview-delivery-summary","subject":"Count distinct target repositories with successful worker dispatch runs in the selected horizon.","objective":"Measure observed reach among registered repositories with successful dispatched worker runs.","acceptance":"Distinct delivered-repositories is limited to registered targets and successful workflow_dispatch worker runs in the selected horizon; it does not establish accepted delivery or authorized coverage.","from":"overview-runs","joins":[{"source":"repositories","type":"inner","on":[{"left":"target-repository","right":"repository-coordinate"}],"fields":[{"field":"repository-coordinate","as":"registered-target-repository"}]}],"filter":{"predicates":[{"field":"event","equals":"workflow_dispatch"},{"field":"run-conclusion","equals":"success"},{"field":"workflow-role","equals":"worker"}]},"aggregate":{"values":[{"field":"target-repository","as":"delivered-repositories","reducer":"distinct-count"}]}},{"name":"overview-value-summary","subject":"Count all observed grader results.","objective":"Identify whether any grader observations are available to the Overview status presentation.","acceptance":"The value-gains field counts observed grader records only; inspect each result's native measure, unit, direction, maturity, and uncertainty before claiming an outcome or improvement.","from":"grader-observations","aggregate":{"values":[{"field":"grader","as":"value-gains","reducer":"count"}]}},{"name":"overview-issue-summary","subject":"Count retained issue and pull request safe-output records for Overview.","objective":"Restore the issue and pull request counter with a link to its evidence inventory.","acceptance":"The count includes retained canonical issue and pull request records, not inferred outcomes; unavailable evidence remains unavailable.","from":"issues","aggregate":{"values":[{"field":"id","as":"value","reducer":"count"}]},"limit":1},{"name":"overview-issue-station","subject":"Present the retained issue and pull request count for Overview.","objective":"Provide a presentation-ready count and accessible evidence description.","acceptance":"The value matches overview-issue-summary and describes retained safe outputs, not accepted outcomes.","from":"overview-issue-summary","compute":[{"as":"detail","function":"concat","args":[{"value":"Retained safe"},{"value":" outputs"}]},{"as":"description","function":"concat","args":[{"field":"value"},{"value":" retained issues and pull requests"}]}],"limit":1},{"name":"overview-value-station","subject":"Present the observed grader-result count as the legacy Value gains counter.","objective":"Restore the Value gains counter while making its observation-count semantics explicit.","acceptance":"The count matches overview-value-summary, including zero; grader presence is not proof of improvement and unavailable evidence is not zero.","from":"overview-value-summary","compute":[{"as":"detail","function":"concat","args":[{"value":"Observed grader"},{"value":" results"}]},{"as":"description","function":"concat","args":[{"field":"value-gains"},{"value":" observed grader results, not verified improvements"}]}],"select":[{"field":"value-gains","as":"value"},{"field":"detail"},{"field":"description"}],"limit":1},{"name":"overview-run-status-input","subject":"Prepare the compact run summary for declarative factory status classification.","objective":"Carry successful-runs, failed-runs, and active-runs into the status join without changing their meaning.","acceptance":"The projected counts retain the selected horizon and match overview-run-summary; the join key is only a presentation key, not additional evidence.","from":"overview-run-summary","compute":[{"as":"status-join-key","function":"concat","args":[{"value":"factory"},{"value":"-status"}]}],"select":[{"field":"status-join-key"},{"field":"successful-runs"},{"field":"failed-runs"},{"field":"active-runs"}]},{"name":"overview-value-status-input","subject":"Prepare the compact value summary for declarative factory status classification.","objective":"Carry the grader-observation count into the optional status join.","acceptance":"The projected value-gains count matches overview-value-summary; a zero count does not establish complete grader coverage, and a nonzero count is not proof of gain.","from":"overview-value-summary","compute":[{"as":"status-join-key","function":"concat","args":[{"value":"factory"},{"value":"-status"}]}],"select":[{"field":"status-join-key"},{"field":"value-gains"}]},{"name":"overview-factory-status","subject":"Classify the factory heading from compact run and optional value evidence.","objective":"Provide a bounded Overview heading based on observed run counts and optional grader-record presence.","acceptance":"The heading matches the declared run-count and optional grader-presence branches; grader presence is not verified value, and the heading does not authorize any policy change.","from":"overview-run-status-input","joins":[{"source":"overview-value-status-input","type":"left","on":[{"left":"status-join-key","right":"status-join-key"}],"fields":[{"field":"value-gains","as":"value-gains"}]}],"compute":[{"as":"has-successful-runs","function":"greater-than","args":[{"field":"successful-runs"},{"value":0}]},{"as":"has-failed-runs","function":"greater-than","args":[{"field":"failed-runs"},{"value":0}]},{"as":"failures-exceed-successes","function":"greater-than","args":[{"field":"failed-runs"},{"field":"successful-runs"}]},{"as":"has-active-runs","function":"greater-than","args":[{"field":"active-runs"},{"value":0}]},{"as":"has-value-gains","function":"greater-than","args":[{"field":"value-gains"},{"value":0}]},{"as":"successful-heading","function":"if","args":[{"field":"has-successful-runs"},{"value":"Your factory is humming."},{"value":"Your factory is idle."}]},{"as":"attention-heading","function":"if","args":[{"field":"has-failed-runs"},{"value":"Your factory needs attention."},{"field":"successful-heading"}]},{"as":"strain-heading","function":"if","args":[{"field":"failures-exceed-successes"},{"value":"Your factory is under strain."},{"field":"attention-heading"}]},{"as":"active-heading","function":"if","args":[{"field":"has-active-runs"},{"value":"Your factory is humming."},{"field":"strain-heading"}]},{"as":"factory-heading","function":"if","args":[{"field":"has-value-gains"},{"value":"Your factory is delivering value."},{"field":"active-heading"}]}],"select":[{"field":"factory-heading"}]},{"name":"overview-registered-repository-summary","subject":"Count canonical repository identities registered in the resolved control-plane scope.","objective":"Provide the registered-repository denominator for observed worker reach.","acceptance":"The count reflects canonical repository records in the resolved scope; it is not evidence of live enrollment, successful execution, or full inventory completeness.","from":"repositories","aggregate":{"values":[{"field":"repository","as":"registered-repositories","reducer":"count"}]}},{"name":"overview-delivery-coverage-input","subject":"Prepare successful delivery totals for the repository coverage summary.","objective":"Carry the distinct delivered-repositories count into the coverage join.","acceptance":"The projected count equals overview-delivery-summary for the selected horizon; the join key adds no repository observations.","from":"overview-delivery-summary","compute":[{"as":"coverage-key","function":"concat","args":[{"value":"repository-coverage"},{"value":""}]}],"select":[{"field":"delivered-repositories"},{"field":"coverage-key"}]},{"name":"overview-registered-repository-coverage-input","subject":"Prepare registered repository totals for the repository coverage summary.","objective":"Carry the registered-repositories count into the coverage denominator join.","acceptance":"The projected count equals overview-registered-repository-summary for the resolved scope; missing inventory is not treated as zero eligible targets.","from":"overview-registered-repository-summary","compute":[{"as":"coverage-key","function":"concat","args":[{"value":"repository-coverage"},{"value":""}]}],"select":[{"field":"registered-repositories"},{"field":"coverage-key"}]},{"name":"overview-rhythm","subject":"Compare all workflow runs by weekday, layering this week over last week.","objective":"Show the observed weekday pattern across both calendar weeks, regardless of status or conclusion.","acceptance":"Verify weekday order, counts including unsuccessful and in-flight runs, and reached-day flags. Missing rhythm is unavailable, not zero activity; do not attribute changes to workflow improvements.","from":"overview-runs","time":{"range":"15d"},"compute":[{"as":"rhythm-point","function":"calendar-week-point","args":[{"field":"started-at"},{"context":"time-end"},{"value":true}]}],"aggregate":{"values":[{"field":"rhythm-point","as":"rhythm","reducer":"calendar-week-rhythm"}]}},{"name":"overview-repository-coverage-summary","subject":"Aggregate reached and total repositories across the resolved organization scope.","objective":"Pair observed reached-repositories and registered-repositories-total for a comparable coverage denominator.","acceptance":"Both totals come from their named input queries and share the resolved scope; verify the left-joined inventory source independently before interpreting a zero total, since a missing join can aggregate to zero.","from":"overview-delivery-coverage-input","joins":[{"source":"overview-registered-repository-coverage-input","type":"left","on":[{"left":"coverage-key","right":"coverage-key"}],"fields":[{"field":"registered-repositories","as":"registered-repositories-total"}]}],"aggregate":{"values":[{"field":"delivered-repositories","as":"reached-repositories","reducer":"sum"},{"field":"registered-repositories-total","as":"registered-repositories-total","reducer":"sum"}]}},{"name":"overview-repository-coverage","subject":"Measure registered repository reach from successful worker execution.","objective":"Present observed successful-worker repository reach as a ratio alongside numerator and denominator.","acceptance":"repository-coverage is reached-repositories divided by registered-repositories-total when available; preserve the counts and undefined denominator, and do not call reach successful outcomes.","from":"overview-repository-coverage-summary","compute":[{"as":"repository-coverage","function":"quotient","args":[{"field":"reached-repositories"},{"field":"registered-repositories-total"}]}],"select":[{"field":"repository-coverage"},{"field":"reached-repositories"},{"field":"registered-repositories-total"}]},{"name":"overview-workflow-health-groups","subject":"Assess current runtime failures for every workflow across CAO and targeted repositories.","objective":"Compute the latest consecutive completed-run failure streak for each repository-scoped workflow without requiring campaign membership.","acceptance":"Group by organization, repository, and workflow; in-flight retries do not clear failures, and later non-failing completed runs reset the streak within the selected horizon.","from":"overview-runs","filter":{"predicates":[{"field":"run-status","equals":"completed"}]},"compute":[{"as":"is-runtime-failure","function":"equals-any","args":[{"field":"run-conclusion"},{"value":"failure"},{"value":"startup-failure"},{"value":"stale"},{"value":"timed-out"}]},{"as":"runtime-failure-streak-point","function":"failure-streak-point","args":[{"field":"started-at"},{"field":"run"},{"field":"is-runtime-failure"}]}],"aggregate":{"by":["organization","repository","workflow"],"values":[{"field":"runtime-failure-streak-point","as":"failure-count","reducer":"latest-failure-streak"}]}},{"name":"overview-workflow-health-summary","subject":"Count all registered workflows and those without current observed runtime failures.","objective":"Provide Factory health numerator and denominator across CAO and targeted repositories, including standalone and campaign workflows.","acceptance":"Each repository-scoped workflow counts once regardless of campaign or role; no retained failure is not proof of successful execution, missing inventory remains unavailable, and missing run evidence marks the result incomplete.","from":"workflows","joins":[{"source":"overview-workflow-health-groups","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"}],"fields":[{"field":"failure-count","as":"observed-failures"}]}],"compute":[{"as":"normalized-failures","function":"coalesce","args":[{"field":"observed-failures"},{"value":0}]},{"as":"problem-present","function":"greater-than","args":[{"field":"normalized-failures"},{"value":0}]}],"aggregate":{"values":[{"field":"workflow","as":"workflows","reducer":"count"},{"field":"workflow","as":"healthy-workflows","reducer":"count","filter":{"predicates":[{"field":"problem-present","equals":false}]}}]}},{"name":"overview-workflow-health-presentation-input","subject":"Prepare all-workflow health counts for Overview presentation.","objective":"Carry Factory health counts into the header and station presentation.","acceptance":"Both counts match overview-workflow-health-summary and preserve missing evidence metadata.","from":"overview-workflow-health-summary","compute":[{"as":"overview-presentation-key","function":"concat","args":[{"value":"overview"},{"value":"-presentation"}]}],"select":[{"field":"overview-presentation-key"},{"field":"workflows"},{"field":"healthy-workflows"}]},{"name":"overview-factory-health-presentation","subject":"Produce presentation-ready Factory health values for the Overview header and floor.","objective":"Display the ratio of workflows without current observed runtime failures to all registered workflows with both underlying counts.","acceptance":"The percentage and detail agree with healthy-workflows and workflows; a missing or zero denominator remains unavailable, and the ratio is not proof of impact.","from":"overview-workflow-health-presentation-input","compute":[{"as":"factory-health","function":"quotient","args":[{"field":"healthy-workflows"},{"field":"workflows"}]},{"as":"factory-health-display","function":"format-percent","args":[{"field":"factory-health"}]},{"as":"healthy-workflows-display","function":"format-count","args":[{"field":"healthy-workflows"}]},{"as":"workflows-display","function":"format-count","args":[{"field":"workflows"}]},{"as":"factory-health-detail","function":"concat","args":[{"field":"healthy-workflows-display"},{"value":"/"},{"field":"workflows-display"},{"value":" healthy workflows"}]},{"as":"factory-health-description","function":"concat","args":[{"field":"factory-health-display"},{"value":" factory health"}]}],"select":[{"field":"overview-presentation-key"},{"field":"factory-health"},{"field":"factory-health-display"},{"field":"factory-health-detail"},{"field":"factory-health-description"}]},{"name":"overview-header-status-presentation-input","subject":"Prepare the factory status heading for the declarative Overview header.","objective":"Carry the factory heading into the Overview header join unchanged.","acceptance":"The heading matches overview-factory-status; the presentation key does not imply additional evidence or a policy recommendation.","from":"overview-factory-status","compute":[{"as":"overview-presentation-key","function":"concat","args":[{"value":"overview"},{"value":"-presentation"}]}],"select":[{"field":"overview-presentation-key"},{"field":"factory-heading"}]},{"name":"overview-header-presentation","subject":"Resolve the Overview heading from declarative status and factory-health evidence.","objective":"Display the configured heading corresponding to observed run status and factory health.","acceptance":"The selected heading follows the declared presentation branches; numeric branch boundaries are UI classification only, not operational targets or rollout thresholds.","from":"overview-header-status-presentation-input","joins":[{"source":"overview-factory-health-presentation","type":"left","on":[{"left":"overview-presentation-key","right":"overview-presentation-key"}],"fields":[{"field":"factory-health","as":"factory-health"}]}],"compute":[{"as":"factory-health-positive","function":"greater-than","args":[{"field":"factory-health"},{"value":0}]},{"as":"factory-health-below-threshold","function":"greater-than","args":[{"value":0.66},{"field":"factory-health"}]},{"as":"positive-factory-health-heading","function":"if","args":[{"field":"factory-health-below-threshold"},{"value":"Your factory needs attention."},{"field":"factory-heading"}]},{"as":"heading","function":"if","args":[{"field":"factory-health-positive"},{"field":"positive-factory-health-heading"},{"field":"factory-heading"}]}],"select":[{"field":"heading"}]},{"name":"overview-run-motion-presentation-input","subject":"Prepare active run state for Overview station presentation.","objective":"Expose whether at least one queued or in-progress run was observed for station display.","acceptance":"active reflects overview-run-summary's active-runs count; no observed active run does not prove the fleet is idle when the snapshot is incomplete.","from":"overview-run-summary","compute":[{"as":"overview-presentation-key","function":"concat","args":[{"value":"overview"},{"value":"-presentation"}]},{"as":"active","function":"greater-than","args":[{"field":"active-runs"},{"value":0}]}],"select":[{"field":"overview-presentation-key"},{"field":"active"}]},{"name":"overview-factory-station","subject":"Provide the presentation-ready Factory health station for Overview.","objective":"Show the all-workflow runtime health ratio, supporting counts, and observed run motion together.","acceptance":"Station value, display, detail, description, and active flag match their input queries; neither absence of failures nor run motion is verified workflow effectiveness.","from":"overview-factory-health-presentation","joins":[{"source":"overview-run-motion-presentation-input","type":"left","on":[{"left":"overview-presentation-key","right":"overview-presentation-key"}],"fields":[{"field":"active","as":"active"}]}],"select":[{"field":"factory-health","as":"value"},{"field":"factory-health-display","as":"display-value"},{"field":"factory-health-detail","as":"detail"},{"field":"factory-health-description","as":"description"},{"field":"active"}]},{"name":"overview-repository-station-presentation-input","subject":"Prepare repository coverage for the presentation-ready Overview station.","objective":"Format repository reach with its reached and registered counts for the station.","acceptance":"The percentage and detail preserve overview-repository-coverage's numerator and denominator; unavailable coverage remains unavailable, not zero or complete reach.","from":"overview-repository-coverage","compute":[{"as":"overview-presentation-key","function":"concat","args":[{"value":"overview"},{"value":"-presentation"}]},{"as":"display-value","function":"format-percent","args":[{"field":"repository-coverage"}]},{"as":"reached-repositories-display","function":"format-count","args":[{"field":"reached-repositories"}]},{"as":"registered-repositories-display","function":"format-count","args":[{"field":"registered-repositories-total"}]},{"as":"detail","function":"concat","args":[{"field":"reached-repositories-display"},{"value":"/"},{"field":"registered-repositories-display"},{"value":" repositories reached"}]},{"as":"description","function":"concat","args":[{"field":"display-value"},{"value":" average repository coverage"}]}],"select":[{"field":"overview-presentation-key"},{"field":"repository-coverage","as":"value"},{"field":"display-value"},{"field":"detail"},{"field":"description"}]},{"name":"overview-repository-station","subject":"Provide the presentation-ready repository coverage station for Overview.","objective":"Show observed registered-repository worker reach and run motion in one station.","acceptance":"Value and formatted evidence match the coverage presentation input, and active matches run motion; neither changes policy or establishes accepted outcomes.","from":"overview-repository-station-presentation-input","joins":[{"source":"overview-run-motion-presentation-input","type":"left","on":[{"left":"overview-presentation-key","right":"overview-presentation-key"}],"fields":[{"field":"active","as":"active"}]}],"select":[{"field":"value"},{"field":"display-value"},{"field":"detail"},{"field":"description"},{"field":"active"}]},{"name":"cost-by-repository","subject":"Present observed AI Credit cost grouped by repository.","objective":"Locate repositories with higher observed AI Credit totals for evidence-led investigation.","acceptance":"Each repository coordinate and native aic total agrees with repository-aic-totals; confirm the selected horizon and underlying runs before attributing cost or proposing a change.","from":"repository-aic-totals","compute":[{"as":"repository-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"encoded-repository","function":"url-encode","args":[{"field":"repository-coordinate"}]},{"as":"repository-dashboard-href","function":"concat","args":[{"value":"#page-repository-detail?repository="},{"field":"encoded-repository"}]},{"as":"repository-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"repository-coordinate"},{"value":" repository dashboard"}]},{"as":"repository-dashboard-link","function":"dashboard-link","args":[{"value":""},{"field":"repository-dashboard-href"},{"field":"repository-dashboard-label"},{"field":"repository-coordinate"}]}],"select":[{"field":"repository-coordinate"},{"field":"repository-dashboard-link"},{"field":"aic"}],"order-by":[{"field":"aic","direction":"desc"}]},{"name":"cost-by-workflow","subject":"Present observed AI Credit cost grouped by repository-owned workflow.","objective":"Locate repository workflows with higher observed AI Credit totals and open their workflow evidence.","acceptance":"Workflow identity, link, and native aic total match workflow-aic-totals in descending order; cost alone does not establish waste, quality, or value.","from":"workflow-aic-totals","compute":[{"as":"repository-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"workflow-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"},{"value":":"},{"field":"workflow"}]},{"as":"encoded-workflow","function":"url-encode","args":[{"field":"workflow-coordinate"}]},{"as":"workflow-dashboard-href","function":"concat","args":[{"value":"#page-workflow-runtime?workflow="},{"field":"encoded-workflow"}]},{"as":"workflow-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"workflow-coordinate"},{"value":" workflow dashboard"}]},{"as":"workflow-dashboard-link","function":"dashboard-link","args":[{"value":""},{"field":"workflow-dashboard-href"},{"field":"workflow-dashboard-label"},{"field":"workflow-coordinate"}]}],"select":[{"field":"repository-coordinate"},{"field":"workflow"},{"field":"workflow-coordinate"},{"field":"workflow-dashboard-link"},{"field":"aic"}],"order-by":[{"field":"aic","direction":"desc"}]},{"name":"cost-per-workflow-run","subject":"Present the average observed AI Credit cost of a single run for each repository-owned workflow.","objective":"Compare observed AI Credit per run across repository workflows with each observed-runs denominator.","acceptance":"Include only workflows with positive-AIC run attempts, and use only those attempts in cost averages; observed-runs still counts all retained attempts.","description":"Observed AI Credit totals divided by positive-AIC run attempts for each declared workflow.","from":"workflow-aic-run-totals","filter":{"predicates":[{"field":"aic-runs","gte":1}]},"compute":[{"as":"aic-per-run","function":"quotient","args":[{"field":"aic"},{"field":"aic-runs"}]},{"as":"repository-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"workflow-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"},{"value":":"},{"field":"workflow"}]},{"as":"encoded-workflow","function":"url-encode","args":[{"field":"workflow-coordinate"}]},{"as":"workflow-dashboard-href","function":"concat","args":[{"value":"#page-workflow-runtime?workflow="},{"field":"encoded-workflow"}]},{"as":"workflow-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"workflow-coordinate"},{"value":" workflow dashboard"}]},{"as":"workflow-dashboard-link","function":"dashboard-link","args":[{"value":""},{"field":"workflow-dashboard-href"},{"field":"workflow-dashboard-label"},{"field":"workflow-coordinate"}]}],"select":[{"field":"repository-coordinate"},{"field":"workflow"},{"field":"workflow-coordinate"},{"field":"workflow-dashboard-link"},{"field":"runs","as":"observed-runs"},{"field":"aic-per-run"}],"order-by":[{"field":"aic-per-run","direction":"desc"}]},{"name":"failure-run-base","subject":"Select retained runs with failure, startup-failure, stale, or timed-out conclusions for the failed-run ledger and streak inputs.","objective":"Provide one consistent failure-conclusion evidence set to downstream Overview queries.","acceptance":"Each selected run has one of the four declared conclusions within the selected horizon; other conclusions remain outside this set, and missing run coverage is not interpreted as no failures.","from":"runs","filter":{"predicates":[{"field":"run-conclusion","in":["failure","startup-failure","stale","timed-out"]}]}},{"name":"failed-runs","subject":"List failed workflow runs that need operator attention.","objective":"Give operators the most recent observed failed runs to inspect in GitHub.","acceptance":"Unprojected run rows retain available conclusion, started-at, and run evidence fields in descending started-at order; inspect source logs and missing links before attributing a cause or declaring resolution.","from":"failure-run-base","order-by":[{"field":"started-at","direction":"desc"}]},{"name":"overview-failing-runs","subject":"Identify failed runs in the selected snapshot horizon so subsequent streak logic can use the same declarative failure definition.","objective":"Project distinct failure-run counts by organization, repository, workflow, and run for streak joins.","acceptance":"Each grouped run identity has a failing-runs count derived from failure-run-base in the selected horizon; this stage does not assert a consecutive streak or require action.","from":"failure-run-base","aggregate":{"by":["organization","repository","workflow","run"],"values":[{"field":"run","as":"failing-runs","reducer":"distinct-count"}]}},{"name":"overview-failing-workflows","subject":"Identify only workflows that have at least one failed run in the selected snapshot horizon before computing streaks.","objective":"Provide workflow identities with observed failed runs for the streak computation.","acceptance":"Each organization/repository/workflow group has a distinct failing-runs count from overview-failing-runs; the count covers observed failures, not the latest consecutive streak.","from":"overview-failing-runs","aggregate":{"by":["organization","repository","workflow"],"values":[{"field":"run","as":"failing-runs","reducer":"distinct-count"}]}},{"name":"overview-repeated-failure-groups","subject":"Group each workflow's latest consecutive failing run sequence in the selected snapshot horizon, resetting the group after any successful run.","objective":"Project the latest observed consecutive failure-count per workflow for downstream blocked-work matching.","acceptance":"failure-count follows run ordering and the declared latest-failure-streak reducer, with non-failing runs breaking the streak; missing earlier runs or incomplete snapshots limit the observed sequence.","from":"runs","joins":[{"source":"overview-failing-workflows","type":"inner","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"}],"fields":[{"field":"failing-runs","as":"failing-runs"}]},{"source":"overview-failing-runs","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"},{"left":"run","right":"run"}],"fields":[{"field":"failing-runs","as":"run-failing-count"}]}],"compute":[{"as":"failure-streak-point","function":"failure-streak-point","args":[{"field":"started-at"},{"field":"run"},{"field":"run-failing-count"}]}],"aggregate":{"by":["organization","repository","workflow"],"values":[{"field":"failure-streak-point","as":"failure-count","reducer":"latest-failure-streak"}]}},{"name":"overview-repeated-failure-candidates","subject":"Attach selected-horizon failure counts to each workflow's latest canonical work item.","objective":"Pair blocked work items with observed workflow failure streaks and retained run evidence before attention filtering.","acceptance":"Candidates are filtered to blocked items with a matching organization/repository/workflow streak; is-repeated reflects failure-count greater than one, while selected evidence-link and run-link can be absent or refer to the work item rather than the latest failed run.","from":"work-items","joins":[{"source":"overview-repeated-failure-groups","type":"inner","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"}],"fields":[{"field":"failure-count","as":"failure-count"}]}],"filter":{"predicates":[{"field":"lifecycle-state","equals":"blocked"}]},"compute":[{"as":"is-repeated","function":"greater-than","args":[{"field":"failure-count"},{"value":1}]},{"as":"attention-signal-id","function":"concat","args":[{"value":"repeated-failure:"},{"field":"organization"},{"value":"/"},{"field":"repository"},{"value":":"},{"field":"workflow"}]},{"as":"kind","function":"coalesce","args":[{"value":"Repeated workflow failures"},{"value":"Repeated workflow failures"}]},{"as":"title","function":"coalesce","args":[{"field":"workflow"},{"value":"Workflow"}]},{"as":"attention-reason","function":"concat","args":[{"field":"failure-count"},{"value":" failed runs in the selected horizon"}]},{"as":"action","function":"coalesce","args":[{"value":"Open latest failed run on GitHub"},{"value":"Open latest failed run on GitHub"}]},{"as":"icon","function":"coalesce","args":[{"value":"x-circle"},{"value":"x-circle"}]},{"as":"tone","function":"coalesce","args":[{"value":"critical"},{"value":"critical"}]},{"as":"priority","function":"number","args":[{"value":0}]}],"select":[{"field":"is-repeated"},{"field":"attention-signal-id"},{"field":"kind"},{"field":"title"},{"field":"scope"},{"field":"attention-reason","as":"reason"},{"field":"observed-at"},{"field":"action"},{"field":"evidence-link"},{"field":"run-link"},{"field":"icon"},{"field":"tone"},{"field":"priority"},{"field":"failure-count"}]},{"name":"overview-repeated-failure-attention","subject":"Keep only unresolved workflows with two or more failures in the selected horizon.","objective":"Surface blocked workflow items with observed repeated failures for bounded run investigation.","acceptance":"Every row inherits a blocked item with is-repeated true and projects evidence-link and run-link when available; verify run order, links, and current state before treating the failure as still unresolved.","from":"overview-repeated-failure-candidates","filter":{"predicates":[{"field":"is-repeated","equals":true}]},"select":[{"field":"attention-signal-id"},{"field":"kind"},{"field":"title"},{"field":"scope"},{"field":"reason"},{"field":"observed-at"},{"field":"action"},{"field":"evidence-link"},{"field":"run-link"},{"field":"icon"},{"field":"tone"},{"field":"priority"},{"field":"failure-count"}]},{"name":"overview-review-attention","subject":"Select only unresolved outputs explicitly awaiting human review with their retained GitHub evidence destination.","objective":"Present review-state work items and their retained GitHub destination to a human reviewer.","acceptance":"Rows are filtered to lifecycle-state review and project the work-item ID as attention-signal-id, plus reason, evidence-link, and run-link where present; reviewer disposition must be checked at source.","from":"work-items","filter":{"predicates":[{"field":"lifecycle-state","equals":"review"}]},"compute":[{"as":"kind","function":"coalesce","args":[{"value":"Human review required"},{"value":"Human review required"}]},{"as":"title","function":"coalesce","args":[{"field":"objective"},{"value":"Produced output"}]},{"as":"action","function":"coalesce","args":[{"value":"Open review item on GitHub"},{"value":"Open review item on GitHub"}]},{"as":"icon","function":"coalesce","args":[{"value":"eye"},{"value":"eye"}]},{"as":"tone","function":"coalesce","args":[{"value":"action"},{"value":"action"}]},{"as":"priority","function":"number","args":[{"value":1}]}],"select":[{"field":"work-item-id","as":"attention-signal-id"},{"field":"kind"},{"field":"title"},{"field":"scope"},{"field":"reason"},{"field":"observed-at"},{"field":"action"},{"field":"evidence-link"},{"field":"run-link"},{"field":"icon"},{"field":"tone"},{"field":"priority"}]},{"name":"overview-needs-attention","subject":"Combine grouped repeated failures and unresolved review outputs without introducing ordinary activity or duplicate work items.","objective":"Prioritize observed blocked repeated-failure work and review-state outputs for investigation.","acceptance":"Rows come only from the repeated-failure or review inputs and retain their source reasons, links, and ordering; confirm fresh source status before acting, and do not equate a missing row with resolved work.","from":"overview-repeated-failure-attention","union":["overview-review-attention"],"order-by":[{"field":"priority","direction":"asc"},{"field":"observed-at","direction":"desc"},{"field":"attention-signal-id","direction":"asc"}]},{"name":"domain-route-record","subject":"Project the selected domain header and one retained run link.","objective":"Identify the selected domain and open a retained run before investigating its traffic evidence.","acceptance":"The route header preserves the selected domain and a run link from its retained observations; missing observations or links remain unavailable, and a header does not establish access policy or traffic completeness.","from":"domains","select":[{"field":"domain"},{"field":"run-link"}]},{"name":"domain-run-records","subject":"Retained run-linked observations for the selected domain.","objective":"Find related runs without returning the unscoped domain collection alongside the paginated view.","acceptance":"Preserve every domain observation field, exact route scope, filtering, ordering, total count, provenance and related-run links; only the bounded view payload crosses the worker boundary.","from":"domains"},{"name":"tool-route-record","subject":"Project the selected MCP tool header and one retained run link.","objective":"Identify the selected MCP tool and open a retained run before investigating its call evidence.","acceptance":"The route header preserves the selected MCP tool label and a run link from its retained calls; absent calls or links remain unavailable and do not imply zero usage or tool effectiveness.","from":"mcp-tool-calls","select":[{"field":"mcp-tool-label"},{"field":"run-link"}]},{"name":"audit-route-record","subject":"Project the selected audit summary header and one retained run link.","objective":"Identify the selected audit summary and open a retained run before investigating its observations.","acceptance":"The route header preserves the selected event summary and a run link from its retained audit observations; absent evidence remains unavailable and neither the header nor its absence establishes incident severity or a clean audit.","from":"audits","select":[{"field":"event-summary"},{"field":"run-link"}]},{"name":"domain-entity-insights","subject":"Summarize one domain entity for its dedicated Insights view.","objective":"Identify domain decisions with request volume worth investigating before considering any egress change.","acceptance":"For the selected domain, request totals match the retained domain observations grouped by decision; missing data or blocked traffic does not establish a need for access, which requires underlying request and policy review.","from":"domains","aggregate":{"by":["domain","decision"],"values":[{"field":"request-count","as":"requests","reducer":"sum"}]},"order-by":[{"field":"requests","direction":"desc"},{"field":"decision","direction":"asc"}]},{"name":"tool-entity-insights","subject":"Summarize one tool entity for its dedicated Insights view.","objective":"Select a tool and status combination whose recorded call volume merits investigation.","acceptance":"For the selected tool, observation counts match retained MCP call observations grouped by server, tool, and status; missing calls are not zero usage and status counts do not establish effectiveness or cause.","from":"mcp-tool-calls","aggregate":{"by":["mcp-tool-label","mcp-server","mcp-tool","mcp-status"],"values":[{"field":"mcp-observation","as":"observations","reducer":"count"}]},"order-by":[{"field":"observations","direction":"desc"},{"field":"mcp-status","direction":"asc"}]},{"name":"audit-entity-insights","subject":"Summarize one audit event entity for its dedicated Insights view.","objective":"Select an audit summary and status requiring closer review of underlying observations.","acceptance":"For the selected summary, counts agree with retained audit observation IDs grouped by event status; repeated observations are not silently treated as distinct incidents, and absence does not prove no findings.","from":"audits","aggregate":{"by":["event-summary","event-status"],"values":[{"field":"id","as":"observations","reducer":"count"}]},"order-by":[{"field":"observations","direction":"desc"},{"field":"event-status","direction":"asc"}]}] +[{"name":"command-queue","subject":"Show the durable local CLI command queue.","objective":"Inspect command lifecycle and reconnect to output without rerunning work.","acceptance":"Preserve persistent command IDs and all six server states; closing output never cancels execution. Unavailable local authority is not an empty queue.","from":"cli-commands","compute":[{"as":"command-action","function":"coalesce","args":[{"field":"actionId"},{"value":""}]},{"as":"command-title","function":"coalesce","args":[{"field":"command"},{"field":"actionId"}]},{"as":"command-target","function":"coalesce","args":[{"field":"repository"},{"field":"campaign"},{"field":"package-source"},{"value":"Local control repository"}]},{"as":"command-created-at","function":"coalesce","args":[{"field":"createdAt"},{"value":null}]},{"as":"command-href","function":"concat","args":[{"value":"#page-command?command="},{"field":"id"}]},{"as":"command-dashboard-link","function":"dashboard-link","args":[{"value":""},{"field":"command-href"},{"field":"command-title"},{"field":"id"}]}]},{"name":"event-base","subject":"Project shared event fields before combining run-owned records.","objective":"Provide the narrow retained event evidence needed for inspection and run import-coverage analysis.","acceptance":"The result unions retained audit, domain, tool, and issue records with their available run identity; an empty or unavailable preview cannot establish zero source activity or complete import coverage.","from":"audits","union":["domains","tools","issues"],"select":[{"field":"organization"},{"field":"repository"},{"field":"workflow"},{"field":"run"},{"field":"run-attempt"},{"field":"event"},{"field":"event-source"},{"field":"event-type"},{"field":"event-summary"},{"field":"event-status"},{"field":"github-entity-type"},{"field":"safe-output-type"},{"field":"safe-output-url"},{"field":"correlation-id"},{"field":"implementation-pull-request-url"},{"field":"event-timestamp"},{"field":"run-link"}]},{"name":"audit-event-runs","subject":"Count imported audit records per run before combining event sources.","objective":"Bound audit evidence for run import-coverage analysis.","acceptance":"Count only retained audit records with event identity by run attempt; missing evidence does not establish zero activity.","from":"audits","aggregate":{"by":["organization","repository","workflow","run","run-attempt"],"values":[{"field":"event","as":"events","reducer":"count"}]}},{"name":"domain-event-runs","subject":"Count imported domain records per run before combining event sources.","objective":"Bound domain evidence for run import-coverage analysis.","acceptance":"Count only retained domain records with event identity by run attempt; missing evidence does not establish zero activity.","from":"domains","aggregate":{"by":["organization","repository","workflow","run","run-attempt"],"values":[{"field":"event","as":"events","reducer":"count"}]}},{"name":"tool-event-runs","subject":"Count imported tool records per run before combining event sources.","objective":"Bound tool evidence for run import-coverage analysis.","acceptance":"Count only retained tool records with event identity by run attempt; missing evidence does not establish zero activity.","from":"tools","aggregate":{"by":["organization","repository","workflow","run","run-attempt"],"values":[{"field":"event","as":"events","reducer":"count"}]}},{"name":"issue-event-runs","subject":"Count imported issue records per run before combining event sources.","objective":"Bound issue evidence for run import-coverage analysis.","acceptance":"Count only retained issue records with event identity by run attempt; missing evidence does not establish zero activity.","from":"issues","aggregate":{"by":["organization","repository","workflow","run","run-attempt"],"values":[{"field":"event","as":"events","reducer":"count"}]}},{"name":"event-runs","subject":"Identify each workflow run that has one or more imported run-owned records.","objective":"Identify run attempts with retained imported records so their presence can be compared with observed runs.","acceptance":"One row per organization, repository, workflow, run, and attempt contains events, the count of matching retained records; no row in an available result does not prove that no event was produced.","description":"Distinct workflow runs represented by imported domain, tool, audit, or issue records.","from":"audit-event-runs","union":["domain-event-runs","tool-event-runs","issue-event-runs"],"aggregate":{"by":["organization","repository","workflow","run","run-attempt"],"values":[{"field":"events","as":"events","reducer":"sum"}]}},{"name":"run-import-status","subject":"Identify observed runs that have one or more imported run-owned records.","objective":"Compare observed run attempts with retained run-owned event evidence to locate import-coverage gaps for investigation.","acceptance":"Keep each observed run and its run-attempt identity; imported-event-count is zero and imported is false without a matching retained event, but missing events alone do not establish an ingestion failure.","description":"Observed runs enriched with imported-record status.","from":"runs","joins":[{"source":"event-runs","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"},{"left":"run","right":"run"},{"left":"run-attempt","right":"run-attempt"}],"fields":[{"field":"events","as":"imported-events"}]}],"compute":[{"as":"imported-event-count","function":"coalesce","args":[{"field":"imported-events"},{"value":0}]},{"as":"imported","function":"greater-than","args":[{"field":"imported-event-count"},{"value":0}]}]},{"name":"workflow-run-totals","subject":"Summarize observed run counts and imported runs by declared workflow.","objective":"Compare observed run attempts, conclusions, and imported-record coverage for each workflow.","acceptance":"Group by organization, repository, and workflow; report distinct run-attempt totals, successful and failed conclusion counts, and imported-run totals only from retained evidence. Missing run records cannot establish zero execution.","description":"Observed run and imported-run totals for each declared workflow.","from":"run-import-status","compute":[{"as":"run-attempt-identity","function":"concat","args":[{"field":"run"},{"value":":"},{"field":"run-attempt"}]}],"aggregate":{"by":["organization","repository","workflow"],"values":[{"field":"run-attempt-identity","as":"runs","reducer":"distinct-count"},{"field":"run-conclusion","as":"successful-runs","reducer":"count","filter":{"predicates":[{"field":"run-conclusion","equals":"success"}]}},{"field":"run-conclusion","as":"failed-runs","reducer":"count","filter":{"predicates":[{"field":"run-conclusion","in":["failure","startup-failure","stale","timed-out"]}]}},{"field":"imported","as":"imported-runs","reducer":"sum"}]}},{"name":"workflow-aic-run-totals","subject":"Summarize observed run attempts and AI Credits for workflow cost comparison.","objective":"Count retained run attempts and recorded AI Credits without loading imported-event coverage.","acceptance":"Count all distinct retained run attempts, but include only positive recorded AIC in cost totals and cost denominators; zero and missing telemetry cannot skew cost averages.","from":"runs","compute":[{"as":"run-attempt-identity","function":"concat","args":[{"field":"run"},{"value":":"},{"field":"run-attempt"}]},{"as":"positive-aic","function":"greater-than","args":[{"field":"aic-total"},{"value":0}]}],"aggregate":{"by":["organization","repository","workflow"],"values":[{"field":"run-attempt-identity","as":"runs","reducer":"distinct-count"},{"field":"run-attempt-identity","as":"aic-runs","reducer":"distinct-count","filter":{"predicates":[{"field":"positive-aic","equals":true}]}},{"field":"aic-total","as":"aic","reducer":"sum","filter":{"predicates":[{"field":"positive-aic","equals":true}]}}]}},{"name":"workflow-aic-totals","subject":"Summarize observed AI Credit usage by declared workflow.","objective":"Expose retained AI Credit consumption per workflow for bounded cost review alongside observed execution.","acceptance":"Sum only positive recorded aic-total by organization, repository, and workflow; exclude zero and missing costs rather than treating them as free execution.","description":"Observed AI Credit totals for each declared workflow.","from":"workflow-aic-run-totals","filter":{"predicates":[{"field":"aic-runs","gte":1}]},"select":[{"field":"organization"},{"field":"repository"},{"field":"workflow"},{"field":"aic"},{"field":"aic-runs"}]},{"name":"mcp-tool-workflow-totals","subject":"Summarize observed MCP calls by tool and workflow before the tool inventory is materialized.","objective":"Keep MCP inventory intermediates bounded without dropping calls or changing byte totals.","acceptance":"Count retained observation identities and sum request and response bytes per server, tool, and workflow; retain safe-output-server classification for downstream exclusion.","from":"mcp-calls","compute":[{"as":"safe-output-server","function":"equals-any","args":[{"field":"mcp-server"},{"value":"safe_outputs"},{"value":"safeoutputs"}]},{"as":"mcp-tool-label","function":"concat","args":[{"field":"mcp-server"},{"value":"/"},{"field":"mcp-tool"}]},{"as":"workflow-key","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"},{"value":":"},{"field":"workflow"}]}],"aggregate":{"by":["safe-output-server","mcp-tool-label","mcp-server","mcp-tool","workflow-key"],"values":[{"field":"mcp-observation","as":"calls","reducer":"count"},{"field":"request-bytes","as":"request-bytes","reducer":"sum"},{"field":"response-bytes","as":"response-bytes","reducer":"sum"}]}},{"name":"mcp-tool-calls","subject":"Prepare MCP tool calls for aggregation with safe-output-server calls identified for downstream exclusion.","objective":"Identify retained MCP call labels and safe-output-server classification for downstream tool-use investigation.","acceptance":"Preserve each retained call with its workflow key and tool label and mark safe-output-server calls explicitly; downstream exclusion must not be mistaken for absence of those calls or complete tool telemetry.","description":"Observed MCP tool calls labeled with whether they belong to the internal safe outputs server.","from":"mcp-calls","compute":[{"as":"safe-output-server","function":"equals-any","args":[{"field":"mcp-server"},{"value":"safe_outputs"},{"value":"safeoutputs"}]},{"as":"mcp-tool-label","function":"concat","args":[{"field":"mcp-server"},{"value":"/"},{"field":"mcp-tool"}]},{"as":"workflow-key","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"},{"value":":"},{"field":"workflow"}]}]},{"name":"issue-safe-outputs","subject":"List retained GitHub issue safe outputs.","objective":"Inspect retained issue safe outputs and their observed closure state before deciding which items need follow-up.","acceptance":"Include only safe_output.result issue records, not pull requests; preserve issue and run links, timestamps, state, and status detail. Unknown or unobserved closure state must not be presented as closed.","description":"Issue-only projection of retained safe-output items.","from":"issues","filter":{"predicates":[{"field":"event-type","equals":"safe_output.result"},{"field":"is-pull-request","equals":false}]},"joins":[{"source":"runs","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"},{"left":"run","right":"run"},{"left":"run-attempt","right":"run-attempt"}],"fields":[{"field":"run-link","as":"linked-run"}]}],"compute":[{"as":"_issue-state-open","function":"equals-any","args":[{"field":"issue-state"},{"value":"OPEN"}]},{"as":"_issue-state-closed","function":"equals-any","args":[{"field":"issue-state"},{"value":"CLOSED"}]},{"as":"_issue-open-status","function":"if","args":[{"field":"_issue-state-open"},{"value":"Open"},{"value":"Unknown"}]},{"as":"issue-status","function":"if","args":[{"field":"_issue-state-closed"},{"value":"Closed"},{"field":"_issue-open-status"}]},{"as":"_issue-closing-reason","function":"coalesce","args":[{"field":"issue-state-reason"},{"value":"unknown"}]},{"as":"_issue-closing-reason-normalized","function":"lower","args":[{"field":"_issue-closing-reason"}]},{"as":"issue-closing-status","function":"title-case","args":[{"field":"_issue-closing-reason-normalized"}]},{"as":"_issue-closed-status-detail","function":"concat","args":[{"value":"Closed: "},{"field":"issue-closing-status"}]},{"as":"issue-status-detail","function":"if","args":[{"field":"_issue-state-closed"},{"field":"_issue-closed-status-detail"},{"field":"issue-status"}]}],"select":[{"field":"event-timestamp","as":"observed-at"},{"field":"github-entity-type"},{"field":"is-pull-request"},{"field":"safe-output-type"},{"field":"issue-state"},{"field":"issue-closed"},{"field":"issue-state-reason"},{"field":"issue-status"},{"field":"issue-closing-status"},{"field":"issue-status-detail"},{"field":"issue-closed-at"},{"field":"issue-status-observed-at"},{"field":"event-summary"},{"field":"correlation-id","as":"entity-url"},{"field":"organization"},{"field":"repository"},{"field":"workflow"},{"field":"run"},{"field":"linked-run","as":"run-link"}],"order-by":[{"field":"observed-at","direction":"desc"},{"field":"entity-url","direction":"asc"}]},{"name":"issue-safe-output-label-options","subject":"List observed safe-output badges for the issue list Labels filter.","objective":"Choose retained safe-output types without scanning or filtering presented cards.","acceptance":"Return distinct observed badge values in ascending order; missing evidence is not an empty label inventory.","from":"issue-safe-outputs","aggregate":{"by":["safe-output-type"],"values":[{"field":"entity-url","as":"items","reducer":"count"}]},"order-by":[{"field":"safe-output-type","direction":"asc"}]},{"name":"issue-status-label-options","subject":"List observed status badges for the issue list Status filter.","objective":"Choose retained issue states and closing reasons without inferring resolution.","acceptance":"Return distinct observed status details in ascending order; Unknown remains distinct from Open and Closed.","from":"issue-safe-outputs","aggregate":{"by":["issue-status-detail"],"values":[{"field":"entity-url","as":"items","reducer":"count"}]},"order-by":[{"field":"issue-status-detail","direction":"asc"}]},{"name":"issue-repository-totals","subject":"Rank the ten repositories with the most retained GitHub issue safe outputs.","objective":"Locate repositories with the largest observed issue-safe-output volume for a bounded review of linked records.","acceptance":"Return at most ten repository coordinates ordered by retained issue-record count; ties or missing issue evidence must not imply a complete fleet ranking or unique issue count.","description":"Top repositories by retained issue safe-output count.","from":"issue-safe-outputs","compute":[{"as":"repository-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]}],"aggregate":{"by":["repository-coordinate"],"values":[{"field":"entity-url","as":"issues","reducer":"count"}]},"order-by":[{"field":"issues","direction":"desc"},{"field":"repository-coordinate","direction":"asc"}],"limit":10},{"name":"campaign-import-audit-count","subject":"Count retained audit identities for campaign inventory source quality.","objective":"Retain audit provenance without reconstructing run coverage.","acceptance":"Count canonical audit IDs; missing evidence stays unavailable and the count is not displayed as import coverage.","from":"audits","aggregate":{"values":[{"field":"id","as":"records","reducer":"count"}]}},{"name":"campaign-import-domain-count","subject":"Count retained domain identities for campaign inventory source quality.","objective":"Retain domain provenance without reconstructing run coverage.","acceptance":"Count canonical domain IDs; missing evidence stays unavailable and the count is not displayed as import coverage.","from":"domains","aggregate":{"values":[{"field":"id","as":"records","reducer":"count"}]}},{"name":"campaign-import-tool-count","subject":"Count retained tool identities for campaign inventory source quality.","objective":"Retain tool provenance without reconstructing run coverage.","acceptance":"Count canonical tool IDs; missing evidence stays unavailable and the count is not displayed as import coverage.","from":"tools","aggregate":{"values":[{"field":"id","as":"records","reducer":"count"}]}},{"name":"campaign-import-issue-count","subject":"Count retained issue identities for campaign inventory source quality.","objective":"Retain issue provenance without reconstructing run coverage.","acceptance":"Count canonical issue IDs; missing evidence stays unavailable and the count is not displayed as import coverage.","from":"issues","aggregate":{"values":[{"field":"id","as":"records","reducer":"count"}]}},{"name":"campaign-workflow-import-evidence","subject":"Compose retained import-source quality for campaign workflow execution totals.","objective":"Preserve all four import dependencies without counting unused per-run or per-workflow coverage.","acceptance":"Compose audit, domain, tool, and issue availability, freshness, and completeness exactly as event-runs. The retained-record count carries source quality only; it is not displayed or used as horizon-specific import coverage, executions, or outcomes. Run and AI Credit totals retain their selected horizon.","from":"campaign-import-audit-count","union":["campaign-import-domain-count","campaign-import-tool-count","campaign-import-issue-count"],"time":{"range":"all"},"compute":[{"as":"import-scope","function":"literal","args":[{"value":"retained"}]}],"aggregate":{"by":["import-scope"],"values":[{"field":"records","as":"events","reducer":"sum"}]}},{"name":"campaign-workflow-execution-base","subject":"Summarize retained run attempts and AI Credits before campaign workflow enrichment.","objective":"Read run identity and recorded AI Credits together instead of enriching every run with import status.","acceptance":"Count distinct run-attempt identities and sum aic-total per organization, repository, and workflow; missing retained evidence is not proof of no execution or cost.","from":"runs","compute":[{"as":"import-scope","function":"literal","args":[{"value":"retained"}]},{"as":"run-attempt-identity","function":"concat","args":[{"field":"run"},{"value":":"},{"field":"run-attempt"}]},{"as":"positive-aic","function":"greater-than","args":[{"field":"aic-total"},{"value":0}]}],"aggregate":{"by":["organization","repository","workflow","import-scope"],"values":[{"field":"run-attempt-identity","as":"runs","reducer":"distinct-count"},{"field":"aic-total","as":"aic","reducer":"sum","filter":{"predicates":[{"field":"positive-aic","equals":true}]}}]}},{"name":"campaign-workflow-execution-totals","subject":"Attach retained import-evidence quality to compact workflow execution totals.","objective":"Preserve the public inventory's run and import availability composition after aggregating run evidence.","acceptance":"Keep runs and AI Credits unchanged; unavailable run evidence fails closed and optional import evidence degrades quality exactly as in run-import-status.","description":"Only source quality is consumed from import evidence. Join its compact retained-source summary after run aggregation; do not build unused run-level import coverage or change horizon-specific execution totals.","from":"campaign-workflow-execution-base","joins":[{"source":"campaign-workflow-import-evidence","type":"left","on":[{"left":"import-scope","right":"import-scope"}],"fields":[{"field":"events","as":"imported-events"}]}],"select":[{"field":"organization"},{"field":"repository"},{"field":"workflow"},{"field":"runs"},{"field":"aic"}]},{"name":"campaign-workflow-declarations","subject":"Project reusable campaign workflow declarations without execution evidence.","objective":"Share declaration display fields between structural topology and execution inventory without joining runs or import evidence.","acceptance":"Preserve raw organization, repository, workflow and declaration fields for joins. Select orchestrator and worker roles once, retaining inactive and unknown declarations; only list consumers select active entries. Display defaults and repository links do not establish execution, enrollment or authority.","from":"workflows","filter":{"predicates":[{"field":"workflow-role","in":["orchestrator","worker"]}]},"compute":[{"as":"repository-slug","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"declared-mode","function":"coalesce","args":[{"field":"rollout-mode"},{"value":"unknown"}]},{"as":"declared-registration","function":"coalesce","args":[{"field":"workflow-active"},{"value":"unknown"}]},{"as":"campaign-title","function":"title-case","args":[{"field":"campaign"}]},{"as":"campaign-display-name","function":"coalesce","args":[{"field":"campaign-name"},{"field":"campaign-title"},{"value":"Repository-owned"}]},{"as":"workflow-display-name","function":"coalesce","args":[{"field":"workflow-name"},{"field":"workflow"}]},{"as":"encoded-repository","function":"url-encode","args":[{"field":"repository-slug"}]},{"as":"repository-dashboard-href","function":"concat","args":[{"value":"#page-repository-detail?repository="},{"field":"encoded-repository"}]},{"as":"repository-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"repository-slug"},{"value":" repository dashboard"}]},{"as":"repository-dashboard-link","function":"dashboard-link","args":[{"field":"repository-link"},{"field":"repository-dashboard-href"},{"field":"repository-dashboard-label"},{"field":"repository-slug"}]}],"select":[{"field":"organization"},{"field":"repository"},{"field":"workflow"},{"field":"campaign"},{"field":"campaign-name"},{"field":"workflow-name"},{"field":"workflow-role"},{"field":"rollout-mode"},{"field":"workflow-active"},{"field":"repository-link"},{"field":"workflow-link"},{"field":"repository-slug"},{"field":"declared-mode"},{"field":"declared-registration"},{"field":"campaign-display-name"},{"field":"workflow-display-name"},{"field":"repository-dashboard-link"}]},{"name":"campaign-workflow-inventory","subject":"Project declared campaign workflows with lean execution and configuration evidence.","objective":"Provide campaign totals and lists from shared declarations with separate execution and import-quality evidence.","acceptance":"Keep all declared orchestrators and workers, including inactive and unobserved entries; preserve inventory ordering, configuration defaults, execution totals, and import-evidence quality.","description":"Lean campaign inventory with execution totals that retain the public workflow inventory's evidence-quality dependencies.","from":"campaign-workflow-declarations","joins":[{"source":"campaign-workflow-execution-totals","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"}],"fields":[{"field":"runs","as":"observed-runs"},{"field":"aic","as":"observed-aic"}]}],"compute":[{"as":"total-runs","function":"coalesce","args":[{"field":"observed-runs"},{"value":0}]},{"as":"total-aic","function":"coalesce","args":[{"field":"observed-aic"},{"value":0}]}],"select":[{"field":"campaign"},{"field":"campaign-name"},{"field":"organization"},{"field":"repository-slug","as":"repository"},{"field":"workflow"},{"field":"workflow-name"},{"field":"workflow-role"},{"field":"declared-mode","as":"rollout-mode"},{"field":"declared-registration","as":"workflow-active"},{"field":"total-runs","as":"runs"},{"field":"total-aic","as":"aic"},{"field":"repository-link"},{"field":"workflow-link"},{"field":"campaign-display-name"},{"field":"workflow-display-name"},{"field":"repository-dashboard-link"}],"order-by":[{"field":"repository","direction":"asc"},{"field":"workflow","direction":"asc"}]},{"name":"workflow-inventory","subject":"List declared workflows with their campaign, repository, configuration, and observed execution totals.","objective":"Compare declared workflow configuration with retained run, import-coverage, and AI Credit evidence to select a workflow for closer inspection.","acceptance":"Keep one row per declared workflow with identity, role, mode, registration, links, observed totals, and ingestion indicator; zero joined totals and missing evidence must not be treated as proof of no execution or complete ingestion.","description":"Central campaign and repository-owned workflow inventory with observed execution totals.","from":"workflows","joins":[{"source":"workflow-run-totals","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"}],"fields":[{"field":"runs","as":"observed-runs"},{"field":"successful-runs","as":"observed-successful-runs"},{"field":"failed-runs","as":"observed-failed-runs"},{"field":"imported-runs","as":"observed-imported-runs"}]},{"source":"workflow-aic-totals","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"}],"fields":[{"field":"aic","as":"observed-aic"},{"field":"aic-runs","as":"observed-aic-runs"}]}],"compute":[{"as":"campaign-title","function":"title-case","args":[{"field":"campaign"}]},{"as":"campaign-display-name","function":"coalesce","args":[{"field":"campaign-name"},{"field":"campaign-title"},{"value":"Repository-owned"}]},{"as":"repository-slug","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"workflow-display-name","function":"coalesce","args":[{"field":"workflow-name"},{"field":"workflow"}]},{"as":"declared-role","function":"coalesce","args":[{"field":"workflow-role"},{"value":"standalone"}]},{"as":"declared-mode","function":"coalesce","args":[{"field":"rollout-mode"},{"value":"unknown"}]},{"as":"declared-registration","function":"coalesce","args":[{"field":"workflow-active"},{"value":"unknown"}]},{"as":"total-runs","function":"coalesce","args":[{"field":"observed-runs"},{"value":0}]},{"as":"total-successful-runs","function":"coalesce","args":[{"field":"observed-successful-runs"},{"value":0}]},{"as":"has-observed-runs","function":"greater-than","args":[{"field":"total-runs"},{"value":0}]},{"as":"total-failed-runs","function":"coalesce","args":[{"field":"observed-failed-runs"},{"value":0}]},{"as":"total-aic","function":"coalesce","args":[{"field":"observed-aic"},{"value":0}]},{"as":"aic-per-run","function":"quotient","args":[{"field":"total-aic"},{"field":"observed-aic-runs"}]},{"as":"total-imported-runs","function":"coalesce","args":[{"field":"observed-imported-runs"},{"value":0}]},{"as":"ingestion-rate","function":"quotient","args":[{"field":"total-imported-runs"},{"field":"total-runs"}]},{"as":"ingestion","function":"format-percent","args":[{"field":"ingestion-rate"}]},{"as":"encoded-campaign","function":"url-encode","args":[{"field":"campaign"}]},{"as":"campaign-dashboard-href","function":"concat","args":[{"value":"#page-campaign-insights?campaign="},{"field":"encoded-campaign"}]},{"as":"campaign-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"campaign-display-name"},{"value":" campaign dashboard"}]},{"as":"campaign-dashboard-link","function":"dashboard-link","args":[{"field":"repository-link"},{"field":"campaign-dashboard-href"},{"field":"campaign-dashboard-label"},{"field":"campaign"}]},{"as":"encoded-repository","function":"url-encode","args":[{"field":"repository-slug"}]},{"as":"repository-dashboard-href","function":"concat","args":[{"value":"#page-repository-detail?repository="},{"field":"encoded-repository"}]},{"as":"repository-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"repository-slug"},{"value":" repository dashboard"}]},{"as":"repository-dashboard-link","function":"dashboard-link","args":[{"field":"repository-link"},{"field":"repository-dashboard-href"},{"field":"repository-dashboard-label"},{"field":"repository-slug"}]},{"as":"workflow-identity","function":"concat","args":[{"field":"repository-slug"},{"value":":"},{"field":"workflow"}]},{"as":"encoded-workflow","function":"url-encode","args":[{"field":"workflow-identity"}]},{"as":"workflow-dashboard-href","function":"concat","args":[{"value":"#page-workflow-runtime?workflow="},{"field":"encoded-workflow"}]},{"as":"workflow-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"workflow-display-name"},{"value":" workflow dashboard"}]},{"as":"workflow-dashboard-link","function":"dashboard-link","args":[{"field":"workflow-link"},{"field":"workflow-dashboard-href"},{"field":"workflow-dashboard-label"},{"field":"workflow-identity"}]}],"select":[{"field":"campaign"},{"field":"campaign-display-name","as":"campaign-name"},{"field":"organization"},{"field":"repository-slug","as":"repository"},{"field":"workflow"},{"field":"workflow-display-name","as":"workflow-name"},{"field":"workflow-identity","as":"workflow-label"},{"field":"declared-role","as":"workflow-role"},{"field":"declared-mode","as":"rollout-mode"},{"field":"declared-registration","as":"workflow-active"},{"field":"total-aic","as":"aic"},{"field":"total-runs","as":"runs"},{"field":"total-successful-runs","as":"successful-runs"},{"field":"total-failed-runs","as":"failed-runs"},{"field":"aic-per-run"},{"field":"has-observed-runs"},{"field":"ingestion"},{"field":"campaign-dashboard-link","as":"campaign-link"},{"field":"repository-dashboard-link","as":"repository-link"},{"field":"workflow-dashboard-link","as":"workflow-link"}],"order-by":[{"field":"repository","direction":"asc"},{"field":"workflow","direction":"asc"}]},{"name":"repository-run-statistics","subject":"Reduce run counts, conclusions, and positive AI Credits before repository enrichment.","objective":"Share one row-local run aggregate between repository execution and cost summaries.","acceptance":"Keep organization/repository grain, distinct run IDs, existing failure and approval counts, and positive recorded AIC. Reduce before joins; missing evidence is not zero activity or free execution.","from":"runs","compute":[{"as":"positive-aic","function":"greater-than","args":[{"field":"aic-total"},{"value":0}]}],"aggregate":{"by":["organization","repository"],"values":[{"field":"run","as":"runs","reducer":"distinct-count"},{"field":"run-conclusion","as":"failed","reducer":"count","filter":{"predicates":[{"field":"run-conclusion","in":["failure","startup-failure","timed-out"]}]}},{"field":"run-conclusion","as":"action-required","reducer":"count","filter":{"predicates":[{"field":"run-conclusion","equals":"action-required"}]}},{"field":"run","as":"aic-runs","reducer":"count","filter":{"predicates":[{"field":"positive-aic","equals":true}]}},{"field":"aic-total","as":"aic","reducer":"sum","filter":{"predicates":[{"field":"positive-aic","equals":true}]}}]}},{"name":"repository-aic-totals","subject":"Summarize observed AI Credit usage by repository.","objective":"Provide repository-level retained AI Credit totals for comparing observed usage with run activity.","acceptance":"Sum only positive recorded aic-total by organization and repository; exclude zero and missing costs rather than treating them as free execution.","description":"Observed AI Credit totals for each repository.","from":"repository-run-statistics","filter":{"predicates":[{"field":"aic-runs","gte":1}]},"select":[{"field":"organization"},{"field":"repository"},{"field":"aic"}]},{"name":"maintenance-repository-versions","subject":"Group installed and current gh-aw compiler versions and upgrade evidence by repository.","objective":"Identify repositories with declared Markdown workflows whose retained compiler-version evidence warrants upgrade review.","acceptance":"Group Markdown workflow declarations by repository coordinate and return distinct recorded installed/current version lists plus upgrade-required and unknown flags; inspect absent or mixed version evidence rather than inferring a repository-wide installed version.","from":"workflows","filter":{"predicates":[{"field":"workflow","includes":".md"}]},"compute":[{"as":"repository-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"update-available","function":"equals-any","args":[{"field":"gh-aw-update-state"},{"value":"update-available"}]},{"as":"upgrade-state-unknown","function":"equals-any","args":[{"field":"gh-aw-update-state"},{"value":"unknown"}]},{"as":"upgrade-state-unknown-value","function":"if","args":[{"field":"upgrade-state-unknown"},{"value":1},{"value":0}]},{"as":"upgrade-required-value","function":"if","args":[{"field":"update-available"},{"value":1},{"value":0}]}],"aggregate":{"by":["repository-coordinate"],"values":[{"field":"gh-aw-version","as":"gh-aw-version","reducer":"distinct-list"},{"field":"gh-aw-current-version","as":"gh-aw-current-version","reducer":"distinct-list"},{"field":"upgrade-required-value","as":"upgrade-required","reducer":"max"},{"field":"upgrade-state-unknown-value","as":"upgrade-state-unknown","reducer":"max"}]}},{"name":"maintenance-repositories","subject":"List each repository with recorded compiler versions and computed upgrade state.","objective":"Expose recorded compiler versions and computed upgrade state per repository, with its GitHub home URL for inspection.","acceptance":"Return repository, repository-url, version lists, upgrade-required, upgrade-state, and upgrade-action-visible. Show Upgrade for outdated or unknown evidence; hide it for known-current repositories. Visibility grants no rollout authority.","from":"maintenance-repository-versions","compute":[{"as":"repository-url","function":"concat","args":[{"value":"https://github.com/"},{"field":"repository-coordinate"}]},{"as":"should-upgrade","function":"equals-any","args":[{"field":"upgrade-required"},{"value":1}]},{"as":"installed-version-unavailable","function":"equals-any","args":[{"field":"gh-aw-version"},{"value":""},{"value":"unknown"}]},{"as":"compiler-versions-match","function":"equals-any","args":[{"field":"gh-aw-version"},{"field":"gh-aw-current-version"}]},{"as":"known-current-versions","function":"if","args":[{"field":"installed-version-unavailable"},{"value":false},{"field":"compiler-versions-match"}]},{"as":"upgrade-status-unavailable","function":"if","args":[{"field":"known-current-versions"},{"value":false},{"value":true}]},{"as":"current-or-unavailable","function":"if","args":[{"field":"upgrade-status-unavailable"},{"value":"Upgrade status unavailable"},{"value":"Current"}]},{"as":"upgrade-action-visible","function":"if","args":[{"field":"should-upgrade"},{"value":true},{"field":"upgrade-status-unavailable"}]},{"as":"upgrade-state","function":"if","args":[{"field":"should-upgrade"},{"value":"Upgrade recommended"},{"field":"current-or-unavailable"}]}],"select":[{"field":"repository-coordinate","as":"repository"},{"field":"repository-url"},{"field":"gh-aw-version"},{"field":"gh-aw-current-version"},{"field":"upgrade-required"},{"field":"upgrade-action-visible"},{"field":"upgrade-state"}],"order-by":[{"field":"repository","direction":"asc"}]},{"name":"maintenance-campaign-updates","subject":"Expose at most one CAO package update row for the Updates navigation indicator.","objective":"Determine whether retained campaign metadata contains an update-available signal for the Updates indicator.","acceptance":"Return zero or one campaign-update-state row only when it equals update-available; an empty result means no matching retained signal, not that every campaign is current.","from":"campaigns","filter":{"predicates":[{"field":"campaign-update-state","equals":"update-available"}]},"select":[{"field":"campaign-update-state"}],"limit":1},{"name":"maintenance-repository-upgrades","subject":"Expose at most one gh-aw compiler upgrade row for the Updates navigation indicator.","objective":"Determine whether repository compiler metadata contains an upgrade-required signal for the Updates indicator.","acceptance":"Return zero or one upgrade-required row only when the retained value is 1; no row does not establish that all repositories are current when version data is missing.","from":"maintenance-repositories","filter":{"predicates":[{"field":"upgrade-required","equals":1}]},"select":[{"field":"upgrade-required"}],"limit":1},{"name":"run-incomplete-outcomes","subject":"Project retained report-incomplete terminal outcomes as concise run diagnoses.","objective":"Find recorded report_incomplete terminal outcomes that can explain a specific run's incomplete reporting.","acceptance":"Include only runs with a recorded report_incomplete terminal outcome, preserving run-attempt identity, outcome kind, and recorded diagnosis; absence is not proof that reporting completed.","description":"One retained incomplete-evidence diagnosis per workflow Run when the agent explicitly reported that required evidence or access was unavailable.","from":"runs","filter":{"predicates":[{"field":"terminal-outcome","equals":"report_incomplete"}]},"select":[{"field":"organization"},{"field":"repository"},{"field":"workflow"},{"field":"run"},{"field":"run-attempt"},{"field":"terminal-outcome","as":"outcome-kind"},{"field":"terminal-outcome-detail","as":"outcome-diagnosis"}]},{"name":"campaign-runs","subject":"Project workflow runs with campaign attribution and retained failure evidence.","objective":"Connect retained run status and failure details to declared campaign/workflow identity for run-level diagnosis.","acceptance":"Expose run and attempt identity, declared attribution, runtime and target repositories, status, failure and incomplete-outcome evidence, timestamps, and drill-down links; do not infer an outcome from runtime success or missing details.","description":"Canonical workflow runs joined to their declared campaign and workflow identity.","from":"runs","joins":[{"source":"workflows","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"}],"fields":[{"field":"campaign","as":"declared-campaign"},{"field":"campaign-name","as":"declared-campaign-name"},{"field":"workflow-name","as":"declared-workflow-name"},{"field":"workflow-role","as":"declared-workflow-role"},{"field":"workflow-link","as":"declared-workflow-link"}]},{"source":"run-incomplete-outcomes","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"},{"left":"run","right":"run"},{"left":"run-attempt","right":"run-attempt"}],"fields":[{"field":"outcome-kind","as":"outcome-kind"},{"field":"outcome-diagnosis","as":"outcome-diagnosis"}]}],"compute":[{"as":"status","function":"coalesce","args":[{"field":"run-conclusion"},{"field":"run-status"},{"value":"unknown"}]},{"as":"effective-outcome-kind","function":"coalesce","args":[{"field":"outcome-kind"},{"field":"terminal-outcome"},{"value":""}]},{"as":"is-incomplete-outcome","function":"equals-any","args":[{"field":"effective-outcome-kind"},{"value":"report_incomplete"}]},{"as":"diagnosis-kind","function":"if","args":[{"field":"is-incomplete-outcome"},{"value":"incomplete_evidence"},{"value":""}]},{"as":"error-signature","function":"coalesce","args":[{"field":"diagnosis-kind"},{"field":"failure-kind"},{"field":"classification"},{"field":"status"}]},{"as":"_error-signature-default-label","function":"title-case","args":[{"field":"error-signature"}]},{"as":"_is-driver-exit","function":"equals-any","args":[{"field":"error-signature"},{"value":"driver_exit"},{"value":"driver-exit"}]},{"as":"error-signature-label","function":"if","args":[{"field":"_is-driver-exit"},{"value":"Agent process exited unexpectedly"},{"field":"_error-signature-default-label"}]},{"as":"status-detail","function":"coalesce","args":[{"field":"outcome-diagnosis"},{"field":"terminal-outcome-detail"},{"field":"failure-detail"},{"field":"failure-message"},{"field":"failure-step"},{"field":"admission-reason"},{"value":""}]},{"as":"runtime-repository","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"is-worker","function":"equals-any","args":[{"field":"declared-workflow-role"},{"value":"worker"}]},{"as":"is-orchestrator","function":"equals-any","args":[{"field":"declared-workflow-role"},{"value":"orchestrator"}]},{"as":"root-dispatch-type","function":"if","args":[{"field":"is-orchestrator"},{"value":"Campaign orchestrator"},{"value":"Standalone workflow"}]},{"as":"dispatch-type","function":"if","args":[{"field":"is-worker"},{"value":"Campaign worker"},{"field":"root-dispatch-type"}]},{"as":"campaign-display-name","function":"coalesce","args":[{"field":"declared-campaign-name"},{"field":"declared-campaign"}]},{"as":"workflow-display-name","function":"coalesce","args":[{"field":"declared-workflow-name"},{"field":"workflow"}]},{"as":"encoded-campaign","function":"url-encode","args":[{"field":"declared-campaign"}]},{"as":"campaign-dashboard-href","function":"concat","args":[{"value":"#page-campaign-insights?campaign="},{"field":"encoded-campaign"}]},{"as":"campaign-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"campaign-display-name"},{"value":" campaign dashboard"}]},{"as":"campaign-dashboard-link","function":"dashboard-link","args":[{"field":"repository-link"},{"field":"campaign-dashboard-href"},{"field":"campaign-dashboard-label"},{"field":"declared-campaign"}]},{"as":"encoded-repository","function":"url-encode","args":[{"field":"runtime-repository"}]},{"as":"repository-dashboard-href","function":"concat","args":[{"value":"#page-repository-detail?repository="},{"field":"encoded-repository"}]},{"as":"repository-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"runtime-repository"},{"value":" repository dashboard"}]},{"as":"repository-dashboard-link","function":"dashboard-link","args":[{"field":"repository-link"},{"field":"repository-dashboard-href"},{"field":"repository-dashboard-label"},{"field":"runtime-repository"}]},{"as":"workflow-identity","function":"concat","args":[{"field":"runtime-repository"},{"value":":"},{"field":"workflow"}]},{"as":"encoded-workflow","function":"url-encode","args":[{"field":"workflow-identity"}]},{"as":"workflow-dashboard-href","function":"concat","args":[{"value":"#page-workflow-runtime?workflow="},{"field":"encoded-workflow"}]},{"as":"workflow-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"workflow-display-name"},{"value":" workflow dashboard"}]},{"as":"workflow-dashboard-link","function":"dashboard-link","args":[{"field":"workflow-link"},{"field":"workflow-dashboard-href"},{"field":"workflow-dashboard-label"},{"field":"workflow-identity"}]}],"select":[{"field":"started-at"},{"field":"dispatch-type"},{"field":"declared-campaign","as":"campaign"},{"field":"declared-campaign-name","as":"campaign-name"},{"field":"declared-workflow-name","as":"workflow-name"},{"field":"run"},{"field":"run-attempt"},{"field":"run-title"},{"field":"event"},{"field":"runtime-repository"},{"field":"target-repository"},{"field":"rollout-mode"},{"field":"status"},{"field":"run-status"},{"field":"error-signature"},{"field":"error-signature-label"},{"field":"status-detail"},{"field":"outcome-kind"},{"field":"outcome-diagnosis"},{"field":"declared-workflow-role","as":"workflow-role"},{"field":"failure-job"},{"field":"failure-message"},{"field":"failure-step"},{"field":"failure-log"},{"field":"engine"},{"field":"engine-version"},{"field":"gh-aw-version"},{"field":"requested-model"},{"field":"resolved-model"},{"field":"aic-total"},{"field":"safe-items-count"},{"field":"resource-reset-at","as":"status-detail-at"},{"field":"organization"},{"field":"repository"},{"field":"workflow"},{"field":"declared-workflow-link","as":"workflow-source-link"},{"field":"run-link"},{"field":"campaign-dashboard-link","as":"campaign-link"},{"field":"repository-dashboard-link","as":"repository-link"},{"field":"workflow-dashboard-link","as":"workflow-link"}],"order-by":[{"field":"started-at","direction":"desc"}]},{"name":"campaign-runtime-health-runs","subject":"Project only the run and workflow fields required to classify current campaign runtime health.","objective":"Provide the retained run identity, timing, role, dispatch type, repository, and status needed to assess campaign runtime-health groups.","acceptance":"Project the selected fields from overview-runs without converting missing statuses or unattributed workflows into failures; unavailable run history leaves health assessment incomplete.","description":"A bounded runtime-health input that excludes audit outcomes and presentation-only campaign run fields.","from":"overview-runs","compute":[{"as":"status","function":"coalesce","args":[{"field":"run-conclusion"},{"field":"run-status"},{"value":"unknown"}]},{"as":"runtime-repository","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"is-worker","function":"equals-any","args":[{"field":"workflow-role"},{"value":"worker"}]},{"as":"is-orchestrator","function":"equals-any","args":[{"field":"workflow-role"},{"value":"orchestrator"}]},{"as":"root-dispatch-type","function":"if","args":[{"field":"is-orchestrator"},{"value":"Campaign orchestrator"},{"value":"Standalone workflow"}]},{"as":"dispatch-type","function":"if","args":[{"field":"is-worker"},{"value":"Campaign worker"},{"field":"root-dispatch-type"}]}],"select":[{"field":"started-at"},{"field":"campaign"},{"field":"campaign-name"},{"field":"workflow"},{"field":"workflow-name"},{"field":"workflow-role"},{"field":"dispatch-type"},{"field":"runtime-repository"},{"field":"run"},{"field":"run-status"},{"field":"status"}]},{"name":"campaign-runtime-health-groups","subject":"Compute each campaign workflow and runtime repository's latest consecutive failure streak in the selected horizon.","objective":"Locate campaign workflow/runtime-repository groups whose most recent retained completed runs have consecutive runtime failures.","acceptance":"Group completed runs by campaign, workflow, role, dispatch type, and runtime repository; failure-count is the latest retained failure streak, not a rate or a claim about runs outside the available horizon.","description":"Current retained failure streaks grouped by campaign workflow and runtime repository, considering only concluded Runs so an in-flight retry cannot mask an active failure streak.","from":"campaign-runtime-health-runs","filter":{"predicates":[{"field":"run-status","equals":"completed"}]},"compute":[{"as":"is-runtime-failure","function":"equals-any","args":[{"field":"status"},{"value":"failure"},{"value":"startup-failure"},{"value":"stale"},{"value":"timed-out"}]},{"as":"runtime-failure-streak-point","function":"failure-streak-point","args":[{"field":"started-at"},{"field":"run"},{"field":"is-runtime-failure"}]}],"aggregate":{"by":["campaign","campaign-name","workflow","workflow-name","workflow-role","dispatch-type","runtime-repository"],"values":[{"field":"runtime-failure-streak-point","as":"failure-count","reducer":"latest-failure-streak"}]}},{"name":"workflow-run-observation-counts","subject":"Count retained Runs for each workflow identity in the selected horizon.","objective":"Measure retained run presence by workflow identity to compare with active orchestrator declarations.","acceptance":"Count overview-runs by organization, repository, and workflow; a missing group indicates no retained matching run in the available horizon, not proof of no executions.","description":"One row per organization, repository, and workflow with retained Run counts, safe to join without row multiplication.","from":"overview-runs","aggregate":{"by":["organization","repository","workflow"],"values":[{"field":"run","as":"observed-run-count","reducer":"count"}]}},{"name":"campaign-active-orchestrator-run-presence","subject":"Count retained Runs for each active campaign orchestrator in the selected horizon.","objective":"Compare active orchestrator declarations with retained run observations to identify missing visibility.","acceptance":"Keep only workflows declared active with orchestrator role and expose their identity, runtime repository, and observed-run-count; a zero joined count means no retained match, not necessarily a stopped schedule.","description":"Active campaign orchestrators annotated with retained Run presence.","from":"workflows","joins":[{"source":"workflow-run-observation-counts","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"}],"fields":[{"field":"observed-run-count","as":"joined-observed-run-count"}]}],"filter":{"predicates":[{"field":"workflow-role","equals":"orchestrator"},{"field":"workflow-active","equals":"true"}]},"compute":[{"as":"runtime-repository","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"observed-run-count","function":"coalesce","args":[{"field":"joined-observed-run-count"},{"value":0}]}],"select":[{"field":"campaign"},{"field":"campaign-name"},{"field":"workflow"},{"field":"workflow-name"},{"field":"workflow-role"},{"field":"runtime-repository"},{"field":"observed-run-count"}]},{"name":"campaign-unobserved-orchestrator-candidates","subject":"Mark active campaign orchestrators with no retained Runs in the selected horizon.","objective":"Mark active orchestrators lacking retained run evidence for bounded telemetry or schedule review.","acceptance":"Preserve active orchestrator identity and observed-run-count; is-unobserved marks zero retained matches and must not be interpreted as a runtime failure or evidence that dispatch was expected.","description":"Active orchestrators annotated with whether runtime evidence is absent.","from":"campaign-active-orchestrator-run-presence","compute":[{"as":"is-unobserved","function":"equals-any","args":[{"field":"observed-run-count"},{"value":0}]},{"as":"failure-count","function":"sum","args":[{"value":0},{"value":0}]},{"as":"dispatch-type","function":"coalesce","args":[{"value":"Campaign orchestrator"},{"value":"Campaign orchestrator"}]},{"as":"problem-kind","function":"coalesce","args":[{"value":"not-observed"},{"value":"not-observed"}]}]},{"name":"campaign-unobserved-orchestrators","subject":"Show active campaign orchestrators with no retained Runs in the selected horizon.","objective":"List active orchestrator declarations with no retained run observations for follow-up on evidence availability.","acceptance":"Return only is-unobserved candidates with their workflow and repository identity; an empty result does not certify run completeness or scheduler health.","description":"Active campaign orchestrators whose runtime state cannot be established from retained evidence.","from":"campaign-unobserved-orchestrator-candidates","filter":{"predicates":[{"field":"is-unobserved","equals":true}]}},{"name":"dispatches","subject":"Select workflow-dispatch runs from campaign-attributed workflow run evidence.","objective":"Inspect retained workflow_dispatch runs attributed to campaigns before comparing campaign dispatch activity.","acceptance":"Include only campaign-runs with event workflow_dispatch and preserve run, attempt, attribution, status, and time; absence does not establish that no dispatch occurred beyond retained evidence.","description":"Canonical workflow runs whose authoritative trigger is workflow_dispatch.","from":"campaign-runs","filter":{"predicates":[{"field":"event","equals":"workflow_dispatch"}]},"order-by":[{"field":"started-at","direction":"desc"}]},{"name":"campaign-dispatch-inventory","subject":"Project retained dispatch identity and campaign attribution before campaign counting.","objective":"Count dispatches without materializing run diagnoses and presentation links.","acceptance":"Keep workflow_dispatch runs in timestamp order with declared campaign attribution; preserve workflow and incomplete-outcome join quality and duplicate-key failure behavior.","description":"Lean dispatch-count input; the incomplete-outcome join preserves the full campaign run source's evidence quality and fail-closed validation.","from":"runs","joins":[{"source":"workflows","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"}],"fields":[{"field":"campaign","as":"declared-campaign"}]},{"source":"run-incomplete-outcomes","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"},{"left":"run","right":"run"},{"left":"run-attempt","right":"run-attempt"}],"fields":[{"field":"outcome-kind","as":"outcome-kind"}]}],"filter":{"predicates":[{"field":"event","equals":"workflow_dispatch"}]},"select":[{"field":"declared-campaign","as":"campaign"},{"field":"run"},{"field":"started-at"}],"order-by":[{"field":"started-at","direction":"desc"}]},{"name":"campaign-dispatch-totals","subject":"Summarize observed workflow dispatches for each centrally managed campaign.","objective":"Compare retained workflow_dispatch run counts across attributed campaigns.","acceptance":"Count distinct run identifiers per campaign from dispatches; do not treat missing campaign attribution or unretained dispatches as zero actual activity.","description":"Observed workflow-dispatch run totals grouped by campaign.","from":"campaign-dispatch-inventory","aggregate":{"by":["campaign"],"values":[{"field":"run","as":"dispatches","reducer":"distinct-count"}]}},{"name":"campaign-workflow-totals","subject":"Summarize observed workflow and execution totals for each centrally managed campaign.","objective":"Compare declared orchestrator/worker composition, rollout registration, observed runs, and AI Credit usage by campaign.","acceptance":"Group only orchestrator and worker workflow-inventory rows by campaign; retain workflow count, distinct roles/modes/registration and summed observed runs and AIC, without inferring successful outcomes.","description":"Observed workflow, rollout, run, and AI Credit totals grouped by campaign.","from":"campaign-workflow-inventory","aggregate":{"by":["campaign"],"values":[{"field":"workflow","as":"workflows","reducer":"count"},{"field":"workflow-role","as":"roles","reducer":"distinct-list"},{"field":"rollout-mode","as":"modes","reducer":"distinct-list"},{"field":"workflow-active","as":"registration","reducer":"distinct-list"},{"field":"runs","as":"runs","reducer":"sum"},{"field":"aic","as":"aic","reducer":"sum"}]}},{"name":"campaign-repository-coverage","subject":"Count distinct registered target repositories reached by successful worker dispatches for each campaign.","objective":"Estimate observed campaign target reach from successful worker workflow_dispatch runs joined to registered repositories.","acceptance":"Count distinct matched target-repository values per campaign only for successful worker dispatches; this is observed reach, not verified target outcomes or complete fleet coverage.","description":"Campaign repository coverage derived from successful worker dispatch runs in the selected horizon.","from":"runs","joins":[{"source":"workflows","type":"inner","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"}],"fields":[{"field":"campaign","as":"campaign"},{"field":"workflow-role","as":"workflow-role"}]},{"source":"repositories","type":"inner","on":[{"left":"target-repository","right":"repository-coordinate"}],"fields":[{"field":"repository-coordinate","as":"registered-target-repository"}]}],"filter":{"predicates":[{"field":"event","equals":"workflow_dispatch"},{"field":"run-conclusion","equals":"success"},{"field":"workflow-role","equals":"worker"}]},"aggregate":{"by":["campaign"],"values":[{"field":"target-repository","as":"covered-repositories","reducer":"distinct-count"}]}},{"name":"campaign-inventory-preview","subject":"Show declared campaigns before execution evidence is evaluated.","objective":"Expose campaign identities and navigation links while observed totals remain pending.","acceptance":"Preserve every declared campaign and its dashboard link without reporting missing execution totals as zero.","from":"campaigns","compute":[{"as":"encoded-campaign","function":"url-encode","args":[{"field":"campaign"}]},{"as":"campaign-dashboard-href","function":"concat","args":[{"value":"#page-campaign-insights?campaign="},{"field":"encoded-campaign"}]},{"as":"campaign-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"campaign-name"},{"value":" campaign dashboard"}]},{"as":"campaign-dashboard-link","function":"dashboard-link","args":[{"value":""},{"field":"campaign-dashboard-href"},{"field":"campaign-dashboard-label"},{"field":"campaign"}]}],"select":[{"field":"campaign"},{"field":"campaign-name"},{"field":"campaign-dashboard-link"}],"order-by":[{"field":"campaign-name","direction":"asc"}]},{"name":"campaign-inventory","subject":"List centrally managed campaigns with their observed workflow and execution totals.","objective":"Compare declared campaigns with retained workflow composition, dispatches, target reach, runs, and AIC to choose an evidence-backed drill-down.","acceptance":"Keep declared campaigns with campaign identity and link plus joined totals; defaulted zero values mean no matching retained evidence and cannot certify no activity, complete coverage, or successful outcomes.","description":"Canonical campaign inventory enriched with observed workflow, rollout, run, repository coverage, and AI Credit totals.","from":"campaigns","joins":[{"source":"campaign-workflow-totals","type":"left","on":[{"left":"campaign","right":"campaign"}],"fields":[{"field":"workflows","as":"observed-workflows"},{"field":"roles","as":"observed-roles"},{"field":"modes","as":"observed-modes"},{"field":"registration","as":"observed-registration"},{"field":"runs","as":"observed-runs"},{"field":"aic","as":"observed-aic"}]},{"source":"campaign-dispatch-totals","type":"left","on":[{"left":"campaign","right":"campaign"}],"fields":[{"field":"dispatches","as":"observed-dispatches"}]},{"source":"campaign-repository-coverage","type":"left","on":[{"left":"campaign","right":"campaign"}],"fields":[{"field":"covered-repositories","as":"observed-covered-repositories"}]}],"compute":[{"as":"workflows","function":"coalesce","args":[{"field":"observed-workflows"},{"value":0}]},{"as":"roles","function":"coalesce","args":[{"field":"observed-roles"},{"value":""}]},{"as":"modes","function":"coalesce","args":[{"field":"observed-modes"},{"field":"campaign-mode"}]},{"as":"registration","function":"coalesce","args":[{"field":"observed-registration"},{"field":"campaign-registration"}]},{"as":"runs","function":"coalesce","args":[{"field":"observed-runs"},{"value":0}]},{"as":"dispatches","function":"coalesce","args":[{"field":"observed-dispatches"},{"value":0}]},{"as":"covered-repositories","function":"coalesce","args":[{"field":"observed-covered-repositories"},{"value":0}]},{"as":"aic","function":"coalesce","args":[{"field":"observed-aic"},{"value":0}]},{"as":"encoded-campaign","function":"url-encode","args":[{"field":"campaign"}]},{"as":"campaign-dashboard-href","function":"concat","args":[{"value":"#page-campaign-insights?campaign="},{"field":"encoded-campaign"}]},{"as":"campaign-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"campaign-name"},{"value":" campaign dashboard"}]},{"as":"campaign-dashboard-link","function":"dashboard-link","args":[{"value":""},{"field":"campaign-dashboard-href"},{"field":"campaign-dashboard-label"},{"field":"campaign"}]}],"select":[{"field":"campaign"},{"field":"campaign-name"},{"field":"campaign-dashboard-link"},{"field":"workflows"},{"field":"roles"},{"field":"modes"},{"field":"registration"},{"field":"runs"},{"field":"dispatches"},{"field":"covered-repositories"},{"field":"aic"}],"order-by":[{"field":"campaign-name","direction":"asc"}]},{"name":"firewall-domain-totals","subject":"Show each observed firewall domain with the number of runs and total accepted and blocked requests.","objective":"Identify domains with observed denied requests for a closer review of firewall evidence.","acceptance":"Report distinct observed runs and native accepted and blocked request totals by domain; a denied request alone does not justify allowing egress, and no row does not prove no requests occurred.","description":"Distinct runs and accepted and blocked request totals by firewall domain.","from":"firewall-observations","filter":{"predicates":[{"field":"decision","in":["allowed","denied"]}]},"aggregate":{"by":["domain"],"values":[{"field":"run","as":"run","reducer":"distinct-count"},{"field":"request-count","as":"accepted","reducer":"sum","filter":{"predicates":[{"field":"decision","equals":"allowed"}]}},{"field":"request-count","as":"blocked","reducer":"sum","filter":{"predicates":[{"field":"decision","equals":"denied"}]}}]},"order-by":[{"field":"blocked","direction":"desc"},{"field":"accepted","direction":"desc"},{"field":"domain","direction":"asc"}]},{"name":"firewall-most-blocked-domains","subject":"Highlight the domains with the most blocked firewall requests.","objective":"Prioritize up to ten observed domains by blocked request total for investigation.","acceptance":"Rank by observed blocked totals and inspect underlying domain/workflow evidence before deciding whether a block needs attention; the ranking is not a policy authorization or an incidence rate.","description":"The ten domains with the highest observed blocked request totals.","from":"firewall-domain-totals","order-by":[{"field":"blocked","direction":"desc"},{"field":"domain","direction":"asc"}],"limit":10},{"name":"firewall-domain-workflows","subject":"Show workflows that allowed or blocked requests to each observed firewall domain.","objective":"Locate which observed workflows contributed accepted or denied requests for a domain.","acceptance":"Preserve workflow scope, source link, distinct runs, and native accepted and blocked totals; investigate the run and egress context rather than assuming a denied request is a failure or grounds for wider access.","description":"Workflow-level accepted and blocked request totals by firewall domain.","from":"firewall-observations","filter":{"predicates":[{"field":"decision","in":["allowed","denied"]}]},"compute":[{"as":"workflow-source-url","function":"link-href","args":[{"field":"workflow-link"}]}],"aggregate":{"by":["domain","organization","repository","workflow","workflow-source-url"],"values":[{"field":"run","as":"runs","reducer":"distinct-count"},{"field":"request-count","as":"accepted","reducer":"sum","filter":{"predicates":[{"field":"decision","equals":"allowed"}]}},{"field":"request-count","as":"blocked","reducer":"sum","filter":{"predicates":[{"field":"decision","equals":"denied"}]}}]},"order-by":[{"field":"blocked","direction":"desc"},{"field":"accepted","direction":"desc"},{"field":"repository","direction":"asc"},{"field":"workflow","direction":"asc"}]},{"name":"mcp-tool-totals","subject":"Group observed MCP activity by tool and count calls and calling workflows, excluding the internal safe outputs server.","objective":"Expose tool-level call, workflow, and byte totals to investigate observed MCP usage.","acceptance":"Group only observed non-safe-output-server calls by server and tool, preserving counts and byte totals; lack of calls does not establish no access, and call volume does not establish value or permission.","description":"Observed MCP tool-call totals grouped by MCP server and tool, with the number of distinct calling workflows.","from":"mcp-tool-workflow-totals","filter":{"predicates":[{"field":"safe-output-server","equals":false}]},"aggregate":{"by":["mcp-tool-label","mcp-server","mcp-tool"],"values":[{"field":"calls","as":"calls","reducer":"sum"},{"field":"workflow-key","as":"workflows","reducer":"distinct-count"},{"field":"request-bytes","as":"request-bytes","reducer":"sum"},{"field":"response-bytes","as":"response-bytes","reducer":"sum"}]},"select":[{"field":"mcp-tool-label"},{"field":"mcp-tool"},{"field":"mcp-server"},{"field":"calls"},{"field":"workflows"},{"field":"request-bytes"},{"field":"response-bytes"}],"order-by":[{"field":"calls","direction":"desc"},{"field":"mcp-tool-label","direction":"asc"}]},{"name":"mcp-top-tools","subject":"Show the ten most frequently called MCP tools.","objective":"Identify up to ten tools with the highest observed non-safe-output-server call counts for inspection.","acceptance":"Rank observed calls by tool label and inspect grouped tool evidence before drawing conclusions; do not treat popularity as effectiveness or authority to add tools.","description":"The ten MCP tools with the most observed calls, excluding the internal safe outputs server.","from":"mcp-tool-totals","order-by":[{"field":"calls","direction":"desc"},{"field":"mcp-tool-label","direction":"asc"}],"limit":10},{"name":"steering-events","subject":"Prepare observed gateway steering warnings for aggregation by steering type and workflow.","objective":"Expose warning identity, run context, type, and timestamp for downstream steering diagnostics.","acceptance":"Project recorded gateway steering events with workflow and run attribution where available; a warning is not a completed budget overrun, failure, or reason to increase limits.","description":"Gateway steering warnings emitted when a run approaches its AI Credit budget, time limit, or another declared limit, labelled with a readable steering type.","from":"audits","filter":{"predicates":[{"field":"event-type","equals":"firewall.steering"}]},"joins":[{"source":"workflows","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"}],"fields":[{"field":"campaign","as":"campaign"},{"field":"workflow-name","as":"workflow-name"}]}],"compute":[{"as":"steering-code","function":"coalesce","args":[{"field":"code"},{"field":"event-status"},{"value":"unknown"}]},{"as":"_token-steering","function":"equals-any","args":[{"field":"steering-code"},{"value":"token_steering"}]},{"as":"_timeout-steering","function":"equals-any","args":[{"field":"steering-code"},{"value":"timeout_steering"}]},{"as":"_turn-steering","function":"equals-any","args":[{"field":"steering-code"},{"value":"turn_steering"},{"value":"max_turns_steering"}]},{"as":"_turn-steering-type","function":"if","args":[{"field":"_turn-steering"},{"value":"Running out of turns"},{"field":"steering-code"}]},{"as":"_timeout-steering-type","function":"if","args":[{"field":"_timeout-steering"},{"value":"Running out of time"},{"field":"_turn-steering-type"}]},{"as":"steering-type","function":"if","args":[{"field":"_token-steering"},{"value":"Running out of tokens"},{"field":"_timeout-steering-type"}]},{"as":"workflow-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"},{"value":":"},{"field":"workflow"}]},{"as":"workflow-label","function":"coalesce","args":[{"field":"workflow-name"},{"field":"workflow-coordinate"}]}],"select":[{"field":"id"},{"field":"organization"},{"field":"repository"},{"field":"workflow"},{"field":"workflow-name"},{"field":"workflow-coordinate"},{"field":"workflow-label"},{"field":"campaign"},{"field":"run"},{"field":"run-link"},{"field":"steering-code"},{"field":"steering-type"},{"field":"event-summary"},{"field":"observed-at"}]},{"name":"steering-type-totals","subject":"Show how often each kind of steering warning occurred.","objective":"Identify steering warning categories to inspect in their run context.","acceptance":"Report observed event totals and distinct runs and workflows by type; confirm underlying warnings before interpreting frequency, and do not infer actual limit breaches.","description":"Observed gateway steering warnings grouped by steering type with the number of affected runs and workflows.","from":"steering-events","aggregate":{"by":["steering-type","steering-code"],"values":[{"field":"id","as":"events","reducer":"count"},{"field":"run","as":"runs","reducer":"distinct-count"},{"field":"workflow-coordinate","as":"workflows","reducer":"distinct-count"}]},"select":[{"field":"steering-type"},{"field":"steering-code"},{"field":"events"},{"field":"runs"},{"field":"workflows"}],"order-by":[{"field":"events","direction":"desc"},{"field":"steering-type","direction":"asc"}]},{"name":"steering-workflow-totals","subject":"Count steering warnings for each workflow.","objective":"Expose workflow-level warning totals and token/time warning breakdowns for downstream review.","acceptance":"Count recorded events and distinct runs by workflow, retaining the declared token/time categories; other types remain in total events and no warning alone establishes a failure.","description":"Gateway steering warnings grouped by workflow, split into token-budget and time-limit warnings.","from":"steering-events","aggregate":{"by":["workflow-coordinate","organization","repository","workflow","workflow-label","campaign"],"values":[{"field":"id","as":"events","reducer":"count"},{"field":"run","as":"runs","reducer":"distinct-count"},{"field":"id","as":"token-events","reducer":"count","filter":{"predicates":[{"field":"steering-code","equals":"token_steering"}]}},{"field":"id","as":"time-events","reducer":"count","filter":{"predicates":[{"field":"steering-code","equals":"timeout_steering"}]}},{"field":"steering-type","as":"steering-types","reducer":"distinct-count"}]},"order-by":[{"field":"events","direction":"desc"},{"field":"workflow-coordinate","direction":"asc"}]},{"name":"steering-workflows","subject":"Present workflow steering totals with a link to each workflow dashboard.","objective":"Show observed workflow steering totals with navigation to the affected run context.","acceptance":"Keep workflow identity, link, events, runs, and warning breakdowns tied to their grouped evidence; use drill-through before recommending changes, not warning counts as a basis to widen budgets.","description":"Workflow steering totals labelled with a link to the workflow runtime page.","from":"steering-workflow-totals","compute":[{"as":"encoded-workflow","function":"url-encode","args":[{"field":"workflow-coordinate"}]},{"as":"workflow-dashboard-href","function":"concat","args":[{"value":"#page-workflow-runtime?workflow="},{"field":"encoded-workflow"}]},{"as":"workflow-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"workflow-coordinate"},{"value":" workflow dashboard"}]},{"as":"workflow-dashboard-link","function":"dashboard-link","args":[{"value":""},{"field":"workflow-dashboard-href"},{"field":"workflow-dashboard-label"},{"field":"workflow-label"}]}],"select":[{"field":"workflow-coordinate"},{"field":"workflow-label"},{"field":"workflow-dashboard-link"},{"field":"organization"},{"field":"repository"},{"field":"campaign"},{"field":"events"},{"field":"runs"},{"field":"token-events"},{"field":"time-events"},{"field":"steering-types"}],"order-by":[{"field":"events","direction":"desc"},{"field":"workflow-coordinate","direction":"asc"}]},{"name":"steering-top-workflows","subject":"Highlight the workflows with the most steering warnings.","objective":"Prioritize up to ten workflows by observed warning count for investigation.","acceptance":"Rank recorded warning totals with workflow context, checking underlying events and telemetry coverage; a high rank neither proves overrun nor justifies a limit change.","description":"The ten workflows with the highest observed gateway steering warning totals.","from":"steering-workflows","order-by":[{"field":"events","direction":"desc"},{"field":"workflow-coordinate","direction":"asc"}],"limit":10},{"name":"entity-workflow-run-totals","subject":"Summarize run outcomes and AI Credit consumption for reusable workflow cards.","objective":"Compare retained run-attempt activity, recorded conclusions, and AI Credit usage per workflow card.","acceptance":"Group by organization, repository, and workflow; expose distinct run-attempt count, success/failure conclusion counts, and sum of recorded AIC, without treating missing run history as zero actual activity.","from":"runs","compute":[{"as":"run-attempt-identity","function":"concat","args":[{"field":"run"},{"value":":"},{"field":"run-attempt"}]},{"as":"positive-aic","function":"greater-than","args":[{"field":"aic-total"},{"value":0}]}],"aggregate":{"by":["organization","repository","workflow"],"values":[{"field":"run-attempt-identity","as":"runs","reducer":"distinct-count"},{"field":"run-attempt-identity","as":"aic-runs","reducer":"distinct-count","filter":{"predicates":[{"field":"positive-aic","equals":true}]}},{"field":"run-conclusion","as":"successful-runs","reducer":"count","filter":{"predicates":[{"field":"run-conclusion","equals":"success"}]}},{"field":"run-conclusion","as":"failed-runs","reducer":"count","filter":{"predicates":[{"field":"run-conclusion","in":["failure","startup-failure","stale","timed-out"]}]}},{"field":"aic-total","as":"aic","reducer":"sum","filter":{"predicates":[{"field":"positive-aic","equals":true}]}}]}},{"name":"entity-workflows","subject":"Project workflow entities for reusable workflow cards and repository drill-down.","objective":"Relate declared workflows to observed run and AIC totals for workflow-level drill-down.","acceptance":"Keep declared workflow identity, role, registration, campaign, link, and joined totals; a missing run match defaults to displayed zeros but does not establish no executions or outcomes.","from":"workflows","joins":[{"source":"entity-workflow-run-totals","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"}],"fields":[{"field":"runs","as":"observed-runs"},{"field":"successful-runs","as":"observed-successful-runs"},{"field":"failed-runs","as":"observed-failed-runs"},{"field":"aic","as":"observed-aic"},{"field":"aic-runs","as":"observed-aic-runs"}]}],"compute":[{"as":"runs","function":"coalesce","args":[{"field":"observed-runs"},{"value":0}]},{"as":"successful-runs","function":"coalesce","args":[{"field":"observed-successful-runs"},{"value":0}]},{"as":"failed-runs","function":"coalesce","args":[{"field":"observed-failed-runs"},{"value":0}]},{"as":"aic","function":"coalesce","args":[{"field":"observed-aic"},{"value":0}]},{"as":"aic-per-run","function":"quotient","args":[{"field":"aic"},{"field":"observed-aic-runs"}]}],"select":[{"field":"organization"},{"field":"repository"},{"field":"workflow"},{"field":"workflow-name"},{"field":"workflow-role"},{"field":"workflow-active"},{"field":"campaign-name"},{"field":"observed-at"},{"field":"runs"},{"field":"successful-runs"},{"field":"failed-runs"},{"field":"aic-per-run"},{"field":"workflow-link"}],"order-by":[{"field":"repository","direction":"asc"},{"field":"workflow","direction":"asc"}]},{"name":"repository-runs","subject":"Project canonical runs into repository-addressable run evidence.","objective":"Expose retained run chronology and status for a selected repository's drill-down.","acceptance":"Retain repository coordinate, workflow, run identity, title, event, start time, conclusion, mode, AIC, and run link; absent details or runs do not establish a healthy or idle repository.","description":"Workflow runs with a stable repository route key.","from":"runs","compute":[{"as":"repository-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]}],"select":[{"field":"repository-coordinate"},{"field":"workflow"},{"field":"run"},{"field":"run-title"},{"field":"event"},{"field":"started-at"},{"field":"run-status"},{"field":"run-conclusion"},{"field":"rollout-mode"},{"field":"aic-total"},{"field":"run-link"}],"order-by":[{"field":"started-at","direction":"desc"},{"field":"run","direction":"desc"}]},{"name":"repository-workflow-totals","subject":"Summarize declared and disabled workflow counts by repository.","objective":"Compare declared and disabled workflow counts for each repository in the retained workflow inventory.","acceptance":"Count declared workflows and workflow-active=false entries by organization and repository; missing declarations must not be interpreted as a complete zero-workflow inventory.","description":"Declared and disabled workflow totals for each repository.","from":"workflows","aggregate":{"by":["organization","repository"],"values":[{"field":"workflow","as":"workflows","reducer":"count"},{"field":"workflow","as":"disabled","reducer":"count","filter":{"predicates":[{"field":"workflow-active","equals":"false"}]}}]}},{"name":"repository-report-totals","subject":"Summarize published outcome report counts by repository.","objective":"Show retained outcome-report volume per repository for comparison with observed execution.","acceptance":"Count retained outcome rows by organization and repository; a missing aggregate does not prove no reports were published or that reported outcomes succeeded.","description":"Published report totals for each repository.","from":"outcomes","aggregate":{"by":["organization","repository"],"values":[{"field":"repository","as":"reports","reducer":"count"}]}},{"name":"repository-run-identities","subject":"Project the run-attempt identities needed to match imported evidence.","objective":"Keep import-coverage joins narrow without carrying run details, links, or costs.","acceptance":"Preserve each selected run attempt and its organization, repository, workflow, run, and attempt keys. Do not deduplicate attempts or change selected-horizon semantics.","from":"runs","select":[{"field":"organization"},{"field":"repository"},{"field":"workflow"},{"field":"run"},{"field":"run-attempt"}]},{"name":"repository-import-totals","subject":"Count selected run attempts with matching retained imported records.","objective":"Join compact run identities to already reduced event evidence, then reduce import coverage by repository.","acceptance":"Match all five run-attempt keys and count each selected run row once when events are positive. Preserve optional-evidence quality and horizon filters; records for unselected runs do not establish coverage.","from":"repository-run-identities","joins":[{"source":"event-runs","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"},{"left":"run","right":"run"},{"left":"run-attempt","right":"run-attempt"}],"fields":[{"field":"events","as":"imported-events"}]}],"compute":[{"as":"imported","function":"greater-than","args":[{"field":"imported-events"},{"value":0}]}],"aggregate":{"by":["organization","repository"],"values":[{"field":"imported","as":"imported-runs","reducer":"sum"}]}},{"name":"repository-run-totals","subject":"Summarize distinct runs, failures, and approval-required runs by repository.","objective":"Join already reduced run statistics and import coverage at repository grain.","acceptance":"Group by organization and repository; preserve distinct run IDs, configured failure/action-required conclusion counts, and imported-run sums. Missing enrichment or run history must not be treated as complete coverage.","description":"Distinct run and conclusion totals for each repository.","from":"repository-run-statistics","joins":[{"source":"repository-import-totals","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"}],"fields":[{"field":"imported-runs","as":"imported-runs"}]}],"select":[{"field":"organization"},{"field":"repository"},{"field":"runs"},{"field":"failed"},{"field":"action-required"},{"field":"imported-runs"}]},{"name":"repository-activity-preview","subject":"List repository identities before execution metrics are computed.","objective":"Show retained repository identities and drill links while activity metrics are pending.","acceptance":"List repositories by organization with repository drill links; this preview does not establish activity totals or outcomes.","description":"Fast repository inventory with drill links; activity fields remain pending.","from":"repositories","compute":[{"as":"repository-slug","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"encoded-repository","function":"url-encode","args":[{"field":"repository-slug"}]},{"as":"repository-dashboard-href","function":"concat","args":[{"value":"#page-repository-detail?repository="},{"field":"encoded-repository"}]},{"as":"repository-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"repository-slug"},{"value":" repository dashboard"}]},{"as":"repository-dashboard-link","function":"dashboard-link","args":[{"field":"repository-link"},{"field":"repository-dashboard-href"},{"field":"repository-dashboard-label"},{"field":"repository-slug"}]}],"select":[{"field":"organization"},{"field":"repository-slug","as":"repository"},{"field":"repository-dashboard-link","as":"repository-link"}],"order-by":[{"field":"repository","direction":"asc"}]},{"name":"repository-activity-core","subject":"Join each repository with its workflow, report, and run totals.","objective":"Attach retained workflow, report, and run aggregates to each repository for bounded inventory review.","acceptance":"Preserve each repository and the available joined aggregates by organization and repository; unmatched metrics remain missing evidence, not confirmed zero activity or evaluated outcomes.","description":"Repository inventory joined with workflow, report, evaluation, and run totals.","from":"repositories","joins":[{"source":"repository-workflow-totals","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"}],"fields":[{"field":"workflows","as":"observed-workflows"},{"field":"disabled","as":"observed-disabled"}]},{"source":"repository-report-totals","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"}],"fields":[{"field":"reports","as":"observed-reports"}]},{"source":"repository-run-totals","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"}],"fields":[{"field":"runs","as":"observed-runs"},{"field":"failed","as":"observed-failed"},{"field":"action-required","as":"observed-action-required"},{"field":"imported-runs","as":"observed-imported-runs"}]}]},{"name":"repository-activity","subject":"Show repository-level execution health, outcome activity, and AI Credit usage in an actionable inventory.","objective":"Prioritize repository drill-down using declared workflows, observed runs, reports, failures, import coverage, and AIC.","acceptance":"Return repository identity and link with retained counts, ingestion indicator, failure summary, AIC, and computed status; statuses describe retained evidence only, and an empty or unavailable preview cannot verify health, outcomes, or zero activity.","description":"Repository-local execution health and attributed outcome totals.","from":"repository-activity-core","joins":[{"source":"repository-aic-totals","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"}],"fields":[{"field":"aic","as":"observed-aic"}]}],"compute":[{"as":"repository-slug","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"workflows","function":"coalesce","args":[{"field":"observed-workflows"},{"value":0}]},{"as":"disabled","function":"coalesce","args":[{"field":"observed-disabled"},{"value":0}]},{"as":"runs","function":"coalesce","args":[{"field":"observed-runs"},{"value":0}]},{"as":"failed","function":"coalesce","args":[{"field":"observed-failed"},{"value":0}]},{"as":"imported-runs","function":"coalesce","args":[{"field":"observed-imported-runs"},{"value":0}]},{"as":"ingestion-rate","function":"quotient","args":[{"field":"imported-runs"},{"field":"runs"}]},{"as":"ingestion","function":"format-percent","args":[{"field":"ingestion-rate"}]},{"as":"action-required","function":"coalesce","args":[{"field":"observed-action-required"},{"value":0}]},{"as":"aic","function":"coalesce","args":[{"field":"observed-aic"},{"value":0}]},{"as":"has-failures","function":"greater-than","args":[{"field":"failed"},{"value":0}]},{"as":"has-action-required","function":"greater-than","args":[{"field":"action-required"},{"value":0}]},{"as":"has-runs","function":"greater-than","args":[{"field":"runs"},{"value":0}]},{"as":"has-disabled","function":"greater-than","args":[{"field":"disabled"},{"value":0}]},{"as":"outcomes-observed","function":"coalesce","args":[{"field":"observed-reports"},{"value":0}]},{"as":"has-outcomes","function":"greater-than","args":[{"field":"outcomes-observed"},{"value":0}]},{"as":"failure-rate","function":"quotient","args":[{"field":"failed"},{"field":"runs"}]},{"as":"failure-percent","function":"format-percent","args":[{"field":"failure-rate"}]},{"as":"failure-count","function":"format-count","args":[{"field":"failed"}]},{"as":"observed-failure-summary","function":"concat","args":[{"field":"failure-percent"},{"value":" · "},{"field":"failure-count"},{"value":" failed"}]},{"as":"failure-summary","function":"if","args":[{"field":"has-runs"},{"field":"observed-failure-summary"},{"value":"—"}]},{"as":"outcome-status","function":"if","args":[{"field":"has-outcomes"},{"value":"Outcomes observed"},{"value":"No recent activity"}]},{"as":"disabled-status","function":"if","args":[{"field":"has-disabled"},{"value":"Disabled workflows"},{"field":"outcome-status"}]},{"as":"run-status","function":"if","args":[{"field":"has-runs"},{"value":"No failures observed"},{"field":"disabled-status"}]},{"as":"action-status","function":"if","args":[{"field":"has-action-required"},{"value":"Approval required"},{"field":"run-status"}]},{"as":"status","function":"if","args":[{"field":"has-failures"},{"value":"Needs attention"},{"field":"action-status"}]},{"as":"encoded-repository","function":"url-encode","args":[{"field":"repository-slug"}]},{"as":"repository-dashboard-href","function":"concat","args":[{"value":"#page-repository-detail?repository="},{"field":"encoded-repository"}]},{"as":"repository-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"repository-slug"},{"value":" repository dashboard"}]},{"as":"repository-dashboard-link","function":"dashboard-link","args":[{"field":"repository-link"},{"field":"repository-dashboard-href"},{"field":"repository-dashboard-label"},{"field":"repository-slug"}]}],"select":[{"field":"organization"},{"field":"repository","as":"repository-name"},{"field":"repository-slug","as":"repository"},{"field":"workflows"},{"field":"observed-reports","as":"reports"},{"field":"runs"},{"field":"ingestion"},{"field":"failure-summary"},{"field":"aic"},{"field":"status"},{"field":"repository-dashboard-link","as":"repository-link"},{"field":"failed"}],"order-by":[{"field":"failed","direction":"desc"},{"field":"runs","direction":"desc"},{"field":"repository","direction":"asc"}]},{"name":"repository-observed-run-counts","subject":"Count distinct retained run IDs by repository without importing event evidence.","objective":"Supply the run-volume chart without computing activity health, ingestion coverage, or workflow costs.","acceptance":"Group by organization and repository coordinate and count distinct retained run IDs, not attempts; missing runs remain missing evidence and global scope and time filters still apply.","from":"runs","compute":[{"as":"repository-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]}],"aggregate":{"by":["organization","repository-coordinate"],"values":[{"field":"run","as":"runs","reducer":"distinct-count"}]}},{"name":"repository-run-inventory","subject":"Registered repositories and distinct retained workflow run IDs in the selected horizon.","objective":"Compare repository execution volume and choose repositories for drill-down.","acceptance":"Keep up to 100 repository identities and drill links, ordered by run count descending with repository tie-breaks. Zero means no retained runs, not proof of inactivity; preserve unavailable and partial evidence. The Table view retains the full inventory.","from":"repository-activity-preview","joins":[{"source":"repository-observed-run-counts","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository-coordinate"}],"fields":[{"field":"runs","as":"observed-runs"}]}],"compute":[{"as":"runs","function":"coalesce","args":[{"field":"observed-runs"},{"value":0}]}],"select":[{"field":"organization"},{"field":"repository"},{"field":"runs"},{"field":"repository-link"}],"order-by":[{"field":"runs","direction":"desc"},{"field":"repository","direction":"asc"}],"limit":100},{"name":"workflow-route-record","subject":"Project the selected workflow's identity and registration for its route shell.","objective":"Identify the workflow and its recorded campaign registration before inspecting route-specific evidence.","acceptance":"Preserve organization, repository, workflow identity, recorded role, activation, campaign, rollout mode, and source link; absent registration is not inferred from runs, and displayed activation does not grant execution authority.","from":"workflows","select":[{"field":"organization"},{"field":"repository"},{"field":"workflow"},{"field":"workflow-name"},{"field":"workflow-role"},{"field":"workflow-active"},{"field":"campaign"},{"field":"campaign-name"},{"field":"rollout-mode"},{"field":"workflow-link"}]},{"name":"workflow-runtime-health-summary","subject":"Count mutually exclusive runtime conclusion classes for the selected workflow.","objective":"Identify workflows whose retained run conclusions or pending execution warrant investigation.","acceptance":"Within each organization, repository, and workflow, successful, failed, approval, pending, and other counts sum to the retained run total; missing or unrecognized conclusions are not treated as success, and runtime success is not a verified outcome.","from":"runs","compute":[{"as":"successful","function":"equals-any","args":[{"field":"run-conclusion"},{"value":"success"}]},{"as":"failed","function":"equals-any","args":[{"field":"run-conclusion"},{"value":"failure"},{"value":"startup-failure"},{"value":"stale"},{"value":"timed-out"}]},{"as":"approval","function":"equals-any","args":[{"field":"run-conclusion"},{"value":"action-required"}]},{"as":"classified","function":"equals-any","args":[{"field":"run-conclusion"},{"value":"success"},{"value":"failure"},{"value":"startup-failure"},{"value":"stale"},{"value":"timed-out"},{"value":"action-required"}]},{"as":"status","function":"concat","args":[{"field":"run-status"},{"value":""}]},{"as":"terminal-or-missing","function":"equals-any","args":[{"field":"status"},{"value":"completed"},{"value":""}]}],"aggregate":{"by":["organization","repository","workflow"],"values":[{"field":"run","as":"total","reducer":"count"},{"field":"run","as":"successful","reducer":"count","filter":{"predicates":[{"field":"successful","equals":true}]}},{"field":"run","as":"failed","reducer":"count","filter":{"predicates":[{"field":"failed","equals":true}]}},{"field":"run","as":"approval","reducer":"count","filter":{"predicates":[{"field":"approval","equals":true}]}},{"field":"run","as":"pending","reducer":"count","filter":{"predicates":[{"field":"classified","equals":false},{"field":"terminal-or-missing","equals":false}]}},{"field":"run","as":"other","reducer":"count","filter":{"predicates":[{"field":"classified","equals":false},{"field":"terminal-or-missing","equals":true}]}}]}},{"name":"workflow-runtime-usage-summary","subject":"Sum retained AI Credits and count telemetry rows for the selected workflow without transferring runs.","objective":"Inspect a workflow's observed AI Credit consumption together with the amount of retained usage telemetry.","acceptance":"AI Credits sum the retained aic values within each organization, repository, and workflow, and telemetry-count counts its usage records; absent telemetry does not establish zero cost or complete run coverage.","from":"usage","compute":[{"as":"positive-aic","function":"greater-than","args":[{"field":"aic"},{"value":0}]}],"aggregate":{"by":["organization","repository","workflow"],"values":[{"field":"aic","as":"aic","reducer":"sum","filter":{"predicates":[{"field":"positive-aic","equals":true}]}},{"field":"run","as":"telemetry-count","reducer":"count"}]}},{"name":"outcome-route-record","subject":"Project the selected safe-output record for the outcome route and its sections.","objective":"Inspect a retained safe output's recorded disposition and follow its durable evidence links.","acceptance":"Preserve safe-output and run identity, title, category, disposition, summary, timestamps, rollout mode, workflow context, and retained links; missing fields stay unknown and a recorded disposition is not independently verified operational impact.","from":"outcomes","select":[{"field":"safe-output"},{"field":"run"},{"field":"outcome-title"},{"field":"outcome-number"},{"field":"outcome-category"},{"field":"outcome-status"},{"field":"outcome-state"},{"field":"outcome-summary"},{"field":"published-at"},{"field":"observed-at"},{"field":"rollout-mode"},{"field":"workflow"},{"field":"workflow-name"},{"field":"workflow-link"},{"field":"external-link"},{"field":"issue-link"},{"field":"pull-request-link"},{"field":"run-link"}]},{"name":"entity-runs","subject":"Project run entities for reusable run cards and workflow drill-down.","objective":"Expose retained run-attempt identity, execution timing, conclusion, and link for a bounded workflow-run inspection.","acceptance":"Keep organization, repository, workflow, run and attempt with status, conclusion, event, branch, duration, timestamps, and run link; missing timing or conclusion remains unknown rather than inferred success.","from":"runs","select":[{"field":"organization"},{"field":"repository"},{"field":"workflow"},{"field":"target-repository"},{"field":"run"},{"field":"run-attempt"},{"field":"run-title"},{"field":"run-status"},{"field":"run-conclusion"},{"field":"event"},{"field":"branch"},{"field":"duration"},{"field":"started-at"},{"field":"ended-at"},{"field":"run-link"}],"order-by":[{"field":"started-at","direction":"desc"}]},{"name":"workflow-runs","subject":"Project canonical runs into route-addressable workflow run evidence.","objective":"Trace retained runs and recorded failure evidence for a selected workflow route.","acceptance":"Preserve workflow route, run identity, start/end, status, conclusion, failure fields, mode, engine/model metadata, and run link; missing failure details do not prove success or rule out incomplete import.","description":"Workflow runs with a stable repository and workflow route key.","from":"runs","compute":[{"as":"repository-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"workflow-route","function":"concat","args":[{"field":"repository-coordinate"},{"value":":"},{"field":"workflow"}]}],"select":[{"field":"workflow-route"},{"field":"organization"},{"field":"repository"},{"field":"workflow"},{"field":"run"},{"field":"run-title"},{"field":"event"},{"field":"started-at"},{"field":"ended-at"},{"field":"run-status"},{"field":"run-conclusion"},{"field":"failure-job"},{"field":"failure-message"},{"field":"failure-step"},{"field":"failure-log"},{"field":"rollout-mode"},{"field":"engine"},{"field":"engine-version"},{"field":"gh-aw-version"},{"field":"requested-model"},{"field":"resolved-model"},{"field":"run-link"}],"order-by":[{"field":"started-at","direction":"desc"},{"field":"run","direction":"desc"}]},{"name":"workflow-failure-trend","subject":"Show recent failure counts and their change for each workflow.","objective":"Spot a change in observed workflow failure activity without treating unknown conclusions as failures.","acceptance":"Each observed failure counts once within its own workflow; the first change is undefined and the seven-observation window is not a seven-day calendar interval.","from":"workflow-runs","compute":[{"as":"is-failure","function":"equals-any","args":[{"field":"run-conclusion"},{"value":"failure"},{"value":"timed_out"}]},{"as":"failure-count","function":"if","args":[{"field":"is-failure"},{"value":1},{"value":0}]}],"window":[{"operation":"rolling","field":"failure-count","as":"recent-failure-count","frame":7,"reducer":"sum","order-by":[{"field":"started-at","direction":"asc"},{"field":"run","direction":"asc"}],"groupby":["workflow-route"]},{"operation":"change","field":"recent-failure-count","as":"failure-count-change","mode":"absolute","order-by":[{"field":"started-at","direction":"asc"},{"field":"run","direction":"asc"}],"groupby":["workflow-route"]}]},{"name":"workflow-reports","subject":"Project retained outcomes into route-addressable workflow reports.","objective":"Review retained workflow outcome reports separately from execution status before interpreting operational results.","acceptance":"Keep route, safe output, report title and summary, recorded status, category, observation time, metadata, and external link; missing reports or status do not imply success or no work.","description":"Workflow outcome reports with stable route keys and disposition fields.","from":"outcomes","compute":[{"as":"report-repository","function":"coalesce","args":[{"field":"runtime-repository"},{"field":"repository"}]},{"as":"workflow-route","function":"concat","args":[{"field":"report-repository"},{"value":":"},{"field":"workflow"}]},{"as":"report-status","function":"coalesce","args":[{"field":"outcome-status"},{"field":"outcome-state"},{"value":"unknown"}]}],"select":[{"field":"workflow-route"},{"field":"safe-output"},{"field":"outcome-title"},{"field":"outcome-summary"},{"field":"report-status","as":"outcome-status"},{"field":"rollout-mode"},{"field":"engine"},{"field":"engine-version"},{"field":"requested-model"},{"field":"resolved-model"},{"field":"outcome-category"},{"field":"observed-at"},{"field":"external-link"}],"order-by":[{"field":"observed-at","direction":"desc"},{"field":"outcome-title","direction":"asc"}]},{"name":"value-evidence-facts","subject":"Published original evidence for frozen workflow value contracts.","objective":"Keep report identity, target repository, workflow and capture together.","acceptance":"Read canonical evidence only. No GitHub acquisition, HTML loading or fabricated evidence on navigation.","from":"operational-value-evidence","time":{"range":"all"},"compute":[{"as":"workflow-route","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"},{"value":":"},{"field":"workflow-path"}]}]},{"name":"value-contracts","subject":"Latest retained report contract per repository, workflow and native measure.","objective":"Prevent old reports or versions from masking newer evidence.","acceptance":"Select the latest cutoff then capture before evaluating missing or incomplete evidence. Preserve separate measures.","from":"value-evidence-facts","filter":{"predicates":[{"field":"fact-kind","equals":"contract"}]},"compute":[{"as":"report-marker","function":"literal","args":[{"value":1}]}],"window":[{"operation":"change","field":"report-marker","as":"older-report","mode":"absolute","groupby":["organization","repository","workflow","metric-id"],"order-by":[{"field":"window-end","direction":"desc"},{"field":"observed-at","direction":"desc"},{"field":"report-id","direction":"desc"}]}]},{"name":"value-capture-order","subject":"Actual captures across the retained measures of each workflow.","objective":"Expose the last accepted capture independently of collection decisions.","acceptance":"Select by original capture time. A deferred or failed check cannot advance evidence clocks.","from":"value-contracts","window":[{"operation":"change","field":"report-marker","as":"later-capture","mode":"absolute","groupby":["organization","repository","workflow"],"order-by":[{"field":"observed-at","direction":"desc"},{"field":"report-id","direction":"desc"}]}]},{"name":"value-latest-capture","subject":"One last accepted capture per workflow, not a freshness claim.","objective":"Join capture and cutoff without multiplying collection registrations.","acceptance":"Missing packets remain unavailable, never zero or an inferred successful collection.","from":"value-capture-order","filter":{"predicates":[{"field":"later-capture","equals":"unknown"}]}},{"name":"value-collection-health","subject":"Reviewed registration and authoritative collection decisions, with independently retained evidence.","objective":"Explain disabled, unconfigured, deferred, failed and not-yet-captured workflows.","acceptance":"Use published collector facts, not missing result cards. Preserve decision, attempt, capture and cutoff as distinct clocks.","from":"workflow-value-collections","time":{"range":"all"},"joins":[{"source":"value-latest-capture","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"}],"fields":[{"field":"observed-at","as":"captured-at"},{"field":"window-end","as":"evidence-cutoff"}]}],"compute":[{"as":"workflow-route","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"},{"value":":"},{"field":"workflow-path"}]},{"as":"workflow-context","function":"concat","args":[{"field":"workflow"},{"value":" · "},{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"capture-missing","function":"equals-any","args":[{"field":"captured-at"},{"value":null}]},{"as":"evidence-state","function":"if","args":[{"field":"capture-missing"},{"value":"No retained capture"},{"value":"Retained evidence available"}]}],"order-by":[{"field":"organization","direction":"asc"},{"field":"repository","direction":"asc"},{"field":"workflow","direction":"asc"}]},{"name":"value-registered-collections","subject":"Reviewed Value registrations, including explicit disables and registrations with no report.","objective":"Make collection health visible before the first accepted packet.","acceptance":"Registration is independent of measured outcomes. No enrollment or acquisition follows from navigation.","from":"value-collection-health","filter":{"predicates":[{"field":"registration","in":["enabled","disabled"]}]},"limit":1000},{"name":"value-snapshots","subject":"Independent repository-state observations and exact item drill-downs.","objective":"Keep everyone's changes separate from workflow-linked delivery.","acceptance":"Retain observed native values, dates and immutable references. Do not invent intermediate observations.","from":"value-evidence-facts","filter":{"predicates":[{"field":"fact-kind","equals":"snapshot"}]},"compute":[{"as":"snapshot-marker","function":"literal","args":[{"value":1}]},{"as":"snapshot-route","function":"concat","args":[{"field":"report-id"},{"value":"|"},{"field":"fact-id"}]},{"as":"encoded-snapshot","function":"url-encode","args":[{"field":"snapshot-route"}]},{"as":"snapshot-href","function":"concat","args":[{"value":"#page-value-snapshot?snapshot="},{"field":"encoded-snapshot"}]}],"order-by":[{"field":"at","direction":"asc"},{"field":"fact-id","direction":"asc"}]},{"name":"value-first-snapshot-order","subject":"First independently observed repository state.","objective":"Name the actual first-snapshot reference rather than an invented baseline.","acceptance":"Strictly use retained snapshot time. A post-adoption snapshot is not a pre-adoption baseline.","from":"value-snapshots","window":[{"operation":"change","field":"snapshot-marker","as":"earlier-snapshot","mode":"absolute","groupby":["report-id"],"order-by":[{"field":"at","direction":"asc"}]}]},{"name":"value-first-snapshot","subject":"First retained snapshot per report.","objective":"Provide the explicit reference value and date.","acceptance":"No retained reference means no comparison.","from":"value-first-snapshot-order","filter":{"predicates":[{"field":"earlier-snapshot","equals":"unknown"}]}},{"name":"value-last-snapshot-order","subject":"Latest independently observed repository state.","objective":"Show the actual last measurement rather than an extrapolation.","acceptance":"Preserve the latest retained snapshot even if unchanged.","from":"value-snapshots","window":[{"operation":"change","field":"snapshot-marker","as":"later-snapshot","mode":"absolute","groupby":["report-id"],"order-by":[{"field":"at","direction":"desc"}]}]},{"name":"value-last-snapshot","subject":"Last retained snapshot per report.","objective":"Provide the current native observation.","acceptance":"One snapshot establishes state, not movement.","from":"value-last-snapshot-order","filter":{"predicates":[{"field":"later-snapshot","equals":"unknown"}]}},{"name":"value-output-counts","subject":"Retained safe outputs and applied creation receipts.","objective":"Describe output activity without treating it as accepted value.","acceptance":"Count distinct validated output facts. Tracking corroboration is not an applied receipt.","from":"value-evidence-facts","filter":{"predicates":[{"field":"fact-kind","equals":"output"}]},"aggregate":{"by":["report-id"],"values":[{"field":"fact-id","as":"retained-outputs","reducer":"count"},{"field":"fact-id","as":"receipt-outputs","reducer":"count","filter":{"predicates":[{"field":"origin","equals":"receipt-verified"}]}}]}},{"name":"value-implementation-counts","subject":"Distinct accepted implementations and their measured native effects.","objective":"Count each accepted implementation once, including zero and negative effects.","acceptance":"Validated implementation identities are unique; many-to-many output edges must not multiply value. Complete coverage is checked separately.","from":"value-evidence-facts","filter":{"predicates":[{"field":"fact-kind","equals":"implementation"}]},"compute":[{"as":"accepted-ms","function":"timestamp","args":[{"field":"at"}]},{"as":"cutoff-ms","function":"timestamp","args":[{"field":"window-end"}]},{"as":"current-start","function":"difference","args":[{"field":"cutoff-ms"},{"value":2419200000}]},{"as":"previous-start","function":"difference","args":[{"field":"cutoff-ms"},{"value":4838400000}]},{"as":"before-current","function":"greater-than","args":[{"field":"current-start"},{"field":"accepted-ms"}]},{"as":"before-previous","function":"greater-than","args":[{"field":"previous-start"},{"field":"accepted-ms"}]},{"as":"current-effect","function":"if","args":[{"field":"before-current"},{"value":0},{"field":"value"}]},{"as":"previous-candidate","function":"if","args":[{"field":"before-previous"},{"value":0},{"field":"value"}]},{"as":"previous-effect","function":"if","args":[{"field":"before-current"},{"field":"previous-candidate"},{"value":0}]}],"aggregate":{"by":["report-id"],"values":[{"field":"fact-id","as":"accepted-implementations","reducer":"count"},{"field":"value","as":"known-result","reducer":"sum"},{"field":"current-effect","as":"known-recent","reducer":"sum"},{"field":"previous-effect","as":"known-previous","reducer":"sum"}]}},{"name":"value-covered-durations","subject":"Explicit complete evidence durations in the report and adjacent 28-day delivery periods.","objective":"Distinguish known zero from gaps or incomplete evidence.","acceptance":"The producer validates non-overlapping bounded coverage. Count only complete intervals, clipped to each exact half-open period.","from":"value-evidence-facts","filter":{"predicates":[{"field":"fact-kind","equals":"coverage"},{"field":"coverage-status","equals":"complete"}]},"compute":[{"as":"left-ms","function":"timestamp","args":[{"field":"at"}]},{"as":"right-ms","function":"timestamp","args":[{"field":"end-at"}]},{"as":"cutoff-ms","function":"timestamp","args":[{"field":"window-end"}]},{"as":"current-start","function":"difference","args":[{"field":"cutoff-ms"},{"value":2419200000}]},{"as":"previous-start","function":"difference","args":[{"field":"cutoff-ms"},{"value":4838400000}]},{"as":"after-current","function":"greater-than","args":[{"field":"left-ms"},{"field":"current-start"}]},{"as":"after-previous","function":"greater-than","args":[{"field":"left-ms"},{"field":"previous-start"}]},{"as":"before-current-end","function":"greater-than","args":[{"field":"current-start"},{"field":"right-ms"}]},{"as":"current-left","function":"if","args":[{"field":"after-current"},{"field":"left-ms"},{"field":"current-start"}]},{"as":"previous-left","function":"if","args":[{"field":"after-previous"},{"field":"left-ms"},{"field":"previous-start"}]},{"as":"previous-right","function":"if","args":[{"field":"before-current-end"},{"field":"right-ms"},{"field":"current-start"}]},{"as":"duration","function":"difference","args":[{"field":"right-ms"},{"field":"left-ms"}]},{"as":"current-duration","function":"difference","args":[{"field":"right-ms"},{"field":"current-left"}]},{"as":"previous-duration","function":"difference","args":[{"field":"previous-right"},{"field":"previous-left"}]},{"as":"positive-current","function":"greater-than","args":[{"field":"current-duration"},{"value":0}]},{"as":"positive-previous","function":"greater-than","args":[{"field":"previous-duration"},{"value":0}]},{"as":"covered-current","function":"if","args":[{"field":"positive-current"},{"field":"current-duration"},{"value":0}]},{"as":"covered-previous","function":"if","args":[{"field":"positive-previous"},{"field":"previous-duration"},{"value":0}]}],"aggregate":{"by":["report-id"],"values":[{"field":"duration","as":"covered-duration","reducer":"sum"},{"field":"covered-current","as":"covered-current","reducer":"sum"},{"field":"covered-previous","as":"covered-previous","reducer":"sum"}]}},{"name":"value-report-delivery","subject":"Evidence-qualified output and accepted-contribution totals.","objective":"Keep populations and native units separate without an implied conversion rate.","acceptance":"Absent output context is unknown. Missing coverage withholds complete totals and recent zero, retaining labelled known subtotals.","from":"value-contracts","joins":[{"source":"value-output-counts","type":"left","on":[{"left":"report-id","right":"report-id"}],"fields":[{"field":"retained-outputs","as":"retained-outputs"},{"field":"receipt-outputs","as":"retained-receipts"}]},{"source":"value-implementation-counts","type":"left","on":[{"left":"report-id","right":"report-id"}],"fields":[{"field":"accepted-implementations","as":"retained-implementations"},{"field":"known-result","as":"known-result"},{"field":"known-recent","as":"known-recent"},{"field":"known-previous","as":"known-previous"}]},{"source":"value-covered-durations","type":"left","on":[{"left":"report-id","right":"report-id"}],"fields":[{"field":"covered-duration","as":"covered-duration"},{"field":"covered-current","as":"covered-current"},{"field":"covered-previous","as":"covered-previous"}]}],"compute":[{"as":"start-ms","function":"timestamp","args":[{"field":"window-start"}]},{"as":"end-ms","function":"timestamp","args":[{"field":"window-end"}]},{"as":"report-duration","function":"difference","args":[{"field":"end-ms"},{"field":"start-ms"}]},{"as":"complete-report","function":"equals-any","args":[{"field":"covered-duration"},{"field":"report-duration"}]},{"as":"complete-current","function":"equals-any","args":[{"field":"covered-current"},{"value":2419200000}]},{"as":"complete-previous","function":"equals-any","args":[{"field":"covered-previous"},{"value":2419200000}]},{"as":"show-workflow-trail","function":"equals-any","args":[{"field":"measurement-basis"},{"value":"workflow-contribution"}]},{"as":"known-output-count","function":"coalesce","args":[{"field":"retained-outputs"},{"value":0}]},{"as":"known-receipt-count","function":"coalesce","args":[{"field":"retained-receipts"},{"value":0}]},{"as":"receipt-outputs","function":"if","args":[{"field":"outputs-available"},{"field":"known-receipt-count"},{"value":null}]},{"as":"accepted-implementations","function":"coalesce","args":[{"field":"retained-implementations"},{"value":0}]},{"as":"output-count","function":"if","args":[{"field":"outputs-available"},{"field":"known-output-count"},{"value":null}]},{"as":"native-result","function":"coalesce","args":[{"field":"known-result"},{"value":0}]},{"as":"current-subtotal","function":"coalesce","args":[{"field":"known-recent"},{"value":0}]},{"as":"previous-subtotal","function":"coalesce","args":[{"field":"known-previous"},{"value":0}]},{"as":"recent-result","function":"if","args":[{"field":"complete-current"},{"field":"current-subtotal"},{"value":null}]},{"as":"previous-result","function":"if","args":[{"field":"complete-previous"},{"field":"previous-subtotal"},{"value":null}]}]},{"name":"value-report-summary","subject":"Shared native card and report comparison against the first retained snapshot.","objective":"Show signed repository-wide movement, the goal direction and the exact comparison dates.","acceptance":"This first/last snapshot comparison is not the adjacent-period alert policy, a pre-adoption baseline or causal workflow credit. One snapshot is not zero change.","from":"value-report-delivery","joins":[{"source":"value-first-snapshot","type":"left","on":[{"left":"report-id","right":"report-id"}],"fields":[{"field":"value","as":"reference-value"},{"field":"at","as":"reference-at"}]},{"source":"value-last-snapshot","type":"left","on":[{"left":"report-id","right":"report-id"}],"fields":[{"field":"value","as":"current-value"},{"field":"at","as":"current-at"},{"field":"snapshot-href","as":"current-snapshot-href"}]}],"compute":[{"as":"same-snapshot","function":"equals-any","args":[{"field":"reference-at"},{"field":"current-at"}]},{"as":"raw-change","function":"difference","args":[{"field":"current-value"},{"field":"reference-value"}]},{"as":"native-change","function":"if","args":[{"field":"same-snapshot"},{"value":null},{"field":"raw-change"}]},{"as":"change-missing","function":"equals-any","args":[{"field":"native-change"},{"value":null}]},{"as":"rising","function":"greater-than","args":[{"field":"native-change"},{"value":0}]},{"as":"falling","function":"greater-than","args":[{"value":0},{"field":"native-change"}]},{"as":"unchanged","function":"equals-any","args":[{"field":"native-change"},{"value":0}]},{"as":"decrease-goal","function":"equals-any","args":[{"field":"snapshot-direction"},{"value":"decrease"}]},{"as":"increase-goal","function":"equals-any","args":[{"field":"snapshot-direction"},{"value":"increase"}]},{"as":"increase-movement","function":"if","args":[{"field":"rising"},{"value":"Better"},{"value":"Worse"}]},{"as":"decrease-movement","function":"if","args":[{"field":"falling"},{"value":"Better"},{"value":"Worse"}]},{"as":"directed-movement","function":"if","args":[{"field":"decrease-goal"},{"field":"decrease-movement"},{"field":"increase-movement"}]},{"as":"known-movement","function":"if","args":[{"field":"unchanged"},{"value":"Unchanged"},{"field":"directed-movement"}]},{"as":"movement","function":"if","args":[{"field":"change-missing"},{"value":"Comparison unavailable"},{"field":"known-movement"}]},{"as":"increase-direction-label","function":"if","args":[{"field":"increase-goal"},{"value":"↑ Higher is better"},{"value":"Direction not retained"}]},{"as":"direction-label","function":"if","args":[{"field":"decrease-goal"},{"value":"↓ Lower is better"},{"field":"increase-direction-label"}]},{"as":"change-arrow","function":"if","args":[{"field":"rising"},{"value":"↑ +"},{"value":"↓ "}]},{"as":"change-number","function":"format-count","args":[{"field":"native-change"}]},{"as":"directional-delta","function":"concat","args":[{"field":"change-arrow"},{"field":"change-number"},{"value":" "},{"field":"snapshot-unit"}]},{"as":"known-delta","function":"if","args":[{"field":"unchanged"},{"value":"Unchanged"},{"field":"directional-delta"}]},{"as":"delta-label","function":"if","args":[{"field":"change-missing"},{"value":"Comparison unavailable"},{"field":"known-delta"}]},{"as":"signed-change","function":"concat","args":[{"field":"change-arrow"},{"field":"change-number"},{"value":" "},{"field":"snapshot-unit"},{"value":" · "},{"field":"movement"}]},{"as":"unchanged-change","function":"if","args":[{"field":"unchanged"},{"value":"Unchanged"},{"field":"signed-change"}]},{"as":"change-label","function":"if","args":[{"field":"change-missing"},{"value":"Comparison unavailable"},{"field":"unchanged-change"}]},{"as":"reference-day","function":"date-day","args":[{"field":"reference-at"}]},{"as":"known-comparison-label","function":"concat","args":[{"value":"Since "},{"field":"reference-day"},{"value":" · Everyone's work"}]},{"as":"comparison-label","function":"if","args":[{"field":"change-missing"},{"value":"No earlier snapshot for comparison"},{"field":"known-comparison-label"}]},{"as":"workflow-label","function":"coalesce","args":[{"field":"workflow-name"},{"field":"workflow"}]},{"as":"workflow-context","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"},{"value":" · "},{"field":"workflow-label"}]},{"as":"encoded-workflow","function":"url-encode","args":[{"field":"workflow-route"}]},{"as":"workflow-value-href","function":"concat","args":[{"value":"#page-workflow-value?workflow="},{"field":"encoded-workflow"}]},{"as":"encoded-report","function":"url-encode","args":[{"field":"report-id"}]},{"as":"report-href","function":"concat","args":[{"value":"#page-value-report?report="},{"field":"encoded-report"}]}]},{"name":"value-workflow-results","subject":"Current published report results per native measure.","objective":"Expose the latest coherent packet on the workflow Value tab.","acceptance":"Never replace missing facts with an older measured version. Explicit report links retain their own version.","from":"value-report-summary","filter":{"predicates":[{"field":"older-report","equals":"unknown"}]}},{"name":"value-intent-sources","subject":"Immutable extracted workflow intent sources.","objective":"Let readers inspect the original goal and requirements.","acceptance":"Only retained HTTPS evidence is linked; workflow text remains untrusted.","from":"value-evidence-facts","filter":{"predicates":[{"field":"fact-kind","equals":"intent-source"}]}},{"name":"value-requirements","subject":"Original full acceptance requirements.","objective":"Distinguish the measured structural facet from all workflow safeguards.","acceptance":"Requirements are source text, not proof they passed.","from":"value-evidence-facts","filter":{"predicates":[{"field":"fact-kind","equals":"requirement"}]}},{"name":"value-outputs","subject":"Retained safe-output lifecycle facts.","objective":"Show receipts, current-at-cutoff state and originating evidence.","acceptance":"A closed output is not automatically an accepted implementation; absence of a link is unknown.","from":"value-evidence-facts","filter":{"predicates":[{"field":"fact-kind","equals":"output"}]},"order-by":[{"field":"at","direction":"desc"},{"field":"fact-id","direction":"asc"}]},{"name":"value-output-origin-evidence","subject":"Retained producer and applied safe-output evidence.","objective":"Let readers distinguish receipt-confirmed creation from corroborated tracking.","acceptance":"Tracking identities locate outputs but do not establish accepted value. Keep unavailable producer evidence explicit.","from":"value-evidence-facts","filter":{"predicates":[{"field":"fact-kind","equals":"output-evidence"}]},"joins":[{"source":"value-outputs","type":"inner","on":[{"left":"report-id","right":"report-id"},{"left":"parent-id","right":"fact-id"}],"fields":[{"field":"label","as":"output-label"},{"field":"url","as":"output-url"}]}]},{"name":"value-implementations","subject":"Accepted implementations and native before/after effects.","objective":"Expose delivery time and immutable acceptance evidence.","acceptance":"Do not equate acceptance with full quality verification or omit negative effects.","from":"value-evidence-facts","filter":{"predicates":[{"field":"fact-kind","equals":"implementation"}]},"order-by":[{"field":"at","direction":"desc"},{"field":"fact-id","direction":"asc"}]},{"name":"value-output-trails","subject":"Explicit output-to-implementation edges.","objective":"Make the trail from a proposal to an accepted measured change inspectable.","acceptance":"Use retained dated edges only. Many-to-many links do not duplicate headline counts or values.","from":"value-evidence-facts","filter":{"predicates":[{"field":"fact-kind","equals":"output-implementation"}]},"joins":[{"source":"value-outputs","type":"inner","on":[{"left":"report-id","right":"report-id"},{"left":"parent-id","right":"fact-id"}],"fields":[{"field":"label","as":"output-label"},{"field":"url","as":"output-url"}]},{"source":"value-implementations","type":"inner","on":[{"left":"report-id","right":"report-id"},{"left":"related-id","right":"fact-id"}],"fields":[{"field":"label","as":"implementation-label"},{"field":"url","as":"implementation-url"},{"field":"value","as":"implementation-value"},{"field":"at","as":"trail-accepted-at"}]}]},{"name":"value-implementation-files","subject":"Measured implementation files and retained lineage sources.","objective":"Link to exact Git facts rather than only a repository tree.","acceptance":"No URL is reconstructed from an unrelated revision. Preserve before, after and replacement file evidence.","from":"value-evidence-facts","filter":{"predicates":[{"field":"fact-kind","in":["implementation-evidence","implementation-lineage"]}]},"joins":[{"source":"value-implementations","type":"inner","on":[{"left":"report-id","right":"report-id"},{"left":"parent-id","right":"fact-id"}],"fields":[{"field":"label","as":"implementation-label"},{"field":"url","as":"implementation-url"}]}]},{"name":"value-quality-checks","subject":"Explicit independent verification checks.","objective":"Keep unverified behavior, tests and other safeguards visible.","acceptance":"Missing or not-verified is not a passing check.","from":"value-evidence-facts","filter":{"predicates":[{"field":"fact-kind","equals":"quality-check"}]}},{"name":"value-limitations","subject":"Retained evidence and attribution limitations.","objective":"Qualify claims without inventing completeness.","acceptance":"Treat source limitations as untrusted text and never suppress them.","from":"value-evidence-facts","filter":{"predicates":[{"field":"fact-kind","equals":"limitation"}]}},{"name":"value-snapshot-items","subject":"Actual counted items at an independent immutable snapshot.","objective":"Open exact per-item evidence from the plotted observation.","acceptance":"Only retained items are shown. Missing item evidence must not look like an empty measured population.","from":"value-evidence-facts","filter":{"predicates":[{"field":"fact-kind","equals":"snapshot-item"}]},"joins":[{"source":"value-snapshots","type":"inner","on":[{"left":"report-id","right":"report-id"},{"left":"parent-id","right":"fact-id"}],"fields":[{"field":"snapshot-route","as":"snapshot-route"},{"field":"at","as":"snapshot-at"}]}]},{"name":"audit-event-summary-buckets","subject":"Aggregate high- and medium-severity audit events with the same severity and summary by workflow.","objective":"Select recurring high- or medium-severity audit summaries for run-level investigation.","acceptance":"Each bucket's event count is traceable to retained audit or tool observations with the same campaign, severity, workflow, and summary; missing workflow attribution stays unknown, and a count alone does not verify impact.","description":"High- and medium-severity audit event counts grouped by severity, workflow, and shared summary.","from":"audits","union":["tools"],"filter":{"predicates":[{"field":"event-type","in":["audit.finding","audit.observability","audit.recommendation","audit.missing_tool","audit.missing_data","audit.noop","audit.mcp_failure","skill.invoked"]},{"field":"event-status","in":["high","medium"]}]},"joins":[{"source":"workflows","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"}],"fields":[{"field":"campaign","as":"campaign"}]}],"aggregate":{"by":["campaign","event-status","workflow","event-summary"],"values":[{"field":"event","as":"events","reducer":"count"}]},"select":[{"field":"campaign"},{"field":"event-status"},{"field":"workflow"},{"field":"event-summary"},{"field":"events"}],"order-by":[{"field":"event-status","direction":"asc"},{"field":"events","direction":"desc"},{"field":"workflow","direction":"asc"},{"field":"event-summary","direction":"asc"}]},{"name":"campaign-workflows","subject":"List campaign-owned orchestrator and worker workflows with database-backed execution totals.","objective":"Choose an active campaign workflow whose observed execution warrants inspection.","acceptance":"Listed workflows match active declared orchestrator or worker inventory entries; runs and AI Credits agree with the selected-horizon inventory, and absence is not evidence of disabled authority or no executions. Rollout mode is context, not permission to change policy.","description":"Campaign workflows projected from lean canonical inventory, with shared declaration names and active-only workflow drill-down links.","from":"campaign-workflow-inventory","filter":{"predicates":[{"field":"workflow-active","equals":"true"}]},"compute":[{"as":"workflow-identity","function":"concat","args":[{"field":"repository"},{"value":":"},{"field":"workflow"}]},{"as":"encoded-workflow","function":"url-encode","args":[{"field":"workflow-identity"}]},{"as":"workflow-dashboard-href","function":"concat","args":[{"value":"#page-workflow-runtime?workflow="},{"field":"encoded-workflow"}]},{"as":"workflow-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"workflow-display-name"},{"value":" workflow dashboard"}]},{"as":"workflow-dashboard-link","function":"dashboard-link","args":[{"field":"workflow-link"},{"field":"workflow-dashboard-href"},{"field":"workflow-dashboard-label"},{"field":"workflow-identity"}]}],"select":[{"field":"campaign"},{"field":"campaign-display-name","as":"campaign-name"},{"field":"organization"},{"field":"repository"},{"field":"workflow"},{"field":"workflow-display-name","as":"workflow-name"},{"field":"workflow-role"},{"field":"rollout-mode"},{"field":"workflow-active"},{"field":"runs"},{"field":"aic"},{"field":"repository-dashboard-link","as":"repository-link"},{"field":"workflow-dashboard-link","as":"workflow-link"}],"order-by":[{"field":"campaign-name","direction":"asc"},{"field":"workflow-role","direction":"asc"},{"field":"workflow-name","direction":"asc"}]},{"name":"campaign-repository-declarations","subject":"List active declared campaign workflows and their owning repositories without execution evidence.","objective":"Inspect campaign repository topology without computing unused run totals or import coverage.","acceptance":"Preserve active orchestrator and worker identities, display names, rollout context, links, and ordering. Declaration counts are not target enrollment, dispatch coverage, or execution totals. Empty inventory and unavailable workflow evidence remain distinct.","description":"Declaration-only repository topology. Run totals and import-evidence quality belong to execution views, not this inventory.","from":"campaign-workflow-declarations","filter":{"predicates":[{"field":"workflow-active","equals":"true"}]},"select":[{"field":"campaign"},{"field":"campaign-display-name","as":"campaign-name"},{"field":"organization"},{"field":"repository-slug","as":"repository"},{"field":"workflow"},{"field":"workflow-display-name","as":"workflow-name"},{"field":"workflow-role"},{"field":"declared-mode","as":"rollout-mode"},{"field":"workflow-active"},{"field":"repository-dashboard-link","as":"repository-link"}],"order-by":[{"field":"repository","direction":"asc"},{"field":"workflow","direction":"asc"}]},{"name":"campaign-repository-inventory","subject":"Present declared campaign repository topology in workflow display order.","objective":"Filter and search projected repository coordinates and workflow names without time-filtering structural declarations.","acceptance":"Preserve the campaign workflow list's stable ordering and declaration-only evidence quality; runtime horizons must not remove declared workflows.","from":"campaign-repository-declarations","order-by":[{"field":"campaign-name","direction":"asc"},{"field":"workflow-role","direction":"asc"},{"field":"workflow-name","direction":"asc"}]},{"name":"campaign-reports","subject":"Project retained outcomes into campaign-addressable report evidence.","objective":"Identify a campaign report whose durable outcome record needs follow-up.","acceptance":"Each report's campaign, title, source link, observation time, and disposition match its retained outcome; missing status is labeled unknown rather than accepted or resolved, and report production is not verified impact.","description":"Campaign outcome reports with database-backed disposition fields.","from":"outcomes","compute":[{"as":"report-status","function":"coalesce","args":[{"field":"outcome-status"},{"field":"outcome-state"},{"value":"unknown"}]}],"select":[{"field":"campaign"},{"field":"safe-output"},{"field":"outcome-title"},{"field":"outcome-summary"},{"field":"report-status","as":"outcome-status"},{"field":"rollout-mode"},{"field":"engine"},{"field":"engine-version"},{"field":"requested-model"},{"field":"resolved-model"},{"field":"outcome-category"},{"field":"observed-at"},{"field":"external-link"}],"order-by":[{"field":"observed-at","direction":"desc"},{"field":"outcome-title","direction":"asc"}]},{"name":"campaign-worker-issues","subject":"Project issue outcomes created by campaign worker workflows.","objective":"Choose a campaign worker issue whose current recorded disposition needs review.","acceptance":"Include only issues whose producing run joins declared worker inventory on organization, repository, and workflow, even when the issue lands elsewhere. Preserve campaign and role across Activity imports. Retain run and status evidence; missing closure details stay unknown and closure is not proof of resolution.","description":"Campaign-addressable issue outcomes restricted to declared worker workflows.","from":"outcomes","joins":[{"source":"workflows","type":"inner","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"}],"fields":[{"field":"workflow-role","as":"declared-workflow-role"}]}],"filter":{"predicates":[{"field":"outcome-category","equals":"issue"},{"field":"declared-workflow-role","equals":"worker"}]},"select":[{"field":"campaign"},{"field":"organization"},{"field":"repository"},{"field":"safe-output"},{"field":"outcome-number"},{"field":"outcome-title","as":"event-summary"},{"field":"outcome-title"},{"field":"outcome-summary"},{"field":"outcome-status"},{"field":"outcome-state"},{"field":"issue-state"},{"field":"issue-closed"},{"field":"issue-state-reason"},{"field":"issue-status"},{"field":"issue-closing-status"},{"field":"issue-status-detail"},{"field":"issue-closed-at"},{"field":"issue-status-observed-at"},{"field":"outcome-category","as":"safe-output-type"},{"field":"workflow"},{"field":"workflow-name"},{"field":"run"},{"field":"observed-at"},{"field":"issue-link"},{"field":"external-link"},{"field":"run-link"}],"order-by":[{"field":"observed-at","direction":"desc"}]},{"name":"campaign-issue-tab-counts","subject":"Count the retained worker issues available for each campaign Reports tab.","objective":"Decide whether a campaign has retained worker issue reports to inspect.","acceptance":"For each returned campaign, items equals the number of rows in campaign-worker-issues for that campaign in the same horizon; missing campaigns are not treated as zero issues or verified resolution.","description":"One campaign row with the number of retained issue outcomes produced by campaign workers.","from":"campaign-worker-issues","aggregate":{"by":["campaign"],"values":[{"field":"campaign","as":"items","reducer":"count"}]}},{"name":"campaign-readme-orchestrators","subject":"Resolve one repository link for each campaign README from its declared orchestrator workflow.","objective":"Locate the declared orchestrator repository to contextualize a campaign README.","acceptance":"Each returned campaign and repository link traces to a declared orchestrator workflow; missing or multiple declarations are reported as uncertain rather than inventing a canonical repository.","from":"workflows","filter":{"predicates":[{"field":"workflow-role","equals":"orchestrator"}]},"select":[{"field":"campaign"},{"field":"repository-link"}]},{"name":"campaign-readme-details","subject":"Present retained campaign README content with its repository-relative link context.","objective":"Open the campaign's retained README in its declared repository context before relying on its guidance.","acceptance":"The README text and path match the campaign record and any repository link resolves through a declared orchestrator; absent content or repository linkage remains unavailable, not inferred.","from":"campaigns","joins":[{"source":"campaign-readme-orchestrators","type":"left","on":[{"left":"campaign","right":"campaign"}],"fields":[{"field":"repository-link","as":"repository-link"}]}],"select":[{"field":"campaign"},{"field":"campaign-readme"},{"field":"campaign-readme-path"},{"field":"repository-link"}]},{"name":"campaign-memory-campaigns","subject":"Provide the registered campaigns whose repository memory can be browsed together.","objective":"Choose a registered campaign for repository-memory inspection.","acceptance":"Each campaign identity and display name matches the retained campaign registry in the selected scope; listing a campaign does not establish that memory observations exist or are complete.","description":"Registered campaigns ordered for the all-campaign repository-memory browser.","from":"campaigns","select":[{"field":"campaign"},{"field":"campaign-name"}],"order-by":[{"field":"campaign-name","direction":"asc"}]},{"name":"campaign-performance-baseline-totals","subject":"Establish a selected-horizon campaign baseline from concluded run attempts while keeping reliability, unverified production, and efficiency as separate facts.","objective":"Select campaigns whose retained run reliability, output production, or AI Credit efficiency merits closer examination.","acceptance":"Concluded and successful attempts, outputs, and mean AI Credits reconcile to filtered retained runs; absent denominators or costs stay unknown. Produced outputs are unverified, not operational value.","description":"Canonical campaign run attempts aggregated into bounded selected-horizon baseline totals without treating runtime success or produced outputs as operational value.","from":"campaign-runs","compute":[{"as":"run-attempt-identity","function":"concat","args":[{"field":"run"},{"value":":"},{"field":"run-attempt"}]},{"as":"positive-aic","function":"greater-than","args":[{"field":"aic-total"},{"value":0}]}],"aggregate":{"by":["campaign"],"values":[{"field":"run-attempt-identity","as":"concluded-runs","reducer":"count","filter":{"predicates":[{"field":"status","in":["success","failure","cancelled","timed-out","action-required","neutral","skipped","stale","startup-failure"]}]}},{"field":"run-attempt-identity","as":"successful-runs","reducer":"count","filter":{"predicates":[{"field":"status","equals":"success"}]}},{"field":"safe-items-count","as":"runs-with-output-evidence","reducer":"count","filter":{"predicates":[{"field":"status","equals":"success"}]}},{"field":"safe-items-count","as":"produced-outputs","reducer":"sum","filter":{"predicates":[{"field":"status","equals":"success"}]}},{"field":"aic-total","as":"aic-per-successful-run","reducer":"mean","filter":{"predicates":[{"field":"status","equals":"success"},{"field":"positive-aic","equals":true}]}}]}},{"name":"campaign-performance-baseline","subject":"Turn each campaign's selected-horizon baseline totals into deterministic reliability and production signals with an explicit successful-run efficiency fact.","objective":"Decide which campaign baseline signal needs run- or output-level verification next.","acceptance":"Success-rate and signal labels follow the retained totals and their explicit denominators; no concluded attempts or output evidence is distinguished from zero verified impact, and AI Credits per successful run remain a separate cost fact rather than a value score.","description":"A bounded, explainable baseline that distinguishes runtime reliability, unverified output production, and AI Credit efficiency.","from":"campaign-performance-baseline-totals","compute":[{"as":"success-rate","function":"quotient","args":[{"field":"successful-runs"},{"field":"concluded-runs"}]},{"as":"success-rate-display","function":"format-percent","args":[{"field":"success-rate"}]},{"as":"success-rate-percent","function":"product","args":[{"field":"success-rate"},{"value":100}]},{"as":"has-concluded-runs","function":"greater-than","args":[{"field":"concluded-runs"},{"value":0}]},{"as":"has-unsuccessful-runs","function":"greater-than","args":[{"field":"concluded-runs"},{"field":"successful-runs"}]},{"as":"observed-reliability-signal","function":"if","args":[{"field":"has-unsuccessful-runs"},{"value":"Unsuccessful runs observed"},{"value":"No unsuccessful runs observed"}]},{"as":"reliability-signal","function":"if","args":[{"field":"has-concluded-runs"},{"field":"observed-reliability-signal"},{"value":"No concluded runs observed"}]},{"as":"has-output-evidence","function":"greater-than","args":[{"field":"runs-with-output-evidence"},{"value":0}]},{"as":"has-produced-outputs","function":"greater-than","args":[{"field":"produced-outputs"},{"value":0}]},{"as":"observed-production-signal","function":"if","args":[{"field":"has-produced-outputs"},{"value":"Outputs produced; acceptance unverified"},{"value":"No outputs observed"}]},{"as":"production-signal","function":"if","args":[{"field":"has-output-evidence"},{"field":"observed-production-signal"},{"value":"Output evidence unavailable"}]}],"select":[{"field":"campaign"},{"field":"concluded-runs"},{"field":"successful-runs"},{"field":"success-rate"},{"field":"success-rate-display"},{"field":"success-rate-percent"},{"field":"reliability-signal"},{"field":"produced-outputs"},{"field":"production-signal"},{"field":"aic-per-successful-run"}]},{"name":"campaign-problem-runs","subject":"List retained failed runs for campaign problem investigation.","objective":"Choose a recent failed campaign run to investigate with its diagnostic evidence.","acceptance":"Each row corresponds to a retained campaign run with a declared failure, startup-failure, stale, or timed-out status; campaign-problem-run-evidence orders matching rows newest first. Absence is not proof of healthy execution or complete ingestion.","description":"Private failed-run input with retained diagnostic metadata; the evidence consumer orders only runs matching current runtime problems.","from":"campaign-runs","filter":{"predicates":[{"field":"status","in":["failure","startup-failure","stale","timed-out"]}]}},{"name":"campaign-problem-runtime-failures","subject":"Select current failing runtime partitions without presentation ordering.","objective":"Retain the exact current-failure eligibility needed by the problem evidence join.","acceptance":"A latest failure streak is a nonnegative integer, so failure-count at least one is equivalent to has-current-failure; missing or incomplete runtime evidence remains unknown.","description":"Private unsorted failure partitions for problem evidence; ordering is supplied by the retained failed runs.","from":"campaign-runtime-health-groups","filter":{"predicates":[{"field":"failure-count","gte":1}]},"compute":[{"as":"problem-kind","function":"coalesce","args":[{"value":"failure"},{"value":"failure"}]}]},{"name":"campaign-problem-runtime-partitions","subject":"Project current runtime problem keys and diagnoses for the failed-run evidence join.","objective":"Avoid sorting and retaining unused runtime problem presentation fields.","acceptance":"Retain both current failures and unobserved orchestrators, including their metadata and duplicate-key failure semantics; this projection does not establish health or root cause.","description":"Private compact equivalent of campaign-runtime-problems for equality enrichment, not presentation.","from":"campaign-problem-runtime-failures","union":["campaign-unobserved-orchestrators"],"select":[{"field":"campaign"},{"field":"workflow"},{"field":"runtime-repository"},{"field":"failure-count"},{"field":"problem-kind"}]},{"name":"campaign-problem-run-evidence","subject":"Attach the current campaign runtime problem summary to each retained failed Run for that partition.","objective":"Inspect the failure count and problem kind alongside a failed run without inferring its root cause.","acceptance":"Each returned row joins a retained failed run to a runtime problem on campaign, workflow, and runtime repository; the inner join drops unmatched runs, so compare with campaign-problem-runs before interpreting absence as no problem.","description":"Failed campaign runs annotated with the failure-count and problem-kind of their active runtime problem, one row per retained failed Run.","from":"campaign-problem-runs","joins":[{"source":"campaign-problem-runtime-partitions","type":"inner","on":[{"left":"campaign","right":"campaign"},{"left":"workflow","right":"workflow"},{"left":"runtime-repository","right":"runtime-repository"}],"fields":[{"field":"failure-count","as":"failure-count"},{"field":"problem-kind","as":"problem-kind"}]}],"order-by":[{"field":"started-at","direction":"desc"},{"field":"run","direction":"desc"}]},{"name":"campaign-problem-latest-target-runs","subject":"Identify the most recent retained failed Run for each campaign workflow target repository.","objective":"Select the latest retained failed run identity for each campaign workflow and target partition.","acceptance":"For every returned campaign, workflow, runtime repository, and target repository, latest-target-run agrees with the maximum retained failed run identity in that partition; a missing partition is not a healthy target.","description":"One row per campaign workflow and target repository with its most recent retained failed Run identity.","from":"campaign-problem-run-evidence","aggregate":{"by":["campaign","workflow","runtime-repository","target-repository"],"values":[{"field":"run","as":"latest-target-run","reducer":"max"}]}},{"name":"campaign-problem-error-groups","subject":"Cluster retained failed Run evidence by workflow, runtime repository, target repository, and error signature so repeated identical failures for one target collapse into one diagnosable group.","objective":"Rank repeated target-specific error signatures for investigation without merging unrelated failures.","acceptance":"Occurrence-count and latest-run match retained failed runs grouped by campaign, workflow, repositories, problem kind, and signature; unknown signatures may group together. Counts do not prove a root cause.","description":"One row per distinct target repository and error signature within a campaign runtime problem partition, with an occurrence count and the most recent matching Run identity for follow-up.","from":"campaign-problem-run-evidence","aggregate":{"by":["campaign","campaign-name","workflow","workflow-name","workflow-role","runtime-repository","target-repository","rollout-mode","failure-count","problem-kind","error-signature","error-signature-label"],"values":[{"field":"run","as":"occurrence-count","reducer":"count"},{"field":"run","as":"latest-run","reducer":"max"}]}},{"name":"campaign-current-problem-error-groups","subject":"Keep only the newest error signature for each campaign workflow target repository.","objective":"Focus investigation on the signature associated with the latest retained failed run per target.","acceptance":"Each returned group joins campaign-problem-latest-target-runs on campaign, workflow, runtime repository, and latest run ID; target repository is not a join key, so verify target identity against underlying runs before claiming one current signature per target.","description":"Current target-specific error groups whose representative Run is the target repository's most recent retained failed Run.","from":"campaign-problem-error-groups","joins":[{"source":"campaign-problem-latest-target-runs","type":"inner","on":[{"left":"campaign","right":"campaign"},{"left":"workflow","right":"workflow"},{"left":"runtime-repository","right":"runtime-repository"},{"left":"latest-run","right":"latest-target-run"}],"fields":[{"field":"latest-target-run","as":"current-target-run"}]}]},{"name":"campaign-problem-items","subject":"Attach the most recent representative Run evidence to each distinct campaign runtime problem error signature.","objective":"Open the representative failed run and target for each current campaign problem group.","acceptance":"Check joined run-link, run ID, campaign, workflow, and runtime repository; verify target against run evidence (not a join key). Unobserved orchestrators need inventory review. Missing evidence remains unknown; rollout mode does not authorize policy changes.","description":"Current campaign runtime problems represented by the newest error signature for each target repository, with its effective rollout mode, an occurrence count, the most recent matching failed Run, and a repair prompt.","from":"campaign-current-problem-error-groups","joins":[{"source":"campaign-problem-run-evidence","type":"inner","on":[{"left":"campaign","right":"campaign"},{"left":"workflow","right":"workflow"},{"left":"runtime-repository","right":"runtime-repository"},{"left":"latest-run","right":"run"}],"fields":[{"field":"started-at","as":"started-at"},{"field":"run","as":"run"},{"field":"status","as":"status"},{"field":"status-detail","as":"status-detail"},{"field":"failure-job","as":"failure-job"},{"field":"failure-message","as":"failure-message"},{"field":"failure-step","as":"failure-step"},{"field":"failure-log","as":"failure-log"},{"field":"gh-aw-version","as":"gh-aw-version"},{"field":"engine","as":"engine"},{"field":"engine-version","as":"engine-version"},{"field":"requested-model","as":"requested-model"},{"field":"resolved-model","as":"resolved-model"},{"field":"run-link","as":"run-link"},{"field":"repository-link","as":"repository-link"},{"field":"workflow-link","as":"workflow-link"},{"field":"workflow-source-link","as":"workflow-source-link"}]}],"union":["campaign-unobserved-orchestrators"],"compute":[{"as":"problem-title","function":"coalesce","args":[{"field":"failure-message"},{"field":"status-detail"},{"field":"error-signature-label"},{"field":"workflow-name"}]},{"as":"_runtime-repository-encoded","function":"url-encode","args":[{"field":"runtime-repository"}]},{"as":"_runtime-repository-href","function":"concat","args":[{"value":"#page-repository-detail?repository="},{"field":"_runtime-repository-encoded"}]},{"as":"runtime-repository-link","function":"dashboard-link","args":[{"field":"repository-link"},{"field":"_runtime-repository-href"},{"field":"runtime-repository"},{"field":"runtime-repository"}]},{"as":"_target-repository-encoded","function":"url-encode","args":[{"field":"target-repository"}]},{"as":"_target-repository-href","function":"concat","args":[{"value":"#page-repository-detail?repository="},{"field":"_target-repository-encoded"}]},{"as":"target-repository-link","function":"dashboard-link","args":[{"field":"target-repository"},{"field":"_target-repository-href"},{"field":"target-repository"}]}],"order-by":[{"field":"workflow-name","direction":"asc"},{"field":"runtime-repository","direction":"asc"},{"field":"occurrence-count","direction":"desc"},{"field":"started-at","direction":"desc"}]},{"name":"campaign-problem-tab-counts","subject":"Count the current runtime problem items available for each campaign Problems tab.","objective":"Determine whether the campaign has current retained failure groups requiring review.","acceptance":"For every returned campaign, items equals the number of campaign-problem-items rows in the same horizon; a missing count does not establish zero failures or healthy execution.","description":"One campaign row with the number of current runtime problem groups.","from":"campaign-problem-items","aggregate":{"by":["campaign"],"values":[{"field":"campaign","as":"items","reducer":"count"}]}},{"name":"campaign-baseline-successful-runs","subject":"Project successful concluded attempts from the selected-horizon campaign baseline.","objective":"Show the successful share of concluded runs without implying verified impact.","acceptance":"Counts reconcile to campaign-performance-baseline-totals; missing campaigns do not imply zero runs.","from":"campaign-performance-baseline-totals","compute":[{"as":"outcome","function":"concat","args":[{"value":"Successful attempts"},{"value":""}]}],"select":[{"field":"campaign"},{"field":"outcome"},{"field":"successful-runs","as":"runs"}]},{"name":"campaign-baseline-other-runs","subject":"Project non-successful concluded attempts from the selected-horizon campaign baseline.","objective":"Show the remaining concluded runs for reliability review.","acceptance":"Runs equal concluded-runs minus successful-runs; the category includes every other concluded status, not just failures.","from":"campaign-performance-baseline-totals","compute":[{"as":"outcome","function":"concat","args":[{"value":"Other concluded attempts"},{"value":""}]},{"as":"other-runs","function":"difference","args":[{"field":"concluded-runs"},{"field":"successful-runs"}]}],"select":[{"field":"campaign"},{"field":"outcome"},{"field":"other-runs","as":"runs"}]},{"name":"campaign-baseline-outcome-distribution","subject":"Compare successful and other concluded attempts in the selected horizon.","objective":"Spot campaign run reliability that needs inspection.","acceptance":"Successful and other counts sum to concluded attempts; neither runtime result nor output production establishes operational value.","from":"campaign-baseline-successful-runs","union":["campaign-baseline-other-runs"]},{"name":"campaign-audit-summary-plot-inventory","subject":"Describe the rendered audit-summary chart using the shared campaign Insights plot contract.","objective":"Find campaigns with retained high- or medium-severity audit summaries worth reviewing.","acceptance":"Each campaign's bucket count equals its retained audit-event-summary-buckets rows; the count describes displayed groups, not distinct incidents or confirmed harm, and missing buckets are not proof of safety.","description":"One plot-inventory row per campaign when its high- and medium-severity audit summary chart has data.","from":"audit-event-summary-buckets","aggregate":{"by":["campaign"],"values":[{"field":"event-summary","as":"buckets","reducer":"count"}]}},{"name":"campaign-insight-plot-inventory","subject":"Inventory every plot rendered on each campaign Insights page through one reusable plot contract.","objective":"Choose an available campaign Insights plot to inspect its underlying evidence.","acceptance":"Each plot entry is supplied by the audit summary plot inventory for the same campaign; experimental operational-value evidence is excluded, no plot count is treated as outcome quality, and unavailable evidence is not synthesized into a plot.","description":"One campaign row per rendered Insights plot, independent of the plot's data source or renderer.","from":"campaign-audit-summary-plot-inventory"},{"name":"campaign-insight-tab-counts","subject":"Count the plots declared by the shared campaign Insights plot inventory.","objective":"Determine whether a campaign has evidence-backed Insights plots to inspect.","acceptance":"For every returned campaign, items equals its rows in campaign-insight-plot-inventory for the same horizon; absent rows do not establish absent value, and plot counts do not measure impact.","description":"One campaign row with the number of rendered Insights plots, independent of plot type.","from":"campaign-insight-plot-inventory","aggregate":{"by":["campaign"],"values":[{"field":"campaign","as":"items","reducer":"count"}]}},{"name":"workflow-ordered-runs","subject":"Order retained run attempts within each workflow by their observed start time.","objective":"Identify each workflow's latest execution without importing event coverage or outcome totals.","acceptance":"The first chronological attempt in each workflow partition has no preceding run delta; break timestamp ties by run ID and attempt, and use creation time for queued runs.","from":"runs","compute":[{"as":"latest-run-at","function":"coalesce","args":[{"field":"started-at"},{"field":"created-at"}]}],"window":[{"operation":"change","field":"run","as":"preceding-run-delta","mode":"absolute","groupby":["organization","repository","workflow"],"order-by":[{"field":"latest-run-at","direction":"desc"},{"field":"run","direction":"desc"},{"field":"run-attempt","direction":"desc"}]}],"select":[{"field":"organization"},{"field":"repository"},{"field":"workflow"},{"field":"run"},{"field":"run-attempt"},{"field":"latest-run-at"},{"field":"run-status"},{"field":"run-conclusion"},{"field":"preceding-run-delta"},{"field":"run-link"}]},{"name":"workflow-latest-runs","subject":"Project the latest retained run attempt for each workflow.","objective":"Expose each workflow's latest observed execution state without implying aggregate outcomes.","acceptance":"Select only the first chronologically ordered attempt per workflow; preserve queued and in-progress states instead of treating unknown conclusions as failures.","from":"workflow-ordered-runs","filter":{"predicates":[{"field":"preceding-run-delta","equals":"unknown"}]},"compute":[{"as":"observed-conclusion","function":"coalesce","args":[{"field":"run-conclusion"},{"value":"unknown"}]},{"as":"completed","function":"equals-any","args":[{"field":"run-status"},{"value":"completed"}]},{"as":"latest-run-status","function":"if","args":[{"field":"completed"},{"field":"observed-conclusion"},{"field":"run-status"}]}],"select":[{"field":"organization"},{"field":"repository"},{"field":"workflow"},{"field":"run"},{"field":"run-attempt"},{"field":"latest-run-at"},{"field":"latest-run-status"},{"field":"run-link"}]},{"name":"workflow-list-preview","subject":"Show workflow declarations while latest-run evidence is still loading.","objective":"Make workflow identities and drill links available before retained runs are evaluated.","acceptance":"Preserve every declared workflow and its drill link; leave latest-run fields absent until the complete projection arrives.","from":"workflows","compute":[{"as":"repository-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"workflow-label","function":"concat","args":[{"field":"repository-coordinate"},{"value":":"},{"field":"workflow"}]},{"as":"workflow-display-name","function":"coalesce","args":[{"field":"workflow-name"},{"field":"workflow"}]},{"as":"declared-role","function":"coalesce","args":[{"field":"workflow-role"},{"value":"standalone"}]},{"as":"declared-mode","function":"coalesce","args":[{"field":"rollout-mode"},{"value":"unknown"}]},{"as":"declared-registration","function":"coalesce","args":[{"field":"workflow-active"},{"value":"unknown"}]},{"as":"encoded-workflow","function":"url-encode","args":[{"field":"workflow-label"}]},{"as":"workflow-dashboard-href","function":"concat","args":[{"value":"#page-workflow-runtime?workflow="},{"field":"encoded-workflow"}]},{"as":"workflow-dashboard-link","function":"dashboard-link","args":[{"field":"workflow-link"},{"field":"workflow-dashboard-href"},{"field":"workflow-display-name"},{"field":"workflow-label"}]}],"select":[{"field":"organization"},{"field":"repository-coordinate","as":"repository"},{"field":"workflow"},{"field":"workflow-display-name","as":"workflow-name"},{"field":"workflow-label"},{"field":"campaign-name"},{"field":"declared-role","as":"workflow-role"},{"field":"declared-mode","as":"rollout-mode"},{"field":"declared-registration","as":"workflow-active"},{"field":"repository-link"},{"field":"workflow-dashboard-link","as":"workflow-link"}],"order-by":[{"field":"repository","direction":"asc"},{"field":"workflow","direction":"asc"}]},{"name":"workflow-list","subject":"List declared workflows in latest observed run order.","objective":"Open a dedicated workflow page from a lightweight inventory with its latest execution status.","acceptance":"Preserve textual run identities and keep unobserved workflows last with an explicit missing-run state; use only workflow declarations and retained runs, not event coverage or aggregate success/failure counters.","from":"workflows","joins":[{"source":"workflow-latest-runs","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"}],"fields":[{"field":"run","as":"latest-run"},{"field":"latest-run-at","as":"latest-run-at"},{"field":"latest-run-status","as":"observed-run-status"},{"field":"run-link","as":"run-link"}]}],"compute":[{"as":"repository-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"workflow-label","function":"concat","args":[{"field":"repository-coordinate"},{"value":":"},{"field":"workflow"}]},{"as":"workflow-display-name","function":"coalesce","args":[{"field":"workflow-name"},{"field":"workflow"}]},{"as":"declared-role","function":"coalesce","args":[{"field":"workflow-role"},{"value":"standalone"}]},{"as":"declared-mode","function":"coalesce","args":[{"field":"rollout-mode"},{"value":"unknown"}]},{"as":"declared-registration","function":"coalesce","args":[{"field":"workflow-active"},{"value":"unknown"}]},{"as":"observed-run-id","function":"coalesce","args":[{"field":"latest-run"},{"value":"0"}]},{"as":"has-observed-run","function":"greater-than","args":[{"field":"observed-run-id"},{"value":0}]},{"as":"latest-run-status","function":"coalesce","args":[{"field":"observed-run-status"},{"value":"No observed run"}]},{"as":"encoded-workflow","function":"url-encode","args":[{"field":"workflow-label"}]},{"as":"workflow-dashboard-href","function":"concat","args":[{"value":"#page-workflow-runtime?workflow="},{"field":"encoded-workflow"}]},{"as":"workflow-dashboard-link","function":"dashboard-link","args":[{"field":"workflow-link"},{"field":"workflow-dashboard-href"},{"field":"workflow-display-name"},{"field":"workflow-label"}]}],"select":[{"field":"organization"},{"field":"repository-coordinate","as":"repository"},{"field":"workflow"},{"field":"workflow-display-name","as":"workflow-name"},{"field":"workflow-label"},{"field":"campaign-name"},{"field":"declared-role","as":"workflow-role"},{"field":"declared-mode","as":"rollout-mode"},{"field":"declared-registration","as":"workflow-active"},{"field":"latest-run"},{"field":"latest-run-at"},{"field":"latest-run-status"},{"field":"has-observed-run"},{"field":"repository-link"},{"field":"workflow-dashboard-link","as":"workflow-link"},{"field":"run-link"}],"order-by":[{"field":"has-observed-run","direction":"desc"},{"field":"latest-run-at","direction":"desc"},{"field":"repository","direction":"asc"},{"field":"workflow","direction":"asc"}]},{"name":"runs-daily-conclusions","subject":"Aggregate workflow run conclusions by UTC day for the Runs stacked area graph.","objective":"Expose changes in observed run conclusions by day for investigation.","acceptance":"Count retained runs by started-at UTC day and recorded conclusion; an empty day or missing conclusion is not evidence of healthy execution or absence of activity.","from":"runs","compute":[{"as":"day","function":"date-day","args":[{"field":"started-at"}]}],"aggregate":{"by":["day","run-conclusion"],"values":[{"field":"run","as":"runs","reducer":"count"}]}},{"name":"entity-events","subject":"Project all run-owned records for reusable cards and run drill-down.","objective":"Expose run-owned event identity, status, provenance, timestamp, and available navigation links for inspection.","acceptance":"Projected event fields and fallback URL trace to the source record; a missing link or event is not proof of no output, and event status alone does not verify downstream impact.","from":"event-base","compute":[{"as":"event-url","function":"coalesce","args":[{"field":"safe-output-url"},{"field":"correlation-id"},{"field":"implementation-pull-request-url"}]}],"select":[{"field":"organization"},{"field":"repository"},{"field":"workflow"},{"field":"run"},{"field":"run-attempt"},{"field":"event"},{"field":"event-source"},{"field":"event-type"},{"field":"event-summary"},{"field":"event-status"},{"field":"github-entity-type"},{"field":"safe-output-type"},{"field":"event-url"},{"field":"event-timestamp","as":"observed-at"},{"field":"run-link"}],"order-by":[{"field":"observed-at","direction":"desc"},{"field":"event","direction":"asc"}]},{"name":"runs-table","subject":"Show observed workflow runs in a table with execution, repository, workflow, engine, model, and navigation details.","objective":"Locate observed runs whose recorded status or conclusion needs closer inspection.","acceptance":"Show recorded run identity, status, conclusion, scope, execution metadata, and source links in newest-first order; absent runs require a freshness and coverage check, and a successful run is not proof of accepted outcomes.","description":"Observed workflow runs ordered from newest to oldest.","from":"runs","compute":[{"as":"repository-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]}],"select":[{"field":"run"},{"field":"run-status"},{"field":"run-conclusion"},{"field":"repository-coordinate"},{"field":"workflow"},{"field":"rollout-mode"},{"field":"engine"},{"field":"engine-version"},{"field":"gh-aw-version"},{"field":"requested-model"},{"field":"resolved-model"},{"field":"started-at"},{"field":"repository-link"},{"field":"workflow-link"},{"field":"run-link"}],"order-by":[{"field":"started-at","direction":"desc"}]},{"name":"workflow-aic-per-run","subject":"List declared workflows with recorded positive AI Credit costs and their average cost per run.","objective":"Identify workflows with observed run AIC averages worth investigating alongside run evidence.","acceptance":"Include only declared workflows with at least one run attempt reporting positive AIC; exclude zero and missing telemetry from the average and ranking, without interpreting missing telemetry as free execution.","description":"Workflow AI Credit averages limited to run attempts with recorded positive AIC.","from":"workflows","joins":[{"source":"workflow-aic-run-totals","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"}],"fields":[{"field":"runs","as":"observed-runs"},{"field":"aic-runs","as":"observed-aic-runs"},{"field":"aic","as":"observed-aic"}]}],"compute":[{"as":"repository-slug","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"workflow-display-name","function":"coalesce","args":[{"field":"workflow-name"},{"field":"workflow"}]},{"as":"workflow-identity","function":"concat","args":[{"field":"repository-slug"},{"value":":"},{"field":"workflow"}]},{"as":"encoded-workflow","function":"url-encode","args":[{"field":"workflow-identity"}]},{"as":"workflow-dashboard-href","function":"concat","args":[{"value":"#page-workflow-runtime?workflow="},{"field":"encoded-workflow"}]},{"as":"workflow-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"workflow-display-name"},{"value":" workflow dashboard"}]},{"as":"workflow-dashboard-link","function":"dashboard-link","args":[{"field":"workflow-link"},{"field":"workflow-dashboard-href"},{"field":"workflow-dashboard-label"},{"field":"workflow-identity"}]},{"as":"aic-per-run","function":"quotient","args":[{"field":"observed-aic"},{"field":"observed-aic-runs"}]}],"filter":{"predicates":[{"field":"observed-aic-runs","gte":1}]},"select":[{"field":"workflow-identity","as":"workflow-label"},{"field":"workflow-dashboard-link","as":"workflow-link"},{"field":"aic-per-run"}],"order-by":[{"field":"aic-per-run","direction":"desc"}],"limit":10},{"name":"dashboard-ingestion-health","subject":"Expose the current collection state for the global ingestion indicator.","objective":"Distinguish reported ingestion failure or recovery from the age of retained workflow evidence.","acceptance":"Use the authorized server collection-health classification, not cumulative failures or browser refresh time. Missing or unauthorized health remains unknown and static dashboards do not request this source.","from":"collection-health","select":[{"field":"configured"},{"field":"health"}],"limit":1},{"name":"dashboard-data-freshness","subject":"Find the newest workflow activity timestamp in retained canonical data.","objective":"Warn globally when the ingested workflow evidence has not advanced for 24 hours.","acceptance":"Use upstream updated-at, falling back to created-at, never browser import or refresh time. Missing or invalid timestamps remain unknown; inactivity alone does not prove an ingestion failure.","from":"runs","compute":[{"as":"data-at","function":"coalesce","args":[{"field":"updated-at"},{"field":"created-at"}]},{"as":"data-at-ms","function":"timestamp","args":[{"field":"data-at"}]}],"aggregate":{"values":[{"field":"data-at-ms","as":"latest-data-at","reducer":"max"}]}},{"name":"indexing-shards","subject":"List retained Activity shard import receipts.","objective":"Inspect which shards were ingested, when, and how many records they committed.","acceptance":"Show shard scope, phase, import status, import timestamp, counts and payload identity from retained receipts. Import time is not upstream freshness and missing receipts do not prove complete coverage.","from":"transactions","filter":{"predicates":[{"field":"kind","in":["ingest-normalized-jsonl","ingest-jsonl","ingest-jsonl-failed","runs","records"]}]},"select":[{"field":"id"},{"field":"payloadScope","as":"shard"},{"field":"kind"},{"field":"activity-status","as":"status"},{"field":"createdAt","as":"ingested-at"},{"field":"committedRecords","as":"committed-records"},{"field":"rawRuns","as":"workflow-runs"},{"field":"payloadHash","as":"payload-hash"}],"order-by":[{"field":"ingested-at","direction":"desc"}]},{"name":"ingestion-queued","subject":"Label the shared collection task queue depth for the administrator queue chart.","objective":"Identify total ready and scheduled collection work, including backfill tasks.","acceptance":"Show the observed shared queue depth only when collection is configured; missing or unauthorized health data is not zero pending work.","from":"collection-health","filter":{"predicates":[{"field":"configured","equals":true}]},"compute":[{"as":"queue","function":"coalesce","args":[{"value":"Ready and scheduled"},{"value":"Ready and scheduled"}]}],"select":[{"field":"queue"},{"field":"queue-depth","as":"tasks"}]},{"name":"ingestion-inflight","subject":"Label current in-flight collection tasks for the administrator queue chart.","objective":"Distinguish leased collection tasks from work awaiting collection.","acceptance":"Show the observed pending task count only when collection is configured; do not infer a count from an unavailable source.","from":"collection-health","filter":{"predicates":[{"field":"configured","equals":true}]},"compute":[{"as":"queue","function":"coalesce","args":[{"value":"In flight"},{"value":"In flight"}]}],"select":[{"field":"queue"},{"field":"pending-tasks","as":"tasks"}]},{"name":"ingestion-backfill","subject":"Label cumulative backfill run admissions for the administrator ingestion chart.","objective":"Compare historically admitted run tasks with current outstanding work without treating admissions as a live backlog.","acceptance":"Show the cumulative run task admissions only when collection is configured; this value does not decrease as tasks complete and missing health data does not imply completed backfill.","from":"collection-health","filter":{"predicates":[{"field":"configured","equals":true}]},"compute":[{"as":"queue","function":"coalesce","args":[{"value":"Backfill admitted (total)"},{"value":"Backfill admitted (total)"}]}],"select":[{"field":"queue"},{"field":"backfill-queued-run-tasks","as":"tasks"}]},{"name":"ingestion-queue-sizes","subject":"Compare current shared queue pressure, in-flight tasks, and cumulative historical backfill admissions from the administrator-only server snapshot.","objective":"Spot a growing backlog without treating past backfill admissions as outstanding work.","acceptance":"Current queue sizes and cumulative admissions come only from an authorized collection-health snapshot; unavailable state is not zero.","from":"ingestion-queued","union":["ingestion-inflight","ingestion-backfill"],"select":[{"field":"queue"},{"field":"tasks"}]},{"name":"ingestion-webhook-status","subject":"Inspect live webhook delivery counters for the current server process.","objective":"Distinguish signature validation, acknowledgements, rejections and failures without polling GitHub.","acceptance":"Show only authorized process-local counters, including in-flight requests, duplicate acknowledgements and signed pings. Counters reset on restart, are not replica totals, and do not establish GitHub-side webhook registration or completed collection. Refresh the active subscription even without canonical data changes.","from":"webhook-status","compute":[{"as":"configuration","function":"if","args":[{"field":"configured"},{"value":"Configured"},{"value":"Not configured"}]}],"limit":1},{"name":"ingestion-health","subject":"Show the current Redis-backed webhook and collection health snapshot.","objective":"Determine whether the reported collection, webhook, queue, and backfill state warrants inspecting ingestion diagnostics.","acceptance":"Report the observed health, queue, failure, success, and projection timestamps together; verify freshness and configuration before calling collection healthy, and treat missing state as unknown rather than zero.","from":"collection-health","select":[{"field":"configured"},{"field":"health"},{"field":"queue-depth"},{"field":"pending-tasks"},{"field":"dead-letters"},{"field":"oldest-pending-age"},{"field":"backfill"},{"field":"backfill-failures"},{"field":"backfill-queued-run-tasks"},{"field":"webhook-load"},{"field":"collection-load"},{"field":"failure-load"},{"field":"last-projected"},{"field":"last-webhook-at"},{"field":"last-failure-at"},{"field":"last-failure-code"},{"field":"last-success-at"},{"field":"webhook-received"},{"field":"webhook-duplicate"},{"field":"webhook-admission-failed"},{"field":"task-queued"},{"field":"task-coalesced"},{"field":"collection-succeeded"},{"field":"collection-failed"},{"field":"collection-retried"},{"field":"collection-dead-lettered"}]},{"name":"github-api-usage","subject":"Show retained GitHub API quota usage per bucket and in aggregate over the last 24 hours.","objective":"Determine whether any GitHub App installation or the CAO fleet as a whole is approaching its GitHub API rate limit.","acceptance":"Report peak usage percentages with their limits, used, and reserved counts; treat a slot without observations as unknown rather than idle, and never infer credentials from bucket identity.","from":"github-quota-usage","select":[{"field":"observed-at"},{"field":"scope"},{"field":"bucket"},{"field":"app"},{"field":"installation"},{"field":"resource"},{"field":"buckets"},{"field":"limit"},{"field":"used"},{"field":"reserved"},{"field":"usage-percent"}]},{"name":"marketplace-directory","subject":"Browse packages from configured marketplace registries.","objective":"Present a stable alphabetical directory that can be loaded in bounded pages.","acceptance":"Preserve resolver-produced provenance and package metadata. Order by package name and immutable source so continuation pages neither skip nor duplicate entries; discovery grants no installation authority.","from":"marketplace-packages","order-by":[{"field":"package-name","direction":"asc"},{"field":"package-source","direction":"asc"}]},{"name":"marketplace-package-detail","subject":"Expose normalized marketplace package records for source-coordinate lookup by the detail view.","objective":"Locate the resolver-produced package record for a source coordinate supplied by the consuming view.","acceptance":"Use the returned package-source, registry, ref, and resolved-commit fields when inspecting a matching record; the query itself does not filter by coordinate, and an absent match is not proof of package nonexistence or approval.","from":"marketplace-packages"},{"name":"friction-by-workflow","subject":"Rank workflows by observed gh-aw audit friction AI Credit totals for investigation.","objective":"Identify which repository and workflow combinations have the largest measured friction totals in retained observations.","acceptance":"Compare friction-aic and distinct runs with the underlying measurement states and attribution evidence; do not equate a ranking with avoidable cost or a validated saving.","description":"Total gh-aw audit friction cost grouped by repository and workflow.","from":"friction","compute":[{"as":"positive-aic","function":"greater-than","args":[{"field":"aic"},{"value":0}]},{"as":"repository-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"workflow-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"},{"value":":"},{"field":"workflow"}]}],"aggregate":{"by":["workflow-coordinate","repository-coordinate","workflow"],"values":[{"field":"aic","as":"friction-aic","reducer":"sum","filter":{"predicates":[{"field":"positive-aic","equals":true}]}},{"field":"run","as":"runs","reducer":"distinct-count"}]},"order-by":[{"field":"friction-aic","direction":"desc"},{"field":"workflow-coordinate","direction":"asc"}]},{"name":"friction-observations","subject":"List retained gh-aw audit friction measurements with their run context and attribution totals.","objective":"Trace each reported friction measurement to a run and distinguish counted, suppressed, and unattributed occurrences.","acceptance":"Preserve native AIC, total-run AIC, measurement state, timestamps, links, and occurrence counts; missing or unattributed evidence remains uncertain, not a verified opportunity for savings.","description":"Newest friction measurements first, preserving the native audit values and uncertainty state.","from":"friction","compute":[{"as":"repository-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"friction-percent","function":"format-percent","args":[{"field":"friction-ratio"}]}],"select":[{"field":"event-timestamp","as":"observed-at"},{"field":"repository-coordinate"},{"field":"workflow"},{"field":"run"},{"field":"run-link"},{"field":"measurement-state"},{"field":"aic"},{"field":"total-run-aic"},{"field":"friction-percent"},{"field":"counted-occurrences"},{"field":"suppressed-occurrences"},{"field":"unattributed-occurrences"}],"order-by":[{"field":"observed-at","direction":"desc"},{"field":"run","direction":"desc"}]},{"name":"indexing-shard-dates","subject":"Read the activity date encoded in each retained transaction's shard filename.","objective":"Separate source shard dates from ingestion timestamps.","acceptance":"Keep every transaction and leave absent, invalid, or structural shard dates unknown; never substitute import time.","from":"transactions","compute":[{"as":"shard-day","function":"activity-shard-day","args":[{"field":"payloadScope"}]},{"as":"missing-shard-day","function":"equals-any","args":[{"field":"shard-day"},{"value":null}]}]},{"name":"indexing-ingestion-runs","subject":"Show retained ingestion transactions at the activity date encoded in their shard filename.","objective":"Compare reported run counts by source shard activity date, independently of import time.","acceptance":"Preserve every dated transaction, including coincident dates, all kinds, and zero counts, without grouping, limits, or page filters. Omit missing or invalid shard dates; never substitute import time. Missing counts use labeled zero-position placeholders, not measured zeroes.","from":"indexing-shard-dates","filter":{"predicates":[{"field":"missing-shard-day","equals":false}]},"compute":[{"as":"workflow-runs","function":"coalesce","args":[{"field":"rawRuns"},{"value":0}]},{"as":"missing-run-count","function":"equals-any","args":[{"field":"rawRuns"},{"value":null}]},{"as":"run-count-status","function":"if","args":[{"field":"missing-run-count"},{"value":"Run count unavailable (shown at 0)"},{"value":"Reported run count"}]}],"select":[{"field":"id"},{"field":"kind"},{"field":"createdAt"},{"field":"shard-day"},{"field":"rawRuns"},{"field":"workflow-runs"},{"field":"run-count-status"}],"order-by":[{"field":"shard-day","direction":"asc"},{"field":"id","direction":"asc"}]},{"name":"indexing-campaigns-table-count","subject":"Count retained campaigns rows in the dashboard database.","objective":"Provide the retained campaigns row count for the table-count diagnostic.","acceptance":"Label the result campaigns and count campaign rows in the current database; absence or zero does not establish completeness or expected campaign coverage.","from":"campaigns","compute":[{"as":"table","function":"literal","args":[{"value":"campaigns"}]}],"aggregate":{"by":["table"],"values":[{"field":"campaign","as":"records","reducer":"count"}]}},{"name":"indexing-repositories-table-count","subject":"Count retained repositories rows in the dashboard database.","objective":"Provide the retained repositories row count for the table-count diagnostic.","acceptance":"Label the result repositories and count repository rows in the current database; absence or zero does not establish completeness or expected repository coverage.","from":"repositories","compute":[{"as":"table","function":"literal","args":[{"value":"repositories"}]}],"aggregate":{"by":["table"],"values":[{"field":"repository","as":"records","reducer":"count"}]}},{"name":"indexing-workflows-table-count","subject":"Count retained workflows rows in the dashboard database.","objective":"Provide the retained workflows row count for the table-count diagnostic.","acceptance":"Label the result workflows and count workflow rows in the current database; absence or zero does not establish completeness or expected workflow coverage.","from":"workflows","compute":[{"as":"table","function":"literal","args":[{"value":"workflows"}]}],"aggregate":{"by":["table"],"values":[{"field":"workflow","as":"records","reducer":"count"}]}},{"name":"indexing-runs-table-count","subject":"Count retained workflow runs rows in the dashboard database.","objective":"Provide the retained workflow runs row count for the table-count diagnostic.","acceptance":"Label the result workflow runs and count run rows in the current database; absence or zero does not establish completeness or expected execution volume.","from":"runs","compute":[{"as":"table","function":"literal","args":[{"value":"runs"}]}],"aggregate":{"by":["table"],"values":[{"field":"run","as":"records","reducer":"count"}]}},{"name":"indexing-domains-table-count","subject":"Count retained network domains rows in the dashboard database.","objective":"Provide the retained network domains row count for the table-count diagnostic.","acceptance":"Label the result network domains and count domain event rows in the current database; absence or zero does not prove no network activity.","from":"domains","compute":[{"as":"table","function":"literal","args":[{"value":"domains"}]}],"aggregate":{"by":["table"],"values":[{"field":"event","as":"records","reducer":"count"}]}},{"name":"indexing-tools-table-count","subject":"Count retained tool events rows in the dashboard database.","objective":"Provide the retained tool events row count for the table-count diagnostic.","acceptance":"Label the result tool events and count tool event rows in the current database; absence or zero does not prove no tool use.","from":"tools","compute":[{"as":"table","function":"literal","args":[{"value":"tools"}]}],"aggregate":{"by":["table"],"values":[{"field":"table","as":"records","reducer":"count"}]}},{"name":"indexing-audits-table-count","subject":"Count retained audit events rows in the dashboard database.","objective":"Provide the retained audit events row count for the table-count diagnostic.","acceptance":"Label the result audit events and count audit event rows in the current database; absence or zero does not prove no audit findings.","from":"audits","compute":[{"as":"table","function":"literal","args":[{"value":"audits"}]}],"aggregate":{"by":["table"],"values":[{"field":"event","as":"records","reducer":"count"}]}},{"name":"indexing-issues-table-count","subject":"Count retained issue events rows in the dashboard database.","objective":"Provide the retained issue events row count for the table-count diagnostic.","acceptance":"Label the result issue events and count issue event rows in the current database; absence or zero does not prove no issues exist.","from":"issues","compute":[{"as":"table","function":"literal","args":[{"value":"issues"}]}],"aggregate":{"by":["table"],"values":[{"field":"event","as":"records","reducer":"count"}]}},{"name":"indexing-operational-values-table-count","subject":"Count retained operational values rows in the dashboard database.","objective":"Provide the retained operational values row count for the table-count diagnostic.","acceptance":"Label the result operational values and count operational-value rows in the current database; absence or zero does not imply zero value or an evaluated outcome.","from":"operational-values","compute":[{"as":"table","function":"literal","args":[{"value":"operationalValues"}]}],"aggregate":{"by":["table"],"values":[{"field":"operational-value","as":"records","reducer":"count"}]}},{"name":"indexing-transactions-table-count","subject":"Count retained ingestion transactions rows in the dashboard database.","objective":"Provide the retained ingestion transactions row count for the table-count diagnostic.","acceptance":"Label the result ingestion transactions and count transaction IDs in the current database; absence or zero does not establish whether upstream ingestion ran.","from":"transactions","compute":[{"as":"table","function":"literal","args":[{"value":"transactions"}]}],"aggregate":{"by":["table"],"values":[{"field":"id","as":"records","reducer":"count"}]}},{"name":"indexing-database-table-counts","subject":"Count retained canonical dashboard database rows by table.","objective":"Compare the retained table row counts to identify tables needing further ingestion or coverage investigation.","acceptance":"Union the named table-count projections and report their table labels and counts; check source availability, retention, and separate transaction evidence before interpreting an empty or small table as an ingestion defect.","from":"indexing-campaigns-table-count","union":["indexing-repositories-table-count","indexing-workflows-table-count","indexing-runs-table-count","indexing-domains-table-count","indexing-tools-table-count","indexing-audits-table-count","indexing-issues-table-count","indexing-operational-values-table-count","indexing-transactions-table-count"],"order-by":[{"field":"records","direction":"desc"},{"field":"table","direction":"asc"}]},{"name":"indexing-transactions","subject":"Prepare retained ingestion transactions for card presentation.","objective":"Expose transaction identity, kind, timestamp, committed-record count, and payload hash for ingestion traceability.","acceptance":"Projected fields match retained transactions without implying successful upstream coverage from a committed count or hash alone; missing transactions require a freshness and availability check.","from":"transactions","select":[{"field":"id"},{"field":"kind"},{"field":"createdAt","as":"created-at"},{"field":"committedRecords","as":"committed-records"},{"field":"payloadHash","as":"payload-hash"}]},{"name":"engines-models-usage","subject":"Summarize run-level AIC and token usage by agent and model identifiers without treating unavailable telemetry as zero.","objective":"Locate agent and model combinations whose observed per-run AIC or token usage merits checking against individual runs.","acceptance":"Report run counts and native minimum, mean, and maximum values only for reported metrics; inspect underlying runs for per-metric telemetry coverage and context before comparing combinations, and infer neither efficiency nor outcome value from usage alone.","description":"Observed workflow runs grouped by agent ID and model ID. AIC statistics use only positive-AIC runs; token statistics use runs that reported each token metric.","from":"runs","compute":[{"as":"summary","function":"concat","args":[{"field":"agent-id"},{"value":" / "},{"field":"model-id"}]},{"as":"positive-aic","function":"greater-than","args":[{"field":"aic-total"},{"value":0}]}],"aggregate":{"by":["summary"],"values":[{"field":"run","as":"runs","reducer":"count"},{"field":"aic-total","as":"minimum-aic-per-run","reducer":"min","filter":{"predicates":[{"field":"positive-aic","equals":true}]}},{"field":"aic-total","as":"average-aic-per-run","reducer":"mean","filter":{"predicates":[{"field":"positive-aic","equals":true}]}},{"field":"aic-total","as":"maximum-aic-per-run","reducer":"max","filter":{"predicates":[{"field":"positive-aic","equals":true}]}},{"field":"input-tokens","as":"minimum-input-tokens-per-run","reducer":"min"},{"field":"input-tokens","as":"average-input-tokens-per-run","reducer":"mean"},{"field":"input-tokens","as":"maximum-input-tokens-per-run","reducer":"max"},{"field":"output-tokens","as":"minimum-output-tokens-per-run","reducer":"min"},{"field":"output-tokens","as":"average-output-tokens-per-run","reducer":"mean"},{"field":"output-tokens","as":"maximum-output-tokens-per-run","reducer":"max"},{"field":"cache-read-tokens","as":"minimum-cache-read-tokens-per-run","reducer":"min"},{"field":"cache-read-tokens","as":"average-cache-read-tokens-per-run","reducer":"mean"},{"field":"cache-read-tokens","as":"maximum-cache-read-tokens-per-run","reducer":"max"},{"field":"cache-write-tokens","as":"minimum-cache-write-tokens-per-run","reducer":"min"},{"field":"cache-write-tokens","as":"average-cache-write-tokens-per-run","reducer":"mean"},{"field":"cache-write-tokens","as":"maximum-cache-write-tokens-per-run","reducer":"max"},{"field":"reasoning-tokens","as":"minimum-reasoning-tokens-per-run","reducer":"min"},{"field":"reasoning-tokens","as":"average-reasoning-tokens-per-run","reducer":"mean"},{"field":"reasoning-tokens","as":"maximum-reasoning-tokens-per-run","reducer":"max"}]},"select":[{"field":"summary"},{"field":"runs"},{"field":"average-aic-per-run"},{"field":"minimum-aic-per-run"},{"field":"maximum-aic-per-run"},{"field":"minimum-input-tokens-per-run"},{"field":"average-input-tokens-per-run"},{"field":"maximum-input-tokens-per-run"},{"field":"minimum-output-tokens-per-run"},{"field":"average-output-tokens-per-run"},{"field":"maximum-output-tokens-per-run"},{"field":"minimum-cache-read-tokens-per-run"},{"field":"average-cache-read-tokens-per-run"},{"field":"maximum-cache-read-tokens-per-run"},{"field":"minimum-cache-write-tokens-per-run"},{"field":"average-cache-write-tokens-per-run"},{"field":"maximum-cache-write-tokens-per-run"},{"field":"minimum-reasoning-tokens-per-run"},{"field":"average-reasoning-tokens-per-run"},{"field":"maximum-reasoning-tokens-per-run"}],"order-by":[{"field":"runs","direction":"desc"},{"field":"summary","direction":"asc"}]},{"name":"skill-invocations","subject":"Select observed skill invocations for skill usage analytics.","objective":"Expose skill event identity, scope, invocation counts, and failed counts for downstream usage analysis.","acceptance":"Keep each observed event and its repository/workflow attribution with native counts; missing records or failed counts alone do not establish whether a skill was useful or available.","from":"skills","select":[{"field":"event","as":"id"},{"field":"name","as":"skill"},{"field":"organization"},{"field":"repository"},{"field":"workflow"},{"field":"invocation-count"},{"field":"failed-count"}]},{"name":"skill-invocations-by-skill","subject":"Rank skills by their observed invocation count.","objective":"Identify skills with the highest observed invocation totals for follow-up inspection.","acceptance":"Sum observed invocation counts by skill and retain the rank as a usage description; do not equate popularity with effectiveness or infer unobserved invocations.","from":"skill-invocations","aggregate":{"by":["skill"],"values":[{"field":"invocation-count","as":"invocations","reducer":"sum"}]},"order-by":[{"field":"invocations","direction":"desc"},{"field":"skill","direction":"asc"}]},{"name":"skill-invocations-by-workflow-totals","subject":"Rank workflows by their observed skill invocation count.","objective":"Produce repository-scoped workflow invocation totals for downstream skill-usage comparison.","acceptance":"Sum observed invocation counts by organization, repository, and workflow; totals describe recorded usage only, not success or expected adoption.","from":"skill-invocations","aggregate":{"by":["organization","repository","workflow"],"values":[{"field":"invocation-count","as":"invocations","reducer":"sum"}]}},{"name":"skill-invocations-by-workflow","subject":"Present workflow skill invocation totals with drill-through navigation to the workflow dashboard.","objective":"Expose observed workflow skill invocation totals with a link to inspect each workflow.","acceptance":"Each projected workflow coordinate, link, and invocation total traces to the grouped source; using a link to investigate does not establish that usage caused an outcome.","from":"skill-invocations-by-workflow-totals","compute":[{"as":"workflow-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"},{"value":":"},{"field":"workflow"}]},{"as":"encoded-workflow","function":"url-encode","args":[{"field":"workflow-coordinate"}]},{"as":"workflow-dashboard-href","function":"concat","args":[{"value":"#page-workflow-runtime?workflow="},{"field":"encoded-workflow"}]},{"as":"workflow-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"workflow-coordinate"},{"value":" workflow dashboard"}]},{"as":"workflow-link","function":"dashboard-link","args":[{"value":""},{"field":"workflow-dashboard-href"},{"field":"workflow-dashboard-label"},{"field":"workflow-coordinate"}]}],"select":[{"field":"workflow-coordinate"},{"field":"workflow-link"},{"field":"invocations"}],"order-by":[{"field":"invocations","direction":"desc"},{"field":"workflow-coordinate","direction":"asc"}]},{"name":"skill-workflow-totals","subject":"Count observed invocations for each skill and workflow.","objective":"Produce skill-by-workflow invocation totals for the downstream inventory.","acceptance":"Sum observed invocation counts by skill, organization, repository, and workflow; missing combinations are not evidence that a skill could not run.","from":"skill-invocations","aggregate":{"by":["skill","organization","repository","workflow"],"values":[{"field":"invocation-count","as":"invocations","reducer":"sum"}]}},{"name":"skill-workflow-inventory","subject":"List observed skills by workflow with drill-through navigation to the workflow dashboard.","objective":"Identify observed skill/workflow combinations and provide a workflow link for inspecting their runs.","acceptance":"Show the repository, workflow, skill, link, and observed invocation total from the grouped evidence; an absent row does not prove non-use, and a high count does not prove effectiveness.","from":"skill-workflow-totals","compute":[{"as":"repository-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"workflow-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"},{"value":":"},{"field":"workflow"}]},{"as":"encoded-workflow","function":"url-encode","args":[{"field":"workflow-coordinate"}]},{"as":"workflow-dashboard-href","function":"concat","args":[{"value":"#page-workflow-runtime?workflow="},{"field":"encoded-workflow"}]},{"as":"workflow-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"workflow-coordinate"},{"value":" workflow dashboard"}]},{"as":"workflow-link","function":"dashboard-link","args":[{"value":""},{"field":"workflow-dashboard-href"},{"field":"workflow-dashboard-label"},{"field":"workflow-coordinate"}]}],"select":[{"field":"skill"},{"field":"repository-coordinate"},{"field":"workflow"},{"field":"workflow-link"},{"field":"invocations"}],"order-by":[{"field":"invocations","direction":"desc"},{"field":"skill","direction":"asc"},{"field":"workflow","direction":"asc"}]},{"name":"experiment-assignment-coverage","subject":"Count observed run assignments for each experiment and workflow without inferring a completion target.","objective":"Expose assignment counts by experiment and workflow for investigating observed experiment coverage.","acceptance":"Count retained assignment rows in each experiment/workflow group, not distinct runs; do not invent a target, infer missing assignments from absent groups, or treat assignments as eval or grader outcomes.","from":"experiment-assignments","compute":[{"as":"workflow-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"},{"value":":"},{"field":"workflow"}]}],"aggregate":{"by":["workflow-coordinate","experiment"],"values":[{"field":"run","as":"assignments","reducer":"count"}]}},{"name":"eval-status-ledger","subject":"Inspect every explicitly classified eval answer, including UNKNOWN.","objective":"Expose retained eval observations with their workflow, run evidence and observation time.","acceptance":"Keep recorded YES, NO and UNKNOWN answers distinct; unknown or absent evidence must not imply success or failure, and historical answers are not current verdicts or validated operational outcomes.","from":"eval-observations","compute":[{"as":"_recorded-run-href","function":"link-href","args":[{"field":"evidence-link"}]},{"as":"_eval-run-href","function":"coalesce","args":[{"field":"_recorded-run-href"},{"field":"evidence-link"}]},{"as":"run-link","function":"link","args":[{"field":"_eval-run-href"},{"field":"run"}]}],"filter":{"predicates":[{"field":"eval-result","in":["YES","NO","UNKNOWN"]}]}},{"name":"eval-answer-counts","subject":"Count recorded YES, NO and UNKNOWN answers for each workflow-scoped eval.","objective":"Provide complete answer denominators before expanding each eval into three bars.","acceptance":"Keep canonical eval identities separate and count only explicitly classified observations. Select at most 33 complete eval groups, never truncate an answer group.","from":"eval-status-ledger","aggregate":{"by":["organization","repository","workflow","eval"],"values":[{"field":"eval-result","as":"answers","reducer":"count"},{"field":"eval-result","as":"yes","reducer":"count","filter":{"predicates":[{"field":"eval-result","equals":"YES"}]}},{"field":"eval-result","as":"no","reducer":"count","filter":{"predicates":[{"field":"eval-result","equals":"NO"}]}},{"field":"eval-result","as":"unknown","reducer":"count","filter":{"predicates":[{"field":"eval-result","equals":"UNKNOWN"}]}}]},"order-by":[{"field":"eval","direction":"asc"},{"field":"organization","direction":"asc"},{"field":"repository","direction":"asc"},{"field":"workflow","direction":"asc"}],"limit":33},{"name":"eval-yes-shares","subject":"Compute the YES share of each eval's recorded answers.","objective":"Expose recorded YES proportions for comparing answer categories without inferring verified operational outcomes.","acceptance":"Emit one YES row per retained canonical eval group, including zero YES counts; answer-share is yes / answers across recorded YES, NO and UNKNOWN observations. Do not count absent observations.","from":"eval-answer-counts","compute":[{"as":"eval-result","function":"literal","args":[{"value":"YES"}]},{"as":"answer-order","function":"literal","args":[{"value":0}]},{"as":"answer-share","function":"quotient","args":[{"field":"yes"},{"field":"answers"}]}]},{"name":"eval-no-shares","subject":"Compute the NO share of each eval's recorded answers.","objective":"Expose recorded NO proportions for comparing answer categories without treating historical answers as current verdicts.","acceptance":"Emit one NO row per retained canonical eval group, including zero NO counts; answer-share is no / answers across recorded YES, NO and UNKNOWN observations. Do not count absent observations.","from":"eval-answer-counts","compute":[{"as":"eval-result","function":"literal","args":[{"value":"NO"}]},{"as":"answer-order","function":"literal","args":[{"value":1}]},{"as":"answer-share","function":"quotient","args":[{"field":"no"},{"field":"answers"}]}]},{"name":"eval-unknown-shares","subject":"Compute the explicit UNKNOWN share of each eval's recorded answers.","objective":"Expose explicitly recorded UNKNOWN proportions without conflating absent observations with classified uncertainty.","acceptance":"Emit one UNKNOWN row per retained canonical eval group, including zero UNKNOWN counts; answer-share is unknown / answers across recorded YES, NO and UNKNOWN observations. Missing observations are not UNKNOWN answers.","from":"eval-answer-counts","compute":[{"as":"eval-result","function":"literal","args":[{"value":"UNKNOWN"}]},{"as":"answer-order","function":"literal","args":[{"value":2}]},{"as":"answer-share","function":"quotient","args":[{"field":"unknown"},{"field":"answers"}]}]},{"name":"eval-answer-distribution","subject":"Compare YES, NO and UNKNOWN percentages within each eval.","objective":"Show three horizontal bars per eval that together account for all recorded answers.","acceptance":"Emit all three answer categories, including zero shares; percentages sum to 100 per canonical eval. Missing observations are not UNKNOWN answers. Preserve workflow and repository attribution.","from":"eval-yes-shares","union":["eval-no-shares","eval-unknown-shares"],"compute":[{"as":"answer-percent","function":"product","args":[{"field":"answer-share"},{"value":100}]},{"as":"eval-label","function":"concat","args":[{"field":"eval"},{"value":" | "},{"field":"organization"},{"value":"/"},{"field":"repository"},{"value":":"},{"field":"workflow"}]}],"order-by":[{"field":"eval-label","direction":"asc"},{"field":"answer-order","direction":"asc"}]},{"name":"grader-observed-maxima","subject":"Find each workflow-scoped grader's maximum retained value in the selected data.","objective":"Provide an observed normalization denominator without mixing grader identities or claiming a theoretical maximum.","acceptance":"Group by canonical grader identity, not display name; ignore missing values and preserve zero or negative maxima without substituting a denominator.","from":"grader-observations","aggregate":{"by":["grader-id"],"values":[{"field":"value","as":"max-grader-value","reducer":"max"}]}},{"name":"grader-normalized-observations","subject":"Normalize each grader observation by that grader's observed maximum.","objective":"Compare relative grader values over time while preserving native measurements and run provenance.","acceptance":"Compute value / max-grader-value without clamping or inverting lower-is-better measures; zero or missing denominators produce null, never a fabricated zero or infinity.","from":"grader-observations","joins":[{"source":"grader-observed-maxima","type":"left","on":[{"left":"grader-id","right":"grader-id"}],"fields":[{"field":"max-grader-value","as":"max-grader-value"}]}],"compute":[{"as":"normalized-value","function":"quotient","args":[{"field":"value"},{"field":"max-grader-value"}]},{"as":"_observation-time","function":"timestamp","args":[{"field":"observed-at"}]},{"as":"_unplottable-value","function":"equals-any","args":[{"field":"normalized-value"},{"value":null}]},{"as":"_unplottable-time","function":"equals-any","args":[{"field":"_observation-time"},{"value":null}]},{"as":"grader-series","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"},{"value":" / "},{"field":"workflow"},{"value":" / "},{"field":"grader"}]}]},{"name":"grader-value-scatter","subject":"Plot timed grader observations with a defined value-to-observed-maximum ratio.","objective":"Show relative grader measurements at their recorded observation times.","acceptance":"Keep each eligible observation and its run link; omit missing ratios or observation times from the plot while retaining those records in the native-value ledger. Ratios are not eval answers or evidence of improvement.","from":"grader-normalized-observations","filter":{"predicates":[{"field":"_unplottable-value","equals":false},{"field":"_unplottable-time","equals":false}]},"order-by":[{"field":"observed-at","direction":"asc"}]},{"name":"grader-status-ledger","subject":"Report grader measurements, units and explicit statuses without confusing them with binary eval answers.","objective":"Preserve numeric grader evidence and distinguish explicit per-observation pass and fail verdicts from unknown statuses.","acceptance":"Retain native grader values, units and statuses. Map only pass/passed to YES and fail/failed to NO in the auxiliary verdict field, leaving all other statuses unknown; never infer an eval answer, current success, causation or policy authority from a grader score.","from":"grader-observations","compute":[{"as":"is-pass","function":"equals-any","args":[{"field":"status"},{"value":"pass"},{"value":"passed"}]},{"as":"is-fail","function":"equals-any","args":[{"field":"status"},{"value":"fail"},{"value":"failed"}]},{"as":"non-pass-verdict","function":"if","args":[{"field":"is-fail"},{"value":"NO"},{"value":"unknown"}]},{"as":"verdict","function":"if","args":[{"field":"is-pass"},{"value":"YES"},{"field":"non-pass-verdict"}]}]},{"name":"routing-session-observations","subject":"Read metadata-only unified-session routing evidence.","objective":"Keep routing analytics independent of native logs and inferred run totals.","acceptance":"Only recognized session events contribute; event clocks remain absent when unrecorded.","from":"audits","filter":{"predicates":[{"field":"event-type","in":["session.format","workflow.info","workflow.job_result","agent.execution","firewall.model_routing","firewall.token_usage","usage.report","firewall.steering","firewall.upstream_error","model.config","model.baseline_estimate","model.resolution","model_routing.outcome","model_endpoint.mismatch","session.collection","session.collection_warning","subagent.request","subagent.started","subagent.configured","subagent.completed","subagent.failed","subagent.model_unavailable"]}]},"compute":[{"as":"record-clock","function":"timestamp","args":[{"field":"event-timestamp"}]},{"as":"event-clock","function":"coalesce","args":[{"field":"routing-session-clock"},{"field":"record-clock"}]},{"as":"routing-run-key","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"},{"value":":"},{"field":"run"}]},{"as":"agent-phase","function":"equals-any","args":[{"field":"phase"},{"value":"agent"}]},{"as":"proxy-selection","function":"equals-any","args":[{"field":"routing-stage"},{"value":"selection"}]},{"as":"proxy-failure","function":"equals-any","args":[{"field":"routing-stage"},{"value":"failure"}]},{"as":"has-agent-name","function":"greater-than","args":[{"field":"routing-agent-name"},{"value":""}]}]},{"name":"routing-session-attempts","from":"routing-session-observations","subject":"Identify available session files and their earliest recorded clocks.","objective":"Keep rerun attempts from multiplying routing denominators.","acceptance":"Attempt order is only a tie-breaker after the recorded session clock.","aggregate":{"by":["routing-run-key","run-attempt"],"values":[{"field":"event-clock","as":"session-clock","reducer":"min"}]}},{"name":"routing-session-order","from":"routing-session-attempts","subject":"Order duplicate run sessions by run time and attempt.","objective":"Keep the latest file for each repository/run identity.","acceptance":"Only one attempt contributes to routing facts.","window":[{"operation":"row-number","field":"run-attempt","as":"session-position","groupby":["routing-run-key"],"order-by":[{"field":"session-clock","direction":"desc"},{"field":"run-attempt","direction":"desc"}]}]},{"name":"routing-latest-sessions","from":"routing-session-order","subject":"Retain one authoritative session attempt per run.","objective":"Avoid mixing picks or accounting from reruns.","acceptance":"Duplicate attempts remain available in session coverage.","filter":{"predicates":[{"field":"session-position","equals":1}]}},{"name":"routing-session-events","from":"routing-session-observations","subject":"Read routing metadata from the latest session file per run.","objective":"Deduplicate rerun attempts before any metric.","acceptance":"Earlier attempts never add cost or change the selected pick.","joins":[{"source":"routing-latest-sessions","type":"inner","on":[{"left":"routing-run-key","right":"routing-run-key"},{"left":"run-attempt","right":"run-attempt"}],"fields":[{"field":"session-clock","as":"session-clock"}]}]},{"name":"routing-run-facts","subject":"Collect per-session source facts without interpreting absence as success.","objective":"Resolve routing states and coverage from runner and proxy evidence.","acceptance":"Agent-phase proxy selection wins over failure and harness status; untimed observations keep unknown time.","from":"routing-session-events","aggregate":{"by":["routing-run-key","organization","repository","workflow","run"],"values":[{"field":"event-clock","as":"run-clock","reducer":"min"},{"field":"run-link","as":"run-link","reducer":"unique"},{"field":"engine","as":"engine","reducer":"unique"},{"field":"event","as":"workflow-info-count","reducer":"count","filter":{"predicates":[{"field":"event-type","equals":"workflow.info"},{"field":"required","equals":true}]}},{"field":"event-status","as":"session-format","reducer":"unique","filter":{"predicates":[{"field":"event-type","equals":"session.format"}]}},{"field":"event","as":"selection-count","reducer":"count","filter":{"predicates":[{"field":"event-type","equals":"firewall.model_routing"},{"field":"routing-stage","equals":"selection"},{"field":"phase","equals":"agent"}]}},{"field":"event","as":"failure-count","reducer":"count","filter":{"predicates":[{"field":"event-type","equals":"firewall.model_routing"},{"field":"routing-stage","equals":"failure"},{"field":"phase","equals":"agent"}]}},{"field":"event","as":"local-effort-failures","reducer":"count","filter":{"predicates":[{"field":"event-type","equals":"firewall.model_routing"},{"field":"routing-stage","equals":"failure"},{"field":"code","equals":"unsupported_reasoning_effort"}]}},{"field":"event","as":"proxy-record-count","reducer":"count","filter":{"predicates":[{"field":"event-type","equals":"firewall.model_routing"},{"field":"phase","equals":"agent"}]}},{"field":"event","as":"agent-accounting-count","reducer":"count","filter":{"predicates":[{"field":"event-type","equals":"firewall.token_usage"},{"field":"phase","equals":"agent"}]}},{"field":"event","as":"subagent-count","reducer":"count","filter":{"predicates":[{"field":"event-type","in":["subagent.started","subagent.request","subagent.configured","subagent.completed","subagent.failed","subagent.model_unavailable"]}]}},{"field":"routing-status","as":"harness-status","reducer":"unique","filter":{"predicates":[{"field":"event-type","equals":"workflow.info"}]}},{"field":"routing-enabled","as":"configured-enabled","reducer":"unique","filter":{"predicates":[{"field":"event-type","equals":"model.config"}]}},{"field":"routing-selected-model","as":"harness-model","reducer":"unique","filter":{"predicates":[{"field":"event-type","equals":"workflow.info"}]}},{"field":"telemetry-model","as":"workflow-model","reducer":"unique","filter":{"predicates":[{"field":"event-type","equals":"workflow.info"}]}},{"field":"routing-selected-effort","as":"harness-effort","reducer":"unique","filter":{"predicates":[{"field":"event-type","equals":"workflow.info"}]}},{"field":"routing-mode","as":"harness-mode","reducer":"unique","filter":{"predicates":[{"field":"event-type","equals":"workflow.info"}]}},{"field":"routing-awf-version","as":"session-awf-version","reducer":"unique","filter":{"predicates":[{"field":"event-type","equals":"workflow.info"}]}},{"field":"routing-goal","as":"configured-goal","reducer":"unique","filter":{"predicates":[{"field":"event-type","equals":"model.config"}]}},{"field":"routing-configured-mode","as":"configured-routing-mode","reducer":"unique","filter":{"predicates":[{"field":"event-type","equals":"model.config"}]}},{"field":"routing-max-credits","as":"configured-max-credits","reducer":"unique","filter":{"predicates":[{"field":"event-type","equals":"model.config"}]}},{"field":"event-status","as":"agent-result","reducer":"unique","filter":{"predicates":[{"field":"event-type","equals":"workflow.job_result"},{"field":"name","equals":"agent"},{"field":"event-status","in":["success","failure","cancelled","skipped"]}]}},{"field":"event","as":"warnings","reducer":"count","filter":{"predicates":[{"field":"event-type","equals":"session.collection_warning"}]}}]}},{"name":"routing-ordered-selections","subject":"Order proxy selections within each session.","objective":"Use the last selection by normalized clock and file order.","acceptance":"Harness and advisory picks never override proxy selections.","from":"routing-session-events","filter":{"predicates":[{"field":"event-type","equals":"firewall.model_routing"},{"field":"routing-stage","equals":"selection"},{"field":"phase","equals":"agent"}]},"window":[{"operation":"row-number","field":"source-sequence","as":"selection-position","groupby":["routing-run-key"],"order-by":[{"field":"event-timestamp","direction":"desc"},{"field":"source-sequence","direction":"desc"}]}]},{"name":"routing-selections","subject":"Retain one authoritative proxy pick per run.","objective":"Avoid multiplying requests or run counts after re-selection.","acceptance":"One row per identified run uses the final proxy selection.","from":"routing-ordered-selections","filter":{"predicates":[{"field":"selection-position","equals":1}]}},{"name":"routing-resolved-runs","subject":"Resolve routing state, pick and label cells from unified sessions.","objective":"Distinguish selected, failed, harness-only, configured, inferred and unknown evidence.","acceptance":"Proxy evidence wins; configuration conflicts are visible; missing picks and time remain unknown.","from":"routing-run-facts","joins":[{"source":"routing-selections","type":"left","on":[{"left":"routing-run-key","right":"routing-run-key"}],"fields":[{"field":"routing-selected-model","as":"proxy-model"},{"field":"routing-selected-effort","as":"proxy-effort"},{"field":"routing-goal","as":"proxy-goal"},{"field":"routing-mode","as":"proxy-mode"},{"field":"routing-configured-mode","as":"proxy-configured-mode"},{"field":"routing-task-type","as":"routing-task-type"},{"field":"routing-scope","as":"routing-scope"},{"field":"routing-complexity","as":"routing-complexity"},{"field":"routing-latency-ms","as":"routing-latency-ms"},{"field":"routing-degraded","as":"routing-degraded"},{"field":"routing-classifier-attempts","as":"routing-classifier-attempts"},{"field":"routing-classifier-model","as":"routing-classifier-model"},{"field":"routing-classifier-effort","as":"routing-classifier-effort"},{"field":"routing-schema","as":"routing-schema"},{"field":"routing-awf-version","as":"proxy-awf-version"},{"field":"routing-router-version","as":"routing-router-version"}]}],"compute":[{"as":"observed-at","function":"iso-timestamp","args":[{"field":"run-clock"}]},{"as":"routing-awf-version","function":"coalesce","args":[{"field":"session-awf-version"},{"field":"proxy-awf-version"}]},{"as":"routing-mode","function":"coalesce","args":[{"field":"proxy-mode"},{"field":"harness-mode"}]},{"as":"routing-goal","function":"coalesce","args":[{"field":"proxy-goal"},{"field":"configured-goal"}]},{"as":"routing-configured-mode","function":"coalesce","args":[{"field":"proxy-configured-mode"},{"field":"configured-routing-mode"}]},{"as":"has-selection","function":"greater-than","args":[{"field":"selection-count"},{"value":0}]},{"as":"has-failure","function":"greater-than","args":[{"field":"failure-count"},{"value":0}]},{"as":"has-harness","function":"equals-any","args":[{"field":"harness-status"},{"value":null}]},{"as":"has-usage","function":"greater-than","args":[{"field":"agent-accounting-count"},{"value":0}]},{"as":"no-proxy","function":"equals-any","args":[{"field":"proxy-record-count"},{"value":0}]},{"as":"usage-state","function":"if","args":[{"field":"has-usage"},{"value":"unrouted_inferred"},{"value":"unknown"}]},{"as":"inferred-state","function":"if","args":[{"field":"no-proxy"},{"field":"usage-state"},{"value":"unknown"}]},{"as":"enabled","function":"equals-any","args":[{"field":"configured-enabled"},{"value":true}]},{"as":"disabled","function":"equals-any","args":[{"field":"configured-enabled"},{"value":false}]},{"as":"enabled-state","function":"if","args":[{"field":"enabled"},{"value":"configured_unrecorded"},{"field":"inferred-state"}]},{"as":"configured-state","function":"if","args":[{"field":"disabled"},{"value":"unrouted"},{"field":"enabled-state"}]},{"as":"reported-state","function":"if","args":[{"field":"has-harness"},{"field":"configured-state"},{"value":"harness_reported"}]},{"as":"failure-state","function":"if","args":[{"field":"has-failure"},{"value":"selection_failed"},{"field":"reported-state"}]},{"as":"routing-state","function":"if","args":[{"field":"has-selection"},{"value":"selected"},{"field":"failure-state"}]},{"as":"observed-pick-model","function":"if","args":[{"field":"has-selection"},{"field":"proxy-model"},{"field":"harness-model"}]},{"as":"observed-pick-effort","function":"if","args":[{"field":"has-selection"},{"field":"proxy-effort"},{"field":"harness-effort"}]},{"as":"pick-model","function":"coalesce","args":[{"field":"observed-pick-model"},{"value":"unknown"}]},{"as":"pick-effort","function":"coalesce","args":[{"field":"observed-pick-effort"},{"value":"unknown"}]},{"as":"pick","function":"concat","args":[{"field":"pick-model"},{"value":" / "},{"field":"pick-effort"}]},{"as":"has-proxy-decision","function":"if","args":[{"field":"has-selection"},{"value":true},{"field":"has-failure"}]},{"as":"has-decision","function":"if","args":[{"field":"has-harness"},{"field":"has-proxy-decision"},{"value":true}]},{"as":"configuration-conflict","function":"if","args":[{"field":"disabled"},{"field":"has-decision"},{"value":false}]},{"as":"unknown-pick-model","function":"equals-any","args":[{"field":"pick-model"},{"value":"unknown"}]},{"as":"unknown-pick-effort","function":"equals-any","args":[{"field":"pick-effort"},{"value":"unknown"}]},{"as":"unknown-pick","function":"if","args":[{"field":"unknown-pick-model"},{"value":true},{"field":"unknown-pick-effort"}]},{"as":"routing-key-encoded","function":"url-encode","args":[{"field":"routing-run-key"}]},{"as":"routing-href","function":"concat","args":[{"value":"#page-routing-run?routing-run="},{"field":"routing-key-encoded"}]},{"as":"routing-dashboard-link","function":"dashboard-link","args":[{"field":"run-link"},{"field":"routing-href"},{"field":"run"}]}],"filter":{"predicates":[{"field":"workflow-info-count","gte":1}]}},{"name":"routing-filter-candidates","from":"routing-aggregates","subject":"Apply one run-level scope before every routing metric and event join.","objective":"Filter complete sessions, never fragments of their evidence.","acceptance":"Unknown run time is excluded from a bounded range; blank filters retain all known values.","parameters":[{"name":"routing-filter-workflow","type":"string"},{"name":"routing-filter-repository","type":"string"},{"name":"routing-filter-engine","type":"string"},{"name":"routing-filter-state","type":"string"},{"name":"routing-filter-goal","type":"string"},{"name":"routing-filter-mode","type":"string"},{"name":"routing-filter-awf","type":"string"},{"name":"routing-filter-start","type":"string"},{"name":"routing-filter-end","type":"string"}],"compute":[{"as":"full-repository","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"all-workflows","function":"equals-any","args":[{"parameter":"routing-filter-workflow"},{"value":""}]},{"as":"same-workflow","function":"equals-any","args":[{"field":"workflow"},{"parameter":"routing-filter-workflow"}]},{"as":"include-workflow","function":"if","args":[{"field":"all-workflows"},{"value":true},{"field":"same-workflow"}]},{"as":"all-repositories","function":"equals-any","args":[{"parameter":"routing-filter-repository"},{"value":""}]},{"as":"same-repository","function":"equals-any","args":[{"field":"full-repository"},{"parameter":"routing-filter-repository"}]},{"as":"include-repository","function":"if","args":[{"field":"all-repositories"},{"value":true},{"field":"same-repository"}]},{"as":"all-engines","function":"equals-any","args":[{"parameter":"routing-filter-engine"},{"value":""}]},{"as":"same-engine","function":"equals-any","args":[{"field":"engine"},{"parameter":"routing-filter-engine"}]},{"as":"include-engine","function":"if","args":[{"field":"all-engines"},{"value":true},{"field":"same-engine"}]},{"as":"all-states","function":"equals-any","args":[{"parameter":"routing-filter-state"},{"value":""}]},{"as":"same-state","function":"equals-any","args":[{"field":"routing-state"},{"parameter":"routing-filter-state"}]},{"as":"include-state","function":"if","args":[{"field":"all-states"},{"value":true},{"field":"same-state"}]},{"as":"all-goals","function":"equals-any","args":[{"parameter":"routing-filter-goal"},{"value":""}]},{"as":"same-goal","function":"equals-any","args":[{"field":"routing-goal"},{"parameter":"routing-filter-goal"}]},{"as":"include-goal","function":"if","args":[{"field":"all-goals"},{"value":true},{"field":"same-goal"}]},{"as":"all-modes","function":"equals-any","args":[{"parameter":"routing-filter-mode"},{"value":""}]},{"as":"same-mode","function":"equals-any","args":[{"field":"routing-mode"},{"parameter":"routing-filter-mode"}]},{"as":"include-mode","function":"if","args":[{"field":"all-modes"},{"value":true},{"field":"same-mode"}]},{"as":"all-awf","function":"equals-any","args":[{"parameter":"routing-filter-awf"},{"value":""}]},{"as":"same-awf","function":"equals-any","args":[{"field":"routing-awf-version"},{"parameter":"routing-filter-awf"}]},{"as":"include-awf","function":"if","args":[{"field":"all-awf"},{"value":true},{"field":"same-awf"}]},{"as":"all-starts","function":"equals-any","args":[{"parameter":"routing-filter-start"},{"value":""}]},{"as":"start-clock","function":"timestamp","args":[{"parameter":"routing-filter-start"}]},{"as":"start-before","function":"difference","args":[{"field":"start-clock"},{"value":1}]},{"as":"after-start","function":"greater-than","args":[{"field":"run-clock"},{"field":"start-before"}]},{"as":"include-start","function":"if","args":[{"field":"all-starts"},{"value":true},{"field":"after-start"}]},{"as":"all-ends","function":"equals-any","args":[{"parameter":"routing-filter-end"},{"value":""}]},{"as":"end-clock","function":"timestamp","args":[{"parameter":"routing-filter-end"}]},{"as":"before-end","function":"greater-than","args":[{"field":"end-clock"},{"field":"run-clock"}]},{"as":"include-end","function":"if","args":[{"field":"all-ends"},{"value":true},{"field":"before-end"}]}]},{"name":"routing-runs","from":"routing-filter-candidates","subject":"Retain identified runs matching every selected routing filter.","objective":"Use the same population for adoption, accounting and outcomes.","acceptance":"A time bound excludes untimed runs and does not remove individual events from retained sessions.","filter":{"predicates":[{"field":"include-workflow","equals":true},{"field":"include-repository","equals":true},{"field":"include-engine","equals":true},{"field":"include-state","equals":true},{"field":"include-goal","equals":true},{"field":"include-mode","equals":true},{"field":"include-awf","equals":true},{"field":"include-start","equals":true},{"field":"include-end","equals":true}]}},{"name":"routing-events","from":"routing-session-events","subject":"Retain all evidence belonging to scoped identified runs.","objective":"Filter event metrics by the resolved run rather than by individual event clocks.","acceptance":"State, pick and accounting are computed before the scope is applied.","joins":[{"source":"routing-runs","type":"inner","on":[{"left":"routing-run-key","right":"routing-run-key"}],"fields":[{"field":"routing-state","as":"run-routing-state"}]}]},{"name":"routing-phase-sources","subject":"Choose one nonoverlapping accounting source per run and phase.","objective":"Prefer proxy token usage over usage reports.","acceptance":"Snapshot totals and cumulative totalAic never enter additive cost.","from":"routing-events","aggregate":{"by":["routing-run-key","phase"],"values":[{"field":"event","as":"proxy-usage-count","reducer":"count","filter":{"predicates":[{"field":"event-type","equals":"firewall.token_usage"}]}},{"field":"event","as":"report-usage-count","reducer":"count","filter":{"predicates":[{"field":"event-type","equals":"usage.report"}]}},{"field":"event","as":"proxy-source-count","reducer":"count","filter":{"predicates":[{"field":"event-type","equals":"session.collection"},{"field":"name","equals":"token-usage.jsonl"},{"field":"event-status","equals":"collected"}]}},{"field":"event","as":"report-source-count","reducer":"count","filter":{"predicates":[{"field":"event-type","equals":"session.collection"},{"field":"name","in":["agent_usage.json","usage.json","usage.jsonl","usage-report.jsonl"]},{"field":"event-status","equals":"collected"}]}}]}},{"name":"routing-accounting-candidates","subject":"Read nonoverlapping per-response accounting records.","objective":"Expose recorded credits and token classes without repricing unknown usage.","acceptance":"Each phase uses proxy accounting when present and usage.report otherwise; absent AIC is counted.","from":"routing-events","joins":[{"source":"routing-phase-sources","type":"left","on":[{"left":"routing-run-key","right":"routing-run-key"},{"left":"phase","right":"phase"}],"fields":[{"field":"proxy-usage-count","as":"proxy-usage-count"}]}],"compute":[{"as":"has-proxy-accounting","function":"greater-than","args":[{"field":"proxy-usage-count"},{"value":0}]},{"as":"accounting-identity","function":"coalesce","args":[{"field":"correlation-id"},{"field":"event"}]},{"as":"accounting-source","function":"if","args":[{"field":"has-proxy-accounting"},{"value":"firewall.token_usage"},{"value":"usage.report"}]},{"as":"selected-accounting","function":"equals-any","args":[{"field":"event-type"},{"field":"accounting-source"}]},{"as":"unknown-aic","function":"equals-any","args":[{"field":"aic"},{"value":null}]},{"as":"unknown-aic-count","function":"if","args":[{"field":"unknown-aic"},{"value":1},{"value":0}]}],"window":[{"operation":"row-number","field":"source-sequence","as":"accounting-position","groupby":["routing-run-key","phase","event-type","accounting-identity"],"order-by":[{"field":"event-timestamp","direction":"desc"},{"field":"source-sequence","direction":"desc"}]}]},{"name":"routing-accounting","subject":"Select the authoritative accounting source for each phase.","objective":"Exclude overlapping usage reports and snapshots.","acceptance":"Every accounting row contributes at most once.","from":"routing-accounting-candidates","filter":{"predicates":[{"field":"selected-accounting","equals":true},{"field":"accounting-position","equals":1},{"field":"phase","in":["agent","detection","evals"]}]}},{"name":"routing-request-candidates","subject":"Keep per-request routing decisions separate from accounting.","objective":"Join routed outcomes by run, phase and request ID.","acceptance":"Rejected requests establish local zero cost; other unmatched requests retain unknown cost.","from":"routing-events","filter":{"predicates":[{"field":"event-type","equals":"firewall.model_routing"},{"field":"routing-stage","equals":"request"}]},"compute":[{"as":"request-identity","function":"coalesce","args":[{"field":"correlation-id"},{"field":"event"}]}],"window":[{"operation":"row-number","field":"source-sequence","as":"request-position","groupby":["routing-run-key","phase","request-identity"],"order-by":[{"field":"event-timestamp","direction":"desc"},{"field":"source-sequence","direction":"desc"}]}]},{"name":"routing-request-records","from":"routing-request-candidates","subject":"Retain the latest record for each request identity.","objective":"Avoid duplicate request joins and overlapping totals.","acceptance":"Requests without IDs remain independent, not falsely correlated.","filter":{"predicates":[{"field":"request-position","equals":1}]}},{"name":"routing-subagent-candidates","subject":"Read engine-reported sub-agent request ownership.","objective":"Use exact request-ID ownership before falling back to unsplit traffic.","acceptance":"Only request identities can assign exact ownership; advisory outcomes never assign credits.","from":"routing-events","filter":{"predicates":[{"field":"event-type","equals":"subagent.request"}]},"compute":[{"as":"subagent-identity","function":"coalesce","args":[{"field":"correlation-id"},{"field":"event"}]}],"window":[{"operation":"row-number","field":"source-sequence","as":"subagent-position","groupby":["routing-run-key","phase","subagent-identity"],"order-by":[{"field":"event-timestamp","direction":"desc"},{"field":"source-sequence","direction":"desc"}]}]},{"name":"routing-subagent-requests","from":"routing-subagent-candidates","subject":"Retain one sub-agent observation per request identity.","objective":"Keep exact ownership joins unique.","acceptance":"Missing identities do not match unrelated requests.","filter":{"predicates":[{"field":"subagent-position","equals":1}]}},{"name":"routing-exact-accounting","subject":"Attribute each accounting record to exactly one traffic bucket.","objective":"Keep detection, evals, classifier, exact sub-agent, main, unsplit and unattributed credits distinct.","acceptance":"Detection and evals use phase, missing purpose is never agent by default, and snapshot credits are excluded.","from":"routing-accounting","joins":[{"source":"routing-request-records","type":"left","on":[{"left":"routing-run-key","right":"routing-run-key"},{"left":"phase","right":"phase"},{"left":"correlation-id","right":"correlation-id"}],"fields":[{"field":"event","as":"request-event"},{"field":"routing-routed","as":"request-routed"},{"field":"routing-deviations","as":"request-deviations"},{"field":"routing-outcome","as":"request-outcome"},{"field":"routing-requested-model","as":"request-model"},{"field":"routing-requested-effort","as":"request-effort"}]},{"source":"routing-subagent-requests","type":"left","on":[{"left":"routing-run-key","right":"routing-run-key"},{"left":"phase","right":"phase"},{"left":"correlation-id","right":"correlation-id"}],"fields":[{"field":"routing-agent-name","as":"exact-agent-name"}]},{"source":"routing-run-facts","type":"left","on":[{"left":"routing-run-key","right":"routing-run-key"}],"fields":[{"field":"subagent-count","as":"subagent-count"}]}],"compute":[{"as":"exact-owner","function":"coalesce","args":[{"field":"routing-agent-name"},{"field":"exact-agent-name"}]},{"as":"no-exact-owner","function":"equals-any","args":[{"field":"exact-owner"},{"value":null}]}]},{"name":"routing-correlation-usage-candidates","from":"routing-exact-accounting","subject":"Find accounting records without exact sub-agent ownership.","objective":"Correlate only fully recorded token quartets in file order.","acceptance":"Missing token classes never match by model alone.","filter":{"predicates":[{"field":"phase","equals":"agent"},{"field":"no-exact-owner","equals":true}]},"compute":[{"as":"token-quartet","function":"sum","args":[{"field":"input-tokens"},{"field":"output-tokens"},{"field":"cache-read-tokens"},{"field":"cache-write-tokens"}]},{"as":"is-classifier","function":"equals-any","args":[{"field":"routing-purpose"},{"value":"routing_classification"}]}]},{"name":"routing-correlation-usage","from":"routing-correlation-usage-candidates","subject":"Order unmatched accounting within model and token quartet.","objective":"Match each engine-reported request at most once.","acceptance":"Classifier, incomplete and already-exact requests are excluded.","filter":{"predicates":[{"field":"token-quartet","gte":0},{"field":"is-classifier","equals":false}]},"window":[{"operation":"row-number","field":"source-sequence","as":"correlation-position","groupby":["routing-run-key","telemetry-model","input-tokens","output-tokens","cache-read-tokens","cache-write-tokens"],"order-by":[{"field":"source-sequence","direction":"asc"}]}]},{"name":"routing-correlation-subagent-candidates","from":"routing-subagent-requests","subject":"Exclude engine requests already matched by proxy request ID.","objective":"Prevent exact and correlated ownership from claiming the same request.","acceptance":"Only engine requests with a complete quartet and a definition name can correlate.","joins":[{"source":"routing-accounting","type":"left","on":[{"left":"routing-run-key","right":"routing-run-key"},{"left":"phase","right":"phase"},{"left":"correlation-id","right":"correlation-id"}],"fields":[{"field":"event","as":"exact-accounting-event"}]}],"compute":[{"as":"token-quartet","function":"sum","args":[{"field":"input-tokens"},{"field":"output-tokens"},{"field":"cache-read-tokens"},{"field":"cache-write-tokens"}]}]},{"name":"routing-correlation-subagents","from":"routing-correlation-subagent-candidates","subject":"Order unmatched engine requests within each model/token quartet.","objective":"Produce deterministic one-to-one correlated ownership.","acceptance":"Correlation is labelled separately from exact evidence.","filter":{"predicates":[{"field":"exact-accounting-event","equals":null},{"field":"token-quartet","gte":0},{"field":"phase","equals":"agent"}]},"window":[{"operation":"row-number","field":"source-sequence","as":"correlation-position","groupby":["routing-run-key","telemetry-model","input-tokens","output-tokens","cache-read-tokens","cache-write-tokens"],"order-by":[{"field":"source-sequence","direction":"asc"}]}]},{"name":"routing-correlated-accounting","from":"routing-correlation-usage","subject":"Join proxy usage with unmatched engine requests by model, quartet and occurrence.","objective":"Use the spec's correlated sub-agent attribution without duplicating credits.","acceptance":"Each engine request and accounting record participates at most once.","joins":[{"source":"routing-correlation-subagents","type":"left","on":[{"left":"routing-run-key","right":"routing-run-key"},{"left":"telemetry-model","right":"telemetry-model"},{"left":"input-tokens","right":"input-tokens"},{"left":"output-tokens","right":"output-tokens"},{"left":"cache-read-tokens","right":"cache-read-tokens"},{"left":"cache-write-tokens","right":"cache-write-tokens"},{"left":"correlation-position","right":"correlation-position"}],"fields":[{"field":"routing-agent-name","as":"correlated-owner"}]}],"select":[{"field":"routing-run-key"},{"field":"event"},{"field":"correlated-owner"}]},{"name":"routing-attributed-accounting","from":"routing-exact-accounting","subject":"Assign every accounting record to exactly one exclusive bucket.","objective":"Keep exact and correlated sub-agent ownership distinct.","acceptance":"Phase wins over purpose; missing ownership remains unsplit or unattributed.","joins":[{"source":"routing-correlated-accounting","type":"left","on":[{"left":"routing-run-key","right":"routing-run-key"},{"left":"event","right":"event"}],"fields":[{"field":"correlated-owner","as":"correlated-owner"}]}],"compute":[{"as":"agent-name","function":"coalesce","args":[{"field":"exact-owner"},{"field":"correlated-owner"}]},{"as":"unknown-agent","function":"equals-any","args":[{"field":"agent-name"},{"value":null}]},{"as":"unknown-request","function":"equals-any","args":[{"field":"request-event"},{"value":null}]},{"as":"has-subagents","function":"greater-than","args":[{"field":"subagent-count"},{"value":0}]},{"as":"is-subagent-purpose","function":"equals-any","args":[{"field":"routing-purpose"},{"value":"subagent"}]},{"as":"is-agent-purpose","function":"equals-any","args":[{"field":"routing-purpose"},{"value":"agent"}]},{"as":"matched-bucket","function":"if","args":[{"field":"has-subagents"},{"value":"agent_unsplit"},{"value":"main_agent"}]},{"as":"request-bucket","function":"if","args":[{"field":"unknown-request"},{"value":"unattributed"},{"field":"matched-bucket"}]},{"as":"subagent-bucket","function":"if","args":[{"field":"is-subagent-purpose"},{"value":"agent_unsplit"},{"field":"request-bucket"}]},{"as":"purpose-bucket","function":"if","args":[{"field":"is-agent-purpose"},{"value":"main_agent"},{"field":"subagent-bucket"}]},{"as":"subagent-attribution","function":"if","args":[{"field":"no-exact-owner"},{"value":"subagent_correlated"},{"value":"subagent_exact"}]},{"as":"ownership-bucket","function":"if","args":[{"field":"unknown-agent"},{"field":"purpose-bucket"},{"field":"subagent-attribution"}]},{"as":"classifier","function":"equals-any","args":[{"field":"routing-purpose"},{"value":"routing_classification"}]},{"as":"classifier-bucket","function":"if","args":[{"field":"classifier"},{"value":"classifier"},{"field":"ownership-bucket"}]},{"as":"evals","function":"equals-any","args":[{"field":"phase"},{"value":"evals"}]},{"as":"phase-bucket","function":"if","args":[{"field":"evals"},{"value":"evals"},{"field":"classifier-bucket"}]},{"as":"detection","function":"equals-any","args":[{"field":"phase"},{"value":"detection"}]},{"as":"bucket","function":"if","args":[{"field":"detection"},{"value":"detection"},{"field":"phase-bucket"}]}]},{"name":"routing-joined-requests","subject":"Inspect per-request deviations and outcomes against proxy picks.","objective":"Keep requests without accounting visible and never invent a deviation cause.","acceptance":"Unmatched requests have unknown cost; each request retains its own requested and selected model.","from":"routing-request-records","joins":[{"source":"routing-accounting","type":"left","on":[{"left":"routing-run-key","right":"routing-run-key"},{"left":"phase","right":"phase"},{"left":"correlation-id","right":"correlation-id"}],"fields":[{"field":"aic","as":"accounted-aic"},{"field":"event","as":"accounting-event"}]}],"compute":[{"as":"missing-accounting","function":"equals-any","args":[{"field":"accounting-event"},{"value":null}]},{"as":"failed-request","function":"equals-any","args":[{"field":"routing-outcome"},{"value":"failed"}]},{"as":"failed-unaccounted","function":"if","args":[{"field":"missing-accounting"},{"field":"failed-request"},{"value":false}]}],"order-by":[{"field":"event-timestamp","direction":"desc"}]},{"name":"routing-unaccounted-failures","from":"routing-joined-requests","subject":"Count failed requests lacking accounting per run.","objective":"Recognize only unambiguous AWF-local effort failures.","acceptance":"A run-level effort failure cannot assign zero to multiple failed requests.","aggregate":{"by":["routing-run-key"],"values":[{"field":"event","as":"failed-unaccounted-count","reducer":"count","filter":{"predicates":[{"field":"failed-unaccounted","equals":true}]}}]}},{"name":"routing-deviations","from":"routing-joined-requests","subject":"Resolve explicit local zero costs and preserve all other unknown request costs.","objective":"Avoid partial-cost comparisons based on missing accounting.","acceptance":"Only guard rejection or an unambiguous local effort failure establishes zero AIC.","joins":[{"source":"routing-unaccounted-failures","type":"left","on":[{"left":"routing-run-key","right":"routing-run-key"}],"fields":[{"field":"failed-unaccounted-count","as":"failed-unaccounted-count"}]},{"source":"routing-run-facts","type":"left","on":[{"left":"routing-run-key","right":"routing-run-key"}],"fields":[{"field":"local-effort-failures","as":"local-effort-failures"}]}],"compute":[{"as":"only-unaccounted-failure","function":"equals-any","args":[{"field":"failed-unaccounted-count"},{"value":1}]},{"as":"has-local-failure","function":"greater-than","args":[{"field":"local-effort-failures"},{"value":0}]},{"as":"unambiguous-local-failure","function":"if","args":[{"field":"only-unaccounted-failure"},{"field":"has-local-failure"},{"value":false}]},{"as":"local-code","function":"equals-any","args":[{"field":"code"},{"value":"unsupported_reasoning_effort"}]},{"as":"local-evidence","function":"if","args":[{"field":"local-code"},{"value":true},{"field":"unambiguous-local-failure"}]},{"as":"local-failure","function":"if","args":[{"field":"failed-request"},{"field":"local-evidence"},{"value":false}]},{"as":"guard-rejection","function":"equals-any","args":[{"field":"routing-outcome"},{"value":"rejected"}]},{"as":"zero-local-cost","function":"if","args":[{"field":"guard-rejection"},{"value":true},{"field":"local-failure"}]},{"as":"local-cost","function":"if","args":[{"field":"zero-local-cost"},{"value":0},{"value":null}]},{"as":"request-aic","function":"coalesce","args":[{"field":"accounted-aic"},{"field":"local-cost"}]},{"as":"unknown-request-cost","function":"equals-any","args":[{"field":"request-aic"},{"value":null}]},{"as":"unknown-request-count","function":"if","args":[{"field":"unknown-request-cost"},{"value":1},{"value":0}]}]},{"name":"routing-phase-usage","from":"routing-accounting","subject":"Sum nonoverlapping accounting per run and phase.","objective":"Establish complete costs only with known response values.","acceptance":"Unknown response costs remain counted.","aggregate":{"by":["routing-run-key","phase"],"values":[{"field":"aic","as":"recorded-aic","reducer":"sum"},{"field":"aic","as":"known-responses","reducer":"count"},{"field":"unknown-aic-count","as":"unknown-responses","reducer":"sum"}]}},{"name":"routing-request-coverage","from":"routing-deviations","subject":"Count requests whose cost remains unknown.","objective":"Exclude incomplete runs from distribution comparisons.","acceptance":"Unmatched nonlocal requests cannot be treated as free.","aggregate":{"by":["routing-run-key","phase"],"values":[{"field":"unknown-request-count","as":"unknown-requests","reducer":"sum"}]}},{"name":"routing-phase-costs","from":"routing-phase-sources","subject":"Evaluate accounting completeness using collected source receipts and request joins.","objective":"Exclude partial costs from medians and comparisons.","acceptance":"A complete phase has its selected accounting source, no missing AIC and no unaccounted nonlocal requests.","joins":[{"source":"routing-phase-usage","type":"left","on":[{"left":"routing-run-key","right":"routing-run-key"},{"left":"phase","right":"phase"}],"fields":[{"field":"recorded-aic","as":"recorded-aic"},{"field":"unknown-responses","as":"unknown-responses"},{"field":"known-responses","as":"known-responses"}]},{"source":"routing-request-coverage","type":"left","on":[{"left":"routing-run-key","right":"routing-run-key"},{"left":"phase","right":"phase"}],"fields":[{"field":"unknown-requests","as":"unknown-requests"}]}],"compute":[{"as":"has-proxy","function":"greater-than","args":[{"field":"proxy-usage-count"},{"value":0}]},{"as":"has-report","function":"greater-than","args":[{"field":"report-usage-count"},{"value":0}]},{"as":"any-source-count","function":"sum","args":[{"field":"proxy-source-count"},{"field":"report-source-count"}]},{"as":"report-or-empty-source","function":"if","args":[{"field":"has-report"},{"field":"report-source-count"},{"field":"any-source-count"}]},{"as":"accounting-source-count","function":"if","args":[{"field":"has-proxy"},{"field":"proxy-source-count"},{"field":"report-or-empty-source"}]},{"as":"source-present","function":"greater-than","args":[{"field":"accounting-source-count"},{"value":0}]},{"as":"missing-responses","function":"coalesce","args":[{"field":"unknown-responses"},{"value":0}]},{"as":"missing-requests","function":"coalesce","args":[{"field":"unknown-requests"},{"value":0}]},{"as":"missing-count","function":"sum","args":[{"field":"missing-responses"},{"field":"missing-requests"}]},{"as":"all-values-known","function":"equals-any","args":[{"field":"missing-count"},{"value":0}]},{"as":"complete","function":"if","args":[{"field":"source-present"},{"field":"all-values-known"},{"value":false}]},{"as":"known-sum","function":"coalesce","args":[{"field":"recorded-aic"},{"value":0}]},{"as":"complete-aic","function":"if","args":[{"field":"complete"},{"field":"known-sum"},{"value":null}]}]},{"name":"routing-agent-costs","from":"routing-phase-costs","subject":"Select complete or explicitly partial agent-phase costs.","objective":"Keep detection and evals out of agent-phase comparisons.","acceptance":"Classifier remains part of agent-phase cost.","filter":{"predicates":[{"field":"phase","equals":"agent"}]}},{"name":"routing-detection-costs","from":"routing-phase-costs","subject":"Retain detection-phase cost completeness separately.","objective":"Do not count detection as classifier or agent traffic.","acceptance":"Missing detection evidence remains unknown, not zero.","filter":{"predicates":[{"field":"phase","equals":"detection"}]}},{"name":"routing-cost-runs","from":"routing-resolved-runs","subject":"Attach accounting completeness to identified routing runs.","objective":"Provide comparable costs only for complete runs.","acceptance":"An absent cost stays unknown and never inherits aggregate run AIC.","joins":[{"source":"routing-runs","type":"inner","on":[{"left":"routing-run-key","right":"routing-run-key"}],"fields":[{"field":"main-aic","as":"main-aic"},{"field":"baseline-model","as":"baseline-model"},{"field":"baseline-aic","as":"baseline-aic"},{"field":"baseline-complete","as":"baseline-complete"}]},{"source":"routing-agent-costs","type":"left","on":[{"left":"routing-run-key","right":"routing-run-key"}],"fields":[{"field":"complete-aic","as":"complete-aic"},{"field":"complete","as":"cost-complete"},{"field":"missing-count","as":"missing-cost-records"}]},{"source":"routing-detection-costs","type":"left","on":[{"left":"routing-run-key","right":"routing-run-key"}],"fields":[{"field":"complete-aic","as":"detection-aic"},{"field":"complete","as":"detection-complete"}]}],"compute":[{"as":"run-cost-complete","function":"if","args":[{"field":"cost-complete"},{"field":"detection-complete"},{"value":false}]},{"as":"run-aic","function":"sum","args":[{"field":"complete-aic"},{"field":"detection-aic"}]},{"as":"budget-use","function":"quotient","args":[{"field":"run-aic"},{"field":"configured-max-credits"}]}]},{"name":"routing-weekly-cost-totals","from":"routing-runs","subject":"Summarize complete agent-phase costs by UTC ISO week and routing state.","objective":"Expose trends without including partial costs.","acceptance":"Untimed runs cannot enter time buckets.","filter":{"predicates":[{"field":"run-clock","gte":0}]},"compute":[{"as":"week","function":"date-bucket","args":[{"field":"observed-at"},{"value":"week"}]}],"aggregate":{"by":["week","routing-state"],"values":[{"field":"run","as":"runs","reducer":"count"},{"field":"complete-aic","as":"complete-runs","reducer":"count"},{"field":"complete-aic","as":"observed-median","reducer":"median"}]}},{"name":"routing-weekly-accounting-cost","from":"routing-weekly-cost-totals","subject":"Gate weekly medians by complete sample size.","objective":"Keep sparse weeks from implying meaningful cost trends.","acceptance":"Weeks below the configurable minimum display insufficient data.","parameters":[{"name":"minimum-sample","type":"number"}],"compute":[{"as":"cost-series","function":"concat","args":[{"value":"Agent-phase accounting: "},{"field":"routing-state"}]},{"as":"sample-floor","function":"difference","args":[{"parameter":"minimum-sample"},{"value":1}]},{"as":"enough-samples","function":"greater-than","args":[{"field":"complete-runs"},{"field":"sample-floor"}]},{"as":"median-aic","function":"if","args":[{"field":"enough-samples"},{"field":"observed-median"},{"value":null}]},{"as":"sample-status","function":"if","args":[{"field":"enough-samples"},{"value":"observational"},{"value":"insufficient data"}]}],"order-by":[{"field":"week","direction":"asc"}]},{"name":"routing-resolutions","from":"routing-session-events","subject":"Read runner-written configured-model resolutions for scoped routing runs.","objective":"Explain what each workflow role's configured model resolved to before the engine launched.","acceptance":"Only model.resolution facts from latest scoped attempts contribute; missing or unsafe values and failed null resolutions remain unknown.","joins":[{"source":"routing-runs","type":"inner","on":[{"left":"routing-run-key","right":"routing-run-key"}],"fields":[{"field":"run-clock","as":"run-clock"},{"field":"observed-at","as":"run-observed-at"},{"field":"full-repository","as":"full-repository"},{"field":"routing-dashboard-link","as":"routing-dashboard-link"},{"field":"routing-state","as":"run-routing-state"}]}],"filter":{"predicates":[{"field":"event-type","equals":"model.resolution"}]},"compute":[{"as":"resolution-engine","function":"coalesce","args":[{"field":"telemetry-engine"},{"value":"unknown"}]},{"as":"resolution-role-label","function":"coalesce","args":[{"field":"resolution-role"},{"value":"unknown"}]},{"as":"configured-model","function":"coalesce","args":[{"field":"resolution-configured-model"},{"value":"unknown"}]},{"as":"resolved-model-label","function":"coalesce","args":[{"field":"resolution-resolved-model"},{"value":"unknown"}]},{"as":"resolution-provider","function":"coalesce","args":[{"field":"provider"},{"value":"unknown"}]},{"as":"resolution-status","function":"coalesce","args":[{"field":"event-status"},{"value":"unknown"}]},{"as":"failed-resolution","function":"equals-any","args":[{"field":"event-status"},{"value":"failed"}]},{"as":"failure-cause","function":"coalesce","args":[{"field":"code"},{"value":"unknown"}]},{"as":"resolution-cause","function":"if","args":[{"field":"failed-resolution"},{"field":"failure-cause"},{"field":"code"}]},{"as":"unknown-resolved-model","function":"equals-any","args":[{"field":"resolution-resolved-model"},{"value":null}]},{"as":"untimed","function":"equals-any","args":[{"field":"run-clock"},{"value":null}]},{"as":"configured-to-resolved","function":"concat","args":[{"field":"configured-model"},{"value":" → "},{"field":"resolved-model-label"}]},{"as":"workflow-key","function":"concat","args":[{"field":"full-repository"},{"value":":"},{"field":"workflow"}]},{"as":"resolution-actor","function":"concat","args":[{"field":"resolution-engine"},{"value":"/"},{"field":"resolution-role-label"},{"value":"/"},{"field":"resolution-provider"}]},{"as":"resolution-series","function":"concat","args":[{"field":"workflow-key"},{"value":" | "},{"field":"resolution-actor"},{"value":" | "},{"field":"configured-model"}]}]},{"name":"routing-health-totals","from":"routing-runs","subject":"Count routed runs and their selection, failure, adherence, outcome and cost evidence per repository and workflow.","objective":"Answer whether routing is on and working from one row per routed workflow.","acceptance":"Only selected, selection_failed, harness_reported and configured_unrecorded runs contribute; runs without evidence stay out of each denominator.","filter":{"predicates":[{"field":"routing-state","in":["selected","selection_failed","harness_reported","configured_unrecorded"]}]},"compute":[{"as":"has-routing-failure","function":"greater-than","args":[{"field":"failure-count"},{"value":0}]},{"as":"failure-or-fallback","function":"if","args":[{"field":"has-routing-failure"},{"value":true},{"field":"routing-degraded"}]},{"as":"adherence-known","function":"greater-than","args":[{"field":"flagged-requests"},{"value":0}]},{"as":"no-deviation","function":"equals-any","args":[{"field":"deviated-requests"},{"value":0}]}],"aggregate":{"by":["full-repository","workflow","baseline-model"],"values":[{"field":"paired-main-aic","as":"paired-main-aic","reducer":"sum"},{"field":"paired-baseline-aic","as":"paired-baseline-aic","reducer":"sum"},{"field":"run","as":"routed-runs","reducer":"count"},{"field":"run","as":"selected-runs","reducer":"count","filter":{"predicates":[{"field":"routing-state","equals":"selected"}]}},{"field":"run","as":"failure-runs","reducer":"count","filter":{"predicates":[{"field":"failure-or-fallback","equals":true}]}},{"field":"run","as":"adherence-known-runs","reducer":"count","filter":{"predicates":[{"field":"adherence-known","equals":true}]}},{"field":"run","as":"followed-runs","reducer":"count","filter":{"predicates":[{"field":"adherence-known","equals":true},{"field":"no-deviation","equals":true}]}},{"field":"agent-result","as":"known-outcomes","reducer":"count"},{"field":"run","as":"successes","reducer":"count","filter":{"predicates":[{"field":"agent-result","equals":"success"}]}},{"field":"complete-aic","as":"complete-runs","reducer":"count"},{"field":"complete-aic","as":"median-aic","reducer":"median"}]}},{"name":"routing-health","subject":"Show routing health shares per repository and workflow.","objective":"Tell whether routing is on and working from selection, failure or fallback, pick adherence, known outcomes and complete cost.","acceptance":"A zero denominator or no complete cost is unknown, never zero; unknown job outcomes are excluded from the success rate.","from":"routing-health-totals","compute":[{"as":"estimated-cost-vs-baseline","function":"quotient","args":[{"field":"paired-main-aic"},{"field":"paired-baseline-aic"}]},{"as":"estimated-cost-percent","function":"format-percent","args":[{"field":"estimated-cost-vs-baseline"}]},{"as":"selected-share","function":"quotient","args":[{"field":"selected-runs"},{"field":"routed-runs"}]},{"as":"failure-share","function":"quotient","args":[{"field":"failure-runs"},{"field":"routed-runs"}]},{"as":"followed-share","function":"quotient","args":[{"field":"followed-runs"},{"field":"adherence-known-runs"}]},{"as":"success-rate","function":"quotient","args":[{"field":"successes"},{"field":"known-outcomes"}]},{"as":"selected-percent","function":"format-percent","args":[{"field":"selected-share"}]},{"as":"failure-percent","function":"format-percent","args":[{"field":"failure-share"}]},{"as":"followed-percent","function":"format-percent","args":[{"field":"followed-share"}]},{"as":"success-percent","function":"format-percent","args":[{"field":"success-rate"}]}],"order-by":[{"field":"routed-runs","direction":"desc"},{"field":"full-repository","direction":"asc"},{"field":"workflow","direction":"asc"}]},{"name":"routing-weekly-models","from":"routing-runs","subject":"Count proxy-selected runs by UTC ISO week and picked model.","objective":"Show what the router chooses over time.","acceptance":"Only selected runs with a known pick model and a recorded run clock contribute; an unrecorded effort does not exclude a run.","filter":{"predicates":[{"field":"routing-state","equals":"selected"},{"field":"unknown-pick-model","equals":false},{"field":"run-clock","gte":0}]},"compute":[{"as":"week","function":"date-bucket","args":[{"field":"observed-at"},{"value":"week"}]}],"aggregate":{"by":["week","pick-model"],"values":[{"field":"run","as":"runs","reducer":"count"}]},"order-by":[{"field":"week","direction":"asc"},{"field":"pick-model","direction":"asc"}]},{"name":"routing-weekly-paired-totals","from":"routing-runs","subject":"Weekly paired complete main-request costs by baseline model.","objective":"Compare routing cost trends with each named baseline using identical main-request populations.","acceptance":"Only timed runs with complete positive baseline estimates and matching known main-request costs contribute to both medians.","filter":{"predicates":[{"field":"paired","equals":true},{"field":"run-clock","gte":0}]},"compute":[{"as":"week","function":"date-bucket","args":[{"field":"observed-at"},{"value":"week"}]}],"aggregate":{"by":["week","baseline-model"],"values":[{"field":"run","as":"complete-runs","reducer":"count"},{"field":"paired-main-aic","as":"observed-main-median","reducer":"median"},{"field":"paired-baseline-aic","as":"baseline-estimate-median","reducer":"median"}]}},{"name":"routing-weekly-paired-cost","from":"routing-weekly-paired-totals","subject":"Paired main-request samples that meet the chosen evidence floor.","objective":"Avoid changing routing policy based on insufficient paired evidence.","acceptance":"Observed and estimated series share the same complete-run count and configurable minimum sample.","parameters":[{"name":"minimum-sample","type":"number"}],"compute":[{"as":"sample-floor","function":"difference","args":[{"parameter":"minimum-sample"},{"value":1}]},{"as":"enough-samples","function":"greater-than","args":[{"field":"complete-runs"},{"field":"sample-floor"}]}]},{"name":"routing-weekly-main-observed","from":"routing-weekly-paired-cost","subject":"Observed main-request AIC for the same eligible runs as each baseline.","objective":"Identify weeks when routed main-request costs exceed the matching baseline estimate.","acceptance":"Observed medians exclude classifier and sub-agent costs and remain unknown below the paired sample floor.","compute":[{"as":"cost-series","function":"concat","args":[{"value":"Main requests observed (baseline: "},{"field":"baseline-model"},{"value":")"}]},{"as":"median-aic","function":"if","args":[{"field":"enough-samples"},{"field":"observed-main-median"},{"value":null}]}]},{"name":"routing-weekly-baseline-estimate","from":"routing-weekly-paired-cost","subject":"Explicitly estimated baseline AIC for paired main-agent requests.","objective":"Show the named counterfactual against which owners can assess routing goal or mode.","acceptance":"The series is labelled estimated, separates baseline models and uses exactly the observed series' eligible runs.","compute":[{"as":"cost-series","function":"concat","args":[{"value":"Baseline estimate (estimated, main requests): "},{"field":"baseline-model"}]},{"as":"median-aic","function":"if","args":[{"field":"enough-samples"},{"field":"baseline-estimate-median"},{"value":null}]}]},{"name":"routing-weekly-cost","from":"routing-weekly-accounting-cost","union":["routing-weekly-main-observed","routing-weekly-baseline-estimate"],"subject":"Compare the same main-agent requests to an explicitly estimated baseline.","objective":"Change routing goal or mode when paired observed cost exceeds the named baseline.","acceptance":"Keep agent-phase accounting separate, baseline models distinct and sparse weeks as gaps.","order-by":[{"field":"week","direction":"asc"},{"field":"cost-series","direction":"asc"}]},{"name":"routing-failure-problems","from":"routing-runs","subject":"Runs whose routing failure codes require investigation.","objective":"Investigate routing configuration or execution failures before changing rollout.","acceptance":"Emit one row per run with recorded routing failure identifiers, excluding upstream errors handled by their own kind.","filter":{"predicates":[{"field":"routing-failure-codes","gte":""}]},"compute":[{"as":"problem-kind","function":"literal","args":[{"value":"routing failure"}]},{"as":"problem-cause","function":"coalesce","args":[{"field":"routing-failure-codes"},{"value":null}]}],"select":[{"field":"routing-run-key"},{"field":"problem-kind"},{"field":"problem-cause"}]},{"name":"routing-deviation-problems","from":"routing-runs","subject":"Runs whose requests deviated from the routing pick.","objective":"Investigate why requests did not follow the selected model or effort.","acceptance":"Emit one row per run with distinct recorded deviation causes, without inferring causes from model names.","filter":{"predicates":[{"field":"routing-deviation-codes","gte":""}]},"compute":[{"as":"problem-kind","function":"literal","args":[{"value":"deviation"}]},{"as":"problem-cause","function":"coalesce","args":[{"field":"routing-deviation-codes"},{"value":null}]}],"select":[{"field":"routing-run-key"},{"field":"problem-kind"},{"field":"problem-cause"}]},{"name":"routing-resolution-problems","from":"routing-runs","subject":"Runs whose configured models could not be resolved.","objective":"Correct model aliases or restore catalogue availability for failed resolutions.","acceptance":"Emit one row per run with recorded resolution failure causes, not absence of resolution evidence.","filter":{"predicates":[{"field":"routing-resolution-codes","gte":""}]},"compute":[{"as":"problem-kind","function":"literal","args":[{"value":"resolution failure"}]},{"as":"problem-cause","function":"coalesce","args":[{"field":"routing-resolution-codes"},{"value":null}]}],"select":[{"field":"routing-run-key"},{"field":"problem-kind"},{"field":"problem-cause"}]},{"name":"routing-upstream-problems","from":"routing-runs","subject":"Provider-rejected requests with distinct upstream error codes.","objective":"Correct model or effort settings rejected by the provider.","acceptance":"Emit one upstream-error row per run with distinct safe codes or unknown, never a duplicate generic routing failure.","filter":{"predicates":[{"field":"routing-upstream-codes","gte":""}]},"compute":[{"as":"problem-kind","function":"literal","args":[{"value":"upstream error"}]},{"as":"problem-cause","function":"coalesce","args":[{"field":"routing-upstream-codes"},{"value":null}]}],"select":[{"field":"routing-run-key"},{"field":"problem-kind"},{"field":"problem-cause"}]},{"name":"routing-candidate-problems","from":"routing-runs","subject":"Runs whose full eligible pool contains choices the router cannot rank.","objective":"Review allowed models when the router cannot rank the complete eligible pool.","acceptance":"Emit one row only when both pool counters are known and overlap is below eligibility, displaying the observed ratio.","filter":{"predicates":[{"field":"candidate-coverage","gte":""}]},"compute":[{"as":"problem-kind","function":"literal","args":[{"value":"candidates not rankable"}]},{"as":"problem-cause","function":"coalesce","args":[{"field":"candidate-coverage"},{"value":null}]}],"select":[{"field":"routing-run-key"},{"field":"problem-kind"},{"field":"problem-cause"}]},{"name":"routing-problems","from":"routing-failure-problems","union":["routing-deviation-problems","routing-resolution-problems","routing-upstream-problems","routing-candidate-problems"],"subject":"List routing failures, deviations and resolution failures with one row per run and kind.","objective":"Show what needs attention and link each problem to its run page.","acceptance":"Time is the run's recorded observation time and stays unknown without a run clock; untimed rows sort after timed rows.","joins":[{"source":"routing-runs","type":"inner","on":[{"left":"routing-run-key","right":"routing-run-key"}],"fields":[{"field":"run","as":"run"},{"field":"full-repository","as":"full-repository"},{"field":"workflow","as":"workflow"},{"field":"run-clock","as":"run-clock"},{"field":"observed-at","as":"observed-at"},{"field":"routing-dashboard-link","as":"routing-dashboard-link"}]}],"compute":[{"as":"untimed","function":"equals-any","args":[{"field":"run-clock"},{"value":null}]}],"order-by":[{"field":"untimed","direction":"asc"},{"field":"run-clock","direction":"desc"},{"field":"run","direction":"desc"},{"field":"problem-kind","direction":"asc"}]},{"name":"simulator-database-inputs","subject":"Model daily run volume and 30-day retained detail from user-supplied scenario inputs.","objective":"Compare hypothetical workload choices without treating results as observed activity.","acceptance":"Each simulated day uses the selected inputs; skipped runs retain summaries and detailed records have a 30-day lifetime.","description":"Each simulated day includes all accumulated run summaries; tools and issues belong only to non-skipped runs and expire after 30 days.","from":"simulation-days","parameters":[{"name":"repositories","type":"number"},{"name":"runs-per-day","type":"number"},{"name":"tools-per-run","type":"number"},{"name":"issues-per-run","type":"number"},{"name":"skip-rate","type":"number"}],"compute":[{"as":"runs-daily","function":"product","args":[{"parameter":"repositories"},{"parameter":"runs-per-day"}]},{"as":"skip-fraction","function":"quotient","args":[{"parameter":"skip-rate"},{"value":100}]},{"as":"active-fraction","function":"difference","args":[{"value":1},{"field":"skip-fraction"}]},{"as":"summary-runs","function":"product","args":[{"field":"day"},{"field":"runs-daily"}]},{"as":"past-ttl","function":"greater-than","args":[{"field":"day"},{"value":30}]},{"as":"detail-days","function":"if","args":[{"field":"past-ttl"},{"value":30},{"field":"day"}]},{"as":"detail-runs","function":"product","args":[{"field":"detail-days"},{"field":"runs-daily"},{"field":"active-fraction"}]},{"as":"tools-per-run","function":"literal","args":[{"parameter":"tools-per-run"}]},{"as":"issues-per-run","function":"literal","args":[{"parameter":"issues-per-run"}]}]},{"name":"simulator-run-size","subject":"Estimate retained run-summary table size at 512 bytes per run.","objective":"Show modeled accumulation of run summaries.","acceptance":"Summary size includes every simulated run at 512 bytes and is not presented as measured storage.","from":"simulator-database-inputs","compute":[{"as":"table","function":"literal","args":[{"value":"Run summaries"}]},{"as":"bytes","function":"product","args":[{"field":"summary-runs"},{"value":512}]}],"select":[{"field":"day"},{"field":"table"},{"field":"bytes"}]},{"name":"simulator-tool-size","subject":"Estimate retained tool table size at 256 bytes per tool on non-skipped runs.","objective":"Show modeled tool-record growth under the selected workload.","acceptance":"Tool size uses only non-skipped simulated runs and 256 bytes per tool over the retained period.","from":"simulator-database-inputs","compute":[{"as":"table","function":"literal","args":[{"value":"Tools (30-day TTL)"}]},{"as":"bytes","function":"product","args":[{"field":"detail-runs"},{"field":"tools-per-run"},{"value":256}]}],"select":[{"field":"day"},{"field":"table"},{"field":"bytes"}]},{"name":"simulator-issue-size","subject":"Estimate retained issue table size at 512 bytes per issue on non-skipped runs.","objective":"Show modeled issue-record growth under the selected workload.","acceptance":"Issue size uses only non-skipped simulated runs and 512 bytes per issue over the retained period.","from":"simulator-database-inputs","compute":[{"as":"table","function":"literal","args":[{"value":"Issues (30-day TTL)"}]},{"as":"bytes","function":"product","args":[{"field":"detail-runs"},{"field":"issues-per-run"},{"value":512}]}],"select":[{"field":"day"},{"field":"table"},{"field":"bytes"}]},{"name":"simulator-database-size","subject":"Show modeled run-summary, tool, and issue table bytes after 30 days.","objective":"Compare hypothetical database table sizes at the end of the retention horizon.","acceptance":"The model presents separate summary, tool, and issue estimates after 30 simulated days, never observed storage.","description":"Run summaries accumulate; detailed records have a 30-day TTL.","from":"simulator-run-size","union":["simulator-tool-size","simulator-issue-size"],"filter":{"predicates":[{"field":"day","equals":30}]},"select":[{"field":"table"},{"field":"bytes"}]},{"name":"simulator-database-total","subject":"Sum the modeled table sizes after 30 days.","objective":"Show the final estimated size of the modeled database tables.","acceptance":"The final value is the sum of the three modeled table sizes after 30 days.","from":"simulator-database-size","compute":[{"as":"total-label","function":"literal","args":[{"value":"Total"}]}],"aggregate":{"by":["total-label"],"values":[{"field":"bytes","as":"bytes","reducer":"sum"}]},"select":[{"field":"total-label","as":"table"},{"field":"bytes"}]},{"name":"simulator-database-summary","subject":"List modeled table sizes and their final total after 30 days.","objective":"Present the 30-day estimate in a compact table.","acceptance":"Three modeled table sizes and their summed final value are shown without a growth chart.","from":"simulator-database-size","union":["simulator-database-total"]},{"name":"overview-run-summary","subject":"Summarize successful, failed, and active runs with rollout-mode counts.","objective":"Expose observed success, failure, and active run counts, including active live and review modes, for the selected horizon.","acceptance":"Each count follows its declared conclusion, status, and rollout-mode filters; run success is not treated as a verified outcome, and incomplete or stale evidence is identified.","from":"overview-runs","aggregate":{"values":[{"field":"run-conclusion","as":"successful-runs","reducer":"count","filter":{"predicates":[{"field":"run-conclusion","equals":"success"}]}},{"field":"run-conclusion","as":"failed-runs","reducer":"count","filter":{"predicates":[{"field":"run-conclusion","in":["failure","startup-failure","stale","timed-out"]}]}},{"field":"run-status","as":"active-runs","reducer":"count","filter":{"predicates":[{"field":"run-status","in":["queued","in-progress","in_progress"]}]}},{"field":"run-status","as":"active-live","reducer":"count","filter":{"predicates":[{"field":"run-status","in":["queued","in-progress","in_progress"]},{"field":"rollout-mode","equals":"live"}]}},{"field":"run-status","as":"active-review","reducer":"count","filter":{"predicates":[{"field":"run-status","in":["queued","in-progress","in_progress"]},{"field":"rollout-mode","equals":"review"}]}}]}},{"name":"overview-delivery-summary","subject":"Count distinct target repositories with successful worker dispatch runs in the selected horizon.","objective":"Measure observed reach among registered repositories with successful dispatched worker runs.","acceptance":"Distinct delivered-repositories is limited to registered targets and successful workflow_dispatch worker runs in the selected horizon; it does not establish accepted delivery or authorized coverage.","from":"overview-runs","joins":[{"source":"repositories","type":"inner","on":[{"left":"target-repository","right":"repository-coordinate"}],"fields":[{"field":"repository-coordinate","as":"registered-target-repository"}]}],"filter":{"predicates":[{"field":"event","equals":"workflow_dispatch"},{"field":"run-conclusion","equals":"success"},{"field":"workflow-role","equals":"worker"}]},"aggregate":{"values":[{"field":"target-repository","as":"delivered-repositories","reducer":"distinct-count"}]}},{"name":"overview-value-summary","subject":"Count all observed grader results.","objective":"Identify whether any grader observations are available to the Overview status presentation.","acceptance":"The value-gains field counts observed grader records only; inspect each result's native measure, unit, direction, maturity, and uncertainty before claiming an outcome or improvement.","from":"grader-observations","aggregate":{"values":[{"field":"grader","as":"value-gains","reducer":"count"}]}},{"name":"overview-issue-summary","subject":"Count retained issue and pull request safe-output records for Overview.","objective":"Restore the issue and pull request counter with a link to its evidence inventory.","acceptance":"The count includes retained canonical issue and pull request records, not inferred outcomes; unavailable evidence remains unavailable.","from":"issues","aggregate":{"values":[{"field":"id","as":"value","reducer":"count"}]},"limit":1},{"name":"overview-issue-station","subject":"Present the retained issue and pull request count for Overview.","objective":"Provide a presentation-ready count and accessible evidence description.","acceptance":"The value matches overview-issue-summary and describes retained safe outputs, not accepted outcomes.","from":"overview-issue-summary","compute":[{"as":"detail","function":"concat","args":[{"value":"Retained safe"},{"value":" outputs"}]},{"as":"description","function":"concat","args":[{"field":"value"},{"value":" retained issues and pull requests"}]}],"limit":1},{"name":"overview-value-station","subject":"Present the observed grader-result count as the legacy Value gains counter.","objective":"Restore the Value gains counter while making its observation-count semantics explicit.","acceptance":"The count matches overview-value-summary, including zero; grader presence is not proof of improvement and unavailable evidence is not zero.","from":"overview-value-summary","compute":[{"as":"detail","function":"concat","args":[{"value":"Observed grader"},{"value":" results"}]},{"as":"description","function":"concat","args":[{"field":"value-gains"},{"value":" observed grader results, not verified improvements"}]}],"select":[{"field":"value-gains","as":"value"},{"field":"detail"},{"field":"description"}],"limit":1},{"name":"overview-run-status-input","subject":"Prepare the compact run summary for declarative factory status classification.","objective":"Carry successful-runs, failed-runs, and active-runs into the status join without changing their meaning.","acceptance":"The projected counts retain the selected horizon and match overview-run-summary; the join key is only a presentation key, not additional evidence.","from":"overview-run-summary","compute":[{"as":"status-join-key","function":"concat","args":[{"value":"factory"},{"value":"-status"}]}],"select":[{"field":"status-join-key"},{"field":"successful-runs"},{"field":"failed-runs"},{"field":"active-runs"}]},{"name":"overview-value-status-input","subject":"Prepare the compact value summary for declarative factory status classification.","objective":"Carry the grader-observation count into the optional status join.","acceptance":"The projected value-gains count matches overview-value-summary; a zero count does not establish complete grader coverage, and a nonzero count is not proof of gain.","from":"overview-value-summary","compute":[{"as":"status-join-key","function":"concat","args":[{"value":"factory"},{"value":"-status"}]}],"select":[{"field":"status-join-key"},{"field":"value-gains"}]},{"name":"overview-factory-status","subject":"Classify the factory heading from compact run and optional value evidence.","objective":"Provide a bounded Overview heading based on observed run counts and optional grader-record presence.","acceptance":"The heading matches the declared run-count and optional grader-presence branches; grader presence is not verified value, and the heading does not authorize any policy change.","from":"overview-run-status-input","joins":[{"source":"overview-value-status-input","type":"left","on":[{"left":"status-join-key","right":"status-join-key"}],"fields":[{"field":"value-gains","as":"value-gains"}]}],"compute":[{"as":"has-successful-runs","function":"greater-than","args":[{"field":"successful-runs"},{"value":0}]},{"as":"has-failed-runs","function":"greater-than","args":[{"field":"failed-runs"},{"value":0}]},{"as":"failures-exceed-successes","function":"greater-than","args":[{"field":"failed-runs"},{"field":"successful-runs"}]},{"as":"has-active-runs","function":"greater-than","args":[{"field":"active-runs"},{"value":0}]},{"as":"has-value-gains","function":"greater-than","args":[{"field":"value-gains"},{"value":0}]},{"as":"successful-heading","function":"if","args":[{"field":"has-successful-runs"},{"value":"Your factory is humming."},{"value":"Your factory is idle."}]},{"as":"attention-heading","function":"if","args":[{"field":"has-failed-runs"},{"value":"Your factory needs attention."},{"field":"successful-heading"}]},{"as":"strain-heading","function":"if","args":[{"field":"failures-exceed-successes"},{"value":"Your factory is under strain."},{"field":"attention-heading"}]},{"as":"active-heading","function":"if","args":[{"field":"has-active-runs"},{"value":"Your factory is humming."},{"field":"strain-heading"}]},{"as":"factory-heading","function":"if","args":[{"field":"has-value-gains"},{"value":"Your factory is delivering value."},{"field":"active-heading"}]}],"select":[{"field":"factory-heading"}]},{"name":"overview-registered-repository-summary","subject":"Count canonical repository identities registered in the resolved control-plane scope.","objective":"Provide the registered-repository denominator for observed worker reach.","acceptance":"The count reflects canonical repository records in the resolved scope; it is not evidence of live enrollment, successful execution, or full inventory completeness.","from":"repositories","aggregate":{"values":[{"field":"repository","as":"registered-repositories","reducer":"count"}]}},{"name":"overview-delivery-coverage-input","subject":"Prepare successful delivery totals for the repository coverage summary.","objective":"Carry the distinct delivered-repositories count into the coverage join.","acceptance":"The projected count equals overview-delivery-summary for the selected horizon; the join key adds no repository observations.","from":"overview-delivery-summary","compute":[{"as":"coverage-key","function":"concat","args":[{"value":"repository-coverage"},{"value":""}]}],"select":[{"field":"delivered-repositories"},{"field":"coverage-key"}]},{"name":"overview-registered-repository-coverage-input","subject":"Prepare registered repository totals for the repository coverage summary.","objective":"Carry the registered-repositories count into the coverage denominator join.","acceptance":"The projected count equals overview-registered-repository-summary for the resolved scope; missing inventory is not treated as zero eligible targets.","from":"overview-registered-repository-summary","compute":[{"as":"coverage-key","function":"concat","args":[{"value":"repository-coverage"},{"value":""}]}],"select":[{"field":"registered-repositories"},{"field":"coverage-key"}]},{"name":"overview-rhythm","subject":"Compare all workflow runs by weekday, layering this week over last week.","objective":"Show the observed weekday pattern across both calendar weeks, regardless of status or conclusion.","acceptance":"Verify weekday order, counts including unsuccessful and in-flight runs, and reached-day flags. Missing rhythm is unavailable, not zero activity; do not attribute changes to workflow improvements.","from":"overview-runs","time":{"range":"15d"},"compute":[{"as":"rhythm-point","function":"calendar-week-point","args":[{"field":"started-at"},{"context":"time-end"},{"value":true}]}],"aggregate":{"values":[{"field":"rhythm-point","as":"rhythm","reducer":"calendar-week-rhythm"}]}},{"name":"overview-repository-coverage-summary","subject":"Aggregate reached and total repositories across the resolved organization scope.","objective":"Pair observed reached-repositories and registered-repositories-total for a comparable coverage denominator.","acceptance":"Both totals come from their named input queries and share the resolved scope; verify the left-joined inventory source independently before interpreting a zero total, since a missing join can aggregate to zero.","from":"overview-delivery-coverage-input","joins":[{"source":"overview-registered-repository-coverage-input","type":"left","on":[{"left":"coverage-key","right":"coverage-key"}],"fields":[{"field":"registered-repositories","as":"registered-repositories-total"}]}],"aggregate":{"values":[{"field":"delivered-repositories","as":"reached-repositories","reducer":"sum"},{"field":"registered-repositories-total","as":"registered-repositories-total","reducer":"sum"}]}},{"name":"overview-repository-coverage","subject":"Measure registered repository reach from successful worker execution.","objective":"Present observed successful-worker repository reach as a ratio alongside numerator and denominator.","acceptance":"repository-coverage is reached-repositories divided by registered-repositories-total when available; preserve the counts and undefined denominator, and do not call reach successful outcomes.","from":"overview-repository-coverage-summary","compute":[{"as":"repository-coverage","function":"quotient","args":[{"field":"reached-repositories"},{"field":"registered-repositories-total"}]}],"select":[{"field":"repository-coverage"},{"field":"reached-repositories"},{"field":"registered-repositories-total"}]},{"name":"overview-workflow-health-groups","subject":"Assess current runtime failures for every workflow across CAO and targeted repositories.","objective":"Compute the latest consecutive completed-run failure streak for each repository-scoped workflow without requiring campaign membership.","acceptance":"Group by organization, repository, and workflow; in-flight retries do not clear failures, and later non-failing completed runs reset the streak within the selected horizon.","from":"overview-runs","filter":{"predicates":[{"field":"run-status","equals":"completed"}]},"compute":[{"as":"is-runtime-failure","function":"equals-any","args":[{"field":"run-conclusion"},{"value":"failure"},{"value":"startup-failure"},{"value":"stale"},{"value":"timed-out"}]},{"as":"runtime-failure-streak-point","function":"failure-streak-point","args":[{"field":"started-at"},{"field":"run"},{"field":"is-runtime-failure"}]}],"aggregate":{"by":["organization","repository","workflow"],"values":[{"field":"runtime-failure-streak-point","as":"failure-count","reducer":"latest-failure-streak"}]}},{"name":"overview-workflow-health-summary","subject":"Count all registered workflows and those without current observed runtime failures.","objective":"Provide Factory health numerator and denominator across CAO and targeted repositories, including standalone and campaign workflows.","acceptance":"Each repository-scoped workflow counts once regardless of campaign or role; no retained failure is not proof of successful execution, missing inventory remains unavailable, and missing run evidence marks the result incomplete.","from":"workflows","joins":[{"source":"overview-workflow-health-groups","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"}],"fields":[{"field":"failure-count","as":"observed-failures"}]}],"compute":[{"as":"normalized-failures","function":"coalesce","args":[{"field":"observed-failures"},{"value":0}]},{"as":"problem-present","function":"greater-than","args":[{"field":"normalized-failures"},{"value":0}]}],"aggregate":{"values":[{"field":"workflow","as":"workflows","reducer":"count"},{"field":"workflow","as":"healthy-workflows","reducer":"count","filter":{"predicates":[{"field":"problem-present","equals":false}]}}]}},{"name":"overview-workflow-health-presentation-input","subject":"Prepare all-workflow health counts for Overview presentation.","objective":"Carry Factory health counts into the header and station presentation.","acceptance":"Both counts match overview-workflow-health-summary and preserve missing evidence metadata.","from":"overview-workflow-health-summary","compute":[{"as":"overview-presentation-key","function":"concat","args":[{"value":"overview"},{"value":"-presentation"}]}],"select":[{"field":"overview-presentation-key"},{"field":"workflows"},{"field":"healthy-workflows"}]},{"name":"overview-factory-health-presentation","subject":"Produce presentation-ready Factory health values for the Overview header and floor.","objective":"Display the ratio of workflows without current observed runtime failures to all registered workflows with both underlying counts.","acceptance":"The percentage and detail agree with healthy-workflows and workflows; a missing or zero denominator remains unavailable, and the ratio is not proof of impact.","from":"overview-workflow-health-presentation-input","compute":[{"as":"factory-health","function":"quotient","args":[{"field":"healthy-workflows"},{"field":"workflows"}]},{"as":"factory-health-display","function":"format-percent","args":[{"field":"factory-health"}]},{"as":"healthy-workflows-display","function":"format-count","args":[{"field":"healthy-workflows"}]},{"as":"workflows-display","function":"format-count","args":[{"field":"workflows"}]},{"as":"factory-health-detail","function":"concat","args":[{"field":"healthy-workflows-display"},{"value":"/"},{"field":"workflows-display"},{"value":" healthy workflows"}]},{"as":"factory-health-description","function":"concat","args":[{"field":"factory-health-display"},{"value":" factory health"}]}],"select":[{"field":"overview-presentation-key"},{"field":"factory-health"},{"field":"factory-health-display"},{"field":"factory-health-detail"},{"field":"factory-health-description"}]},{"name":"overview-header-status-presentation-input","subject":"Prepare the factory status heading for the declarative Overview header.","objective":"Carry the factory heading into the Overview header join unchanged.","acceptance":"The heading matches overview-factory-status; the presentation key does not imply additional evidence or a policy recommendation.","from":"overview-factory-status","compute":[{"as":"overview-presentation-key","function":"concat","args":[{"value":"overview"},{"value":"-presentation"}]}],"select":[{"field":"overview-presentation-key"},{"field":"factory-heading"}]},{"name":"overview-header-presentation","subject":"Resolve the Overview heading from declarative status and factory-health evidence.","objective":"Display the configured heading corresponding to observed run status and factory health.","acceptance":"The selected heading follows the declared presentation branches; numeric branch boundaries are UI classification only, not operational targets or rollout thresholds.","from":"overview-header-status-presentation-input","joins":[{"source":"overview-factory-health-presentation","type":"left","on":[{"left":"overview-presentation-key","right":"overview-presentation-key"}],"fields":[{"field":"factory-health","as":"factory-health"}]}],"compute":[{"as":"factory-health-positive","function":"greater-than","args":[{"field":"factory-health"},{"value":0}]},{"as":"factory-health-below-threshold","function":"greater-than","args":[{"value":0.66},{"field":"factory-health"}]},{"as":"positive-factory-health-heading","function":"if","args":[{"field":"factory-health-below-threshold"},{"value":"Your factory needs attention."},{"field":"factory-heading"}]},{"as":"heading","function":"if","args":[{"field":"factory-health-positive"},{"field":"positive-factory-health-heading"},{"field":"factory-heading"}]}],"select":[{"field":"heading"}]},{"name":"overview-run-motion-presentation-input","subject":"Prepare active run state for Overview station presentation.","objective":"Expose whether at least one queued or in-progress run was observed for station display.","acceptance":"active reflects overview-run-summary's active-runs count; no observed active run does not prove the fleet is idle when the snapshot is incomplete.","from":"overview-run-summary","compute":[{"as":"overview-presentation-key","function":"concat","args":[{"value":"overview"},{"value":"-presentation"}]},{"as":"active","function":"greater-than","args":[{"field":"active-runs"},{"value":0}]}],"select":[{"field":"overview-presentation-key"},{"field":"active"}]},{"name":"overview-factory-station","subject":"Provide the presentation-ready Factory health station for Overview.","objective":"Show the all-workflow runtime health ratio, supporting counts, and observed run motion together.","acceptance":"Station value, display, detail, description, and active flag match their input queries; neither absence of failures nor run motion is verified workflow effectiveness.","from":"overview-factory-health-presentation","joins":[{"source":"overview-run-motion-presentation-input","type":"left","on":[{"left":"overview-presentation-key","right":"overview-presentation-key"}],"fields":[{"field":"active","as":"active"}]}],"select":[{"field":"factory-health","as":"value"},{"field":"factory-health-display","as":"display-value"},{"field":"factory-health-detail","as":"detail"},{"field":"factory-health-description","as":"description"},{"field":"active"}]},{"name":"overview-repository-station-presentation-input","subject":"Prepare repository coverage for the presentation-ready Overview station.","objective":"Format repository reach with its reached and registered counts for the station.","acceptance":"The percentage and detail preserve overview-repository-coverage's numerator and denominator; unavailable coverage remains unavailable, not zero or complete reach.","from":"overview-repository-coverage","compute":[{"as":"overview-presentation-key","function":"concat","args":[{"value":"overview"},{"value":"-presentation"}]},{"as":"display-value","function":"format-percent","args":[{"field":"repository-coverage"}]},{"as":"reached-repositories-display","function":"format-count","args":[{"field":"reached-repositories"}]},{"as":"registered-repositories-display","function":"format-count","args":[{"field":"registered-repositories-total"}]},{"as":"detail","function":"concat","args":[{"field":"reached-repositories-display"},{"value":"/"},{"field":"registered-repositories-display"},{"value":" repositories reached"}]},{"as":"description","function":"concat","args":[{"field":"display-value"},{"value":" average repository coverage"}]}],"select":[{"field":"overview-presentation-key"},{"field":"repository-coverage","as":"value"},{"field":"display-value"},{"field":"detail"},{"field":"description"}]},{"name":"overview-repository-station","subject":"Provide the presentation-ready repository coverage station for Overview.","objective":"Show observed registered-repository worker reach and run motion in one station.","acceptance":"Value and formatted evidence match the coverage presentation input, and active matches run motion; neither changes policy or establishes accepted outcomes.","from":"overview-repository-station-presentation-input","joins":[{"source":"overview-run-motion-presentation-input","type":"left","on":[{"left":"overview-presentation-key","right":"overview-presentation-key"}],"fields":[{"field":"active","as":"active"}]}],"select":[{"field":"value"},{"field":"display-value"},{"field":"detail"},{"field":"description"},{"field":"active"}]},{"name":"cost-by-repository","subject":"Present observed AI Credit cost grouped by repository.","objective":"Locate repositories with higher observed AI Credit totals for evidence-led investigation.","acceptance":"Each repository coordinate and native aic total agrees with repository-aic-totals; confirm the selected horizon and underlying runs before attributing cost or proposing a change.","from":"repository-aic-totals","compute":[{"as":"repository-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"encoded-repository","function":"url-encode","args":[{"field":"repository-coordinate"}]},{"as":"repository-dashboard-href","function":"concat","args":[{"value":"#page-repository-detail?repository="},{"field":"encoded-repository"}]},{"as":"repository-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"repository-coordinate"},{"value":" repository dashboard"}]},{"as":"repository-dashboard-link","function":"dashboard-link","args":[{"value":""},{"field":"repository-dashboard-href"},{"field":"repository-dashboard-label"},{"field":"repository-coordinate"}]}],"select":[{"field":"repository-coordinate"},{"field":"repository-dashboard-link"},{"field":"aic"}],"order-by":[{"field":"aic","direction":"desc"}]},{"name":"cost-by-workflow","subject":"Present observed AI Credit cost grouped by repository-owned workflow.","objective":"Locate repository workflows with higher observed AI Credit totals and open their workflow evidence.","acceptance":"Workflow identity, link, and native aic total match workflow-aic-totals in descending order; cost alone does not establish waste, quality, or value.","from":"workflow-aic-totals","compute":[{"as":"repository-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"workflow-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"},{"value":":"},{"field":"workflow"}]},{"as":"encoded-workflow","function":"url-encode","args":[{"field":"workflow-coordinate"}]},{"as":"workflow-dashboard-href","function":"concat","args":[{"value":"#page-workflow-runtime?workflow="},{"field":"encoded-workflow"}]},{"as":"workflow-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"workflow-coordinate"},{"value":" workflow dashboard"}]},{"as":"workflow-dashboard-link","function":"dashboard-link","args":[{"value":""},{"field":"workflow-dashboard-href"},{"field":"workflow-dashboard-label"},{"field":"workflow-coordinate"}]}],"select":[{"field":"repository-coordinate"},{"field":"workflow"},{"field":"workflow-coordinate"},{"field":"workflow-dashboard-link"},{"field":"aic"}],"order-by":[{"field":"aic","direction":"desc"}]},{"name":"cost-per-workflow-run","subject":"Present the average observed AI Credit cost of a single run for each repository-owned workflow.","objective":"Compare observed AI Credit per run across repository workflows with each observed-runs denominator.","acceptance":"Include only workflows with positive-AIC run attempts, and use only those attempts in cost averages; observed-runs still counts all retained attempts.","description":"Observed AI Credit totals divided by positive-AIC run attempts for each declared workflow.","from":"workflow-aic-run-totals","filter":{"predicates":[{"field":"aic-runs","gte":1}]},"compute":[{"as":"aic-per-run","function":"quotient","args":[{"field":"aic"},{"field":"aic-runs"}]},{"as":"repository-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"}]},{"as":"workflow-coordinate","function":"concat","args":[{"field":"organization"},{"value":"/"},{"field":"repository"},{"value":":"},{"field":"workflow"}]},{"as":"encoded-workflow","function":"url-encode","args":[{"field":"workflow-coordinate"}]},{"as":"workflow-dashboard-href","function":"concat","args":[{"value":"#page-workflow-runtime?workflow="},{"field":"encoded-workflow"}]},{"as":"workflow-dashboard-label","function":"concat","args":[{"value":"View "},{"field":"workflow-coordinate"},{"value":" workflow dashboard"}]},{"as":"workflow-dashboard-link","function":"dashboard-link","args":[{"value":""},{"field":"workflow-dashboard-href"},{"field":"workflow-dashboard-label"},{"field":"workflow-coordinate"}]}],"select":[{"field":"repository-coordinate"},{"field":"workflow"},{"field":"workflow-coordinate"},{"field":"workflow-dashboard-link"},{"field":"runs","as":"observed-runs"},{"field":"aic-per-run"}],"order-by":[{"field":"aic-per-run","direction":"desc"}]},{"name":"failure-run-base","subject":"Select retained runs with failure, startup-failure, stale, or timed-out conclusions for the failed-run ledger and streak inputs.","objective":"Provide one consistent failure-conclusion evidence set to downstream Overview queries.","acceptance":"Each selected run has one of the four declared conclusions within the selected horizon; other conclusions remain outside this set, and missing run coverage is not interpreted as no failures.","from":"runs","filter":{"predicates":[{"field":"run-conclusion","in":["failure","startup-failure","stale","timed-out"]}]}},{"name":"failed-runs","subject":"List failed workflow runs that need operator attention.","objective":"Give operators the most recent observed failed runs to inspect in GitHub.","acceptance":"Unprojected run rows retain available conclusion, started-at, and run evidence fields in descending started-at order; inspect source logs and missing links before attributing a cause or declaring resolution.","from":"failure-run-base","order-by":[{"field":"started-at","direction":"desc"}]},{"name":"overview-failing-runs","subject":"Identify failed runs in the selected snapshot horizon so subsequent streak logic can use the same declarative failure definition.","objective":"Project distinct failure-run counts by organization, repository, workflow, and run for streak joins.","acceptance":"Each grouped run identity has a failing-runs count derived from failure-run-base in the selected horizon; this stage does not assert a consecutive streak or require action.","from":"failure-run-base","aggregate":{"by":["organization","repository","workflow","run"],"values":[{"field":"run","as":"failing-runs","reducer":"distinct-count"}]}},{"name":"overview-failing-workflows","subject":"Identify only workflows that have at least one failed run in the selected snapshot horizon before computing streaks.","objective":"Provide workflow identities with observed failed runs for the streak computation.","acceptance":"Each organization/repository/workflow group has a distinct failing-runs count from overview-failing-runs; the count covers observed failures, not the latest consecutive streak.","from":"overview-failing-runs","aggregate":{"by":["organization","repository","workflow"],"values":[{"field":"run","as":"failing-runs","reducer":"distinct-count"}]}},{"name":"overview-repeated-failure-groups","subject":"Group each workflow's latest consecutive failing run sequence in the selected snapshot horizon, resetting the group after any successful run.","objective":"Project the latest observed consecutive failure-count per workflow for downstream blocked-work matching.","acceptance":"failure-count follows run ordering and the declared latest-failure-streak reducer, with non-failing runs breaking the streak; missing earlier runs or incomplete snapshots limit the observed sequence.","from":"runs","joins":[{"source":"overview-failing-workflows","type":"inner","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"}],"fields":[{"field":"failing-runs","as":"failing-runs"}]},{"source":"overview-failing-runs","type":"left","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"},{"left":"run","right":"run"}],"fields":[{"field":"failing-runs","as":"run-failing-count"}]}],"compute":[{"as":"failure-streak-point","function":"failure-streak-point","args":[{"field":"started-at"},{"field":"run"},{"field":"run-failing-count"}]}],"aggregate":{"by":["organization","repository","workflow"],"values":[{"field":"failure-streak-point","as":"failure-count","reducer":"latest-failure-streak"}]}},{"name":"overview-repeated-failure-candidates","subject":"Attach selected-horizon failure counts to each workflow's latest canonical work item.","objective":"Pair blocked work items with observed workflow failure streaks and retained run evidence before attention filtering.","acceptance":"Candidates are filtered to blocked items with a matching organization/repository/workflow streak; is-repeated reflects failure-count greater than one, while selected evidence-link and run-link can be absent or refer to the work item rather than the latest failed run.","from":"work-items","joins":[{"source":"overview-repeated-failure-groups","type":"inner","on":[{"left":"organization","right":"organization"},{"left":"repository","right":"repository"},{"left":"workflow","right":"workflow"}],"fields":[{"field":"failure-count","as":"failure-count"}]}],"filter":{"predicates":[{"field":"lifecycle-state","equals":"blocked"}]},"compute":[{"as":"is-repeated","function":"greater-than","args":[{"field":"failure-count"},{"value":1}]},{"as":"attention-signal-id","function":"concat","args":[{"value":"repeated-failure:"},{"field":"organization"},{"value":"/"},{"field":"repository"},{"value":":"},{"field":"workflow"}]},{"as":"kind","function":"coalesce","args":[{"value":"Repeated workflow failures"},{"value":"Repeated workflow failures"}]},{"as":"title","function":"coalesce","args":[{"field":"workflow"},{"value":"Workflow"}]},{"as":"attention-reason","function":"concat","args":[{"field":"failure-count"},{"value":" failed runs in the selected horizon"}]},{"as":"action","function":"coalesce","args":[{"value":"Open latest failed run on GitHub"},{"value":"Open latest failed run on GitHub"}]},{"as":"icon","function":"coalesce","args":[{"value":"x-circle"},{"value":"x-circle"}]},{"as":"tone","function":"coalesce","args":[{"value":"critical"},{"value":"critical"}]},{"as":"priority","function":"number","args":[{"value":0}]}],"select":[{"field":"is-repeated"},{"field":"attention-signal-id"},{"field":"kind"},{"field":"title"},{"field":"scope"},{"field":"attention-reason","as":"reason"},{"field":"observed-at"},{"field":"action"},{"field":"evidence-link"},{"field":"run-link"},{"field":"icon"},{"field":"tone"},{"field":"priority"},{"field":"failure-count"}]},{"name":"overview-repeated-failure-attention","subject":"Keep only unresolved workflows with two or more failures in the selected horizon.","objective":"Surface blocked workflow items with observed repeated failures for bounded run investigation.","acceptance":"Every row inherits a blocked item with is-repeated true and projects evidence-link and run-link when available; verify run order, links, and current state before treating the failure as still unresolved.","from":"overview-repeated-failure-candidates","filter":{"predicates":[{"field":"is-repeated","equals":true}]},"select":[{"field":"attention-signal-id"},{"field":"kind"},{"field":"title"},{"field":"scope"},{"field":"reason"},{"field":"observed-at"},{"field":"action"},{"field":"evidence-link"},{"field":"run-link"},{"field":"icon"},{"field":"tone"},{"field":"priority"},{"field":"failure-count"}]},{"name":"overview-review-attention","subject":"Select only unresolved outputs explicitly awaiting human review with their retained GitHub evidence destination.","objective":"Present review-state work items and their retained GitHub destination to a human reviewer.","acceptance":"Rows are filtered to lifecycle-state review and project the work-item ID as attention-signal-id, plus reason, evidence-link, and run-link where present; reviewer disposition must be checked at source.","from":"work-items","filter":{"predicates":[{"field":"lifecycle-state","equals":"review"}]},"compute":[{"as":"kind","function":"coalesce","args":[{"value":"Human review required"},{"value":"Human review required"}]},{"as":"title","function":"coalesce","args":[{"field":"objective"},{"value":"Produced output"}]},{"as":"action","function":"coalesce","args":[{"value":"Open review item on GitHub"},{"value":"Open review item on GitHub"}]},{"as":"icon","function":"coalesce","args":[{"value":"eye"},{"value":"eye"}]},{"as":"tone","function":"coalesce","args":[{"value":"action"},{"value":"action"}]},{"as":"priority","function":"number","args":[{"value":1}]}],"select":[{"field":"work-item-id","as":"attention-signal-id"},{"field":"kind"},{"field":"title"},{"field":"scope"},{"field":"reason"},{"field":"observed-at"},{"field":"action"},{"field":"evidence-link"},{"field":"run-link"},{"field":"icon"},{"field":"tone"},{"field":"priority"}]},{"name":"overview-needs-attention","subject":"Combine grouped repeated failures and unresolved review outputs without introducing ordinary activity or duplicate work items.","objective":"Prioritize observed blocked repeated-failure work and review-state outputs for investigation.","acceptance":"Rows come only from the repeated-failure or review inputs and retain their source reasons, links, and ordering; confirm fresh source status before acting, and do not equate a missing row with resolved work.","from":"overview-repeated-failure-attention","union":["overview-review-attention"],"order-by":[{"field":"priority","direction":"asc"},{"field":"observed-at","direction":"desc"},{"field":"attention-signal-id","direction":"asc"}]},{"name":"domain-route-record","subject":"Project the selected domain header and one retained run link.","objective":"Identify the selected domain and open a retained run before investigating its traffic evidence.","acceptance":"The route header preserves the selected domain and a run link from its retained observations; missing observations or links remain unavailable, and a header does not establish access policy or traffic completeness.","from":"domains","select":[{"field":"domain"},{"field":"run-link"}]},{"name":"domain-run-records","subject":"Retained run-linked observations for the selected domain.","objective":"Find related runs without returning the unscoped domain collection alongside the paginated view.","acceptance":"Preserve every domain observation field, exact route scope, filtering, ordering, total count, provenance and related-run links; only the bounded view payload crosses the worker boundary.","from":"domains"},{"name":"tool-route-record","subject":"Project the selected MCP tool header and one retained run link.","objective":"Identify the selected MCP tool and open a retained run before investigating its call evidence.","acceptance":"The route header preserves the selected MCP tool label and a run link from its retained calls; absent calls or links remain unavailable and do not imply zero usage or tool effectiveness.","from":"mcp-tool-calls","select":[{"field":"mcp-tool-label"},{"field":"run-link"}]},{"name":"audit-route-record","subject":"Project the selected audit summary header and one retained run link.","objective":"Identify the selected audit summary and open a retained run before investigating its observations.","acceptance":"The route header preserves the selected event summary and a run link from its retained audit observations; absent evidence remains unavailable and neither the header nor its absence establishes incident severity or a clean audit.","from":"audits","select":[{"field":"event-summary"},{"field":"run-link"}]},{"name":"domain-entity-insights","subject":"Summarize one domain entity for its dedicated Insights view.","objective":"Identify domain decisions with request volume worth investigating before considering any egress change.","acceptance":"For the selected domain, request totals match the retained domain observations grouped by decision; missing data or blocked traffic does not establish a need for access, which requires underlying request and policy review.","from":"domains","aggregate":{"by":["domain","decision"],"values":[{"field":"request-count","as":"requests","reducer":"sum"}]},"order-by":[{"field":"requests","direction":"desc"},{"field":"decision","direction":"asc"}]},{"name":"tool-entity-insights","subject":"Summarize one tool entity for its dedicated Insights view.","objective":"Select a tool and status combination whose recorded call volume merits investigation.","acceptance":"For the selected tool, observation counts match retained MCP call observations grouped by server, tool, and status; missing calls are not zero usage and status counts do not establish effectiveness or cause.","from":"mcp-tool-calls","aggregate":{"by":["mcp-tool-label","mcp-server","mcp-tool","mcp-status"],"values":[{"field":"mcp-observation","as":"observations","reducer":"count"}]},"order-by":[{"field":"observations","direction":"desc"},{"field":"mcp-status","direction":"asc"}]},{"name":"audit-entity-insights","subject":"Summarize one audit event entity for its dedicated Insights view.","objective":"Select an audit summary and status requiring closer review of underlying observations.","acceptance":"For the selected summary, counts agree with retained audit observation IDs grouped by event status; repeated observations are not silently treated as distinct incidents, and absence does not prove no findings.","from":"audits","aggregate":{"by":["event-summary","event-status"],"values":[{"field":"id","as":"observations","reducer":"count"}]},"order-by":[{"field":"observations","direction":"desc"},{"field":"event-status","direction":"asc"}]}] diff --git a/dashboard/site/src/data/adapters/gh-aw-logs.js b/dashboard/site/src/data/adapters/gh-aw-logs.js index 85f6f20cb..d0147a21c 100644 --- a/dashboard/site/src/data/adapters/gh-aw-logs.js +++ b/dashboard/site/src/data/adapters/gh-aw-logs.js @@ -9,6 +9,7 @@ import { } from '../model/ids.js'; import { canonicalTimestamp, OPERATIONAL_VALUE_PERIOD_FIELDS, operationalValuePeriod, requiredString } from '../model/schema.js'; import { validateOperationalValueEvidence } from '../model/operational-value-evidence.js'; +import { validateWorkflowValueCollection } from '../model/workflow-value-collection.js'; import cachedJsonlExpression from '../ingest/expressions/gh-aw-logs-v2.json' with { type: 'json' }; import { createDebug } from '../../debug.js'; import { normalizeSessionMcpEvents, parseUnifiedSession, parseUnifiedSessionDocument } from './unified-session.js'; @@ -1141,6 +1142,8 @@ function createCachedGhAwJsonlAccumulator(options) { const operationalValues = []; /** @type {Record[]} */ const evidencePackets = []; + /** @type {Record[]} */ + const valueCollections = []; /** @type {Map} */ const latestRunByGithubId = new Map(); /** @type {Map} */ @@ -1166,6 +1169,10 @@ function createCachedGhAwJsonlAccumulator(options) { evidencePackets.push(validateOperationalValueEvidence(objectValue(envelope.operational_value_evidence, 'operational_value_evidence'))); return; } + if (envelope.kind === 'workflow_value_collection') { + valueCollections.push(validateWorkflowValueCollection(objectValue(envelope.workflow_value_collection, 'workflow_value_collection'))); + return; + } if (envelope.kind === 'github_api_rate_limit') { rateLimitEnvelopes.push({ envelope, line }); } @@ -1345,6 +1352,21 @@ function createCachedGhAwJsonlAccumulator(options) { observedAt: packet.observedAt, data: { ...packet, repositoryId: parentId, workflowId } }); } + for (const record of valueCollections) { + const [owner, repository] = record.repository.split('/'); + const parentId = repositoryCoordinateId(owner, repository); + const workflowId = workflowCoordinateId(owner, repository, record.sourcePath); + observations.push({ + kind: 'repository', source: OBSERVATION_SOURCE, sourceId: record.repository, observedAt: record.observedAt, + data: { id: parentId, owner, name: repository } + }, { + kind: 'workflow', source: OBSERVATION_SOURCE, sourceId: record.sourcePath, observedAt: record.observedAt, + data: { id: workflowId, repositoryId: parentId, name: record.workflow, path: record.sourcePath, state: 'unknown' } + }, { + kind: 'workflow-value-collection', source: OBSERVATION_SOURCE, sourceId: record.id, observedAt: record.observedAt, + data: { ...record, repositoryId: parentId, workflowId } + }); + } for (const { value, line } of operationalValues) { const repository = requiredString(value.repository, `gh-aw JSONL line ${line}.operational_value.repository`); const coordinates = repositoryCoordinates(repository); diff --git a/dashboard/site/src/data/ingest/coordinator.js b/dashboard/site/src/data/ingest/coordinator.js index 177d99f67..29bcdccd0 100644 --- a/dashboard/site/src/data/ingest/coordinator.js +++ b/dashboard/site/src/data/ingest/coordinator.js @@ -41,7 +41,7 @@ import { AUDIT_CURATION_TRANSACTION_ID, AUDIT_CURATION_VERSION } from '../model/ const debug = createDebug('data:ingestion'); const DASHBOARD_SOURCE_INGESTION_VERSION = 9; -export const GH_AW_JSONL_INGESTION_VERSION = 14; +export const GH_AW_JSONL_INGESTION_VERSION = 15; export const NORMALIZED_JSONL_INGESTION_VERSION = 5; const MIN_NORMALIZED_JSONL_SCHEMA_VERSION = 17; const PRE_EVIDENCE_INGESTION_VERSION = 3; @@ -61,6 +61,7 @@ const NORMALIZED_BATCH_COLLECTIONS = /** @type {const} */ ([ 'issues', 'operationalValues', 'operationalValueEvidence', + 'workflowValueCollections', 'marketplacePackages', 'experiments', 'experimentAssignments', 'graders', 'graderObservations', 'evals', 'evalObservations' ]); @@ -714,7 +715,7 @@ export function ingestNormalizedJsonl(indexedDB, chunks, options) { throw new TypeError(`Normalized activity JSONL line ${lineNumber} must contain a canonical record`); } const excluded = header.phase === 'runs' - ? ['domains', 'tools', 'skills', 'friction', 'audits', 'issues', 'operationalValues', 'operationalValueEvidence', + ? ['domains', 'tools', 'skills', 'friction', 'audits', 'issues', 'operationalValues', 'operationalValueEvidence', 'workflowValueCollections', 'graders', 'graderObservations', 'evals', 'evalObservations'] : header.phase === 'records' ? ['campaigns', 'repositories', 'workflows', 'runs', 'experiments', 'experimentAssignments'] diff --git a/dashboard/site/src/data/ingest/expressions/gh-aw-logs-v2.json b/dashboard/site/src/data/ingest/expressions/gh-aw-logs-v2.json index 0c5be9dc8..fda0719c4 100644 --- a/dashboard/site/src/data/ingest/expressions/gh-aw-logs-v2.json +++ b/dashboard/site/src/data/ingest/expressions/gh-aw-logs-v2.json @@ -4,6 +4,11 @@ "source": "gh-aw-logs", "sourceSchemaVersions": [2, 4, 5], "variants": { + "workflow_value_collection": { + "payloadPath": "workflow_value_collection", + "emits": ["repository", "workflow", "workflow-value-collection"], + "identity": ["id"] + }, "operational_value_evidence": { "payloadPath": "operational_value_evidence", "emits": ["repository", "operational-value-evidence"], diff --git a/dashboard/site/src/data/model/schema.js b/dashboard/site/src/data/model/schema.js index 313cc743e..14e3e1a49 100644 --- a/dashboard/site/src/data/model/schema.js +++ b/dashboard/site/src/data/model/schema.js @@ -2,7 +2,7 @@ import { createDebug } from '../../debug.js'; const debugSchema = createDebug('schema'); -export const CANONICAL_SCHEMA_VERSION = 34; +export const CANONICAL_SCHEMA_VERSION = 35; export const ENTITY_KINDS = /** @type {const} */ ([ 'campaign', @@ -17,6 +17,7 @@ export const ENTITY_KINDS = /** @type {const} */ ([ 'issue', 'operational-value', 'operational-value-evidence', + 'workflow-value-collection', 'marketplace-package', 'experiment', 'experiment-assignment', 'grader', 'grader-observation', 'eval', 'eval-observation' ]); @@ -72,6 +73,7 @@ const RUN_LINKED_COLLECTIONS = /** @type {const} */ ([ * @property {Record[]} issues * @property {Record[]} operationalValues * @property {Record[]} [operationalValueEvidence] + * @property {Record[]} [workflowValueCollections] * @property {Record[]} marketplacePackages * @property {Record[]} [experiments] * @property {Record[]} [experimentAssignments] @@ -229,10 +231,10 @@ export function relationshipErrors(batch) { requireReference(record, 'runId', 'runs'); } } - for (const record of [...batch.operationalValues ?? [], ...batch.operationalValueEvidence ?? []]) { + for (const record of [...batch.operationalValues ?? [], ...batch.operationalValueEvidence ?? [], ...batch.workflowValueCollections ?? []]) { requireReference(record, 'repositoryId', 'repositories'); } - for (const record of batch.operationalValueEvidence ?? []) { + for (const record of [...batch.operationalValueEvidence ?? [], ...batch.workflowValueCollections ?? []]) { requireReference(record, 'workflowId', 'workflows'); if (workflowsById.get(record.workflowId)?.repositoryId !== record.repositoryId) { errors.push(`${String(record.id)}.workflowId references a workflow from another repository`); diff --git a/dashboard/site/src/data/model/workflow-value-collection.js b/dashboard/site/src/data/model/workflow-value-collection.js new file mode 100644 index 000000000..56fe4bb85 --- /dev/null +++ b/dashboard/site/src/data/model/workflow-value-collection.js @@ -0,0 +1,90 @@ +import { repositoryCoordinateId, workflowCoordinateId } from './ids.js'; +import { timestampMilliseconds } from './schema.js'; + +export const VALUE_COLLECTION_REASONS = { + unconfigured: 'No collector is registered for this workflow in the reviewed policy.', + disabled: 'The reviewed registration explicitly disables future collection; retained evidence is unchanged.', + 'activity-disabled': 'Activity collection is disabled in the reviewed policy.', + 'never-captured': 'No accepted capture is present in retained collection history.', + 'api-budget': 'GitHub API capacity is exhausted or reserved for ordinary Activity collection.', + 'budget-unavailable': 'GitHub API capacity could not be verified; retained evidence is unchanged.', + 'shared-budget-unavailable': 'Automatic remote acquisition is deferred until shared API request budgets can be enforced. Activity retains priority.', + 'fast-mode': 'Fast mode retains Value history without acquiring new evidence.', + 'public-only': 'Public-only collection retains Value history without acquiring new evidence.', + timeout: 'The collector exceeded its time budget; previous accepted evidence is retained.', + 'collector-failed': 'The collector failed; previous accepted evidence is retained.', + 'invalid-evidence': 'The collector returned invalid or incomplete evidence; previous accepted evidence is retained.', + 'batch-budget': 'The collection batch exhausted its bounded time or output budget.', + captured: 'Accepted evidence is available at its original capture and cutoff dates.', + 'not-due': 'The frozen cadence is already covered by retained evidence; no new evidence was acquired.' +}; +const STATE_REASONS = { + unconfigured: ['unconfigured'], disabled: ['disabled', 'activity-disabled'], + 'never-captured': ['never-captured'], + deferred: ['api-budget', 'budget-unavailable', 'shared-budget-unavailable', 'fast-mode', 'public-only', 'batch-budget'], + failed: ['timeout', 'collector-failed', 'invalid-evidence', 'batch-budget'], + available: ['captured', 'not-due'] +}; + +/** @param {string} repository @param {string} workflow */ +export function workflowValueCollectionId(repository, workflow) { + return `workflow-value-collection:${encodeURIComponent(`${repository.toLowerCase()}:${workflow}`)}`; +} + +/** Collection facts never supply an outcome measurement or grant authority. + * @param {Record} record */ +export function validateWorkflowValueCollection(record) { + const fail = () => { throw new TypeError('Invalid workflow Value collection record'); }; + if (!record || record.schemaVersion !== 1 + || ['repository', 'workflow', 'observedAt', 'policyDigest'].some(field => typeof record[field] !== 'string') + || !/^[A-Za-z0-9][A-Za-z0-9-]*\/[A-Za-z0-9._-]+$/.test(record.repository) + || !/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(record.workflow) + || record.sourcePath !== `.github/workflows/${record.workflow}.md` + || record.id !== workflowValueCollectionId(record.repository, record.workflow) + || timestampMilliseconds(record.observedAt) === null + || !/^[a-f0-9]{64}$/.test(record.policyDigest) + || !['enabled', 'disabled', 'unconfigured'].includes(record.registration) + || !['unconfigured', 'disabled', 'never-captured', 'deferred', 'failed', 'available'].includes(record.state) + || !Object.hasOwn(VALUE_COLLECTION_REASONS, record.reasonCode) + || record.reason !== VALUE_COLLECTION_REASONS[/** @type {keyof typeof VALUE_COLLECTION_REASONS} */ (record.reasonCode)] + || !STATE_REASONS[/** @type {keyof typeof STATE_REASONS} */ (record.state)]?.includes(record.reasonCode)) fail(); + const fields = new Set(['schemaVersion', 'id', 'repository', 'workflow', 'sourcePath', 'observedAt', + 'registration', 'collector', 'state', 'reasonCode', 'reason', 'policyDigest', 'lastAttemptAt', + 'lastAttemptOutcome', 'repositoryId', 'workflowId', 'provenance']); + if (Object.keys(record).some(field => !fields.has(field))) fail(); + if (record.registration === 'unconfigured') { + if (record.state !== 'unconfigured' || record.collector !== undefined) fail(); + } else if (record.collector !== undefined && (typeof record.collector !== 'string' + || !/^[A-Za-z0-9._/-]+\.mjs$/.test(record.collector) + || record.collector.split('/').some((/** @type {string} */ part) => !part || part === '.' || part === '..')) + || record.registration === 'enabled' && record.collector === undefined + || record.registration === 'disabled' && record.state !== 'disabled' + || record.registration === 'enabled' && record.state === 'unconfigured') fail(); + if (record.lastAttemptAt !== undefined || record.lastAttemptOutcome !== undefined) { + if (timestampMilliseconds(record.lastAttemptAt) === null + || Date.parse(record.lastAttemptAt) > Date.parse(record.observedAt) + || !['available', 'failed'].includes(record.lastAttemptOutcome)) fail(); + } + const [owner, repository] = record.repository.split('/'); + if (record.repositoryId !== undefined && record.repositoryId !== repositoryCoordinateId(owner, repository) + || record.workflowId !== undefined && record.workflowId !== workflowCoordinateId(owner, repository, record.sourcePath)) fail(); + return record; +} + +/** Replace a complete decision without rolling back its independent attempt clock. + * @param {Record | undefined} previous @param {Record} incoming */ +export function mergeWorkflowValueCollection(previous, incoming) { + validateWorkflowValueCollection(incoming); + if (!previous) return incoming; + const before = Date.parse(previous.observedAt), after = Date.parse(incoming.observedAt); + if (before > after) return previous; + const fields = ['registration', 'collector', 'state', 'reasonCode', 'policyDigest', 'lastAttemptAt', 'lastAttemptOutcome']; + if (before === after && fields.some(field => previous[field] !== incoming[field])) { + throw new TypeError('Conflicting workflow Value collection decisions at the same time'); + } + if (previous.lastAttemptAt && (!incoming.lastAttemptAt + || Date.parse(incoming.lastAttemptAt) < Date.parse(previous.lastAttemptAt))) { + throw new TypeError('Workflow Value collection attempt history regressed'); + } + return incoming; +} diff --git a/dashboard/site/src/data/normalize/index.js b/dashboard/site/src/data/normalize/index.js index 301702c31..b0d20e7a3 100644 --- a/dashboard/site/src/data/normalize/index.js +++ b/dashboard/site/src/data/normalize/index.js @@ -4,6 +4,7 @@ import { mergeCanonicalRun, pruneCanonicalRecord } from '../model/fields.js'; import { createDebug } from '../../debug.js'; import { curateBatchAudits } from '../model/audit-curation.js'; import { mergeOperationalValueEvidence } from '../model/operational-value-evidence.js'; +import { mergeWorkflowValueCollection } from '../model/workflow-value-collection.js'; import { compactRoutingRuns } from './model-routing.js'; const debugNormalize = createDebug('normalize:index'); @@ -22,6 +23,7 @@ const COLLECTIONS = { issue: 'issues', 'operational-value': 'operationalValues', 'operational-value-evidence': 'operationalValueEvidence', + 'workflow-value-collection': 'workflowValueCollections', 'marketplace-package': 'marketplacePackages', experiment: 'experiments', 'experiment-assignment': 'experimentAssignments', grader: 'graders', 'grader-observation': 'graderObservations', @@ -177,6 +179,7 @@ export function normalize(observations, options = {}) { issues: new Map(), operationalValues: new Map(), operationalValueEvidence: new Map(), + workflowValueCollections: new Map(), marketplacePackages: new Map(), experiments: new Map(), experimentAssignments: new Map(), graders: new Map(), graderObservations: new Map(), evals: new Map(), evalObservations: new Map() @@ -202,7 +205,9 @@ export function normalize(observations, options = {}) { : {}; const incoming = withoutUndefined(pruneCanonicalRecord(collection, observation.data)); const evidenceRecord = collection === 'operationalValueEvidence' - ? mergeOperationalValueEvidence(entities[collection].get(id), incoming) : null; + ? mergeOperationalValueEvidence(entities[collection].get(id), incoming) + : collection === 'workflowValueCollections' + ? mergeWorkflowValueCollection(entities[collection].get(id), incoming) : null; entities[collection].set(id, { ...(collection === 'runs' ? mergeCanonicalRun(current, incoming) : evidenceRecord ?? { ...current, ...incoming }), diff --git a/dashboard/site/src/data/queries/database.js b/dashboard/site/src/data/queries/database.js index 8ea537eba..83b82bd02 100644 --- a/dashboard/site/src/data/queries/database.js +++ b/dashboard/site/src/data/queries/database.js @@ -37,7 +37,7 @@ const databaseQueryIndex = dashboardQueryIndex(databaseQueries); const RUN_RECORD_STORES = new Set(['domains', 'tools', 'skills', 'friction', 'audits', 'issues']); const DIRECT_EVIDENCE_SOURCES = new Set([ 'experiments', 'experiment-assignments', 'graders', - 'grader-observations', 'evals', 'eval-observations' + 'grader-observations', 'evals', 'eval-observations', 'workflow-value-collections' ]); const EXTERNAL_SOURCES = new Set([ ...SERVER_SOURCE_VALUES, 'configuration-policy', 'marketplace-registries' diff --git a/dashboard/site/src/data/queries/database.json b/dashboard/site/src/data/queries/database.json index 97e9b2d1b..a1ced8162 100644 --- a/dashboard/site/src/data/queries/database.json +++ b/dashboard/site/src/data/queries/database.json @@ -51,6 +51,25 @@ { "field": "routingComplexity", "as": "routing-complexity" } ] }, + { + "name": "workflow-value-collections", + "stores": ["workflowValueCollections", "repositories"], + "from": "$workflowValueCollections", + "joins": [{ + "source": "$repositories", "type": "left", + "on": [{ "left": "repositoryId", "right": "id" }], + "fields": [{ "field": "owner", "as": "organization" }, { "field": "name", "as": "repository-name" }] + }], + "select": [ + { "field": "id" }, { "field": "organization" }, { "field": "repository-name", "as": "repository" }, + { "field": "workflow" }, { "field": "sourcePath", "as": "workflow-path" }, + { "field": "registration" }, { "field": "collector" }, { "field": "state", "as": "collection-state" }, + { "field": "reasonCode", "as": "reason-code" }, { "field": "reason" }, + { "field": "observedAt", "as": "checked-at" }, { "field": "policyDigest", "as": "policy-digest" }, + { "field": "lastAttemptAt", "as": "last-attempt-at" }, + { "field": "lastAttemptOutcome", "as": "last-attempt-outcome" } + ] + }, { "name": "operational-value-evidence", "stores": ["operationalValueEvidence"], diff --git a/dashboard/site/src/data/storage/indexeddb.js b/dashboard/site/src/data/storage/indexeddb.js index 8f164e7ad..c36cd8b2c 100644 --- a/dashboard/site/src/data/storage/indexeddb.js +++ b/dashboard/site/src/data/storage/indexeddb.js @@ -18,7 +18,7 @@ import { const debug = createDebug('data:indexeddb'); export const DATABASE_NAME = 'gh-aw-cao-dashboard-data'; -export const DATABASE_VERSION = 44; +export const DATABASE_VERSION = 45; /** @type {Set<(versions: { oldVersion: number, newVersion: number }) => void>} */ const upgradeListeners = new Set(); @@ -52,6 +52,7 @@ export const ENTITY_STORES = /** @type {const} */ ([ 'issues', 'operationalValues', 'operationalValueEvidence', + 'workflowValueCollections', 'marketplacePackages', 'experiments', 'experimentAssignments', 'graders', 'graderObservations', 'evals', 'evalObservations' ]); @@ -135,6 +136,10 @@ export const CANONICAL_DATABASE_SCHEMA = /** @type {Record< keyPath: 'id', indexes: { byRepository: 'repositoryId', byWorkflow: 'workflowId' } }, + workflowValueCollections: { + keyPath: 'id', + indexes: { byRepository: 'repositoryId', byWorkflow: 'workflowId' } + }, marketplacePackages: { keyPath: 'id', indexes: { @@ -796,7 +801,7 @@ async function reconcileCanonicalDatabase(indexedDB, options) { validRunIds.add(id); referencedWorkflowIds.add(workflowId); referencedRepositoryIds.add(repositoryId); - } else if (storeName === 'operationalValueEvidence') { + } else if (storeName === 'operationalValueEvidence' || storeName === 'workflowValueCollections') { const repositoryId = String(record.repositoryId); const workflowId = String(record.workflowId); if (!repositoryIds.has(repositoryId) || workflowRepositories.get(workflowId) !== repositoryId) { diff --git a/dashboard/site/src/data/storage/retention.js b/dashboard/site/src/data/storage/retention.js index 4044ae354..c091496b7 100644 --- a/dashboard/site/src/data/storage/retention.js +++ b/dashboard/site/src/data/storage/retention.js @@ -2,6 +2,7 @@ import { orderRunRecords } from '../normalize/index.js'; import { EVIDENCE_DEFINITION_STORES, mergeEvidenceDefinition } from '../model/schema.js'; import { createDebug } from '../../debug.js'; import { mergeOperationalValueEvidence } from '../model/operational-value-evidence.js'; +import { mergeWorkflowValueCollection } from '../model/workflow-value-collection.js'; const debugRetention = createDebug('retention'); @@ -43,6 +44,7 @@ const STORES = /** @type {const} */ ([ 'issues', 'operationalValues', 'operationalValueEvidence', + 'workflowValueCollections', 'marketplacePackages', 'experiments', 'experimentAssignments', 'graders', 'graderObservations', 'evals', 'evalObservations' ]); @@ -180,6 +182,7 @@ export function capCanonicalBatchSize(batch, maxBytes) { runs: batch.runs.filter((record) => !evictedRuns.has(String(record.id))), operationalValues: batch.operationalValues ?? [], operationalValueEvidence: batch.operationalValueEvidence ?? [], + workflowValueCollections: batch.workflowValueCollections ?? [], marketplacePackages: batch.marketplacePackages ?? [], experiments: batch.experiments ?? [], graders: batch.graders ?? [], @@ -279,7 +282,8 @@ function upsertRecords( } } records.set(id, storeName === 'operationalValueEvidence' - ? mergeOperationalValueEvidence(records.get(id), record) : EVIDENCE_DEFINITION_STORES.has(storeName) + ? mergeOperationalValueEvidence(records.get(id), record) : storeName === 'workflowValueCollections' + ? mergeWorkflowValueCollection(records.get(id), record) : EVIDENCE_DEFINITION_STORES.has(storeName) ? mergeEvidenceDefinition(records.get(id), record) : record); } merged[storeName] = records; @@ -343,6 +347,10 @@ function pruneOrphans(merged) { if (!repositories.has(String(record.repositoryId)) || workflows.get(String(record.workflowId))?.repositoryId !== record.repositoryId) merged.operationalValueEvidence.delete(id); } + for (const [id, record] of merged.workflowValueCollections) { + if (!repositories.has(String(record.repositoryId)) + || workflows.get(String(record.workflowId))?.repositoryId !== record.repositoryId) merged.workflowValueCollections.delete(id); + } if (orphanedRunCount > 0) debugRetention({ event: 'orphans-pruned', orphanedRunCount }); } @@ -360,6 +368,7 @@ function collectUnreferencedParents(merged, incoming) { const referencedWorkflows = new Set([ ...[...merged.runs.values()].map((run) => String(run.workflowId)), ...[...merged.operationalValueEvidence.values()].map((packet) => String(packet.workflowId)), + ...[...merged.workflowValueCollections.values()].map((record) => String(record.workflowId)), ...['experiments', 'graders', 'evals'].flatMap((store) => [...merged[store].values()].map((record) => String(record.workflowId))) ]); @@ -370,7 +379,8 @@ function collectUnreferencedParents(merged, incoming) { ...[...merged.workflows.values()].map((workflow) => String(workflow.repositoryId)), ...[...merged.runs.values()].map((run) => String(run.repositoryId)), ...[...merged.operationalValues.values()].map((value) => String(value.repositoryId)), - ...[...merged.operationalValueEvidence.values()].map((value) => String(value.repositoryId)) + ...[...merged.operationalValueEvidence.values()].map((value) => String(value.repositoryId)), + ...[...merged.workflowValueCollections.values()].map((value) => String(value.repositoryId)) ]); for (const [id] of merged.repositories) { if (!incomingRepositories.has(id) && !referencedRepositories.has(id)) merged.repositories.delete(id); diff --git a/dashboard/site/src/data/storage/shards.js b/dashboard/site/src/data/storage/shards.js index b0ee5bbed..fcb06fd94 100644 --- a/dashboard/site/src/data/storage/shards.js +++ b/dashboard/site/src/data/storage/shards.js @@ -1,6 +1,7 @@ import { EVIDENCE_DEFINITION_STORES, mergeEvidenceDefinition } from '../model/schema.js'; import { mergeCanonicalRun } from '../model/fields.js'; import { mergeOperationalValueEvidence } from '../model/operational-value-evidence.js'; +import { mergeWorkflowValueCollection } from '../model/workflow-value-collection.js'; import { auditCurationRunFacts, discardAudit, AUDIT_CURATION_TRANSACTION_ID, AUDIT_CURATION_VERSION } from '../model/audit-curation.js'; @@ -94,6 +95,10 @@ export async function writeAccountedRecords(transaction, storeName, records, rem ? withStorageMetadata(storeName, mergeOperationalValueEvidence( withoutStorageMetadata(previous), withoutStorageMetadata(record) )) + : previous && storeName === 'workflowValueCollections' + ? withStorageMetadata(storeName, mergeWorkflowValueCollection( + withoutStorageMetadata(previous), withoutStorageMetadata(record) + )) : record); } const incoming = [...unique.values()]; @@ -135,6 +140,10 @@ export async function writeAccountedRecords(transaction, storeName, records, rem record = withStorageMetadata(storeName, mergeOperationalValueEvidence( existing ? withoutStorageMetadata(existing) : undefined, withoutStorageMetadata(record) )); + } else if (storeName === 'workflowValueCollections') { + record = withStorageMetadata(storeName, mergeWorkflowValueCollection( + existing ? withoutStorageMetadata(existing) : undefined, withoutStorageMetadata(record) + )); } else if (EVIDENCE_DEFINITION_STORES.has(storeName)) { record = withStorageMetadata(storeName, mergeEvidenceDefinition( existing ? withoutStorageMetadata(existing) : undefined, withoutStorageMetadata(record) diff --git a/dashboard/site/src/specification.js b/dashboard/site/src/specification.js index c8f4aa305..eedff236c 100644 --- a/dashboard/site/src/specification.js +++ b/dashboard/site/src/specification.js @@ -415,6 +415,7 @@ export const TABLE_VALUES = [ 'findings', 'operational-values', 'operational-value-evidence', + 'workflow-value-collections', 'github-api-rate-limits', 'github-api-collector-health', 'github-api-call-stacks', @@ -516,6 +517,10 @@ export const TABLE_FIELDS = { 'safe-output-performance': ['organization', 'repository', 'workflow', 'run', 'run-conclusion', 'rollout-mode', 'safe-output-kind', 'safe-output-label', 'safe-output-status', 'safe-output-count', 'observed-at', 'run-link'], findings: ['organization', 'repository', 'workflow', 'run', 'safe-output', 'code', 'finding-kind', 'finding-severity', 'finding-status', 'finding-summary', 'observed-at', 'engine', 'engine-version', 'requested-model', 'resolved-model', 'issue-link', 'pull-request-link', 'run-link', 'external-link', 'organization-link', 'repository-link', 'workflow-link'], 'operational-values': ['id', 'organization', 'repository', 'repository-name', 'workflow', 'campaign', 'campaign-name', 'campaign-icon', 'evaluator-digest', 'cadence-days', 'window-start', 'window-end', 'measurement-kind', 'coverage-status', 'missing-reason', 'eligible-count', 'population-digest', 'evidence-digest', 'operational-value', 'operational-value-definition', 'operational-value-role', 'operational-value-name', 'operational-value-unit', 'operational-value-direction', 'rollup-numerator', 'rollup-denominator', 'maturity-status', 'adoption-at', 'evaluation-mode', 'workflow-slug', 'workflow-name', 'observed-at', 'organization-link', 'repository-link', 'campaign-link', 'run-link'], + 'workflow-value-collections': [ + 'id', 'organization', 'repository', 'workflow', 'workflow-path', 'registration', 'collector', + 'collection-state', 'reason-code', 'reason', 'checked-at', 'policy-digest', 'last-attempt-at', 'last-attempt-outcome' + ], 'operational-value-evidence': [ 'report-id', 'organization', 'repository', 'workflow', 'workflow-path', 'observed-at', 'window-start', 'window-end', 'contract-digest', 'fact-kind', 'fact-id', 'parent-id', 'related-id', 'label', 'title', 'url', 'at', 'accepted-at', 'end-at', diff --git a/dashboard/site/test/e2e/canonical-data.spec.js b/dashboard/site/test/e2e/canonical-data.spec.js index 133c7dc49..bd2503f6c 100644 --- a/dashboard/site/test/e2e/canonical-data.spec.js +++ b/dashboard/site/test/e2e/canonical-data.spec.js @@ -23,7 +23,8 @@ const currentFixtureDates = (value) => JSON.parse(JSON.stringify(value).replace( const canonicalEntityTables = [ 'audits', 'campaigns', 'domains', 'evalObservations', 'evals', 'experimentAssignments', 'experiments', 'friction', 'graderObservations', 'graders', 'issues', 'marketplacePackages', - 'operationalValueEvidence', 'operationalValues', 'repositories', 'runs', 'skills', 'tools', 'workflows' + 'operationalValueEvidence', 'operationalValues', 'repositories', 'runs', 'skills', 'tools', + 'workflowValueCollections', 'workflows' ]; function ghAwLogInput() { diff --git a/dashboard/site/test/e2e/workflow-value.spec.js b/dashboard/site/test/e2e/workflow-value.spec.js index a8fd8292c..105428011 100644 --- a/dashboard/site/test/e2e/workflow-value.spec.js +++ b/dashboard/site/test/e2e/workflow-value.spec.js @@ -11,8 +11,8 @@ import ledgerFixture from '../fixtures/operational-value-ledger.json' with { typ registerSmokeRoutes(); -/** @param {typeof ledgerFixture} ledger */ -function publishedShards(ledger) { +/** @param {typeof ledgerFixture} ledger @param {{includeEvidence?: boolean, defer?: string | null, previousHealth?: string}} [options] */ +function publishedShards(ledger, { includeEvidence = true, defer = 'shared-budget-unavailable', previousHealth = '' } = {}) { const root = resolve('../..'); mkdirSync(join(root, '.tmp'), { recursive: true }); const directory = mkdtempSync(join(root, '.tmp', 'workflow-value-browser-')); @@ -23,7 +23,23 @@ function publishedShards(ledger) { execFileSync(process.execPath, [ '.github/skills/add-operational-value/scripts/render-pulse.mjs', input, output ], { cwd: root, stdio: 'pipe' }); - const original = readFileSync(join(directory, 'pulse-evidence.jsonl'), 'utf8'); + const policy = join(directory, 'cao.json'); + writeFileSync(policy, JSON.stringify({ version: 1, 'gh-aw-version': 'v0.93.1', 'control-plane': { + scope: { 'allowed-repositories': ['octo/example'] }, activity: { repositories: ['octo/example'] }, + campaigns: { activity: { 'workflow-values': [ + { repository: 'octo/example', workflow: 'verify-bugs', collector: 'collectors/not-imported.mjs' }, + { repository: 'octo/example', workflow: 'disabled-worker', enabled: false } + ] } }, + } })); + const health = join(directory, 'collection.jsonl'); + if (previousHealth) writeFileSync(health, previousHealth); + execFileSync(process.execPath, [ + 'activity/workflow-values.mjs', '--root', directory, '--policy', policy, + '--repository', 'octo/example', '--output', join(directory, 'values.jsonl'), + '--healthOutput', health, '--workspace', join(directory, 'proofs'), + ...(defer ? ['--defer', defer] : []) + ], { cwd: root, stdio: 'pipe' }); + const original = readFileSync(health, 'utf8') + (includeEvidence ? readFileSync(join(directory, 'pulse-evidence.jsonl'), 'utf8') : ''); const batch = normalize(adaptCachedGhAwJsonl(original).observations); const records = Object.entries(batch).flatMap(([collection, rows]) => Array.isArray(rows) ? rows.map(record => ({ kind: 'record', collection, record })) : []); @@ -36,7 +52,7 @@ function publishedShards(ledger) { const selected = records.filter(({ collection }) => runs.has(collection) === (phase === 'runs')); const content = [ { kind: 'metadata', schemaVersion: CANONICAL_SCHEMA_VERSION, ingestionVersion: NORMALIZED_JSONL_INGESTION_VERSION, - sourceRecords: 1, phase, records: selected.length }, + sourceRecords: original.trim().split('\n').length, phase, records: selected.length }, ...selected ].map(record => JSON.stringify(record)).join('\n') + '\n'; const hash = createHash('sha256').update(content).digest('hex'); @@ -44,7 +60,7 @@ function publishedShards(ledger) { manifest[name] = hash; contents[`/${name}`] = content; } - return { manifest, contents }; + return { manifest, contents, health: readFileSync(health, 'utf8') }; } finally { rmSync(directory, { recursive: true, force: true }); } @@ -53,7 +69,7 @@ function publishedShards(ledger) { for (const width of [1440, 390]) { test(`workflow Value card opens native evidence and exact items at ${width}px`, async ({ page, context }) => { await page.setViewportSize({ width, height: 900 }); - let publication = publishedShards(structuredClone(ledgerFixture)); + let publication = publishedShards(structuredClone(ledgerFixture), { includeEvidence: false, defer: 'api-budget' }); const inventory = { repositories: { rows: [{ organization: 'octo', repository: 'example' }], metadata: { 'as-of': ledgerFixture.observedAt } }, workflows: { rows: [{ organization: 'octo', repository: 'example', workflow: ledgerFixture.sourcePath, @@ -112,6 +128,20 @@ for (const width of [1440, 390]) { await expect(page.getByRole('heading', { level: 1, name: 'Value', exact: true })).toBeVisible(); await expect(page.getByRole('link', { name: 'Repository measurements', exact: true })).toHaveCount(0); await expect(page.locator('a[href^="#page-operational-value"]')).toHaveCount(0); + await expect(page.getByText('GitHub API capacity is exhausted or reserved for ordinary Activity collection.', { exact: true })).toBeVisible(); + await expect(page.getByText('No retained capture', { exact: true }).first()).toBeVisible(); + await expect(page.getByText('disabled', { exact: true }).first()).toBeVisible(); + await expect(page.getByRole('link', { name: '↓ -1 defects', exact: true })).toHaveCount(0); + publication = publishedShards(structuredClone(ledgerFixture), { defer: null, previousHealth: publication.health }); + await page.evaluate(async ({ dashboard }) => { + const { loadCanonicalDashboardSources } = await import(`${location.origin}/src/data-processor.js`); + await loadCanonicalDashboardSources(`${location.origin}/payload-hashes.json`, [], { + pages: dashboard.dashboard.pages, queries: dashboard.dashboard.queries, views: dashboard.dashboard.views + }); + }, { dashboard: authoritativeDashboard }); + await expect(page.getByText('Retained evidence available', { exact: true })).toBeVisible(); + await expect(page.getByText('The collector failed; previous accepted evidence is retained.', { exact: true })).toBeVisible(); + await expect(page.getByText('failed', { exact: true }).first()).toBeVisible(); await page.getByRole('link', { name: '↓ -1 defects', exact: true }).click(); await expect(page.locator('.value-report-heading')).toContainText('Resolve confirmed defects.'); await expect(page.locator('.value-report-movement')).toHaveText('↓ -1 defects · Better'); @@ -135,7 +165,7 @@ for (const width of [1440, 390]) { items: [{ label: 'Defect 3', url: 'https://github.com/octo/example/issues/3' }, { label: 'Defect 4', url: 'https://github.com/octo/example/issues/4' }] }); - publication = publishedShards(newer); + publication = publishedShards(newer, { previousHealth: publication.health }); await page.evaluate(async ({ dashboard }) => { const { loadCanonicalDashboardSources } = await import(`${location.origin}/src/data-processor.js`); await loadCanonicalDashboardSources(`${location.origin}/payload-hashes.json`, [], { diff --git a/dashboard/site/test/fixtures/workflow-value-collection.jsonl b/dashboard/site/test/fixtures/workflow-value-collection.jsonl new file mode 100644 index 000000000..0746b80a6 --- /dev/null +++ b/dashboard/site/test/fixtures/workflow-value-collection.jsonl @@ -0,0 +1 @@ +{"schema_version":2,"kind":"workflow_value_collection","workflow_value_collection":{"schemaVersion":1,"id":"workflow-value-collection:octo%2Fexample%3Averify-bugs","repository":"octo/example","workflow":"verify-bugs","sourcePath":".github/workflows/verify-bugs.md","observedAt":"2026-10-23T14:00:00.000Z","registration":"enabled","collector":".github/value-collectors/verify-bugs.mjs","state":"deferred","reasonCode":"api-budget","reason":"GitHub API capacity is exhausted or reserved for ordinary Activity collection.","policyDigest":"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb","lastAttemptAt":"2026-10-22T12:00:00.000Z","lastAttemptOutcome":"failed"}} diff --git a/dashboard/site/test/fixtures/workflow-value-view-contract.json b/dashboard/site/test/fixtures/workflow-value-view-contract.json index 3908dbb54..d3de73ea9 100644 --- a/dashboard/site/test/fixtures/workflow-value-view-contract.json +++ b/dashboard/site/test/fixtures/workflow-value-view-contract.json @@ -3,6 +3,10 @@ "view": "workflow-value-cards", "query": "value-workflow-results", "card": "workflow-value-result", + "collectionView": "workflow-value-collection-health", + "collectionQuery": "value-collection-health", + "collectionCard": "workflow-value-collection", + "collectionSource": "workflow-value-collections", "reportPage": "value-report", "reportElement": "workflow-value-report", "snapshotPage": "value-snapshot", diff --git a/dashboard/site/test/unit/data-indexeddb.test.js b/dashboard/site/test/unit/data-indexeddb.test.js index f8e51a081..f6f1dc598 100644 --- a/dashboard/site/test/unit/data-indexeddb.test.js +++ b/dashboard/site/test/unit/data-indexeddb.test.js @@ -278,6 +278,7 @@ describe('canonical IndexedDB', () => { 'storageShards', 'tools', 'transactions', + 'workflowValueCollections', 'workflows' ]); expect(database.transaction('repositories').objectStore('repositories').keyPath).toBe('id'); @@ -431,6 +432,7 @@ describe('canonical IndexedDB', () => { 'storageShards', 'tools', 'transactions', + 'workflowValueCollections', 'workflows' ]); expect(await readCollection(indexedDB, 'repositories')).toEqual([]); @@ -498,6 +500,7 @@ describe('canonical IndexedDB', () => { 'storageShards', 'tools', 'transactions', + 'workflowValueCollections', 'workflows' ]); expect([...database.objectStoreNames]).not.toContain('packages'); diff --git a/dashboard/site/test/unit/workflow-value-collection.test.js b/dashboard/site/test/unit/workflow-value-collection.test.js new file mode 100644 index 000000000..1cd901625 --- /dev/null +++ b/dashboard/site/test/unit/workflow-value-collection.test.js @@ -0,0 +1,52 @@ +// @vitest-environment node +import { readFileSync } from 'node:fs'; +import { IDBFactory } from 'fake-indexeddb'; +import { describe, expect, it } from 'vitest'; +import { adaptCachedGhAwJsonl } from '../../src/data/adapters/gh-aw-logs.js'; +import { ingestCachedGhAwJsonl } from '../../src/data/ingest/coordinator.js'; +import { validateWorkflowValueCollection } from '../../src/data/model/workflow-value-collection.js'; +import { maintainCanonicalDatabase, readCollection } from '../../src/data/storage/indexeddb.js'; + +const source = readFileSync(new URL('../fixtures/workflow-value-collection.jsonl', import.meta.url), 'utf8'); +const fixture = JSON.parse(source); + +describe('canonical workflow Value collection facts', () => { + it('fails closed on contradictory states, clocks, identities and measurements disguised as health', () => { + const record = fixture.workflow_value_collection; + expect(validateWorkflowValueCollection(record)).toEqual(record); + for (const changes of [ + { registration: 'disabled' }, { state: 'available' }, { reason: 'invented' }, + { lastAttemptAt: '2026-10-24T12:00:00Z' }, { lastAttemptOutcome: 'deferred' }, + { id: 'wrong' }, { collector: '../escape.mjs' }, { value: 0 }, { capturedAt: record.observedAt }, + { workflowId: 'workflow:other' }, { schemaVersion: '1' } + ]) expect(() => validateWorkflowValueCollection({ ...record, ...changes })).toThrow(); + expect(adaptCachedGhAwJsonl(source).observations.map(item => item.kind)) + .toEqual(['repository', 'workflow', 'workflow-value-collection']); + }); + + it('preserves independent attempt clocks, rejects conflicting decisions, and retains structural parents without runs', async () => { + const database = new IDBFactory(); + const now = Date.parse('2026-10-25T00:00:00Z'); + await ingestCachedGhAwJsonl(database, source, { now, payloadScope: 'health' }); + const older = structuredClone(fixture); + older.workflow_value_collection.observedAt = '2026-10-22T13:00:00Z'; + await ingestCachedGhAwJsonl(database, JSON.stringify(older), { now, payloadScope: 'older' }); + const [retained] = await readCollection(database, 'workflowValueCollections'); + expect(retained.observedAt).toBe(fixture.workflow_value_collection.observedAt); + const conflicting = structuredClone(fixture); + conflicting.workflow_value_collection.policyDigest = 'c'.repeat(64); + await expect(ingestCachedGhAwJsonl(database, JSON.stringify(conflicting), { now, payloadScope: 'conflict' })).rejects.toThrow(); + const regressed = structuredClone(fixture); + regressed.workflow_value_collection.observedAt = '2026-10-24T00:00:00Z'; + delete regressed.workflow_value_collection.lastAttemptAt; + delete regressed.workflow_value_collection.lastAttemptOutcome; + await expect(ingestCachedGhAwJsonl(database, JSON.stringify(regressed), { now, payloadScope: 'regression' })).rejects.toThrow(); + await maintainCanonicalDatabase(database, { + now: now + 365 * 86400000, retentionWindowMs: 86400000, maxDatabaseBytes: Number.MAX_SAFE_INTEGER, + }); + expect(await readCollection(database, 'workflowValueCollections')).toHaveLength(1); + expect(await readCollection(database, 'repositories')).toHaveLength(1); + expect(await readCollection(database, 'workflows')).toHaveLength(1); + expect(await readCollection(database, 'runs')).toEqual([]); + }); +}); diff --git a/dashboard/site/test/unit/workflow-value-view-contract.test.js b/dashboard/site/test/unit/workflow-value-view-contract.test.js index 83d6a24fa..5a37cdbc1 100644 --- a/dashboard/site/test/unit/workflow-value-view-contract.test.js +++ b/dashboard/site/test/unit/workflow-value-view-contract.test.js @@ -81,7 +81,8 @@ describe('native workflow value production contract', () => { it('declares a shared card, native report, complete source contract and exact-item route', () => { const value = dashboard.pages.find((/** @type {{ id: string }} */ page) => page.id === 'value'); expect(value).toMatchObject({ title: 'Value', icon: 'trophy' }); - expect(value.views[0]).toMatchObject({ data: { source: contract.query }, list: { card: contract.card } }); + expect(value.views[0]).toMatchObject({ data: { source: 'value-registered-collections' }, list: { card: contract.collectionCard } }); + expect(value.views[1]).toMatchObject({ data: { source: contract.query }, list: { card: contract.card } }); expect(dashboard.navigation.flatMap((/** @type {{ pages: string[] }} */ group) => group.pages)).toContain('value'); expect(value.route?.tabs).toBeUndefined(); expect(value.views[0]['empty-message']).not.toContain('Repository measurements'); @@ -95,6 +96,10 @@ describe('native workflow value production contract', () => { query.name.startsWith('operational-value-'))).toBe(false); const page = dashboard.pages.find((/** @type {{ id: string }} */ page) => page.id === contract.page); expect(page.views[0]).toMatchObject({ + id: contract.collectionView, data: { source: contract.collectionQuery, arguments: [{ name: 'workflow', field: 'workflow-route' }] }, + mark: 'list', list: { card: contract.collectionCard } + }); + expect(page.views[1]).toMatchObject({ id: contract.view, data: { source: contract.query, 'route-field': 'workflow-route' }, mark: 'list', list: { card: contract.card, drill: { page: contract.reportPage } } }); @@ -110,7 +115,7 @@ describe('native workflow value production contract', () => { it('resolves lower-is-better movement, all report evidence and exact snapshot items from emitted canonical facts', async () => { const packet = await publish(fileLedger()); - const [cards] = await execute(contract.page, { workflow: contract.route }); + const [, cards] = await execute(contract.page, { workflow: contract.route }); expect(cards.rows).toHaveLength(1); expect(cards.rows[0]).toMatchObject({ 'change-label': contract.headline, movement: 'Worse', 'reference-value': 16, 'current-value': 54, @@ -129,12 +134,12 @@ describe('native workflow value production contract', () => { expect(snapshotSources[0].rows).toHaveLength(1); expect(snapshotSources[1].rows).toHaveLength(54); expect(snapshotSources[1].rows[0].url).toMatch(/^https:\/\/github.com\/octo\/example\/blob\/abc123\/pkg\/file-\d+.go$/); - expect((await execute(contract.page, { workflow: 'octo/other:.github/workflows/verify-bugs.md' }))[0].rows).toEqual([]); + expect((await execute(contract.page, { workflow: 'octo/other:.github/workflows/verify-bugs.md' }))[1].rows).toEqual([]); }); it('interprets the same native movement using the frozen desired direction', async () => { await publish(fileLedger('increase')); - expect((await execute(contract.page, { workflow: contract.route }))[0].rows[0]).toMatchObject({ + expect((await execute(contract.page, { workflow: contract.route }))[1].rows[0]).toMatchObject({ 'change-label': '↑ +38 files · Better', movement: 'Better', 'direction-label': '↑ Higher is better' }); }); @@ -158,7 +163,7 @@ describe('native workflow value production contract', () => { ledger.events[0].observedAt = '2026-09-02T00:00:00Z'; ledger.events[0].lineage[0].at = '2026-08-31T00:00:00Z'; await publish(ledger); - expect((await execute(contract.page, { workflow: contract.route }))[0].rows[0]).toMatchObject({ + expect((await execute(contract.page, { workflow: contract.route }))[1].rows[0]).toMatchObject({ 'complete-report': true, 'recent-result': 0, 'previous-result': 1 }); }); @@ -167,20 +172,20 @@ describe('native workflow value production contract', () => { const ledger = structuredClone(ledgerFixture); ledger.repositoryState.observations.splice(0, 1); await publish(ledger); - expect((await execute(contract.page, { workflow: contract.route }))[0].rows[0]).toMatchObject({ + expect((await execute(contract.page, { workflow: contract.route }))[1].rows[0]).toMatchObject({ 'current-value': 0, 'native-change': null, movement: 'Comparison unavailable' }); ledger.repositoryState.observations.unshift({ ...ledger.repositoryState.observations[0], at: '2026-10-01T00:00:00Z' }); ledger.observedAt = '2026-10-20T12:01:00Z'; await publish(ledger); - expect((await execute(contract.page, { workflow: contract.route }))[0].rows[0]).toMatchObject({ + expect((await execute(contract.page, { workflow: contract.route }))[1].rows[0]).toMatchObject({ 'native-change': 0, movement: 'Unchanged', 'change-label': 'Unchanged' }); }); it('keeps absent output, snapshot and quality evidence unknown', async () => { await publish({ ...structuredClone(ledgerFixture), outputs: undefined, repositoryState: undefined, checks: undefined }); - const [cards] = await execute(contract.page, { workflow: contract.route }); + const [, cards] = await execute(contract.page, { workflow: contract.route }); expect(cards.rows[0]).toMatchObject({ 'output-count': null, 'receipt-outputs': null, 'current-value': null, 'native-change': null, movement: 'Comparison unavailable', 'direction-label': 'Direction not retained', @@ -194,7 +199,7 @@ describe('native workflow value production contract', () => { ledger.outputs.items = []; ledger.coverage[0].status = 'complete'; await publish(ledger); - const [cards] = await execute(contract.page, { workflow: contract.route }); + const [, cards] = await execute(contract.page, { workflow: contract.route }); expect(cards.rows[0]).toMatchObject({ 'output-count': 0, 'receipt-outputs': 0, 'accepted-implementations': 0, 'native-result': 0, 'complete-report': true, 'recent-result': 0, 'previous-result': 0 @@ -208,9 +213,45 @@ describe('native workflow value production contract', () => { newer.metric.version = 'v2'; newer.repositoryState.observations.splice(0, 1); await publish(newer); - const [cards] = await execute(contract.page, { workflow: contract.route }); + const [, cards] = await execute(contract.page, { workflow: contract.route }); expect(cards.rows).toHaveLength(1); expect(cards.rows[0]).toMatchObject({ 'metric-version': 'v2', movement: 'Comparison unavailable' }); expect((await execute(contract.reportPage, { report: older.id }))[0].rows[0]['change-label']).toBe(contract.headline); }); + + it('publishes real registration decisions through the producer, canonical storage and worker before any packet exists', async () => { + const policy = join(directory, 'cao.json'); + writeFileSync(policy, JSON.stringify({ version: 1, 'gh-aw-version': 'v0.93.1', 'control-plane': { + scope: { 'allowed-repositories': ['octo/example'] }, activity: { repositories: ['octo/example'] }, + campaigns: { activity: { 'workflow-values': [{ + repository: 'octo/example', workflow: 'verify-bugs', collector: 'absent-by-design.mjs' + }] } } + } })); + const healthOutput = join(directory, 'health.jsonl'); + execFileSync(process.execPath, ['activity/workflow-values.mjs', + '--root', directory, '--policy', policy, '--database', join(directory, 'unused.sqlite'), + '--output', join(directory, 'packets.jsonl'), '--workspace', join(directory, 'proof'), + '--repository', 'octo/example', '--healthOutput', healthOutput, '--defer', 'api-budget' + ], { cwd: repository, stdio: 'pipe' }); + const checkedAt = JSON.parse(readFileSync(healthOutput, 'utf8')).workflow_value_collection.observedAt; + await ingestCachedGhAwJsonl(indexedDB, readFileSync(healthOutput, 'utf8'), { + payloadScope: 'first-health', now: Date.parse(checkedAt) + }); + const [health, reports] = await execute(contract.page, { workflow: contract.route }); + expect(health.rows).toHaveLength(1); + expect(health.rows[0]).toMatchObject({ + registration: 'enabled', 'collection-state': 'deferred', 'reason-code': 'api-budget', + 'checked-at': checkedAt, 'captured-at': null, 'evidence-cutoff': null, 'evidence-state': 'No retained capture' + }); + expect(health.rows[0]['last-attempt-at']).toBeUndefined(); + expect(reports.rows).toEqual([]); + expect((await execute('value', {}))[0].rows).toEqual(health.rows); + const packet = await publish(); + const [retained] = await execute(contract.page, { workflow: contract.route }); + expect(retained.rows[0]).toMatchObject({ + 'collection-state': 'deferred', 'captured-at': packet.observedAt, + 'evidence-cutoff': packet.windowEnd, 'evidence-state': 'Retained evidence available' + }); + expect((await execute(contract.page, { workflow: 'octo/other:.github/workflows/verify-bugs.md' }))[0].rows).toEqual([]); + }); }); diff --git a/dependabot/operational-value.mjs b/dependabot/operational-value.mjs index 3818cfdda..5ea60793c 100644 --- a/dependabot/operational-value.mjs +++ b/dependabot/operational-value.mjs @@ -27,6 +27,7 @@ try { } if ( request?.schemaVersion !== 1 + || (request.localOnly !== undefined && typeof request.localOnly !== "boolean") || typeof request.timestamp !== "string" || Number.isNaN(Date.parse(request.timestamp)) || !Array.isArray(request.repositories) @@ -93,11 +94,13 @@ for (const moduleFile of moduleFiles) { valueIds: definition.metrics.map((metric) => `${definition.slug}.${metric.id}`), ...(valueModule.historyBatch === true ? { historyBatch: true } : {}), })); + if (request.localOnly && request.disabledWorkflows?.includes(definition.slug)) continue; const supported = new Set( definition.evidence.repositories.map((repository) => String(repository).toLowerCase()), ); - const repositories = request.repositories.filter((repository) => supported.has(repository.toLowerCase())); + const repositories = request.repositories.filter((repository) => supported.has(repository.toLowerCase()) + && !(request.localOnly && request.disabledCollections?.includes(`${repository.toLowerCase()}:${definition.slug}`))); if (repositories.length === 0) continue; const { durationDays, maturationDays } = definition.evidence.window; @@ -176,10 +179,16 @@ for (const moduleFile of moduleFiles) { } } + if (request.localOnly && valueModule.localCollection !== true) { + console.log(JSON.stringify({ kind: "operational_value_deferred", workflowSlug: definition.slug, + reason: "Remote acquisition requires enforceable shared API admission; retained evidence is unchanged." })); + continue; + } let collections; try { collections = await collectBatch(windows, { database: request.database, + ...(request.localOnly ? { localOnly: true } : {}), ...(history ? { history: true } : {}), }); } catch (error) { diff --git a/docs/cao-cli.md b/docs/cao-cli.md index 359569abe..60eb92302 100644 --- a/docs/cao-cli.md +++ b/docs/cao-cli.md @@ -497,7 +497,8 @@ static Pages have no direct-publication endpoint; Pages uses Activity transport. **Collection is wired automatically by the skill** once its frozen function and repository-local recurring collector pass verification. It stages the exact pair with `value enable ... --if-absent`, preserving existing registrations and -explicit disables. Review, commit and deploy those files to start collection. +explicit disables. Review, commit and deploy those files to publish the reviewed +registration; registration does not bypass collection admission. For manual registration or an intentional re-enable, replace `COLLECTOR_PATH.mjs` with that collector's actual path; an evidence file or renderer is not a collector: @@ -510,9 +511,10 @@ gh cao value disable github/gh-aw daily-file-diet These commands edit local `.github/workflows/cao.json`; review, commit and deploy that policy and collector together. They do not enable the measured workflow, enroll repositories, upload executable code or immediately start a collection. -The existing Activity/hosted collection cycle refreshes only registered, -in-scope pairs when their frozen cadence is due. No new schedule or model call -is needed. A failed refresh retains the last accepted capture without changing +Recurring remote acquisition remains deferred pending enforceable shared API +budgets. Activity publishes the enabled registration and actual deferral reason, +while bounded local-only computations run outside its publication path. +A failed refresh retains the last accepted capture without changing its timestamp or inventing a zero. Disable stops future collection, not history. An explicit disable persists even if the skill is used again. See the [collector contract](operational-value.md#recurring-collection-after-opt-in). diff --git a/docs/dashboard-data-model.md b/docs/dashboard-data-model.md index c4261b11c..2d1367477 100644 --- a/docs/dashboard-data-model.md +++ b/docs/dashboard-data-model.md @@ -55,6 +55,7 @@ the exact identities and parent relationships. | **Issue** | `github:issue:/:` | Run | Records issue and pull-request safe outputs. | | **Operational Value** | Deterministic repository, value ID, and timestamp identity | Repository | Records a campaign-defined numeric repository metric. | | **Operational Value Evidence** | Deterministic repository, workflow, metric, and metric-version identity | Repository and Workflow | Retains a coherent evidence packet connecting intent, safe outputs, accepted implementations, and independent repository snapshots. | +| **Workflow Value Collection** | Deterministic repository and workflow identity | Repository and Workflow | Retains the reviewed registration and latest collection decision separately from actual attempts and accepted capture/cutoff clocks. | Names, paths, timestamps, and ingestion order are not canonical identities. Stable upstream IDs take precedence; deterministic source coordinates are used only when an upstream system provides no stable ID. @@ -122,7 +123,7 @@ The complete normative [cached gh-aw JSONL mapping](https://github.com/githubnex The canonical model is version 34. The browser database is `gh-aw-cao-dashboard-data`, IndexedDB version 44. Its canonical stores are `campaigns`, `repositories`, `workflows`, `runs`, `domains`, `tools`, `skills`, -`friction`, `audits`, `issues`, `operationalValues`, `operationalValueEvidence`, `marketplacePackages`, +`friction`, `audits`, `issues`, `operationalValues`, `operationalValueEvidence`, `workflowValueCollections`, `marketplacePackages`, `experiments`, `experimentAssignments`, `graders`, `graderObservations`, `evals`, and `evalObservations`; all use `id` as the key. diff --git a/docs/operational-value-how-to.md b/docs/operational-value-how-to.md index 338c149da..67ec86976 100644 --- a/docs/operational-value-how-to.md +++ b/docs/operational-value-how-to.md @@ -112,8 +112,11 @@ revisions. Reuse that fixed definition for subsequent evaluations. To keep it current, the skill automatically stages its exact registration after the frozen function and bounded collector pass verification; no separate enable step is needed. -Review, commit and deploy the policy and collector together. The existing collection cycle -refreshes only opted-in, in-scope workflows at their fixed cadence. Failures +Review, commit and deploy the policy and collector together. Activity shows its +real collection health even before a first capture. Recurring remote acquisition +remains deferred until shared API budgets can be enforced; registration alone +does not guarantee fresh measurements. Bounded local-only computations run +separately without holding up ordinary publication. Failures and deferrals keep the last capture; disabling collection keeps history. For a one-time hosted upload, use `gh cao value publish ... --server URL --input REPORT-evidence.jsonl`; uploading alone does not enable collection. diff --git a/docs/operational-value.md b/docs/operational-value.md index 459ab9ada..e2fa02ed6 100644 --- a/docs/operational-value.md +++ b/docs/operational-value.md @@ -12,8 +12,9 @@ For the short intent → output → Git evidence flow, see Research and replay details are in the [blog article](/gh-cao/blog/measuring-agent-work-value/). -Open **Value** in the sidebar (the trophy icon) to see evidence-backed workflow -result cards; a workflow's **Value** tab is also a shortcut to its reports. +Open **Value** in the sidebar (the trophy icon) to see reviewed registrations, +collection health and evidence-backed workflow result cards. A workflow's +**Value** tab shows its collection decision and retained reports. The legacy **Operational Value** page and its **Repository measurements** tab have been removed. Existing native observations remain in the canonical data model; missing measurements are not zero value. @@ -27,7 +28,13 @@ their Git evidence; select a measured dot to inspect the exact counted items. The card and native report share one canonical evidence packet, not a saved HTML page. Opening either does not collect new evidence or silently fill missing measurements. Each workflow still needs a frozen measurement contract and -published evidence; no packet produces an explicit unconfigured state. +published evidence. No packet does not mean unconfigured: an enabled collector +can be deferred before its first capture. Only an authoritative policy check +establishes an unconfigured or disabled state. +Health cards keep the decision time, last actual attempt, successful capture and +evidence cutoff separate. A newer failure or deferral does not make retained +evidence fresh. "No retained capture" describes available history, not every +historical archive. These evidence routes keep their declared cohort and cutoff when the dashboard's global display horizon changes; they are not new evaluations of that horizon. @@ -74,16 +81,32 @@ measurement uses the same fixed rules, never a new model-generated assessment. Keep immutable measurements and receipts in the supplied per-workflow workspace for reuse. Uploaded report packets cannot register or execute collector code. -The existing Activity cycle or hosted collector invokes only due, opted-in -collectors at the frozen cadence. It follows new safe-output lifecycle and -acceptance evidence, measures the independent repository state, and publishes -a validated capture into the same canonical facts consumed by **Value**. -Opening a report does not trigger collection. Fast/recycle-only runs do not -silently request fresh measurements. A failed acquisition, insufficient budget -or invalid packet leaves the previous evidence and capture timestamp intact; -it is not a fresh success or zero. Collection timing is bounded by the existing -cycle and available credentials, not a guarantee of an observation at every -wall-clock instant. +**Recurring remote acquisition remains deferred pending enforceable shared-budget +admission.** Existing subprocess collectors do not participate in shared +per-request REST, search and GraphQL accounting. A separate worker is not +separate API quota, and a remaining-quota probe cannot reserve capacity against +concurrent consumers. Activity therefore publishes the enabled registration +with an explicit deferral reason, retaining accepted packets and immutable proof. +Observed API exhaustion, fast mode and public-only mode retain their actual +reasons; otherwise the reason identifies unavailable shared-budget enforcement. +This is health visibility and core isolation, not guaranteed fresh collection. + +Bounded cache-only/local computation remains available separately. +`CAO Local Value` runs only after successful default-branch Activity publication, +checks the exact snapshot and policy digest, and uses the reviewed local-only +adapter without target credentials. Local-capable modules (currently Optimization) +may query that snapshot; remote modules may only reuse exact versioned observations. +Older/custom adapters defer rather than ignoring local-only mode. The job has a +five-minute ceiling, with two minutes per computation batch and thirty seconds +per adapter; it does not backfill history. Existing fast, public-only and +API-limited gates remain. A later Activity snapshot imports completed results. +The hosted collector uses the same local runtime under a separate lease and +private snapshot, never the core projection lease. + +Opening a report does not trigger collection. A failed acquisition, timeout or +invalid result leaves previous evidence and its capture/cutoff timestamps intact; +it is not a fresh success or zero. Explicit operator evaluation and one-time +publication remain separate, subject to their existing authority and budgets. ### Daily File Diet collector @@ -109,8 +132,9 @@ The control policy explicitly lists the same six repositories previously collected from `scope.allowed-repositories`; this pins Activity enrollment without adding targets or activating Daily File Diet itself. Only the exact File Diet pair is registered for recurring Value acquisition. -Registration takes effect after the collector and policy are reviewed and -deployed together. It does not override `campaigns.dashboard.deploy: false`: +Registration is visible after the collector and policy are reviewed and +deployed together; remote acquisition remains deferred as described above. +It does not override `campaigns.dashboard.deploy: false`: this repository intentionally disables standalone Pages deployment because Documentation Pages owns the combined site. The existing publication chain is CAO Activity, then the CAO Dashboard artifact/cache, then Documentation Pages @@ -124,14 +148,14 @@ administrator OAuth session. CAO uses one shared campaign module for both collection paths: -- By default, scheduled `cao operational-value` collection evaluates only the current repository observation and publishes compact numeric records to the canonical data model. Retention keeps one observation per declared cadence bucket: closed cadence-aligned observations remain fixed, while repeated collections replace the latest observation in the still-open bucket. +- Explicit `cao operational-value` collection evaluates the current repository observation and publishes compact numeric records to the canonical data model. Automatic local-only computation uses the same contract without remote acquisition. Retention keeps one observation per declared cadence bucket: closed cadence-aligned observations remain fixed, while repeated collections replace the latest observation in the still-open bucket. - Explicit historical evaluation incrementally fills missing immutable observations and produces the evidence archive, timeline, chart, and definitions page. Both paths import the same frozen evidence contract, collector, and scoring functions. Default routine collection does not rebuild repository history, and a metric cannot drift between the dashboard record and its historical report. -Accepted operational-value observations are queryable from any local or downloaded canonical SQLite snapshot with `cao query --collection operationalValues`. Querying alone does not publish or reconstruct history. The Activity compute path may explicitly query missing cadence observations for a named campaign while their authoritative source evidence remains in its bounded canonical database; it writes only the resulting numeric observations into the same canonical Activity shard used for current values. No history archive is installed with the campaign. The Dashboard workflow then deploys those canonical records to Pages through the normal Activity snapshot pipeline. +Accepted operational-value observations are queryable from any local or downloaded canonical SQLite snapshot with `cao query --collection operationalValues`. Querying alone does not publish or reconstruct history. An explicit historical evaluation may query missing cadence observations for a named campaign while their authoritative source evidence remains in its bounded canonical database. The automatic local lane does not request that backfill. No history archive is installed with the campaign. Completed numeric records use the ordinary Activity snapshot pipeline; Dashboard artifact production and the configured Pages deployment owner remain unchanged. -The rolling Activity database is a query source for current observations, not the definition of operational-value history. Explicit evaluation schedules observations from adoption and incrementally preserves accepted snapshots. Git and other immutable repository facts can be reconstructed at historical cutoffs. Ephemeral run, usage, artifact, queue, and tool-call facts can be backfilled only while their source remains available; an expired interval without a contemporaneous snapshot is missing, not zero. The current live Activity publication retains 30 days of operational-value records compacted to each metric's declared cadence plus its latest open-bucket observation, while the explicit evidence archive is the durable since-adoption record. +The rolling Activity database is a query source for current observations, not the definition of operational-value history. Explicit evaluation schedules observations from adoption and incrementally preserves accepted snapshots. Git and other immutable repository facts can be reconstructed at historical cutoffs. Ephemeral run, usage, artifact, queue, and tool-call facts can be backfilled only while their source remains available; an expired interval without a contemporaneous snapshot is missing, not zero. Compact operational-value history retains its separate 365-day window, compacted to each metric's declared cadence plus its latest open-bucket observation, while the explicit evidence archive is the durable since-adoption record. ## Standalone design reference diff --git a/internal/dashboardquery/snapshot.go b/internal/dashboardquery/snapshot.go index 8764eeb41..ed05b7188 100644 --- a/internal/dashboardquery/snapshot.go +++ b/internal/dashboardquery/snapshot.go @@ -13,7 +13,7 @@ import ( ) const DatabaseName = "gh-aw-cao-dashboard-data" -const DatabaseVersion = 44 +const DatabaseVersion = 45 // SnapshotReader accepts a database or an already pinned read transaction. type SnapshotReader interface { diff --git a/optimization/operational-value.mjs b/optimization/operational-value.mjs index 3818cfdda..5ea60793c 100644 --- a/optimization/operational-value.mjs +++ b/optimization/operational-value.mjs @@ -27,6 +27,7 @@ try { } if ( request?.schemaVersion !== 1 + || (request.localOnly !== undefined && typeof request.localOnly !== "boolean") || typeof request.timestamp !== "string" || Number.isNaN(Date.parse(request.timestamp)) || !Array.isArray(request.repositories) @@ -93,11 +94,13 @@ for (const moduleFile of moduleFiles) { valueIds: definition.metrics.map((metric) => `${definition.slug}.${metric.id}`), ...(valueModule.historyBatch === true ? { historyBatch: true } : {}), })); + if (request.localOnly && request.disabledWorkflows?.includes(definition.slug)) continue; const supported = new Set( definition.evidence.repositories.map((repository) => String(repository).toLowerCase()), ); - const repositories = request.repositories.filter((repository) => supported.has(repository.toLowerCase())); + const repositories = request.repositories.filter((repository) => supported.has(repository.toLowerCase()) + && !(request.localOnly && request.disabledCollections?.includes(`${repository.toLowerCase()}:${definition.slug}`))); if (repositories.length === 0) continue; const { durationDays, maturationDays } = definition.evidence.window; @@ -176,10 +179,16 @@ for (const moduleFile of moduleFiles) { } } + if (request.localOnly && valueModule.localCollection !== true) { + console.log(JSON.stringify({ kind: "operational_value_deferred", workflowSlug: definition.slug, + reason: "Remote acquisition requires enforceable shared API admission; retained evidence is unchanged." })); + continue; + } let collections; try { collections = await collectBatch(windows, { database: request.database, + ...(request.localOnly ? { localOnly: true } : {}), ...(history ? { history: true } : {}), }); } catch (error) { diff --git a/optimization/operational-value/optimization-token-optimizer.mjs b/optimization/operational-value/optimization-token-optimizer.mjs index ab0892fbb..298a00630 100644 --- a/optimization/operational-value/optimization-token-optimizer.mjs +++ b/optimization/operational-value/optimization-token-optimizer.mjs @@ -22,6 +22,7 @@ const TERMINAL_CONCLUSIONS = [ const FAILURE_CONCLUSIONS = ["failure", "timed_out", "startup_failure"]; export const historyBatch = true; +export const localCollection = true; export const definition = { schemaVersion: 3, @@ -389,6 +390,9 @@ function queryEfficiencyWindows(database, requests) { } export async function collectBatch(requests, context = {}) { + if (context.localOnly && !context.database) { + fail("Local-only Optimization collection requires an existing Activity database"); + } if (context.history && !context.database) { fail("Historical Optimization collection requires a preserved Activity database; remote acquisition is disabled"); } diff --git a/server/README.md b/server/README.md index 31c18c26a..7781bc4f2 100644 --- a/server/README.md +++ b/server/README.md @@ -2855,8 +2855,20 @@ advances the revision. Value-dependent queries key their bounded result cache by that revision; other query caches retain their existing fixed lifetime. This endpoint does not activate ongoing collection: explicitly register a reviewed collector in policy through `gh cao value enable`, then deploy policy -and collector together. Recurring work uses the existing collector's enrolled -repository credentials, not an administrator's browser session. +and collector together. Recurring remote acquisition remains deferred pending +enforceable shared-budget admission. Health publication is credential-free and +keeps enabled registrations visibly deferred, with original capture/cutoff dates. +It does not mint a token or treat a quota preflight as a shared reservation. + +Bounded local-only computation has its own `value-local` lease, a verified private +Activity snapshot and one attempt per completed projection generation. It does +not hold the projection lease or evidence lock while computing. The two-minute +batch/30-second adapter budgets cancel the owned process tree; final publication +uses a short evidence lock and rechecks enrollment. Completed output waits for +the next ordinary projection, avoiding a Value-generated retry loop. An +unsupported adapter, missing input, timeout or failure preserves accepted history. +This improves health visibility and core isolation, not guaranteed fresh Value +collection or separate capacity for external consumers. The hosted dashboard shows a user icon at the lower left of the navigation. It appears only after the server confirms an authenticated GitHub session and diff --git a/server/internal/collect/lake_values.go b/server/internal/collect/lake_values.go index 9648358db..4ab0888ef 100644 --- a/server/internal/collect/lake_values.go +++ b/server/internal/collect/lake_values.go @@ -16,6 +16,9 @@ func (l Lake) filterOperationalValues(keep func(string) bool) error { if err := operationalvalue.FilterRepositories(l.operationalValuesPath(), keep); err != nil { return err } + if err := operationalvalue.FilterCollectionRepositories(filepath.Join(l.ShardDirectory(), "workflow-values-collections.jsonl"), keep); err != nil { + return err + } // Normalized files are disposable, potentially shared projections, not // independent evidence. Drop an affected file as a unit and let compaction // regenerate it from the preserved raw sources, rather than editing hashes, @@ -73,7 +76,7 @@ func containsWithdrawnValue(path string, keep func(string) bool) (bool, error) { if err := json.Unmarshal(scanner.Bytes(), &item); err != nil { return false, errors.New("invalid normalized evidence while erasing operational values") } - if item.Kind != "record" || item.Collection != "operationalValues" { + if item.Kind != "record" || item.Collection != "operationalValues" && item.Collection != "workflowValueCollections" { continue } coordinate, found := strings.CutPrefix(item.Record.RepositoryID, "repository:") diff --git a/server/internal/collect/projector.go b/server/internal/collect/projector.go index c177f4d0f..9707694d7 100644 --- a/server/internal/collect/projector.go +++ b/server/internal/collect/projector.go @@ -18,7 +18,6 @@ import ( "github.com/githubnext/gh-cao/server/internal/ingest" "github.com/githubnext/gh-cao/server/internal/logger" "github.com/githubnext/gh-cao/server/internal/operational" - "github.com/githubnext/gh-cao/server/internal/operationalvalue" "github.com/githubnext/gh-cao/server/internal/postgresx" ) @@ -215,13 +214,6 @@ func (p Projector) project(ctx context.Context, force bool) (ingest.Result, erro return ingest.Result{}, fmt.Errorf("record projection completion: %w", err) } projectorLog.Printf("activated dashboard data revision=%d sources=%d", result.Revision, len(result.Counts)) - revision, err := p.refreshWorkflowValues(ctx) - if revision > result.Revision { - result.Revision = revision - } - if err != nil { - projectorLog.Printf("opted-in workflow Value collection failed; retaining accepted evidence") - } return result, nil } @@ -272,18 +264,10 @@ func (p Projector) refreshCompaction(ctx context.Context) error { } projectorLog.Printf("inventory discovery failed; retaining the previous valid inventory") } - if err := p.refreshManifest(ctx); err != nil { - return err - } - if p.Tokens != nil { - if err := p.refreshOperationalValues(ctx); err != nil { - // Match the Actions profile: operational value is best-effort and - // must not prevent newer Activity evidence from being projected. - projectorLog.Printf("operational value reconstruction failed; continuing without refreshed values") - } - return p.refreshManifest(ctx) + if err := p.refreshWorkflowValueHealth(ctx); err != nil { + projectorLog.Printf("Value collection health could not be refreshed; retaining the previous dated decisions") } - return nil + return p.refreshManifest(ctx) } // refreshManifest regenerates payload-hashes.json, gh-aw-logs-runs, and @@ -302,78 +286,6 @@ func (p Projector) refreshManifest(ctx context.Context) error { return p.run(ctx, arguments) } -// refreshOperationalValues collects current outcomes from the retained Activity -// projection without reconstructing historical windows, using -// one installation-scoped token per enrolled repository. -func (p Projector) refreshOperationalValues(ctx context.Context) error { - repositories, err := p.enrolledRepositories(ctx) - if err != nil { - return err - } - if len(repositories) == 0 { - return nil - } - workspace, err := os.MkdirTemp("", "cao-operational-value-") - if err != nil { - return fmt.Errorf("create operational value workspace: %w", err) - } - defer func() { - _ = os.RemoveAll(workspace) - }() - database := filepath.Join(workspace, "activity.sqlite") - retentionDays := strconv.Itoa(p.windowDays()) - if err := p.run(ctx, []string{ - filepath.Join(p.CatalogRoot, "activity", "cao.mjs"), - "ingest-jsonl", - "--database", database, - "--runs-dir", p.Lake.RunsDirectory(), - "--records-dir", p.Lake.RecordsDirectory(), - "--retention-days", retentionDays, - "--run-retention-days", retentionDays, - }); err != nil { - return err - } - observedAt := time.Now().UTC() - output := p.Lake.operationalValuesPath() - for _, repository := range repositories { - installationID, err := p.Enrollment.InstallationFor(ctx, repository) - if err != nil { - return fmt.Errorf("resolve installation for %s: %w", repository, err) - } - if installationID <= 0 { - return fmt.Errorf("resolve installation for %s: no installation is enrolled", repository) - } - reserve, err := p.rateLimitReserve(ctx, installationID) - if err != nil { - return err - } - token, err := p.Tokens.InstallationToken(ctx, installationID) - if err != nil { - return err - } - environment := append(collectionEnvironment(p.GitHubAPIURL), []string{ - "CAO_OPERATIONAL_VALUE_GH_TOKEN=" + token, - "GH_TOKEN=" + token, - "CAO_GITHUB_API_MIN_REMAINING=" + strconv.Itoa(reserve), - }...) - result, err := operationalvalue.Collect(ctx, operationalvalue.Config{ - Root: p.CatalogRoot, Database: database, Output: output, - ObservedAt: observedAt, Repositories: []string{repository}, - Retention: operationalvalue.DefaultRetention, - NodeBinary: p.node(), GitHubBinary: p.GitHubBinary, - Environment: environment, RedactValues: []string{token}, - RateLimitReserve: reserve, - }) - if err != nil { - return err - } - if len(result.Warnings) > 0 { - projectorLog.Printf("operational value adapters failed count=%d", len(result.Warnings)) - } - } - return nil -} - func (p Projector) rateLimitReserve(ctx context.Context, installationID int64) (int, error) { if p.Budget == nil { return 2000, nil diff --git a/server/internal/collect/projector_local_value_test.go b/server/internal/collect/projector_local_value_test.go new file mode 100644 index 000000000..aef6bf239 --- /dev/null +++ b/server/internal/collect/projector_local_value_test.go @@ -0,0 +1,93 @@ +package collect + +import ( + "context" + "crypto/sha256" + "encoding/hex" + "encoding/json" + "os" + "path/filepath" + "strings" + "testing" + + "github.com/githubnext/gh-cao/server/internal/ingest" + "github.com/githubnext/gh-cao/server/internal/operational" +) + +type localValueAttemptState struct { + operational.StateStore + values map[string][]byte +} + +func (s *localValueAttemptState) OperationalState(_ context.Context, key string) ([]byte, error) { + return s.values[key], nil +} + +func (s *localValueAttemptState) SetOperationalState(_ context.Context, key string, value []byte) error { + s.values[key] = value + return nil +} + +func TestLocalValueFailureDoesNotRetryOrRequestCoreProjection(t *testing.T) { + state := &localValueAttemptState{values: map[string][]byte{projectionCompletedKey: []byte("generation-1")}} + projector := Projector{ + Leases: &workflowValueLease{acquire: true}, State: state, + CatalogRoot: "unused", PolicyPath: "unused", Lake: Lake{Directory: t.TempDir()}, + } + if err := projector.CollectLocalValues(t.Context()); err == nil { + t.Fatal("missing snapshot must explicitly fail optional work") + } + if string(state.values[localValueAttemptKey]) != "generation-1" || len(state.values) != 2 { + t.Fatalf("optional failure changed core state: %v", state.values) + } + if err := projector.CollectLocalValues(t.Context()); err != nil { + t.Fatalf("the same completed input was retried: %v", err) + } +} + +func TestLocalValueSnapshotIsPrivateVerifiedAndBounded(t *testing.T) { + lake := Lake{Directory: t.TempDir()} + for _, directory := range []string{lake.RunsDirectory(), lake.ShardDirectory()} { + if err := os.MkdirAll(directory, 0o700); err != nil { + t.Fatal(err) + } + } + content := []byte("{}\n") + digest := sha256.Sum256(content) + name := "gh-aw-logs-runs/fixture.jsonl" + source := filepath.Join(lake.Directory, filepath.FromSlash(name)) + manifest, _ := json.Marshal(ingest.Manifest{name: hex.EncodeToString(digest[:])}) + for file, value := range map[string][]byte{ + source: content, lake.ManifestPath(): manifest, + filepath.Join(lake.ShardDirectory(), "workflow-value-local.json"): []byte("[]"), + lake.operationalValuesPath(): []byte("retained\n"), + } { + if err := os.WriteFile(file, value, 0o600); err != nil { + t.Fatal(err) + } + } + destination := t.TempDir() + if err := copyLocalValueSnapshot(t.Context(), lake, destination); err != nil { + t.Fatal(err) + } + if _, _, _, err := ingest.ValidateManifest(destination); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(source, []byte("changed"), 0o600); err != nil { + t.Fatal(err) + } + if err := copyLocalValueSnapshot(t.Context(), lake, t.TempDir()); err == nil || + !strings.Contains(err.Error(), "hash mismatch") { + t.Fatalf("changed inputs were accepted as immutable: %v", err) + } + if err := os.Truncate(source, 17<<20); err != nil { + t.Fatal(err) + } + if err := copyLocalValueSnapshot(t.Context(), lake, t.TempDir()); err == nil || + !strings.Contains(err.Error(), "oversized") { + t.Fatalf("oversized input was read or accepted: %v", err) + } + if retained, err := os.ReadFile(lake.operationalValuesPath()); err != nil || string(retained) != "retained\n" { + t.Fatal("a failed disposable snapshot changed accepted evidence") + } +} diff --git a/server/internal/collect/projector_workflow_values.go b/server/internal/collect/projector_workflow_values.go index 4bed2fddd..30c18df3f 100644 --- a/server/internal/collect/projector_workflow_values.go +++ b/server/internal/collect/projector_workflow_values.go @@ -1,151 +1,229 @@ package collect import ( + "bytes" "context" "encoding/json" "errors" + "fmt" + "io" "os" "path/filepath" + "sort" "strconv" "strings" "time" + "github.com/githubnext/gh-cao/server/internal/ingest" "github.com/githubnext/gh-cao/server/internal/operationalvalue" - "github.com/githubnext/gh-cao/server/internal/postgresx" ) -// CollectWorkflowValues uses the existing projection driver's tick even when a -// quiet repository produced no new run artifacts. The projection lease excludes -// snapshot replacement and another collector; this is not a second scheduler. -func (p Projector) CollectWorkflowValues(ctx context.Context) (int64, error) { - if p.Data == nil || p.Leases == nil || p.CatalogRoot == "" || p.PolicyPath == "" || p.Tokens == nil { - return 0, nil +const localValueLockName = "value-local" +const localValueAttemptKey = "collect:value-local-attempt" + +var ErrLocalValueBusy = errors.New("a local Value computation is already running") + +func (p Projector) refreshWorkflowValueHealth(ctx context.Context) error { + if p.CatalogRoot == "" || p.PolicyPath == "" || p.Enrollment.Metadata == nil { + return nil + } + repositories, err := p.enrolledRepositories(ctx) + if err != nil { + return err + } + if len(repositories) == 0 { + return nil + } + return operationalvalue.WriteCollectionHealth(ctx, operationalvalue.Config{ + Root: p.CatalogRoot, NodeBinary: p.node(), Repositories: repositories, + Environment: collectionEnvironment(p.GitHubAPIURL), WorkerTimeout: 30 * time.Second, + }, p.PolicyPath, p.Lake.Directory) +} + +// CollectLocalValues never acquires a target credential or the projection lease. +// Its immutable snapshot and computation are disposable; only a short final +// publication shares the evidence lock with core collection and erasure. +func (p Projector) CollectLocalValues(ctx context.Context) error { + if p.Leases == nil || p.State == nil || p.CatalogRoot == "" || p.PolicyPath == "" { + return nil } token, err := operationToken() if err != nil { - return 0, err + return err } - acquired, err := p.Leases.TryLock(ctx, projectionLockName, token, p.lockTTL()) + acquired, err := p.Leases.TryLock(ctx, localValueLockName, token, 3*time.Minute) if err != nil { - return 0, err + return err } if !acquired { - return 0, ErrProjectionBusy + return ErrLocalValueBusy } defer func() { release, cancel := context.WithTimeout(context.WithoutCancel(ctx), 3*time.Second) defer cancel() - _ = p.Leases.Unlock(release, projectionLockName, token) + _ = p.Leases.Unlock(release, localValueLockName, token) }() - ctx, cancel := context.WithTimeout(ctx, p.timeout()) + ctx, cancel := context.WithTimeout(ctx, 2*time.Minute) defer cancel() - return p.refreshWorkflowValues(ctx) -} - -// Recurring rich packets use the same reviewed Node producer as Activity and -// the same atomic publication boundary as manual uploads, never HTTP sessions. -func (p Projector) refreshWorkflowValues(ctx context.Context) (revision int64, err error) { - if p.CatalogRoot == "" || p.PolicyPath == "" || p.Tokens == nil { - return revision, nil + generation, err := p.State.OperationalState(ctx, projectionCompletedKey) + if err != nil || len(generation) == 0 { + return err + } + attempted, err := p.State.OperationalState(ctx, localValueAttemptKey) + if err != nil || bytes.Equal(generation, attempted) { + return err + } + // One bounded attempt per published input, not a per-workflow retry loop. + if err := p.State.SetOperationalState(ctx, localValueAttemptKey, generation); err != nil { + return err + } + workspace, err := os.MkdirTemp("", "cao-local-value-") + if err != nil { + return err + } + defer func() { _ = os.RemoveAll(workspace) }() + if err := copyLocalValueSnapshot(ctx, p.Lake, workspace); err != nil { + return err } + output := filepath.Join(workspace, "operational-values.jsonl") config := operationalvalue.Config{ - Root: p.CatalogRoot, NodeBinary: p.node(), GitHubBinary: p.GitHubBinary, - ObservedAt: time.Now().UTC(), Environment: collectionEnvironment(p.GitHubAPIURL), + Root: p.CatalogRoot, NodeBinary: p.node(), Output: output, + Database: filepath.Join(workspace, "activity.sqlite"), + Environment: collectionEnvironment(p.GitHubAPIURL), WorkerTimeout: 2 * time.Minute, } - entries, err := operationalvalue.WorkflowRegistrations(ctx, config, p.PolicyPath) - if err != nil || len(entries) == 0 { - return revision, err + if err := operationalvalue.ComputeLocalSnapshot(ctx, config, p.PolicyPath, workspace, strconv.Itoa(p.windowDays())); err != nil { + return err } - repositories, err := p.enrolledRepositories(ctx) + content, err := readLocalValueFile(ctx, output, 16<<20) + if errors.Is(err, os.ErrNotExist) { + return nil + } + if err != nil || len(content) > 16<<20 { + return errors.New("local Value output is unreadable or exceeds its byte budget") + } + publication, stop := context.WithTimeout(ctx, 2*time.Second) + defer stop() + unlock, err := p.Lake.lockEvidence(publication) + if err != nil { + return err + } + defer unlock() + repositories, err := p.enrolledRepositories(publication) if err != nil { - return revision, err + return err } enrolled := map[string]bool{} for _, repository := range repositories { enrolled[strings.ToLower(repository)] = true } - workspace := filepath.Join(p.Lake.Directory, "workflow-value-workspaces") - if err := os.MkdirAll(workspace, 0o700); err != nil { - return revision, err + if err := operationalvalue.FilterRepositories(output, func(repository string) bool { return enrolled[repository] }); err != nil { + return err } - scratch, err := os.MkdirTemp(workspace, ".projection-") + content, err = readLocalValueFile(publication, output, 16<<20) if err != nil { - return revision, err - } - defer func() { _ = os.RemoveAll(scratch) }() - config.Database = filepath.Join(scratch, "activity.sqlite") - retention := strconv.Itoa(p.windowDays()) - if err := p.run(ctx, []string{ - filepath.Join(p.CatalogRoot, "activity", "cao.mjs"), "ingest-jsonl", - "--database", config.Database, "--runs-dir", p.Lake.RunsDirectory(), - "--records-dir", p.Lake.RecordsDirectory(), "--retention-days", retention, - "--run-retention-days", retention, - }); err != nil { - return revision, err - } - grouped := map[string][]operationalvalue.WorkflowRegistration{} - for _, entry := range entries { - if enrolled[strings.ToLower(entry.Repository)] { - grouped[strings.ToLower(entry.Repository)] = append(grouped[strings.ToLower(entry.Repository)], entry) - } + return err } - for repository, registrations := range grouped { - installation, err := p.Enrollment.InstallationFor(ctx, repository) - if err != nil || installation <= 0 { - return revision, errors.New("workflow Value repository installation is unavailable") - } - reserve, err := p.rateLimitReserve(ctx, installation) - if err != nil { - return revision, err + previous, err := readLocalValueFile(publication, p.Lake.operationalValuesPath(), 16<<20) + if err != nil && !errors.Is(err, os.ErrNotExist) { + return err + } + if bytes.Equal(content, previous) { + return nil + } + // The next ordinary projection publishes this result. Value must not create + // a compute -> projection -> compute retry loop on incomplete local evidence. + return WriteFileAtomic(p.Lake.operationalValuesPath(), content) +} + +func copyLocalValueSnapshot(ctx context.Context, lake Lake, destination string) error { + content, err := readLocalValueFile(ctx, lake.ManifestPath(), 1<<20) + if err != nil { + return err + } + var manifest ingest.Manifest + if err := json.Unmarshal(content, &manifest); err != nil { + return err + } + var names []string + for name := range manifest { + if (strings.HasPrefix(name, "gh-aw-logs-runs/") || strings.HasPrefix(name, "gh-aw-logs-records/")) && + strings.HasSuffix(name, ".jsonl") { + if filepath.ToSlash(filepath.Clean(name)) != name || filepath.IsAbs(name) { + return errors.New("local Value snapshot contains an unsafe path") + } + names = append(names, name) } - token, err := p.Tokens.InstallationToken(ctx, installation) - if err != nil { - return revision, err + } + sort.Strings(names) + names = append(names, "gh-aw-logs-shards/workflow-value-local.json") + var total int64 + for _, name := range names { + if err := ctx.Err(); err != nil { + return err } - previous := []byte{} - for _, entry := range registrations { - packet, err := p.Data.ReadOperationalValue(ctx, repository, entry.Workflow) - if errors.Is(err, postgresx.ErrValueNotFound) || errors.Is(err, postgresx.ErrValueParentMissing) { - continue - } - if err != nil { - return revision, err - } - content, err := json.Marshal(map[string]any{ - "schema_version": 2, "kind": "operational_value_evidence", "operational_value_evidence": packet, - }) - if err != nil { - return revision, err - } - previous = append(previous, content...) - previous = append(previous, '\n') + source := filepath.Join(lake.Directory, filepath.FromSlash(name)) + info, err := os.Lstat(source) + if err != nil || !info.Mode().IsRegular() || info.Size() > 16<<20 { + return errors.New("local Value snapshot contains an invalid or oversized file") } - previousPath := filepath.Join(scratch, "previous.jsonl") - if err := os.WriteFile(previousPath, previous, 0o600); err != nil { - return revision, err + if total+info.Size() > 256<<20 { + return errors.New("local Value snapshot exceeds its byte budget") } - config.Repositories = []string{repository} - config.RateLimitReserve = reserve - config.Environment = append(collectionEnvironment(p.GitHubAPIURL), - "GH_TOKEN="+token, "CAO_OPERATIONAL_VALUE_GH_TOKEN="+token, - "CAO_GITHUB_API_MIN_REMAINING="+strconv.Itoa(reserve)) - config.RedactValues = []string{token} - packets, warnings, err := operationalvalue.CollectWorkflows(ctx, config, p.PolicyPath, workspace, previousPath) + content, err := readLocalValueFile(ctx, source, min(16<<20, 256<<20-total)) if err != nil { - projectorLog.Printf("workflow Value acquisition failed; retaining accepted evidence") - continue + return err } - if len(warnings) > 0 { - projectorLog.Printf("workflow Value acquisition incomplete count=%d", len(warnings)) + total += int64(len(content)) + target := filepath.Join(destination, filepath.FromSlash(name)) + if err := os.MkdirAll(filepath.Dir(target), 0o700); err != nil { + return err } - for _, packet := range packets { - publication, err := p.Data.PublishOperationalValue(ctx, packet) - if err != nil { - projectorLog.Printf("workflow Value publication rejected; retaining accepted evidence") - } else if publication.Updated { - revision = publication.Revision - } + if err := os.WriteFile(target, content, 0o600); err != nil { + return err } } - return revision, nil + content, err = json.Marshal(manifest) + if err != nil { + return err + } + if err := os.WriteFile(filepath.Join(destination, "payload-hashes.json"), content, 0o600); err != nil { + return err + } + if _, _, _, err := ingest.ValidateManifest(destination); err != nil { + return fmt.Errorf("local Value input changed during snapshotting: %w", err) + } + retained, err := readLocalValueFile(ctx, lake.operationalValuesPath(), 16<<20) + if errors.Is(err, os.ErrNotExist) { + return nil + } + if err != nil { + return err + } + return os.WriteFile(filepath.Join(destination, "operational-values.jsonl"), retained, 0o600) +} + +func readLocalValueFile(ctx context.Context, path string, maxBytes int64) ([]byte, error) { + if err := ctx.Err(); err != nil { + return nil, err + } + info, err := os.Lstat(path) + if err != nil { + return nil, err + } + if !info.Mode().IsRegular() || info.Size() > maxBytes { + return nil, errors.New("local Value input is not a bounded regular file") + } + file, err := os.Open(path) // #nosec G304 -- confined snapshot or private output path, size checked before reading. + if err != nil { + return nil, err + } + defer func() { _ = file.Close() }() + content, err := io.ReadAll(io.LimitReader(file, maxBytes+1)) + if err != nil { + return nil, err + } + if int64(len(content)) > maxBytes { + return nil, errors.New("local Value input grew beyond its byte budget") + } + return content, ctx.Err() } diff --git a/server/internal/collect/projector_workflow_values_test.go b/server/internal/collect/projector_workflow_values_test.go index eef510b77..1c2cfc51d 100644 --- a/server/internal/collect/projector_workflow_values_test.go +++ b/server/internal/collect/projector_workflow_values_test.go @@ -3,13 +3,10 @@ package collect import ( "context" "errors" - "os" - "path/filepath" "testing" "time" "github.com/githubnext/gh-cao/server/internal/operational" - "github.com/githubnext/gh-cao/server/internal/postgresx" ) type workflowValueLease struct { @@ -20,8 +17,8 @@ type workflowValueLease struct { } func (l *workflowValueLease) TryLock(_ context.Context, name, _ string, _ time.Duration) (bool, error) { - if name != projectionLockName { - return false, errors.New("recurring values must share the projection lease") + if name != localValueLockName { + return false, errors.New("optional local values must not acquire the projection lease") } l.locks++ return l.acquire, nil @@ -40,37 +37,35 @@ func (quietProjectionState) OperationalState(context.Context, string) ([]byte, e return nil, nil } -func TestQuietProjectionTickDrivesReviewedWorkflowValuesWithoutNewActivity(t *testing.T) { - root, err := filepath.Abs("../../..") - if err != nil { - t.Fatal(err) - } - directory, err := os.MkdirTemp(".", ".quiet-workflow-values-") - if err != nil { - t.Fatal(err) - } - t.Cleanup(func() { _ = os.RemoveAll(directory) }) - policy, _ := filepath.Abs(filepath.Join(directory, "cao.json")) - if err := os.WriteFile(policy, []byte(`{"version":1,"gh-aw-version":"v0.92.5","control-plane":{"campaigns":{"activity":{"workflow-values":[]}}}}`), 0o600); err != nil { - t.Fatal(err) - } +func TestLocalValuesHaveAnIndependentOwnedLoop(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() lease := &workflowValueLease{acquire: true, release: cancel} worker := Worker{Projector: Projector{ - State: quietProjectionState{}, Leases: lease, Data: &postgresx.Store{}, - CatalogRoot: root, PolicyPath: policy, Tokens: fakeTokens{}, MinInterval: time.Millisecond, + State: quietProjectionState{}, Leases: lease, + CatalogRoot: "unused", PolicyPath: "unused", MinInterval: time.Millisecond, }} - worker.projectionLoop(ctx) + worker.localValueLoop(ctx) if lease.locks == 0 { - t.Fatalf("quiet repository did not use the existing projection driver for Value cadence: locks=%d", lease.locks) + t.Fatalf("independent local computation did not check its own lease: locks=%d", lease.locks) + } +} + +func TestLocalValueLeaseBoundsConcurrencyWithoutBlockingProjection(t *testing.T) { + lease := &workflowValueLease{} + projector := Projector{Leases: lease, State: quietProjectionState{}, CatalogRoot: "unused", PolicyPath: "unused"} + if err := projector.CollectLocalValues(context.Background()); !errors.Is(err, ErrLocalValueBusy) || lease.locks != 1 { + t.Fatalf("local producer bypassed its concurrency bound: locks=%d err=%v", lease.locks, err) } } -func TestWorkflowValueCollectionSharesProjectionLease(t *testing.T) { +func TestQuietProjectionDoesNotWaitForOptionalValueWork(t *testing.T) { lease := &workflowValueLease{} - projector := Projector{Leases: lease, Data: &postgresx.Store{}, CatalogRoot: "unused", PolicyPath: "unused", Tokens: fakeTokens{}} - if _, err := projector.CollectWorkflowValues(context.Background()); !errors.Is(err, ErrProjectionBusy) || lease.locks != 1 { - t.Fatalf("recurring producer bypassed snapshot lease: locks=%d err=%v", lease.locks, err) + worker := Worker{Projector: Projector{State: quietProjectionState{}, Leases: lease, MinInterval: time.Millisecond}} + ctx, cancel := context.WithTimeout(t.Context(), 10*time.Millisecond) + defer cancel() + worker.projectionLoop(ctx) + if lease.locks != 0 { + t.Fatal("core projection must not start or wait for optional Value work") } } diff --git a/server/internal/collect/withdrawal_values_test.go b/server/internal/collect/withdrawal_values_test.go index becb28825..4be4cdd66 100644 --- a/server/internal/collect/withdrawal_values_test.go +++ b/server/internal/collect/withdrawal_values_test.go @@ -292,15 +292,15 @@ func TestWithdrawalSharedValuesEndToEnd(t *testing.T) { t.Fatalf("withdrawal retry did not publish a fresh revision: %+v, %v", next, err) } assertValues(1) - if tokens.calls != 1 { - t.Fatalf("token acquisition failure was not exercised: calls=%d", tokens.calls) + if tokens.calls != 0 { + t.Fatalf("core publication must not mint Value acquisition credentials: calls=%d", tokens.calls) } withdraw("octo/other") if _, err := w.Projector.Project(ctx); err != nil { t.Fatal(err) } assertValues(0) - if tokens.calls != 1 { + if tokens.calls != 0 { t.Fatalf("empty enrollment attempted acquisition: calls=%d", tokens.calls) } for _, directory := range []string{lake.ShardDirectory(), lake.RunsDirectory(), lake.RecordsDirectory()} { diff --git a/server/internal/collect/worker.go b/server/internal/collect/worker.go index 0d6803a82..cd8c2b19e 100644 --- a/server/internal/collect/worker.go +++ b/server/internal/collect/worker.go @@ -120,13 +120,19 @@ func (w Worker) Run(ctx context.Context) error { if w.Project { projectionCtx, cancelProjection := context.WithCancel(ctx) projectionDone := make(chan struct{}) + valueDone := make(chan struct{}) go func() { defer close(projectionDone) w.projectionLoop(projectionCtx) }() + go func() { + defer close(valueDone) + w.localValueLoop(projectionCtx) + }() defer func() { cancelProjection() <-projectionDone + <-valueDone }() } for ctx.Err() == nil { @@ -324,13 +330,6 @@ func (w Worker) projectionLoop(ctx context.Context) { continue } if !pending { - revision, err := w.Projector.CollectWorkflowValues(ctx) - if revision > 0 && w.OnProjection != nil { - w.OnProjection(revision) - } - if err != nil && !errors.Is(err, ErrProjectionBusy) { - workerLog.Printf("opted-in workflow Value collection failed") - } continue } result, err := w.Projector.Project(ctx) @@ -346,6 +345,21 @@ func (w Worker) projectionLoop(ctx context.Context) { } } +func (w Worker) localValueLoop(ctx context.Context) { + ticker := time.NewTicker(w.Projector.minInterval()) + defer ticker.Stop() + for { + select { + case <-ctx.Done(): + return + case <-ticker.C: + if err := w.Projector.CollectLocalValues(ctx); err != nil && !errors.Is(err, ErrLocalValueBusy) && ctx.Err() == nil { + workerLog.Printf("local Value computation deferred or failed; core Activity publication is independent") + } + } + } +} + func sleep(ctx context.Context, duration time.Duration) { timer := time.NewTimer(duration) defer timer.Stop() diff --git a/server/internal/model/model.go b/server/internal/model/model.go index f21e3078d..e9c465002 100644 --- a/server/internal/model/model.go +++ b/server/internal/model/model.go @@ -1,6 +1,6 @@ package model -const SchemaVersion = 18 +const SchemaVersion = 19 type Row map[string]any diff --git a/server/internal/operationalvalue/collector.go b/server/internal/operationalvalue/collector.go index 69971ff87..e8d37a817 100644 --- a/server/internal/operationalvalue/collector.go +++ b/server/internal/operationalvalue/collector.go @@ -123,6 +123,7 @@ type valueRecord struct { type parsedOutput struct { definitions []definition values []valueRecord + deferred []string } type envelope struct { @@ -224,6 +225,7 @@ func Collect(ctx context.Context, config Config) (Result, error) { continue } values = append(values, envelopes(entry.campaign, current.values)...) + result.Warnings = append(result.Warnings, current.deferred...) if len(current.definitions) > 0 { activeIDs[entry.campaign] = map[string]struct{}{} for _, item := range current.definitions { @@ -597,6 +599,18 @@ func parseOutput(content []byte, source string, repositories []string) (parsedOu if err := json.Unmarshal(scanner.Bytes(), &header); err != nil { return output, fmt.Errorf("%s:%d emitted invalid JSON: %w", source, line, err) } + if header.Kind == "operational_value_deferred" { + var record struct { + WorkflowSlug string `json:"workflowSlug"` + Reason string `json:"reason"` + } + if err := json.Unmarshal(scanner.Bytes(), &record); err != nil || + !slugPattern.MatchString(record.WorkflowSlug) || strings.TrimSpace(record.Reason) == "" || len(record.Reason) > 1024 { + return output, errors.New("invalid operational value deferral") + } + output.deferred = append(output.deferred, record.WorkflowSlug+": "+record.Reason) + continue + } if header.Kind == "operational_value_definition" { var record definitionRecord if err := json.Unmarshal(scanner.Bytes(), &record); err != nil { diff --git a/server/internal/operationalvalue/local.go b/server/internal/operationalvalue/local.go new file mode 100644 index 000000000..aa16f3e3c --- /dev/null +++ b/server/internal/operationalvalue/local.go @@ -0,0 +1,90 @@ +package operationalvalue + +import ( + "context" + "encoding/json" + "errors" + "log/slog" + "os/exec" + "path/filepath" + "slices" + "strings" + "time" +) + +func WriteCollectionHealth(ctx context.Context, config Config, policy, snapshot string) error { + arguments := make([]string, 0, 19+2*len(config.Repositories)) + arguments = append(arguments, + filepath.Join(config.Root, "activity", "workflow-values.mjs"), + "--root", config.Root, "--policy", policy, "--defer", "shared-budget-unavailable", + "--database", filepath.Join(snapshot, "unused-value.sqlite"), + "--output", filepath.Join(snapshot, "gh-aw-logs-shards", "workflow-values.jsonl"), + "--inventory", filepath.Join(snapshot, "inventory-sources.json"), + "--workspace", filepath.Join(snapshot, "workflow-value-workspaces"), + "--localRequest", filepath.Join(snapshot, "gh-aw-logs-shards", "workflow-value-local.json"), + "--snapshot", "hosted", + ) + for _, repository := range config.Repositories { + arguments = append(arguments, "--repository", repository) + } + return runLocalRuntime(ctx, config, arguments) +} + +func ComputeLocalSnapshot(ctx context.Context, config Config, policy, snapshot, retentionDays string) error { + if err := runLocalRuntime(ctx, config, []string{ + filepath.Join(config.Root, "activity", "cao.mjs"), "ingest-jsonl", + "--database", config.Database, "--runs-dir", filepath.Join(snapshot, "gh-aw-logs-runs"), + "--records-dir", filepath.Join(snapshot, "gh-aw-logs-records"), + "--retention-days", retentionDays, "--run-retention-days", retentionDays, + }); err != nil { + return err + } + return runLocalRuntime(ctx, config, []string{ + filepath.Join(config.Root, "activity", "local-values.mjs"), "compute", + "--root", config.Root, "--policy", policy, "--snapshot", snapshot, "--snapshotKey", "hosted", + "--database", config.Database, "--output", config.Output, + }) +} + +func runLocalRuntime(ctx context.Context, config Config, arguments []string) error { + timeout := config.WorkerTimeout + if timeout <= 0 { + timeout = 2 * time.Minute + } + ctx, cancel := context.WithTimeout(ctx, timeout) + defer cancel() + node := config.NodeBinary + if node == "" { + node = "node" + } + command := exec.CommandContext(ctx, node, arguments...) // #nosec G204 -- fixed trusted local runtime and explicit paths. + command.Dir = config.Root + command.Env = slices.DeleteFunc(slices.Clone(config.Environment), func(value string) bool { + return strings.HasPrefix(value, "GH_TOKEN=") || strings.HasPrefix(value, "GITHUB_TOKEN=") || + strings.HasPrefix(value, "CAO_OPERATIONAL_VALUE_GH_TOKEN=") + }) + command.Env = append(command.Env, "CAO_VALUE_SHARED_PROCESS_GROUP=1") + configureProcessTree(command) + command.Cancel = func() error { return terminateProcessTree(command.Process) } + command.WaitDelay = 5 * time.Second + stdout, stderr := newLimitedBuffer(1<<20, cancel), newLimitedBuffer(16384, cancel) + command.Stdout, command.Stderr = stdout, stderr + err := command.Run() + _ = terminateProcessTree(command.Process) + if err != nil || stdout.Exceeded() || stderr.Exceeded() { + return errors.New("local Value runtime failed or exceeded its budget; accepted evidence retained") + } + if len(stdout.Bytes()) != 0 { + var result struct { + Warnings []json.RawMessage `json:"warnings"` + } + if err := json.Unmarshal(stdout.Bytes(), &result); err != nil { + return errors.New("local Value runtime returned an invalid result") + } + if len(result.Warnings) != 0 { + slog.WarnContext(ctx, "local Value adapters deferred or failed; only completed evidence retained", + "warning_count", len(result.Warnings)) + } + } + return nil +} diff --git a/server/internal/operationalvalue/local_test.go b/server/internal/operationalvalue/local_test.go new file mode 100644 index 000000000..2aeb2fbbe --- /dev/null +++ b/server/internal/operationalvalue/local_test.go @@ -0,0 +1,101 @@ +package operationalvalue + +import ( + "context" + "encoding/json" + "os" + "path/filepath" + "testing" + "time" +) + +func TestLocalCollectionHealthNeedsNeitherCollectorNorCredential(t *testing.T) { + root, err := filepath.Abs("../../..") + if err != nil { + t.Fatal(err) + } + snapshot := t.TempDir() + policy := filepath.Join(snapshot, "cao.json") + content := `{"version":1,"gh-aw-version":"v0.93.1","control-plane":{ + "scope":{"allowed-repositories":["org/repo"]},"activity":{"repositories":["org/repo"]}, + "campaigns":{"activity":{"workflow-values":[ + {"repository":"org/repo","workflow":"worker","collector":"not-present.mjs"} + ]}}}}` + if err := os.WriteFile(policy, []byte(content), 0o600); err != nil { + t.Fatal(err) + } + if err := os.WriteFile(filepath.Join(snapshot, "inventory-sources.json"), + []byte(`{"repositories":{"rows":[]},"workflows":{"rows":[]}}`), 0o600); err != nil { + t.Fatal(err) + } + config := Config{Root: root, Repositories: []string{"org/repo"}, Environment: []string{ + "PATH=" + os.Getenv("PATH"), "GH_TOKEN=test-only", "GITHUB_TOKEN=test-only", + }} + if err := WriteCollectionHealth(t.Context(), config, policy, snapshot); err != nil { + t.Fatal(err) + } + data, err := os.ReadFile(filepath.Join(snapshot, "gh-aw-logs-shards", "workflow-values-collections.jsonl")) // #nosec G304 -- fixed test-owned temporary output. + if err != nil { + t.Fatal(err) + } + var envelope struct { + Record map[string]any `json:"workflow_value_collection"` + } + if err := json.Unmarshal(data, &envelope); err != nil { + t.Fatal(err) + } + if envelope.Record["registration"] != "enabled" || envelope.Record["state"] != "deferred" || + envelope.Record["reasonCode"] != "shared-budget-unavailable" || envelope.Record["lastAttemptAt"] != nil { + t.Fatalf("hosted health did not preserve registration without an attempt: %v", envelope.Record) + } + if _, err := os.Stat(filepath.Join(snapshot, "workflow-value-workspaces")); !os.IsNotExist(err) { + t.Fatal("health publication must not start acquisition or create proof workspaces") + } +} + +func TestLocalRuntimeCancellationOwnsDescendantsAndStripsCredentials(t *testing.T) { + directory := t.TempDir() + started, leaked := filepath.Join(directory, "started"), filepath.Join(directory, "leaked") + marker, _ := json.Marshal(started) + target, _ := json.Marshal(leaked) + child := `require("node:fs").writeFileSync(` + string(marker) + `,"ready"); + setTimeout(()=>require("node:fs").writeFileSync(` + string(target) + `,"leaked"),500); + setInterval(()=>{},1000)` + childSource, _ := json.Marshal(child) + source := `if(process.env.GH_TOKEN || process.env.GITHUB_TOKEN || process.env.CAO_OPERATIONAL_VALUE_GH_TOKEN) + throw new Error("credentials crossed local boundary"); + require("node:child_process").spawn(process.execPath,["-e",` + string(childSource) + `]); + setInterval(()=>{},1000)` + ctx, cancel := context.WithCancel(t.Context()) + defer cancel() + done := make(chan error, 1) + go func() { + done <- runLocalRuntime(ctx, Config{Root: directory, WorkerTimeout: 5 * time.Second, + Environment: []string{"PATH=" + os.Getenv("PATH"), "GH_TOKEN=test-only", "GITHUB_TOKEN=test-only", + "CAO_OPERATIONAL_VALUE_GH_TOKEN=test-only"}}, + []string{"-e", source}) + }() + deadline := time.Now().Add(3 * time.Second) + for { + if _, err := os.Stat(started); err == nil { + break + } + select { + case err := <-done: + t.Fatalf("local child did not start with credentials removed: %v", err) + default: + } + if time.Now().After(deadline) { + t.Fatal("local runtime did not start within its bounded deadline") + } + time.Sleep(10 * time.Millisecond) + } + cancel() + if err := <-done; err == nil { + t.Fatal("canceled local work must report failure") + } + time.Sleep(600 * time.Millisecond) + if _, err := os.Stat(leaked); !os.IsNotExist(err) { + t.Fatal("a descendant survived local runtime cancellation") + } +} diff --git a/server/internal/operationalvalue/retained.go b/server/internal/operationalvalue/retained.go index 86ad6d74d..c6e5a2385 100644 --- a/server/internal/operationalvalue/retained.go +++ b/server/internal/operationalvalue/retained.go @@ -15,6 +15,14 @@ import ( // The caller must serialize this read/replace with collection and projection. // This boundary does not own independently published value-evidence packets. func FilterRepositories(path string, keep func(string) bool) error { + return filterRepositories(path, "operational_value", keep) +} + +func FilterCollectionRepositories(path string, keep func(string) bool) error { + return filterRepositories(path, "workflow_value_collection", keep) +} + +func filterRepositories(path, kind string, keep func(string) bool) error { file, err := os.Open(path) // #nosec G304 -- operator-configured collector shard. if errors.Is(err, os.ErrNotExist) { return nil @@ -34,14 +42,27 @@ func FilterRepositories(path string, keep func(string) bool) error { content.WriteByte('\n') continue } - var item envelope + var item struct { + SchemaVersion int `json:"schema_version"` + Kind string `json:"kind"` + Value struct { + Repository string `json:"repository"` + } `json:"operational_value"` + Collection struct { + Repository string `json:"repository"` + } `json:"workflow_value_collection"` + } if err := json.Unmarshal(raw, &item); err != nil { return fmt.Errorf("retained operational value line %d: invalid JSON", line) } - if item.SchemaVersion != 2 || item.Kind != "operational_value" { + if item.SchemaVersion != 2 || item.Kind != kind { return fmt.Errorf("retained operational value line %d: unexpected envelope", line) } - repositories, err := normalizeRepositories([]string{item.OperationalValue.Repository}) + repository := item.Value.Repository + if kind == "workflow_value_collection" { + repository = item.Collection.Repository + } + repositories, err := normalizeRepositories([]string{repository}) if err != nil { return fmt.Errorf("retained operational value line %d: invalid repository", line) } diff --git a/server/internal/postgresx/native.go b/server/internal/postgresx/native.go index 0e18c063d..09031fbc4 100644 --- a/server/internal/postgresx/native.go +++ b/server/internal/postgresx/native.go @@ -185,6 +185,9 @@ func (s *Store) BeginIngestion(ctx context.Context) (*Writer, error) { if err := writer.preserveValuePublications(ctx); err != nil { return fail(err) } + if err := writer.preserveCollectionDecisions(ctx); err != nil { + return fail(err) + } writer.preserveValues = true if err := writer.stageAdmittedRuns(ctx); err != nil { return fail(err) @@ -239,6 +242,11 @@ func (w *Writer) AppendInventory(ctx context.Context, source string, row model.R } func (w *Writer) append(ctx context.Context, source string, row model.Row, inventory bool) error { + if source == "$workflowValueCollections" { + if err := validateWorkflowValueCollection(row); err != nil { + return err + } + } if source == "$operationalValueEvidence" { if w.preserveValues { var previous time.Time @@ -551,6 +559,9 @@ func (w *Writer) Publish(ctx context.Context, dataRevision string) (State, error if _, err := w.tx.Exec(ctx, "SELECT cao_analyze_native()"); err != nil { return State{}, fmt.Errorf("refresh native statistics: %w", err) } + if err := w.validateCollectionDecisionReplacement(ctx); err != nil { + return State{}, err + } if err := overlayRepositoryLifecycle(ctx, w.store.namespace, func(ctx context.Context, statement string, args ...any) error { _, err := w.tx.Exec(ctx, statement, args...) return err @@ -567,6 +578,8 @@ func (w *Writer) Publish(ctx context.Context, dataRevision string) (State, error WHERE r.namespace=$1 AND r.repository_id<>p.repository_id LIMIT 1`, `SELECT 1 FROM operational_value_evidence e JOIN workflows p ON p.namespace=e.namespace AND p.id=e.workflow_id WHERE e.namespace=$1 AND e.repository_id<>p.repository_id LIMIT 1`, + `SELECT 1 FROM workflow_value_collections e JOIN workflows p ON p.namespace=e.namespace AND p.id=e.workflow_id + WHERE e.namespace=$1 AND e.repository_id<>p.repository_id LIMIT 1`, `SELECT 1 FROM experiment_assignments o JOIN runs r ON r.namespace=o.namespace AND r.id=o.run_id JOIN experiments d ON d.namespace=o.namespace AND d.id=o.experiment_id WHERE o.namespace=$1 AND r.workflow_id<>d.workflow_id LIMIT 1`, `SELECT 1 FROM grader_observations o JOIN runs r ON r.namespace=o.namespace AND r.id=o.run_id diff --git a/server/internal/postgresx/schema.gen.go b/server/internal/postgresx/schema.gen.go index 138c9e9ff..96b3dbfd8 100644 --- a/server/internal/postgresx/schema.gen.go +++ b/server/internal/postgresx/schema.gen.go @@ -857,6 +857,24 @@ var entityTables = map[string]entityTable{ {field: "last-failure-at", name: "last_failure_at", kind: "timestamp", sql: "TIMESTAMPTZ"}, {field: "last-ping-at", name: "last_ping_at", kind: "timestamp", sql: "TIMESTAMPTZ"}, }}, + "$workflowValueCollections": {name: "workflow_value_collections", runtime: false, canonical: true, partitioned: false, columns: []entityColumn{ + {field: "id", name: "id", kind: "", sql: "TEXT"}, + {field: "schemaVersion", name: "schema_version", kind: "numeric", sql: "BIGINT"}, + {field: "repository", name: "repository", kind: "", sql: "TEXT"}, + {field: "workflow", name: "workflow", kind: "", sql: "TEXT"}, + {field: "sourcePath", name: "source_path", kind: "", sql: "TEXT"}, + {field: "observedAt", name: "observed_at", kind: "timestamp", sql: "TIMESTAMPTZ"}, + {field: "registration", name: "registration", kind: "", sql: "TEXT"}, + {field: "collector", name: "collector", kind: "", sql: "TEXT"}, + {field: "state", name: "state", kind: "", sql: "TEXT"}, + {field: "reasonCode", name: "reason_code", kind: "", sql: "TEXT"}, + {field: "reason", name: "reason", kind: "", sql: "TEXT"}, + {field: "policyDigest", name: "policy_digest", kind: "", sql: "TEXT"}, + {field: "lastAttemptAt", name: "last_attempt_at", kind: "timestamp", sql: "TIMESTAMPTZ"}, + {field: "lastAttemptOutcome", name: "last_attempt_outcome", kind: "", sql: "TEXT"}, + {field: "repositoryId", name: "repository_id", kind: "", sql: "TEXT"}, + {field: "workflowId", name: "workflow_id", kind: "", sql: "TEXT"}, + }}, "work-items": {name: "work_items", runtime: false, canonical: false, partitioned: false, columns: []entityColumn{ {field: "id", name: "id", kind: "", sql: "TEXT"}, {field: "work-item-id", name: "work_item_id", kind: "", sql: "TEXT"}, diff --git a/server/internal/postgresx/schema.sql b/server/internal/postgresx/schema.sql index 5ef633cbe..21bda4e8f 100644 --- a/server/internal/postgresx/schema.sql +++ b/server/internal/postgresx/schema.sql @@ -66,7 +66,7 @@ CREATE TABLE IF NOT EXISTS cao_quality ( retrieved_at TIMESTAMPTZ, PRIMARY KEY (namespace, collection), FOREIGN KEY (namespace) REFERENCES cao_state(namespace) ON DELETE CASCADE, - CHECK (collection IN ('$repositories','$campaigns','$workflows','$runs','$audits','$domains','$evals','$experiments','$evalObservations','$experimentAssignments','$friction','$graders','$graderObservations','$issues','$operationalValueEvidence','$operationalValues','$outcomes','$security-findings','$skills','$tools','$transactions','work-items')), + CHECK (collection IN ('$repositories','$campaigns','$workflows','$runs','$audits','$domains','$evals','$experiments','$evalObservations','$experimentAssignments','$friction','$graders','$graderObservations','$issues','$operationalValueEvidence','$operationalValues','$outcomes','$security-findings','$skills','$tools','$transactions','$workflowValueCollections','work-items')), CHECK (availability IN ('available','empty','unavailable')), CHECK (completeness IN ('complete','partial','unknown')), CHECK (freshness IN ('current','stale','unknown')) @@ -1149,6 +1149,41 @@ CREATE TABLE IF NOT EXISTS transactions ( FOREIGN KEY (namespace) REFERENCES cao_state(namespace) ON DELETE CASCADE ); +CREATE TABLE IF NOT EXISTS workflow_value_collections ( + namespace TEXT NOT NULL, + ordinal BIGINT NOT NULL CHECK (ordinal >= 0), + present_fields BIT VARYING NOT NULL, + id TEXT NOT NULL CHECK (id <> ''), + schema_version BIGINT, + repository TEXT, + workflow TEXT, + source_path TEXT, + observed_at TIMESTAMPTZ, + registration TEXT, + collector TEXT, + state TEXT, + reason_code TEXT, + reason TEXT, + policy_digest TEXT, + last_attempt_at TIMESTAMPTZ, + last_attempt_outcome TEXT, + repository_id TEXT, + workflow_id TEXT, + + PRIMARY KEY (namespace, id), + UNIQUE (namespace, ordinal), + CHECK (bit_length(present_fields) = 16), + FOREIGN KEY (namespace) REFERENCES cao_state(namespace) ON DELETE CASCADE, + CHECK (repository_id IS NOT NULL AND repository_id <> ''), + FOREIGN KEY (namespace, repository_id) REFERENCES repositories(namespace, id) DEFERRABLE INITIALLY DEFERRED, + CHECK (workflow_id IS NOT NULL AND workflow_id <> ''), + FOREIGN KEY (namespace, workflow_id) REFERENCES workflows(namespace, id) DEFERRABLE INITIALLY DEFERRED +); + +CREATE INDEX IF NOT EXISTS workflow_value_collections_repository_id ON workflow_value_collections (namespace, repository_id, ordinal); + +CREATE INDEX IF NOT EXISTS workflow_value_collections_workflow_id ON workflow_value_collections (namespace, workflow_id, ordinal); + CREATE TABLE IF NOT EXISTS work_items ( namespace TEXT NOT NULL, ordinal BIGINT NOT NULL CHECK (ordinal >= 0), diff --git a/server/internal/postgresx/sql_plan.go b/server/internal/postgresx/sql_plan.go index 27be41edc..9f49655f9 100644 --- a/server/internal/postgresx/sql_plan.go +++ b/server/internal/postgresx/sql_plan.go @@ -281,6 +281,13 @@ func (r *readTransaction) rootMetadata(ctx context.Context, name string) (model. } completeness, freshness = "unknown", "unknown" } + if name == "$workflowValueCollections" { + if err := r.tx.QueryRowContext(ctx, `SELECT min(observed_at),min(observed_at) + FROM workflow_value_collections WHERE namespace=$1`, r.store.namespace).Scan(&asOf, &retrieved); err != nil { + return nil, err + } + completeness, freshness = "unknown", "unknown" + } value := model.Metadata{"source-id": name, "source-kind": "canonical", "availability": availability, "completeness": completeness, "freshness": freshness} var evaluated time.Time if err := r.tx.QueryRowContext(ctx, "SELECT evaluated_at FROM cao_state WHERE namespace=$1", r.store.namespace).Scan(&evaluated); err != nil { diff --git a/server/internal/postgresx/workflow_value_collection.go b/server/internal/postgresx/workflow_value_collection.go new file mode 100644 index 000000000..8833c0c42 --- /dev/null +++ b/server/internal/postgresx/workflow_value_collection.go @@ -0,0 +1,134 @@ +package postgresx + +import ( + "context" + "errors" + "fmt" + "regexp" + "slices" + "strings" + + "github.com/githubnext/gh-cao/server/internal/model" +) + +func (w *Writer) preserveCollectionDecisions(ctx context.Context) error { + _, err := w.tx.Exec(ctx, `CREATE TEMP TABLE workflow_value_collections_previous ON COMMIT DROP AS + SELECT id, observed_at, registration, collector, state, reason_code, policy_digest, + last_attempt_at, last_attempt_outcome + FROM workflow_value_collections WHERE namespace=$1`, w.store.namespace) + return err +} + +func (w *Writer) validateCollectionDecisionReplacement(ctx context.Context) error { + var invalid bool + err := w.tx.QueryRow(ctx, `SELECT EXISTS ( + SELECT 1 FROM workflow_value_collections incoming + JOIN workflow_value_collections_previous previous USING (id) + WHERE incoming.namespace=$1 AND ( + incoming.observed_at < previous.observed_at OR + (incoming.observed_at = previous.observed_at AND + ROW(incoming.registration, incoming.collector, incoming.state, incoming.reason_code, + incoming.policy_digest, incoming.last_attempt_at, incoming.last_attempt_outcome) + IS DISTINCT FROM + ROW(previous.registration, previous.collector, previous.state, previous.reason_code, + previous.policy_digest, previous.last_attempt_at, previous.last_attempt_outcome)) OR + (previous.last_attempt_at IS NOT NULL AND + (incoming.last_attempt_at IS NULL OR incoming.last_attempt_at < previous.last_attempt_at)) + ))`, w.store.namespace).Scan(&invalid) + if err != nil { + return err + } + if invalid { + return errors.New("workflow Value collection decision regressed or conflicts with accepted history") + } + return nil +} + +var valueCollectorPath = regexp.MustCompile(`^[A-Za-z0-9._/-]+\.mjs$`) +var valueCollectionReasons = map[string]string{ + "unconfigured": "No collector is registered for this workflow in the reviewed policy.", + "disabled": "The reviewed registration explicitly disables future collection; retained evidence is unchanged.", + "activity-disabled": "Activity collection is disabled in the reviewed policy.", + "never-captured": "No accepted capture is present in retained collection history.", + "api-budget": "GitHub API capacity is exhausted or reserved for ordinary Activity collection.", + "budget-unavailable": "GitHub API capacity could not be verified; retained evidence is unchanged.", + "shared-budget-unavailable": "Automatic remote acquisition is deferred until shared API request budgets can be enforced. Activity retains priority.", + "fast-mode": "Fast mode retains Value history without acquiring new evidence.", + "public-only": "Public-only collection retains Value history without acquiring new evidence.", + "timeout": "The collector exceeded its time budget; previous accepted evidence is retained.", + "collector-failed": "The collector failed; previous accepted evidence is retained.", + "invalid-evidence": "The collector returned invalid or incomplete evidence; previous accepted evidence is retained.", + "batch-budget": "The collection batch exhausted its bounded time or output budget.", + "captured": "Accepted evidence is available at its original capture and cutoff dates.", + "not-due": "The frozen cadence is already covered by retained evidence; no new evidence was acquired.", +} +var valueCollectionStateReasons = map[string][]string{ + "unconfigured": {"unconfigured"}, "disabled": {"disabled", "activity-disabled"}, + "never-captured": {"never-captured"}, + "deferred": {"api-budget", "budget-unavailable", "shared-budget-unavailable", "fast-mode", "public-only", "batch-budget"}, + "failed": {"timeout", "collector-failed", "invalid-evidence", "batch-budget"}, + "available": {"captured", "not-due"}, +} + +func validateWorkflowValueCollection(row model.Row) error { + fail := errors.New("invalid workflow Value collection record") + repository, workflow := evidenceText(row["repository"]), evidenceText(row["workflow"]) + observed, err := evidenceTime(row["observedAt"]) + registration, state := evidenceText(row["registration"]), evidenceText(row["state"]) + reason := evidenceText(row["reasonCode"]) + if err != nil || fmt.Sprint(row["schemaVersion"]) != "1" || evidenceText(row["schemaVersion"]) != "" || + !targetCoordinate.MatchString(repository) || !evidenceSlug.MatchString(workflow) || + row["sourcePath"] != ".github/workflows/"+workflow+".md" || + row["id"] != "workflow-value-collection:"+evidenceComponent(strings.ToLower(repository)+":"+workflow) || + !evidenceDigest.MatchString(evidenceText(row["policyDigest"])) || + !slices.Contains([]string{"enabled", "disabled", "unconfigured"}, registration) || + !slices.Contains(valueCollectionStateReasons[state], reason) || + evidenceText(row["reason"]) != valueCollectionReasons[reason] { + return fail + } + collector, hasCollector := row["collector"] + if registration == "unconfigured" { + if hasCollector || state != "unconfigured" { + return fail + } + } else { + if registration == "enabled" && (!hasCollector || state == "unconfigured") || + registration == "disabled" && state != "disabled" { + return fail + } + if hasCollector { + if !valueCollectorPath.MatchString(evidenceText(collector)) { + return fail + } + for _, part := range strings.Split(evidenceText(collector), "/") { + if part == "" || part == "." || part == ".." { + return fail + } + } + } + } + attempt, hasAttempt := row["lastAttemptAt"] + outcome, hasOutcome := row["lastAttemptOutcome"] + if hasAttempt || hasOutcome { + started, err := evidenceTime(attempt) + if err != nil || started.After(observed) || !slices.Contains([]string{"available", "failed"}, evidenceText(outcome)) { + return fail + } + } + for key := range row { + if !slices.Contains([]string{"schemaVersion", "id", "repository", "workflow", "sourcePath", "observedAt", + "registration", "collector", "state", "reasonCode", "reason", "policyDigest", "lastAttemptAt", + "lastAttemptOutcome", "repositoryId", "workflowId", "provenance"}, key) { + return fail + } + } + for field, expected := range map[string]string{ + "repositoryId": "repository:" + evidenceComponent(strings.ToLower(repository)), + "workflowId": "workflow:" + evidenceComponent(strings.ToLower(repository)+":"+evidenceText(row["sourcePath"])), + } { + if row[field] != expected { + return fail + } + } + return nil +} diff --git a/server/internal/postgresx/workflow_value_collection_test.go b/server/internal/postgresx/workflow_value_collection_test.go new file mode 100644 index 000000000..ba0a8c4eb --- /dev/null +++ b/server/internal/postgresx/workflow_value_collection_test.go @@ -0,0 +1,162 @@ +package postgresx + +import ( + "encoding/json" + "maps" + "os" + "strings" + "testing" + "time" + + "github.com/githubnext/gh-cao/server/internal/model" +) + +func collectionFixture(t *testing.T) model.Row { + t.Helper() + content, err := os.ReadFile("../../../dashboard/site/test/fixtures/workflow-value-collection.jsonl") + if err != nil { + t.Fatal(err) + } + var envelope struct { + Record model.Row `json:"workflow_value_collection"` + } + if err := json.Unmarshal(content, &envelope); err != nil { + t.Fatal(err) + } + envelope.Record["repositoryId"] = "repository:octo%2Fexample" + envelope.Record["workflowId"] = "workflow:octo%2Fexample%3A.github%2Fworkflows%2Fverify-bugs.md" + return envelope.Record +} + +func TestWorkflowValueCollectionValidation(t *testing.T) { + if err := validateWorkflowValueCollection(collectionFixture(t)); err != nil { + t.Fatal(err) + } + for field, value := range map[string]any{ + "id": "wrong", "sourcePath": ".github/workflows/other.md", "schemaVersion": "1", + "registration": "disabled", "lastAttemptAt": "2026-10-25T00:00:00Z", + "lastAttemptOutcome": "deferred", "capturedAt": "2026-10-23T14:00:00Z", + "collector": "../escape.mjs", "workflowId": "workflow:other", "reason": "invented", + "state": "available", + } { + record := collectionFixture(t) + record[field] = value + if err := validateWorkflowValueCollection(record); err == nil { + t.Fatalf("invalid %s must fail before native storage", field) + } + disabled := collectionFixture(t) + delete(disabled, "collector") + disabled["registration"], disabled["state"], disabled["reasonCode"] = "disabled", "disabled", "disabled" + disabled["reason"] = valueCollectionReasons["disabled"] + if err := validateWorkflowValueCollection(disabled); err != nil { + t.Fatal("a disabled registration need not retain an executable collector", err) + } + } +} + +func TestWorkflowValueCollectionHostedStorage(t *testing.T) { + store, _ := nativeTestStore(t) + record := collectionFixture(t) + writer, err := store.BeginIngestion(t.Context()) + if err != nil { + t.Fatal(err) + } + + defer writer.Abort(t.Context()) + for source, row := range map[string]model.Row{ + "$repositories": {"id": record["repositoryId"], "owner": "octo", "name": "example"}, + "$workflows": {"id": record["workflowId"], "repositoryId": record["repositoryId"], "path": record["sourcePath"], "state": "unknown"}, + "$workflowValueCollections": record, + } { + if err := writer.Append(t.Context(), source, row); err != nil { + t.Fatal(err) + } + } + if _, err := writer.Publish(t.Context(), "collection-without-a-capture"); err != nil { + t.Fatal(err) + } + sources, _, err := store.ExecuteSQLPlan(t.Context(), canonicalProjectionDefinitions(t), []string{"workflow-value-collections"}) + if err != nil { + t.Fatal(err) + } + result := sources["workflow-value-collections"] + if len(result.Rows) != 1 || result.Rows[0]["registration"] != "enabled" || + result.Rows[0]["collection-state"] != "deferred" || result.Rows[0]["reason-code"] != "api-budget" { + t.Fatalf("collection facts were lost or required a report: %+v", result) + } + for field, original := range map[string]string{"checked-at": "observedAt", "last-attempt-at": "lastAttemptAt"} { + got, err := evidenceTime(result.Rows[0][field]) + want, _ := evidenceTime(record[original]) + if err != nil || !got.Equal(want) { + t.Fatalf("original %s changed: %v", field, result.Rows[0]) + } + } + if result.Metadata["freshness"] != "unknown" { + t.Fatalf("a decision must not declare measurement freshness: %v", result.Metadata) + } +} + +func TestWorkflowValueCollectionRejectsRegressiveSnapshots(t *testing.T) { + store, _ := nativeTestStore(t) + original := collectionFixture(t) + publish := func(record model.Row, revision string) error { + writer, err := store.BeginIngestion(t.Context()) + if err != nil { + return err + } + defer writer.Abort(t.Context()) + if record != nil { + for source, row := range map[string]model.Row{ + "$repositories": {"id": record["repositoryId"], "owner": "octo", "name": "example"}, + "$workflows": {"id": record["workflowId"], "repositoryId": record["repositoryId"], "path": record["sourcePath"], "state": "unknown"}, + "$workflowValueCollections": record, + } { + if err := writer.Append(t.Context(), source, row); err != nil { + return err + } + } + } + _, err = writer.Publish(t.Context(), revision) + return err + } + if err := publish(original, "original"); err != nil { + t.Fatal(err) + } + clock, _ := evidenceTime(original["observedAt"]) + for _, scenario := range []string{"stale", "conflicting", "lost-attempt"} { + record := maps.Clone(original) + switch scenario { + case "stale": + record["observedAt"] = clock.Add(-time.Second).Format(time.RFC3339) + case "conflicting": + record["reasonCode"] = "shared-budget-unavailable" + record["reason"] = valueCollectionReasons["shared-budget-unavailable"] + case "lost-attempt": + record["observedAt"] = clock.Add(time.Hour).Format(time.RFC3339) + delete(record, "lastAttemptAt") + delete(record, "lastAttemptOutcome") + } + if err := publish(record, scenario); err == nil || !strings.Contains(err.Error(), "accepted history") { + t.Fatalf("%s snapshot must not overwrite accepted decisions: %v", scenario, err) + } + } + sources, _, err := store.ExecuteSQLPlan(t.Context(), canonicalProjectionDefinitions(t), []string{"workflow-value-collections"}) + if err != nil { + t.Fatal(err) + } + rows := sources["workflow-value-collections"].Rows + if len(rows) != 1 || rows[0]["reason-code"] != "api-budget" || rows[0]["last-attempt-outcome"] != "failed" { + t.Fatalf("failed imports changed accepted health: %v", rows) + } + disabled := maps.Clone(original) + disabled["observedAt"] = clock.Add(time.Hour).Format(time.RFC3339) + disabled["registration"], disabled["state"], disabled["reasonCode"] = "disabled", "disabled", "disabled" + disabled["reason"] = valueCollectionReasons["disabled"] + delete(disabled, "collector") + if err := publish(disabled, "disabled"); err != nil { + t.Fatal(err) + } + if err := publish(nil, "withdrawn"); err != nil { + t.Fatal("protecting clocks must not restore withdrawn collection records", err) + } +} diff --git a/server/internal/sqlitex/diagnostics.go b/server/internal/sqlitex/diagnostics.go index 587cd07bc..412466336 100644 --- a/server/internal/sqlitex/diagnostics.go +++ b/server/internal/sqlitex/diagnostics.go @@ -35,6 +35,8 @@ func (r *reader) Diagnostics(ctx context.Context) (model.Diagnostics, error) { {"operationalValues", "repositoryId", "repositories"}, {"experiments", "workflowId", "workflows"}, {"operationalValueEvidence", "repositoryId", "repositories"}, {"operationalValueEvidence", "workflowId", "workflows"}, + {"workflowValueCollections", "repositoryId", "repositories"}, + {"workflowValueCollections", "workflowId", "workflows"}, {"graders", "workflowId", "workflows"}, {"evals", "workflowId", "workflows"}, {"experimentAssignments", "runId", "runs"}, {"experimentAssignments", "experimentId", "experiments"}, {"graderObservations", "runId", "runs"}, {"graderObservations", "graderId", "graders"}, diff --git a/server/internal/sqlitex/operational_value_evidence_test.go b/server/internal/sqlitex/operational_value_evidence_test.go index 73c879414..4f663efd8 100644 --- a/server/internal/sqlitex/operational_value_evidence_test.go +++ b/server/internal/sqlitex/operational_value_evidence_test.go @@ -17,6 +17,7 @@ func TestSnapshotOperationalValueEvidenceFromExportedLedger(t *testing.T) { if err != nil { t.Fatal(err) } + var envelope struct { Packet model.Row `json:"operational_value_evidence"` } @@ -64,3 +65,52 @@ func TestSnapshotOperationalValueEvidenceFromExportedLedger(t *testing.T) { } } } + +func TestSnapshotWorkflowValueCollectionWithoutReport(t *testing.T) { + content, err := os.ReadFile("../../../dashboard/site/test/fixtures/workflow-value-collection.jsonl") + if err != nil { + t.Fatal(err) + } + var envelope struct { + Record model.Row `json:"workflow_value_collection"` + } + if err := json.Unmarshal(content, &envelope); err != nil { + t.Fatal(err) + } + record := envelope.Record + record["repositoryId"] = "repository:octo%2Fexample" + record["workflowId"] = "workflow:octo%2Fexample%3A.github%2Fworkflows%2Fverify-bugs.md" + path := testutil.SQLiteSnapshot(t, map[string][]model.Row{ + "workflowValueCollections": {record}, + "repositories": {{"id": record["repositoryId"], "owner": "octo", "name": "example"}}, + "workflows": {{"id": record["workflowId"], "repositoryId": record["repositoryId"], "path": record["sourcePath"]}}, + }) + store, err := Open(t.Context(), path) + if err != nil { + t.Fatal(err) + } + t.Cleanup(func() { _ = store.Close() }) + content, err = os.ReadFile("../../../dashboard/site/src/data/queries/database.json") + if err != nil { + t.Fatal(err) + } + var definitions []query.Definition + if err := json.Unmarshal(content, &definitions); err != nil { + t.Fatal(err) + } + err = store.WithReadTransaction(t.Context(), func(ctx context.Context, reader dashboardstore.Reader) error { + sources, _, err := reader.ExecuteSQLPlan(ctx, definitions, []string{"workflow-value-collections"}) + if err != nil { + return err + } + rows := sources["workflow-value-collections"].Rows + if len(rows) != 1 || rows[0]["registration"] != "enabled" || rows[0]["reason-code"] != "api-budget" || + rows[0]["checked-at"] != record["observedAt"] || rows[0]["last-attempt-at"] != record["lastAttemptAt"] { + t.Fatalf("SQLite lost independent decision and attempt facts without a report: %+v", rows) + } + return nil + }) + if err != nil { + t.Fatal(err) + } +} diff --git a/server/internal/testutil/sqlite.go b/server/internal/testutil/sqlite.go index aa1afd7be..344d73e49 100644 --- a/server/internal/testutil/sqlite.go +++ b/server/internal/testutil/sqlite.go @@ -41,7 +41,7 @@ func SQLiteSnapshot(t testing.TB, sources map[string][]model.Row) string { } for _, name := range []string{ "campaigns", "repositories", "workflows", "runs", "domains", "tools", "skills", "friction", "audits", "issues", - "operationalValues", "operationalValueEvidence", "marketplacePackages", "experiments", "experimentAssignments", "graders", "graderObservations", + "operationalValues", "operationalValueEvidence", "workflowValueCollections", "marketplacePackages", "experiments", "experimentAssignments", "graders", "graderObservations", "evals", "evalObservations", "transactions", } { if _, err := db.ExecContext(t.Context(), `INSERT INTO __idb_stores VALUES (?,?,'id')`, dashboardquery.DatabaseName, name); err != nil { diff --git a/server/postgres/canonical-grants.sql b/server/postgres/canonical-grants.sql index 07569bdc5..e09028faa 100644 --- a/server/postgres/canonical-grants.sql +++ b/server/postgres/canonical-grants.sql @@ -20,7 +20,7 @@ GRANT SELECT, INSERT, UPDATE, DELETE ON :"schema".runs, :"schema".audits, :"schema".domains, :"schema".evals, :"schema".experiments, :"schema".eval_observations, :"schema".experiment_assignments, :"schema".friction, :"schema".graders, :"schema".grader_observations, - :"schema".issues, :"schema".operational_values, :"schema".outcome_performance, + :"schema".issues, :"schema".operational_values, :"schema".workflow_value_collections, :"schema".outcome_performance, :"schema".security_findings, :"schema".skills, :"schema".tools, :"schema".transactions, :"schema".work_items TO :"runtime"; -- The database administrator must separately grant TEMPORARY on this database diff --git a/server/spec/storage.test.mjs b/server/spec/storage.test.mjs index 226f097e1..681cb9ae2 100644 --- a/server/spec/storage.test.mjs +++ b/server/spec/storage.test.mjs @@ -56,7 +56,7 @@ function inputFields(definition) { test('TypeSpec declares exactly one root table per canonical dashboard collection', () => { assert.deepEqual([...tables.keys()].sort(), [ - '$campaigns', '$repositories', '$workflows', '$runs', ...records, '$operationalValues', '$operationalValueEvidence', + '$campaigns', '$repositories', '$workflows', '$runs', ...records, '$operationalValues', '$operationalValueEvidence', '$workflowValueCollections', '$marketplacePackages', '$experiments', '$experimentAssignments', '$graders', '$graderObservations', '$evals', '$evalObservations' ].sort()); @@ -126,6 +126,9 @@ test('native table fields cover database projections and joins without speculati required.get('$runs').add('repositoryId'); // Cross-parent canonical integrity. // This input normalizes the packet and its typed child values, not root columns. required.set('$operationalValueEvidence', new Set(tables.get('$operationalValueEvidence'))); + for (const field of ['schemaVersion', 'repository', 'workflowId']) { + required.get('$workflowValueCollections').add(field); // Versioned producer identity and parent integrity. + } for (const definition of definitions) { if (definition.from === '$operationalValueEvidence') continue; const sources = [definition.from]; diff --git a/server/spec/storage.tsp b/server/spec/storage.tsp index 3b6a685e9..df700a313 100644 --- a/server/spec/storage.tsp +++ b/server/spec/storage.tsp @@ -490,6 +490,28 @@ model operationalValueEvidence { facts: Values.OperationalValueFact[]; } +/** Latest reviewed registration and collection decision, independent of outcome evidence. */ +model workflowValueCollections { + id: string; + schemaVersion: int64; + repository: string; + workflow: string; + sourcePath: string; + observedAt: utcDateTime; + registration: string; + collector?: string; + state: string; + reasonCode: string; + reason: string; + policyDigest: string; + lastAttemptAt?: utcDateTime; + lastAttemptOutcome?: string; + @parent("repositories") + repositoryId: string; + @parent("workflows") + workflowId: string; +} + model operationalValues { @minValueExclusive(0) `cadence-days`?: decimal; diff --git a/specs/dashboard-data.md b/specs/dashboard-data.md index 11e25e683..762a45b08 100644 --- a/specs/dashboard-data.md +++ b/specs/dashboard-data.md @@ -40,7 +40,7 @@ Audit retains typed routing identifiers, classifier labels, request identities, sub-agent ownership, token classes, per-response AIC and collection receipts. It MUST NOT retain prompts, bodies, free-form errors/reasons, raw tool payloads or content-derived hashes. -Canonical schema 34 and IndexedDB version 44 invalidate older browser projections; +Canonical schema 35 and IndexedDB version 45 invalidate older browser projections; hosted PostgreSQL deployments require a fresh schema with the generated Audit and Run aggregate columns. Inventory (`model.inventory`) and generic proxy (`firewall.event`) rows SHALL NOT be retained, including replayed cached @@ -2888,14 +2888,15 @@ with policy. The skill SHALL stage registration automatically only after the frozen function and bounded collector pass verification, preserving existing registrations and explicit `enabled: false` disables. Function presence alone SHALL NOT grant execution authority or enroll a repository. -The existing Activity or hosted collection cycle SHALL intersect +An admitted collection SHALL intersect that selection with effective repository collection scope and the frozen cadence. It SHALL preserve reusable immutable proof and actual capture/cutoff timestamps. Collection failure SHALL retain the previous accepted evidence, not advance freshness or fabricate zero. Disable SHALL stop future acquisition without deleting retained history. Navigation, report publication and workflow discovery SHALL NOT infer opt-in. No per-workflow schedule or model assessment -is required for continued measurement. +is required for continued measurement. The health-first admission and deferral +contract in section 31.3 governs automatic acquisition. The single logical source `operational-value-evidence` SHALL purely normalize these originals. Every row SHALL expose `report-id`, `organization`, @@ -2930,6 +2931,83 @@ presentation SHALL be Dashboard Language queries over these factual rows, re-executed within the active abort-scoped worker subscription. No navigation handler SHALL fetch saved reports or acquire missing evidence. +## 31.3 Workflow Value collection health + +Canonical schema 35 SHALL retain `workflowValueCollections`, independently of +`operationalValueEvidence`: one current bounded record per exact repository and +workflow filename stem. A schema-v2 `workflow_value_collection` JSONL envelope +SHALL carry the record through the ordinary Activity adapter, normalized +publication, browser IndexedDB, local SQLite and hosted PostgreSQL paths. +Registration and health are collection facts, not outcome measurements or +authorization to execute a target workflow. + +The producer SHALL resolve the reviewed policy within effective Activity scope. +It SHALL publish `registration` (`enabled`, `disabled`, or `unconfigured`), +the confined collector path when configured (optional for an explicit disable), a policy digest, the actual +decision `observedAt`, `state`, `reasonCode` and a bounded non-sensitive reason. +States are `unconfigured`, `disabled`, `never-captured`, `deferred`, `failed` +and `available`. Unconfigured requires an observed workflow and an explicit +policy check; absent reports or absent collection records do not establish it. +Never-captured describes the absence of an accepted capture in the retained +collection history, not a claim about unavailable historical archives. +The latest decision replaces the entire health record; stale imports MUST NOT +roll it back. Health records retain structural parents without requiring a Run. + +`lastAttemptAt` and `lastAttemptOutcome`, when present, SHALL describe an actual +collector process invocation, including a cadence check. Deferral before +invocation MUST NOT advance them. Disabled or removed registrations preserve +recorded attempts and accepted evidence. Last successful evidence capture and +cutoff SHALL come from original accepted packets, never the decision timestamp. +The `workflow-value-collections` logical source and declarative Value views SHALL +keep these clocks separate and show registration health before a first report. +No health observation promotes outcome completeness or freshness. +Explicit disables without a collector path SHALL remain disabled, not +unconfigured. Newer decisions MUST NOT discard or regress a known attempt clock; +conflicting decisions at the same observation time SHALL fail. + +Optional Value acquisition MUST NOT delay ordinary Activity publication, consume +its protected API headroom, or hold the hosted projection lease. A separate job +or process alone does not isolate GitHub quota. The existing recurring +subprocess collectors do not participate in shared, per-request REST, search and +GraphQL admission; automatic Activity and hosted cycles SHALL therefore publish +health and retain evidence without invoking remote acquisition. Observed API exhaustion, +fast mode and public-only mode retain their precise deferral reasons; otherwise +the decision SHALL name unavailable shared-budget enforcement. No quota probe, +token mint, historical seed, retry loop or backfill is needed to publish that +decision. Explicit operator evaluation and evidence publication remain separate. + +This deferral SHALL NOT disable bounded cache-only or deterministic local +computations. An independent optional lane MAY compute against an already +published, policy-matched eligible Activity snapshot, without target credentials, +quota probes, downloads, automatic backfill, or remote collector execution. +Only the reviewed local-only-capable standard adapter may run there; older or +custom adapters that cannot enforce that contract SHALL defer. Modules must +explicitly declare their local capability; other modules may reuse exact, +version-matched retained observations but SHALL NOT acquire missing inputs. +Existing fast, public-only and API-limited snapshot gates SHALL remain intact. + +Actions SHALL complete Activity publication before starting the optional local +workflow. A later Activity snapshot may import its validated, bounded results. +The hosted worker SHALL use its own single-owner lease and a verified private +snapshot, not the projection lease or a long-held core evidence lock. Computation +SHALL be bounded to two minutes per batch and thirty seconds per adapter. +Local output and retained imports SHALL remain within 16 MiB; the hosted private +snapshot SHALL remain within 256 MiB with individual inputs bounded to 16 MiB. +An optional result import failure MUST retain accepted evidence without failing +ordinary Activity publication. +Completed local results SHALL wait for the next ordinary projection, not create +a compute/publication retry loop. A final short publication rechecks enrollment; +failure, timeout or withdrawal MUST NOT replace accepted evidence or hold up +ordinary Activity publication. These bounds do not claim isolation from unrelated +host CPU/I/O consumers, Actions transport requests, or external API consumers. + +Resuming automatic acquisition requires request-accounted shared admission, +protected core headroom and bounded requests, elapsed time and concurrency, +including other work sharing the credential. Expensive historical acquisition +requires a separately bounded explicit action. Immutable facts may be reused +only under the frozen contract; old mutable observations MUST NOT become current +merely by replaying retained proof. + --- # 32. Bounded Ingestion diff --git a/tests/unit/activity-partial-collection.test.mjs b/tests/unit/activity-partial-collection.test.mjs index 6957ceb5f..10a649614 100644 --- a/tests/unit/activity-partial-collection.test.mjs +++ b/tests/unit/activity-partial-collection.test.mjs @@ -199,9 +199,15 @@ test("partial fragments skip extra API work without bypassing authentication and const steps = workflow.jobs.collect.steps; assert.equal(steps.find(({ name }) => name === "Enrich owner-scoped issue statuses").if, "steps.activity-logs.outputs.rate-limited != 'true' && matrix.publicOnly != true"); - const value = steps.find(({ name }) => name === "Compute owner-scoped operational value"); + const value = steps.find(({ name }) => name === "Retain Value evidence and publish collection health"); assert.equal(value.env.REPORT_RATE_LIMITED, "${{ steps.activity-logs.outputs.rate-limited }}"); assert.ok(value.run.indexOf('cp "$retained_values" "$value_output"') < value.run.indexOf('"$REPORT_RATE_LIMITED" == "true"')); + assert.match(value.run, /reason=api-budget/); + assert.match(value.run, /--defer "\$reason"/); + assert.equal(value.env.GH_TOKEN, ""); + assert.equal(value["timeout-minutes"], 1); + assert.equal(value["continue-on-error"], true); + assert.doesNotMatch(value.run, /cao\.mjs operational-value|gh api/); assert.equal(steps.find(({ name }) => name === "Select independent activity credential")["continue-on-error"], undefined); assert.equal(steps.find(({ name }) => name === "Validate repository visibility boundary")["continue-on-error"], undefined); assert.match(workflow.jobs.index.if, /needs\.collect\.result == 'success'/); diff --git a/tests/unit/cao-operational-value-evidence.test.mjs b/tests/unit/cao-operational-value-evidence.test.mjs index 23c975158..adc0c82d5 100644 --- a/tests/unit/cao-operational-value-evidence.test.mjs +++ b/tests/unit/cao-operational-value-evidence.test.mjs @@ -1,6 +1,6 @@ import assert from 'node:assert/strict'; import { execFileSync } from 'node:child_process'; -import { mkdirSync, readFileSync, readdirSync, rmSync } from 'node:fs'; +import { mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from 'node:fs'; import path from 'node:path'; import test from 'node:test'; import { exportOperationalValueEvidence, operationalValueEvidenceJsonl } from '../../.github/skills/add-operational-value/scripts/export-evidence.mjs'; @@ -74,6 +74,16 @@ test('shared writePulse publishes adjacent replayable evidence and normal CLI ca writePulse(ledger, output); const evidence = output.replace(/\.html$/, '-evidence.jsonl'); assert.deepEqual(JSON.parse(readFileSync(evidence)), JSON.parse(operationalValueEvidenceJsonl(ledger))); + const policy = path.join(directory, 'cao.json'); + writeFileSync(policy, JSON.stringify({ version: 1, 'gh-aw-version': 'v0.93.1', 'control-plane': { + scope: { 'allowed-repositories': ['octo/example'] }, activity: { repositories: ['octo/example'] }, + campaigns: { activity: { 'workflow-values': [{ + repository: 'octo/example', workflow: 'verify-bugs', collector: 'collectors/not-imported.mjs', + }] } }, + } })); + execFileSync(process.execPath, ['activity/workflow-values.mjs', '--root', directory, '--policy', policy, + '--output', evidence, '--healthOutput', path.join(directory, 'collection.jsonl'), '--repository', 'octo/example', + '--defer', 'api-budget'], { stdio: 'pipe' }); const database = path.join(directory, 'dashboard.sqlite'); execFileSync(process.execPath, ['activity/cao.mjs', 'ingest-jsonl', '--database', database, '--input-dir', directory, '--retention-days', 'all'], { stdio: 'pipe' }); @@ -81,15 +91,35 @@ test('shared writePulse publishes adjacent replayable evidence and normal CLI ca '--database', database, '--collection', 'operationalValueEvidence'], { encoding: 'utf8' })); assert.equal(rows.length, 1); assert.equal(rows[0].facts.length, exportOperationalValueEvidence(ledger).facts.length); + const health = JSON.parse(execFileSync(process.execPath, ['activity/cao.mjs', 'query', + '--database', database, '--collection', 'workflowValueCollections'], { encoding: 'utf8' })); + assert.equal(health.length, 1); + assert.equal(health[0].registration, 'enabled'); + assert.equal(health[0].reasonCode, 'api-budget'); + assert.equal(health[0].lastAttemptAt, undefined); + assert.equal(rows[0].observedAt, ledger.observedAt); const published = path.join(directory, 'normalized'); + const runPhase = path.join(published, 'runs'); + const recordPhase = path.join(published, 'records'); execFileSync(process.execPath, ['activity/cao.mjs', 'hash-payloads', '--database', database, - '--shard-dir', directory, '--normalized-dir', published, '--output', path.join(directory, 'payload-hashes.json')], + '--shard-dir', directory, '--runs-dir', runPhase, '--records-dir', recordPhase, + '--output', path.join(directory, 'payload-hashes.json')], { stdio: 'pipe' }); - const records = readdirSync(published).filter(name => name.endsWith('.jsonl')).flatMap(name => - readFileSync(path.join(published, name), 'utf8').trim().split('\n').map(line => JSON.parse(line))); + const records = [runPhase, recordPhase].flatMap(phase => + readdirSync(phase).filter(name => name.endsWith('.jsonl')).flatMap(name => + readFileSync(path.join(phase, name), 'utf8').trim().split('\n').map(line => JSON.parse(line)))); const packet = records.find(record => record.collection === 'operationalValueEvidence')?.record; assert.equal(packet.id, rows[0].id); assert.equal(packet.facts.length, rows[0].facts.length); + const normalizedHealth = records.find(record => record.collection === 'workflowValueCollections')?.record; + assert.equal(normalizedHealth.id, health[0].id); + assert.equal(normalizedHealth.observedAt, health[0].observedAt); + const replay = path.join(directory, 'replay.sqlite'); + execFileSync(process.execPath, ['activity/cao.mjs', 'ingest-jsonl', '--database', replay, + '--runs-dir', runPhase, '--records-dir', recordPhase, '--retention-days', 'all'], { stdio: 'pipe' }); + const replayed = JSON.parse(execFileSync(process.execPath, ['activity/cao.mjs', 'query', + '--database', replay, '--collection', 'workflowValueCollections'], { encoding: 'utf8' })); + assert.deepEqual(replayed, health); } finally { rmSync(directory, { recursive: true, force: true }); } diff --git a/tests/unit/cao-operational-value.test.mjs b/tests/unit/cao-operational-value.test.mjs index 52e9de1b6..5c1007a17 100644 --- a/tests/unit/cao-operational-value.test.mjs +++ b/tests/unit/cao-operational-value.test.mjs @@ -1,10 +1,11 @@ import assert from 'node:assert/strict'; import { execFileSync, spawn, spawnSync } from 'node:child_process'; +import { createHash } from 'node:crypto'; import { chmodSync, existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'; import os from 'node:os'; import path from 'node:path'; import test from 'node:test'; -import { runOperationalValue } from '../../activity/operational-value.mjs'; +import { LOCAL_VALUE_ADAPTER_DIGEST, MAX_LOCAL_VALUE_BYTES, runOperationalValue } from '../../activity/operational-value.mjs'; const root = path.resolve(import.meta.dirname, '..', '..'); const cao = path.join(root, 'activity', 'cao.mjs'); @@ -170,10 +171,10 @@ export function collectBatch(windows) { export function scoreMetric(id, evidence) { return evidence.value; } `; writeFileSync(modulePath, moduleSource); - const run = (timestamp) => JSON.parse(execFileSync(process.execPath, [ + const run = (timestamp, extra = []) => JSON.parse(execFileSync(process.execPath, [ cao, 'operational-value', '--database', database, '--root', temporary, '--output', output, '--timestamp', timestamp, '--repository', 'octo/api', - '--retention-days', '30' + '--retention-days', '30', ...extra ], { encoding: 'utf8' })); const ingest = () => execFileSync(process.execPath, [ cao, 'ingest-jsonl', '--database', database, '--input', output @@ -210,6 +211,11 @@ export function scoreMetric(id, evidence) { return evidence.value; } assert.equal(reused.values[0].evidenceDigest, first.values[0].evidenceDigest); assert.equal(reused.values[0].populationDigest, first.values[0].populationDigest); assert.equal(readFileSync(output, 'utf8').trim().split('\n').length, 1); + const localReuse = run('2026-09-24T11:01:00Z', ['--local-only', '--max-github-api-rate-limit', '-2000']); + assert.deepEqual(localReuse.warnings, []); + assert.equal(localReuse.values[0].timestamp, first.values[0].timestamp); + assert.equal(localReuse.values[0].evidenceDigest, first.values[0].evidenceDigest); + assert.equal(callCount(), 1, 'cache-only reuse must not perform remote acquisition or a quota probe'); const accepted = JSON.parse(readFileSync(output, 'utf8').trim()); const unavailable = { ...accepted, operational_value: { @@ -244,6 +250,112 @@ export function scoreMetric(id, evidence) { return evidence.value; } } }); +test('local-only mode admits the reviewed adapter, computes declared local modules and defers remote or legacy code', async (t) => { + const temporary = mkdtempSync(path.join(root, '.tmp', 'value-local-only-')); + t.after(() => rmSync(temporary, { recursive: true, force: true })); + const campaign = path.join(temporary, 'example'); + const modules = path.join(campaign, 'operational-value'); + mkdirSync(modules, { recursive: true }); + const template = readFileSync(path.join(root, '.github/skills/add-operational-value/templates/campaign-operational-value.mjs')); + assert.equal(createHash('sha256').update(template).digest('hex'), LOCAL_VALUE_ADAPTER_DIGEST); + writeFileSync(path.join(campaign, 'operational-value.mjs'), template); + const called = path.join(temporary, 'local-called'); + for (const slug of ['local-worker', 'remote-worker', 'disabled-worker']) { + const local = slug === 'local-worker'; + writeFileSync(path.join(modules, `${slug}.mjs`), ` +import { writeFileSync } from "node:fs"; +export const localCollection = ${local}; +export const definition = { + slug: "${slug}", adoption: {adoptedAt:"2026-09-01T00:00:00Z"}, + evaluation: {mode:"attainment-only"}, + evidence: {repositories:["octo/api"], window:{durationDays:7,maturationDays:0,cadenceDays:1}}, + metrics: [{id:"count",name:"Count",role:"primary",unit:"items",direction:"decrease"}] +}; +export function collectBatch(windows, context) { + if (!${local} || !context.localOnly || process.env.GH_TOKEN || process.env.GITHUB_TOKEN + || process.env.CAO_OPERATIONAL_VALUE_GH_TOKEN) throw new Error("remote boundary crossed"); + writeFileSync(${JSON.stringify(called)}, "local"); + return windows.map(() => ({evidence:{value:3}})); +} +export function scoreMetric(id, evidence) { return evidence.value; } +`); + } + const legacy = path.join(temporary, 'legacy'); + mkdirSync(legacy); + writeFileSync(path.join(legacy, 'operational-value.mjs'), `throw new Error("legacy adapter must never execute");`); + const output = path.join(temporary, 'retained.jsonl'); + const disabled = { schema_version: 2, kind: 'operational_value', operational_value: { + timestamp: '2026-10-19T12:00:00Z', campaign: 'example', repository: 'octo/api', + value_id: 'disabled-worker.count', value: 7, + } }; + writeFileSync(output, JSON.stringify(disabled) + '\n'); + const result = await runOperationalValue({ + root: temporary, databasePath: path.join(temporary, 'empty.sqlite'), repositories: ['octo/api'], + localOnly: true, rateLimitReserve: 2000, timestamp: '2026-10-20T12:00:00Z', + disabledWorkflows: ['disabled-worker'], outputPath: output, retentionWindow: 365 * 86400000, + }); + assert.equal(result.values.length, 1); + assert.equal(result.values[0].value, 3); + assert.equal(readFileSync(called, 'utf8'), 'local'); + assert.equal(result.warnings.length, 2); + assert.ok(result.warnings.some(warning => warning.message.includes('Remote acquisition requires enforceable shared API admission'))); + assert.ok(result.warnings.some(warning => warning.message.includes('no reviewed local-only boundary'))); + assert.ok(readFileSync(output, 'utf8').trim().split('\n').some(line => JSON.stringify(JSON.parse(line)) === JSON.stringify(disabled))); +}); + +test('local-only input, combined output and cumulative worker budgets preserve accepted evidence', async (t) => { + const temporary = mkdtempSync(path.join(os.tmpdir(), 'cao-local-value-budget-')); + t.after(() => rmSync(temporary, { recursive: true, force: true })); + const template = readFileSync(path.join(root, '.github/skills/add-operational-value/templates/campaign-operational-value.mjs')); + const output = path.join(temporary, 'values.jsonl'); + const config = { + root: temporary, databasePath: path.join(temporary, 'empty.sqlite'), repositories: ['octo/api'], + outputPath: output, localOnly: true, timestamp: '2026-10-20T12:00:00Z', retentionWindow: 365 * 86400000, + }; + const accepted = { schema_version: 2, kind: 'operational_value', operational_value: { + campaign: 'retained', repository: 'octo/api', value_id: 'worker.count', + timestamp: '2026-10-19T12:00:00Z', value: 0, + }, padding: '' }; + const sizedEvidence = bytes => { + accepted.padding = ''; + accepted.padding = 'x'.repeat(bytes - Buffer.byteLength(JSON.stringify(accepted)) - 1); + return JSON.stringify(accepted) + '\n'; + }; + const oversized = sizedEvidence(MAX_LOCAL_VALUE_BYTES + 1); + writeFileSync(output, oversized); + await assert.rejects(runOperationalValue(config), /Retained local Value exceeds its byte budget/); + assert.equal(readFileSync(output, 'utf8'), oversized); + + const addCampaign = (name, metricBytes) => { + const campaign = path.join(temporary, name); + mkdirSync(path.join(campaign, 'operational-value'), { recursive: true }); + writeFileSync(path.join(campaign, 'operational-value.mjs'), template); + writeFileSync(path.join(campaign, 'operational-value/worker.mjs'), ` +export const localCollection = true; +export const definition = { + slug: "worker", adoption: {adoptedAt:"2026-09-01T00:00:00Z"}, evaluation: {mode:"attainment-only"}, + evidence: {repositories:["octo/api"], window:{durationDays:7,maturationDays:0,cadenceDays:1}}, + metrics: [{id:"count",name:"x".repeat(${metricBytes}),role:"primary",unit:"items",direction:"decrease"}] +}; +export function collectBatch(windows) { return windows.map(() => ({evidence:{value:1}})); } +export function scoreMetric(id, evidence) { return evidence.value; } +`); + }; + addCampaign('first', 5); + const retained = sizedEvidence(MAX_LOCAL_VALUE_BYTES - 32); + writeFileSync(output, retained); + await assert.rejects(runOperationalValue(config), /Combined local Value exceeds its output budget/); + assert.equal(readFileSync(output, 'utf8'), retained); + + accepted.padding = ''; + const original = JSON.stringify(accepted) + '\n'; + writeFileSync(output, original); + addCampaign('first', MAX_LOCAL_VALUE_BYTES / 2 + 1024); + addCampaign('second', MAX_LOCAL_VALUE_BYTES / 2 + 1024); + await assert.rejects(runOperationalValue(config), /Local Value batch exceeded its output budget/); + assert.equal(readFileSync(output, 'utf8'), original); +}); + function writeProcessTreeWorker(packageDirectory, config) { writeFileSync(path.join(packageDirectory, 'config.json'), JSON.stringify(config)); writeFileSync(path.join(packageDirectory, 'descendant.mjs'), ` diff --git a/tests/unit/workflow-contract-dashboard-delivery.test.mjs b/tests/unit/workflow-contract-dashboard-delivery.test.mjs index 395004f44..418b67e40 100644 --- a/tests/unit/workflow-contract-dashboard-delivery.test.mjs +++ b/tests/unit/workflow-contract-dashboard-delivery.test.mjs @@ -463,7 +463,7 @@ test("Dashboard campaign builds artifacts and deploys Pages in one workflow", () assert.doesNotMatch(activityWorkflow, /REPORT_VALUE_CACHE/); assert.doesNotMatch(activityWorkflow, /REPORT_VALUE_REPLAY_CACHE/); assert.match(dashboardWorkflow, /actions\/cache\/restore@[0-9a-f]{40}/); - assert.equal((activityWorkflow.match(/actions\/cache\/restore@/g) || []).length, 3); + assert.equal((activityWorkflow.match(/actions\/cache\/restore@/g) || []).length, 4); assert.equal((activityWorkflow.match(/actions\/cache\/save@/g) || []).length, 1); assert.doesNotMatch(activityWorkflow, /dashboard-operational-values/); assert.match(activityWorkflow, /Resolve gh-aw compiler version[\s\S]*control\.mjs compiler-version \.github\/workflows\/cao\.json/); @@ -503,6 +503,7 @@ test("Activity campaign owns the shared collected-data cache contract", () => { assert.equal(activityManifest.name, "CAO Activity"); assert.deepEqual(activityManifest.includes, [ ".github/workflows/cao-activity.yml", + ".github/workflows/cao-value-local.yml", ]); assert.equal(activityManifest.resources, undefined); assert.ok(rootManifest.includes.includes("activity/aw.yml")); @@ -539,15 +540,20 @@ test("Activity campaign owns the shared collected-data cache contract", () => { assert.match(activityCollector, /REPORT_DEFER_ISSUE_STATUS/); assert.match(workflow, /Download owner-scoped agentic workflow logs[\s\S]*?REPORT_DEFER_ISSUE_STATUS: "1"[\s\S]*?Enrich owner-scoped issue statuses[\s\S]*?cao\.mjs issue-status[\s\S]*?Generate phased activity shards/); assert.match(workflow, /Ingest activity database[\s\S]*?gh-aw-logs\.sqlite[\s\S]*?ingest-jsonl/); - assert.match(workflow, /Compute owner-scoped operational value[\s\S]*?cao\.mjs operational-value[\s\S]*?--max-github-api-rate-limit "\$REPORT_MAX_GITHUB_API_RATE_LIMIT"/); - assert.match(workflow, /cao\.mjs operational-value[\s\S]*?--retention-days 365/); + assert.doesNotMatch(workflow, /cao\.mjs operational-value/); + assert.match(workflow, /Retain Value evidence and publish collection health[\s\S]*?--defer "\$reason"/); assert.doesNotMatch(workflow, /--history-campaign/); - assert.match(workflow, /Compute owner-scoped operational value[\s\S]*?REPORT_VALUE_SEED_SHARDS:[\s\S]*?cp "\$retained_values" "\$value_output"[\s\S]*?ingest-jsonl[\s\S]*?--input "\$value_output"/); + assert.match(workflow, /Retain Value evidence and publish collection health[\s\S]*?REPORT_VALUE_SEED_SHARDS:[\s\S]*?cp "\$retained_values" "\$value_output"/); assert.match(workflow, /paths:[\s\S]*?- "activity\/\*\*"/); assert.match(workflow, /paths:[\s\S]*?- "\*\/operational-value\/\*\*"/); assert.match(workflow, /Select independent activity credential[\s\S]*?id: activity-credential[\s\S]*?echo "token=\$token" >> "\$GITHUB_OUTPUT"/); - assert.match(workflow, /Compute owner-scoped operational value[\s\S]*?CAO_OPERATIONAL_VALUE_GH_TOKEN: \$\{\{ steps\.activity-credential\.outputs\.token \}\}/); - assert.match(workflow, /if ! node activity\/cao\.mjs operational-value[\s\S]*?Operational value collection failed for \$ACTIVITY_OWNER/); + assert.match(workflow, /Retain Value evidence and publish collection health[\s\S]*?CAO_OPERATIONAL_VALUE_GH_TOKEN: ""/); + assert.match(workflow, /Report collection-health publication failure/); + const optionalImport = parse(workflow).jobs.index.steps.find(step => step.id === "local-value-import"); + assert.equal(optionalImport["continue-on-error"], true); + assert.equal(optionalImport["timeout-minutes"], 1); + assert.match(optionalImport.if, /inputs.recycle-only != true/); + assert.match(workflow, /Report optional local Value import failure/); assert.equal((workflow.match(/path: \$\{\{ runner\.temp \}\}\/cao-activity\s*$/gm) || []).length, 1); assert.match(workflow, /cao-activity-v5-\$\{\{ github\.run_id \}\}-/); assert.equal(campaignDocument.scripts["activity:local"], undefined); diff --git a/tests/unit/workflow-values-recurring.test.mjs b/tests/unit/workflow-values-recurring.test.mjs index 76470e3e5..99690369f 100644 --- a/tests/unit/workflow-values-recurring.test.mjs +++ b/tests/unit/workflow-values-recurring.test.mjs @@ -1,12 +1,18 @@ import assert from 'node:assert/strict'; import { mkdtemp, mkdir, readFile, readdir, rm, symlink, writeFile } from 'node:fs/promises'; import path from 'node:path'; +import { tmpdir } from 'node:os'; import test from 'node:test'; import { assertValueHistory, confinedCollector, runWorkflowValues, workflowValueRegistrations } from '../../activity/workflow-values.mjs'; import { controlSettings, parsePolicy } from '../../.github/workflows/shared/policy.mjs'; import { activityCollectionPlan } from '../../activity/authentication.mjs'; import { adaptCachedGhAwJsonl } from '../../dashboard/site/src/data/adapters/gh-aw-logs.js'; import { normalize } from '../../dashboard/site/src/data/normalize/index.js'; +import { localValuePlan, retainLocalValues } from '../../activity/local-values.mjs'; + +async function collection(options) { + return JSON.parse(await readFile(options.output.replace(/\.jsonl$/, '-collections.jsonl'), 'utf8')).workflow_value_collection; +} const entry = { repository: 'org/repo', workflow: 'daily-review', collector: 'collectors/value.mjs' }; function policy() { @@ -33,7 +39,7 @@ function packet(observedAt = '2026-10-20T12:00:00.000Z') { } async function fixture(t, body) { - const root = await mkdtemp(path.resolve('.workflow-values-test-')); + const root = await mkdtemp(path.join(tmpdir(), 'cao-workflow-values-test-')); t.after(() => rm(root, { recursive: true, force: true })); await mkdir(path.join(root, 'collectors')); const policyPath = path.join(root, 'cao.json'); @@ -189,3 +195,146 @@ test('a due capture reuses workflow proofs, preserves original facts, and advanc assert.equal(evidence.windowStart, packet().operational_value_evidence.windowStart); assert.deepEqual(evidence.facts[0], packet().operational_value_evidence.facts[0]); }); + +test('first-capture deferrals publish enabled registration without importing a collector or reserving shared quota', async (t) => { + const options = await fixture(t); + await writeFile(path.join(options.root, entry.collector), "throw new Error('must not import');"); + for (const reason of ['api-budget', 'shared-budget-unavailable', 'fast-mode', 'public-only']) { + const result = await runWorkflowValues({ ...options, defer: reason }); + assert.equal(result.deferred, 1); + assert.equal(result.failed, 0); + const fact = await collection(options); + assert.equal(fact.registration, 'enabled'); + assert.equal(fact.state, 'deferred'); + assert.equal(fact.reasonCode, reason); + assert.equal(fact.lastAttemptAt, undefined); + await assert.rejects(readFile(options.output), { code: 'ENOENT' }); + await assert.rejects(readdir(options.workspace), { code: 'ENOENT' }); + const batch = normalize(adaptCachedGhAwJsonl(`${JSON.stringify({ + schema_version: 2, kind: 'workflow_value_collection', workflow_value_collection: fact, + })}\n`).observations); + assert.equal(batch.workflowValueCollections.length, 1); + assert.equal(batch.workflows[0].state, 'unknown'); + assert.equal(batch.runs.length, 0); + } +}); + +test('a newer failure, deferral, disable and removal retain capture, proof and the actual last attempt separately', async (t) => { + const options = await fixture(t); + let clock = '2026-10-23T10:00:00.000Z'; + options.now = () => clock; + await runWorkflowValues(options); + const original = await readFile(options.output, 'utf8'); + const [proof] = await readdir(options.workspace); + const proofPath = path.join(options.workspace, proof, 'proof.json'); + const originalProof = await readFile(proofPath, 'utf8'); + options.observedAt = '2026-10-21T12:00:00.000Z'; + options.timeout = 50; + await writeFile(path.join(options.root, entry.collector), 'await new Promise(resolve => setTimeout(resolve, 10000));'); + clock = '2026-10-23T11:00:00.000Z'; + await runWorkflowValues(options); + const failed = await collection(options); + assert.equal(failed.reasonCode, 'timeout'); + assert.equal(failed.lastAttemptOutcome, 'failed'); + assert.equal(failed.lastAttemptAt, clock); + clock = '2026-10-23T12:00:00.000Z'; + await runWorkflowValues({ ...options, defer: 'api-budget' }); + const deferred = await collection(options); + assert.equal(deferred.observedAt, clock); + assert.equal(deferred.lastAttemptAt, failed.lastAttemptAt); + assert.equal(deferred.lastAttemptOutcome, 'failed'); + const disabled = policy(); + disabled['control-plane'].campaigns.activity['workflow-values'] = [{ ...entry, enabled: false }]; + await writeFile(options.policy, JSON.stringify(disabled)); + clock = '2026-10-23T13:00:00.000Z'; + await runWorkflowValues({ ...options, defer: 'api-budget' }); + assert.equal((await collection(options)).registration, 'disabled'); + assert.equal((await collection(options)).state, 'disabled'); + disabled['control-plane'].campaigns.activity['workflow-values'] = []; + await writeFile(options.policy, JSON.stringify(disabled)); + clock = '2026-10-23T14:00:00.000Z'; + await runWorkflowValues({ ...options, defer: 'api-budget' }); + assert.equal((await collection(options)).state, 'unconfigured'); + assert.equal((await collection(options)).collector, undefined); + assert.equal((await collection(options)).lastAttemptAt, failed.lastAttemptAt); + assert.equal(await readFile(options.output, 'utf8'), original); + assert.equal(await readFile(proofPath, 'utf8'), originalProof); +}); + +test('missing inventory availability does not hide a reviewed registration and local eligibility respects every existing gate', async (t) => { + const options = await fixture(t); + const snapshot = path.join(options.root, 'snapshot'); + const inventory = path.join(options.root, 'inventory.json'); + await writeFile(inventory, JSON.stringify({ + repositories: { rows: [], metadata: { availability: 'unavailable' } }, + workflows: { rows: [], metadata: { availability: 'unavailable' } }, + })); + for (const reason of ['shared-budget-unavailable', 'api-budget', 'fast-mode', 'public-only']) { + const localRequest = path.join(snapshot, 'gh-aw-logs-shards', 'workflow-value-local.json'); + await runWorkflowValues({ ...options, inventory, defer: reason, localRequest, snapshot: '1-1' }); + assert.equal((await collection(options)).state, 'deferred'); + const plan = await localValuePlan({ policy: options.policy, snapshot, snapshotKey: '1-1' }); + assert.deepEqual(plan.repositories, reason === 'shared-budget-unavailable' ? ['org/repo'] : []); + assert.deepEqual((await localValuePlan({ policy: options.policy, snapshot, snapshotKey: '1-2' })).repositories, []); + } +}); + +test('a bounded batch defers without an invocation and withdrawn scope is not republished', async (t) => { + const options = await fixture(t); + await runWorkflowValues({ ...options, batchTimeout: 0 }); + assert.equal((await collection(options)).reasonCode, 'batch-budget'); + assert.equal((await collection(options)).lastAttemptAt, undefined); + await writeFile(options.output, `${JSON.stringify(packet())}\n`); + await runWorkflowValues({ ...options, repositories: ['org/other'], defer: 'shared-budget-unavailable' }); + assert.equal(await readFile(options.output, 'utf8'), ''); + assert.equal(await readFile(options.output.replace(/\.jsonl$/, '-collections.jsonl'), 'utf8'), ''); +}); + +test('local scope keeps the explicit allowed-repository fallback without widening rich collector opt-in', async (t) => { + const options = await fixture(t); + const document = policy(); + delete document['control-plane'].activity; + document['control-plane'].scope = { 'allowed-repositories': ['org/repo'] }; + await writeFile(options.policy, JSON.stringify(document)); + const snapshot = path.join(options.root, 'snapshot'); + await runWorkflowValues({ + ...options, defer: 'shared-budget-unavailable', + localRequest: path.join(snapshot, 'gh-aw-logs-shards', 'workflow-value-local.json'), snapshot: '1-1', + }); + assert.deepEqual((await localValuePlan({ policy: options.policy, snapshot, snapshotKey: '1-1' })).repositories, ['org/repo']); + assert.equal(await readFile(options.output.replace(/\.jsonl$/, '-collections.jsonl'), 'utf8'), ''); + await assert.rejects(readdir(options.workspace), { code: 'ENOENT' }); +}); + +test('an explicit disable without a collector remains disabled rather than unconfigured', async (t) => { + const options = await fixture(t); + const document = policy(); + document['control-plane'].campaigns.activity['workflow-values'] = [{ + repository: entry.repository, workflow: entry.workflow, enabled: false, + }]; + await writeFile(options.policy, JSON.stringify(document)); + await runWorkflowValues({ ...options, defer: 'shared-budget-unavailable' }); + const fact = await collection(options); + assert.equal(fact.state, 'disabled'); + assert.equal(fact.registration, 'disabled'); + assert.equal(fact.collector, undefined); +}); + +test('completed local imports validate the canonical envelope, retain known zero and reject invalid optional replacements', async (t) => { + const options = await fixture(t); + const input = path.join(options.root, 'incoming.jsonl'); + const output = path.join(options.root, 'local.jsonl'); + const original = { schema_version: 2, kind: 'operational_value', operational_value: { + repository: 'org/repo', campaign: 'example', value_id: 'daily-review.count', value: 0, + timestamp: '2026-10-20T12:00:00.000Z', + } }; + await writeFile(output, JSON.stringify(original) + '\n'); + await writeFile(input, JSON.stringify({ ...original, operational_value: { ...original.operational_value, value: null } })); + await retainLocalValues({ policy: options.policy, input, output }); + assert.deepEqual(JSON.parse(await readFile(output, 'utf8')), original); + const withdrawn = structuredClone(original); + withdrawn.operational_value.repository = 'outside/scope'; + await writeFile(input, JSON.stringify(withdrawn)); + await retainLocalValues({ policy: options.policy, input, output }); + assert.deepEqual(JSON.parse(await readFile(output, 'utf8')), original); +}); From 3298b321813a7101765910155b38bd36db05eff6 Mon Sep 17 00:00:00 2001 From: Mara Nikola Kiefer <8320933+mnkiefer@users.noreply.github.com> Date: Fri, 23 Oct 2026 18:10:22 +0200 Subject: [PATCH 2/5] Preserve Value health across cache loss and harden runtime integration Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: e45b84aa-0ee5-49c3-8eea-a54a5eb80b03 --- .github/workflows/cao-activity.yml | 8 +++-- .github/workflows/shared/materialize-cao.mjs | 1 + activity/cli/cache.mjs | 26 +++++++++++++--- activity/workflow-values.mjs | 5 +-- .../data/model/workflow-value-collection.js | 10 +++--- .../unit/workflow-value-collection.test.js | 12 +++++-- docs/dashboard-data-ingestion.md | 8 ++--- docs/dashboard-data-model.md | 6 ++-- runtime/package.json | 3 ++ server/internal/postgresx/native.go | 2 +- .../postgresx/workflow_value_collection.go | 17 +++++++++- .../workflow_value_collection_test.go | 24 +++++++++++--- specs/dashboard-data.md | 16 ++++++---- tests/unit/activity-cache-recycling.test.mjs | 19 ++++++++++++ ...perational-value-file-diet-replay.test.mjs | 2 +- tests/unit/cao-runtime-artifact.test.mjs | 31 +++++++++++++++++++ ...rkflow-contract-activity-dispatch.test.mjs | 29 +++++++++++++---- .../workflow-contract-authentication.test.mjs | 10 ++++-- 18 files changed, 184 insertions(+), 45 deletions(-) diff --git a/.github/workflows/cao-activity.yml b/.github/workflows/cao-activity.yml index 606a1a152..3a894dc0b 100644 --- a/.github/workflows/cao-activity.yml +++ b/.github/workflows/cao-activity.yml @@ -377,8 +377,12 @@ jobs: if [[ -f "$health_seed" ]]; then cp "$health_seed" "$health_output"; fi proof_seed="$RUNNER_TEMP/cao-activity/workflow-value-workspaces/$ACTIVITY_ARTIFACT" proof_output="$RUNNER_TEMP/cao-activity-partial/$ACTIVITY_ARTIFACT/workflow-value-workspaces/$ACTIVITY_ARTIFACT" - mkdir -p "$proof_output" - if [[ -d "$proof_seed" ]]; then cp -R "$proof_seed/." "$proof_output/"; fi + proof_staging="$RUNNER_TEMP/cao-value-proof-staging/$ACTIVITY_ARTIFACT" + if [[ -d "$proof_seed" ]]; then + mkdir -p "$proof_staging" "$(dirname "$proof_output")" + cp -R "$proof_seed/." "$proof_staging/" + mv "$proof_staging" "$proof_output" + fi retained_values="$REPORT_VALUE_SEED_SHARDS/operational-values-$ACTIVITY_ARTIFACT.jsonl" value_output="$REPORT_GH_AW_LOGS_SHARDS/operational-values-$ACTIVITY_ARTIFACT.jsonl" if [[ -f "$retained_values" ]]; then diff --git a/.github/workflows/shared/materialize-cao.mjs b/.github/workflows/shared/materialize-cao.mjs index 0924b4da0..bdc402bbd 100644 --- a/.github/workflows/shared/materialize-cao.mjs +++ b/.github/workflows/shared/materialize-cao.mjs @@ -520,6 +520,7 @@ export function verifyCaoRuntime(bundle, repositoryRoot = process.cwd()) { activity: [ 'activity/cao.mjs', 'activity/workflow-values.mjs', + 'activity/workflow-value-history.mjs', 'activity/workflow-value-status.mjs', 'activity/local-values.mjs', 'dashboard/site/src/data/model/operational-value-evidence.js', diff --git a/activity/cli/cache.mjs b/activity/cli/cache.mjs index 48571180f..3c1d9d42a 100644 --- a/activity/cli/cache.mjs +++ b/activity/cli/cache.mjs @@ -228,14 +228,28 @@ export async function mergeActivityFragments(fragmentDirectory, outputDirectory) const inventories = []; const incoming = new Map(); const localValueRequests = []; + let localValueRequestBytes = 0; for (const fragment of roots) { inventories.push(JSON.parse(await readFile(path.join(fragment, 'inventory-sources.json'), 'utf8'))); + const shards = await shardPaths(path.join(fragment, 'gh-aw-logs-shards'), { allowMissing: true }); try { - const requests = JSON.parse(await readFile(path.join(fragment, 'gh-aw-logs-shards', 'workflow-value-local.json'), 'utf8')); - if (!Array.isArray(requests)) throw new Error('Invalid owner-scoped local Value requests'); + const filename = path.join(fragment, 'gh-aw-logs-shards', 'workflow-value-local.json'); + const info = await lstat(filename); + if (!info.isFile() || localValueRequestBytes + info.size > 16 * 1024 * 1024) { + throw new Error('Local Value request metadata exceeds its input budget'); + } + const content = await readFile(filename, 'utf8'); + const requests = JSON.parse(content); + if (!Array.isArray(requests) || localValueRequests.length + requests.length > 1000) { + throw new Error('Invalid or oversized owner-scoped local Value requests'); + } + localValueRequestBytes += Buffer.byteLength(content); + if (localValueRequestBytes > 16 * 1024 * 1024) throw new Error('Local Value requests exceed their byte budget'); localValueRequests.push(...requests); } catch (error) { - if (error.code !== 'ENOENT') throw error; + if (error.code !== 'ENOENT') { + console.warn('Local Value request metadata is invalid or unavailable; this optional fragment is deferred without delaying Activity.'); + } } const proofs = path.join(fragment, 'workflow-value-workspaces'); try { @@ -252,7 +266,7 @@ export async function mergeActivityFragments(fragmentDirectory, outputDirectory) if (error.code !== 'ENOENT') throw error; } // Artifact archives omit empty directories from successful collections. - for (const file of await shardPaths(path.join(fragment, 'gh-aw-logs-shards'), { allowMissing: true })) { + for (const file of shards) { const name = path.basename(file); if (incoming.has(name)) throw new Error(`Duplicate owner-scoped shard: ${name}`); incoming.set(name, file); @@ -266,6 +280,8 @@ export async function mergeActivityFragments(fragmentDirectory, outputDirectory) } for (const [name, file] of incoming) await rename(file, path.join(destination, name)); await writeFile(path.join(outputDirectory, 'inventory-sources.json'), `${JSON.stringify(inventory, null, 2)}\n`); - await writeFile(path.join(destination, 'workflow-value-local.json'), `${JSON.stringify(localValueRequests)}\n`); + const localRequest = path.join(destination, 'workflow-value-local.json'); + if (localValueRequests.length) await writeFile(localRequest, `${JSON.stringify(localValueRequests)}\n`); + else await rm(localRequest, { force: true }); return { fragments: roots.length, shards: incoming.size }; } diff --git a/activity/workflow-values.mjs b/activity/workflow-values.mjs index 41535a63a..90baa9159 100644 --- a/activity/workflow-values.mjs +++ b/activity/workflow-values.mjs @@ -4,7 +4,7 @@ // The return value is the original schema-v2 operational_value_evidence envelope. import { spawn, spawnSync } from 'node:child_process'; import { createHash } from 'node:crypto'; -import { lstat, mkdir, mkdtemp, readdir, rm, writeFile } from 'node:fs/promises'; +import { lstat, mkdir, mkdtemp, readdir, rename, rm, writeFile } from 'node:fs/promises'; import path from 'node:path'; import { pathToFileURL } from 'node:url'; import { loadPolicyFile } from '../.github/workflows/shared/policy.mjs'; @@ -155,12 +155,13 @@ export async function runWorkflowValues(options) { if (options.localRequest) { if (!options.snapshot) throw new Error('Local Value request requires a snapshot identity'); await mkdir(path.dirname(options.localRequest), { recursive: true }); - await writeFile(options.localRequest, JSON.stringify([{ + await writeFile(`${options.localRequest}.pending`, JSON.stringify([{ schemaVersion: 1, snapshot: options.snapshot, policyDigest: health.policyDigest, eligible: !health.activityDisabled && options.defer === 'shared-budget-unavailable', reason: health.activityDisabled ? 'activity-disabled' : options.defer, repositories: options.repositories.filter(repository => valueRepositoryInScope(policy, options.repositories, repository, true)), }]) + '\n', { mode: 0o600 }); + await rename(`${options.localRequest}.pending`, options.localRequest); } const result = { collected: 0, skipped: 0, deferred: 0, failed: 0, warnings: [] }; const fresh = []; diff --git a/dashboard/site/src/data/model/workflow-value-collection.js b/dashboard/site/src/data/model/workflow-value-collection.js index 56fe4bb85..a84cd19f8 100644 --- a/dashboard/site/src/data/model/workflow-value-collection.js +++ b/dashboard/site/src/data/model/workflow-value-collection.js @@ -78,13 +78,15 @@ export function mergeWorkflowValueCollection(previous, incoming) { if (!previous) return incoming; const before = Date.parse(previous.observedAt), after = Date.parse(incoming.observedAt); if (before > after) return previous; + const next = previous.lastAttemptAt && !incoming.lastAttemptAt ? { + ...incoming, lastAttemptAt: previous.lastAttemptAt, lastAttemptOutcome: previous.lastAttemptOutcome, + } : incoming; const fields = ['registration', 'collector', 'state', 'reasonCode', 'policyDigest', 'lastAttemptAt', 'lastAttemptOutcome']; - if (before === after && fields.some(field => previous[field] !== incoming[field])) { + if (before === after && fields.some(field => previous[field] !== next[field])) { throw new TypeError('Conflicting workflow Value collection decisions at the same time'); } - if (previous.lastAttemptAt && (!incoming.lastAttemptAt - || Date.parse(incoming.lastAttemptAt) < Date.parse(previous.lastAttemptAt))) { + if (previous.lastAttemptAt && Date.parse(next.lastAttemptAt) < Date.parse(previous.lastAttemptAt)) { throw new TypeError('Workflow Value collection attempt history regressed'); } - return incoming; + return next; } diff --git a/dashboard/site/test/unit/workflow-value-collection.test.js b/dashboard/site/test/unit/workflow-value-collection.test.js index 1cd901625..bcf0698e9 100644 --- a/dashboard/site/test/unit/workflow-value-collection.test.js +++ b/dashboard/site/test/unit/workflow-value-collection.test.js @@ -38,9 +38,17 @@ describe('canonical workflow Value collection facts', () => { await expect(ingestCachedGhAwJsonl(database, JSON.stringify(conflicting), { now, payloadScope: 'conflict' })).rejects.toThrow(); const regressed = structuredClone(fixture); regressed.workflow_value_collection.observedAt = '2026-10-24T00:00:00Z'; - delete regressed.workflow_value_collection.lastAttemptAt; - delete regressed.workflow_value_collection.lastAttemptOutcome; + regressed.workflow_value_collection.lastAttemptAt = '2026-10-21T12:00:00Z'; await expect(ingestCachedGhAwJsonl(database, JSON.stringify(regressed), { now, payloadScope: 'regression' })).rejects.toThrow(); + const unknown = structuredClone(fixture); + unknown.workflow_value_collection.observedAt = '2026-10-24T00:00:00Z'; + delete unknown.workflow_value_collection.lastAttemptAt; + delete unknown.workflow_value_collection.lastAttemptOutcome; + await ingestCachedGhAwJsonl(database, JSON.stringify(unknown), { now, payloadScope: 'unknown-attempt' }); + const [preserved] = await readCollection(database, 'workflowValueCollections'); + expect(preserved.observedAt).toBe(unknown.workflow_value_collection.observedAt); + expect(preserved.lastAttemptAt).toBe(fixture.workflow_value_collection.lastAttemptAt); + expect(preserved.lastAttemptOutcome).toBe(fixture.workflow_value_collection.lastAttemptOutcome); await maintainCanonicalDatabase(database, { now: now + 365 * 86400000, retentionWindowMs: 86400000, maxDatabaseBytes: Number.MAX_SAFE_INTEGER, }); diff --git a/docs/dashboard-data-ingestion.md b/docs/dashboard-data-ingestion.md index 67f250347..4735db238 100644 --- a/docs/dashboard-data-ingestion.md +++ b/docs/dashboard-data-ingestion.md @@ -181,7 +181,7 @@ failed resolutions appear in the Model routing Problems view once per run, with an unknown time unless the session clock is recorded, and per-run resolution roles stay on the run page. Routed sessions are expected to lack these events, and legacy sessions report no resolution evidence rather -than failure. Canonical schema 34 / IndexedDB version 44 rebuild older browser +than failure. Canonical schema 35 / IndexedDB version 45 rebuild older browser projections; hosted PostgreSQL needs a fresh generated schema with the new Audit columns and compact Run routing aggregates. Ingestion derives the aggregate with shared Dashboard Language accounting, retains request evidence needed by @@ -191,10 +191,10 @@ The activity shard manifest is the dashboard's published operational input. The The complete normative [cached gh-aw JSONL mapping](https://github.com/githubnext/gh-cao/blob/main/specs/dashboard-gh-aw-jsonl-mapping.md) describes source fields, canonical entities, identity, ownership, and accounting. -The canonical model is version 34. The browser database is -`gh-aw-cao-dashboard-data`, IndexedDB version 44. Its canonical stores are +The canonical model is version 35. The browser database is +`gh-aw-cao-dashboard-data`, IndexedDB version 45. Its canonical stores are `campaigns`, `repositories`, `workflows`, `runs`, `domains`, `tools`, `skills`, -`friction`, `audits`, `issues`, `operationalValues`, `operationalValueEvidence`, `marketplacePackages`, +`friction`, `audits`, `issues`, `operationalValues`, `operationalValueEvidence`, `workflowValueCollections`, `marketplacePackages`, `experiments`, `experimentAssignments`, `graders`, `graderObservations`, `evals`, and `evalObservations`; all use `id` as the key. diff --git a/docs/dashboard-data-model.md b/docs/dashboard-data-model.md index 2d1367477..da2c35c4e 100644 --- a/docs/dashboard-data-model.md +++ b/docs/dashboard-data-model.md @@ -96,7 +96,7 @@ Run-scoped Audit facts remain for request, attribution and resolution drill-down inventory and generic proxy events are discarded. Complete paired main-request costs can be compared to a named, explicitly estimated baseline, separately from total accounting. Missing costs remain unknown; partial runs do not -enter cost quantiles. Browser schema 34 / IndexedDB version 44 rebuild older +enter cost quantiles. Browser schema 35 / IndexedDB version 45 rebuild older projections, and hosted PostgreSQL requires a fresh generated schema. A Run owns ordered Domain, Tool, Skill, Friction, Audit, and Issue records combining observations @@ -120,8 +120,8 @@ The activity shard manifest is the dashboard's published operational input. Norm The complete normative [cached gh-aw JSONL mapping](https://github.com/githubnext/gh-cao/blob/main/specs/dashboard-gh-aw-jsonl-mapping.md) describes source fields, canonical entities, identity, ownership, and accounting. -The canonical model is version 34. The browser database is -`gh-aw-cao-dashboard-data`, IndexedDB version 44. Its canonical stores are +The canonical model is version 35. The browser database is +`gh-aw-cao-dashboard-data`, IndexedDB version 45. Its canonical stores are `campaigns`, `repositories`, `workflows`, `runs`, `domains`, `tools`, `skills`, `friction`, `audits`, `issues`, `operationalValues`, `operationalValueEvidence`, `workflowValueCollections`, `marketplacePackages`, `experiments`, `experimentAssignments`, `graders`, `graderObservations`, diff --git a/runtime/package.json b/runtime/package.json index 77836c715..702dca2ab 100644 --- a/runtime/package.json +++ b/runtime/package.json @@ -33,6 +33,7 @@ "activity/inventory.mjs", "activity/jsonl.mjs", "activity/local-runner.mjs", + "activity/local-values.mjs", "activity/logs.mjs", "activity/marketplace.mjs", "activity/mcp-server.mjs", @@ -40,6 +41,8 @@ "activity/normalized-shards.mjs", "activity/operational-value.mjs", "activity/workflow-values.mjs", + "activity/workflow-value-history.mjs", + "activity/workflow-value-status.mjs", "activity/problem-clustering.mjs", "activity/repository-memory.mjs", "activity/repository-visibility.mjs", diff --git a/server/internal/postgresx/native.go b/server/internal/postgresx/native.go index 09031fbc4..1f7eb34bf 100644 --- a/server/internal/postgresx/native.go +++ b/server/internal/postgresx/native.go @@ -559,7 +559,7 @@ func (w *Writer) Publish(ctx context.Context, dataRevision string) (State, error if _, err := w.tx.Exec(ctx, "SELECT cao_analyze_native()"); err != nil { return State{}, fmt.Errorf("refresh native statistics: %w", err) } - if err := w.validateCollectionDecisionReplacement(ctx); err != nil { + if err := w.reconcileCollectionDecisions(ctx); err != nil { return State{}, err } if err := overlayRepositoryLifecycle(ctx, w.store.namespace, func(ctx context.Context, statement string, args ...any) error { diff --git a/server/internal/postgresx/workflow_value_collection.go b/server/internal/postgresx/workflow_value_collection.go index 8833c0c42..c21f61e64 100644 --- a/server/internal/postgresx/workflow_value_collection.go +++ b/server/internal/postgresx/workflow_value_collection.go @@ -19,7 +19,22 @@ func (w *Writer) preserveCollectionDecisions(ctx context.Context) error { return err } -func (w *Writer) validateCollectionDecisionReplacement(ctx context.Context) error { +func (w *Writer) reconcileCollectionDecisions(ctx context.Context) error { + presence := "incoming.present_fields" + for index, column := range entityTables["$workflowValueCollections"].columns { + if column.field == "lastAttemptAt" || column.field == "lastAttemptOutcome" { + presence = fmt.Sprintf("set_bit(%s,%d,1)", presence, index) + } + } + // An absent attempt means unknown, including after a local cache loss. + if _, err := w.tx.Exec(ctx, `UPDATE workflow_value_collections incoming SET + last_attempt_at=previous.last_attempt_at, last_attempt_outcome=previous.last_attempt_outcome, + present_fields=`+presence+` FROM workflow_value_collections_previous previous + WHERE incoming.namespace=$1 AND incoming.id=previous.id + AND incoming.observed_at>=previous.observed_at + AND incoming.last_attempt_at IS NULL AND previous.last_attempt_at IS NOT NULL`, w.store.namespace); err != nil { + return err + } var invalid bool err := w.tx.QueryRow(ctx, `SELECT EXISTS ( SELECT 1 FROM workflow_value_collections incoming diff --git a/server/internal/postgresx/workflow_value_collection_test.go b/server/internal/postgresx/workflow_value_collection_test.go index ba0a8c4eb..84eb04d2b 100644 --- a/server/internal/postgresx/workflow_value_collection_test.go +++ b/server/internal/postgresx/workflow_value_collection_test.go @@ -123,7 +123,7 @@ func TestWorkflowValueCollectionRejectsRegressiveSnapshots(t *testing.T) { t.Fatal(err) } clock, _ := evidenceTime(original["observedAt"]) - for _, scenario := range []string{"stale", "conflicting", "lost-attempt"} { + for _, scenario := range []string{"stale", "conflicting", "regressed-attempt"} { record := maps.Clone(original) switch scenario { case "stale": @@ -131,10 +131,9 @@ func TestWorkflowValueCollectionRejectsRegressiveSnapshots(t *testing.T) { case "conflicting": record["reasonCode"] = "shared-budget-unavailable" record["reason"] = valueCollectionReasons["shared-budget-unavailable"] - case "lost-attempt": + case "regressed-attempt": record["observedAt"] = clock.Add(time.Hour).Format(time.RFC3339) - delete(record, "lastAttemptAt") - delete(record, "lastAttemptOutcome") + record["lastAttemptAt"] = clock.Add(-48 * time.Hour).Format(time.RFC3339) } if err := publish(record, scenario); err == nil || !strings.Contains(err.Error(), "accepted history") { t.Fatalf("%s snapshot must not overwrite accepted decisions: %v", scenario, err) @@ -148,8 +147,23 @@ func TestWorkflowValueCollectionRejectsRegressiveSnapshots(t *testing.T) { if len(rows) != 1 || rows[0]["reason-code"] != "api-budget" || rows[0]["last-attempt-outcome"] != "failed" { t.Fatalf("failed imports changed accepted health: %v", rows) } + unknown := maps.Clone(original) + unknown["observedAt"] = clock.Add(time.Hour).Format(time.RFC3339) + delete(unknown, "lastAttemptAt") + delete(unknown, "lastAttemptOutcome") + if err := publish(unknown, "unknown-attempt"); err != nil { + t.Fatal("unknown attempts must not erase known history or prevent ordinary publication", err) + } + sources, _, err = store.ExecuteSQLPlan(t.Context(), canonicalProjectionDefinitions(t), []string{"workflow-value-collections"}) + if err != nil { + t.Fatal(err) + } + rows = sources["workflow-value-collections"].Rows + if len(rows) != 1 || rows[0]["last-attempt-outcome"] != "failed" || rows[0]["last-attempt-at"] == nil { + t.Fatalf("unknown attempts erased accepted history: %v", rows) + } disabled := maps.Clone(original) - disabled["observedAt"] = clock.Add(time.Hour).Format(time.RFC3339) + disabled["observedAt"] = clock.Add(2 * time.Hour).Format(time.RFC3339) disabled["registration"], disabled["state"], disabled["reasonCode"] = "disabled", "disabled", "disabled" disabled["reason"] = valueCollectionReasons["disabled"] delete(disabled, "collector") diff --git a/specs/dashboard-data.md b/specs/dashboard-data.md index 762a45b08..c8cb93e50 100644 --- a/specs/dashboard-data.md +++ b/specs/dashboard-data.md @@ -633,10 +633,10 @@ The implementation profile defined by this specification is: | Layer | Version | Physical structure | | --- | ---: | --- | -| Canonical model | 34 | Campaign, Repository, Workflow, Run, Domain, Tool, Skill, Friction, Audit, Issue, Operational Value, Operational Value Evidence, Marketplace Package, Experiment, Experiment Assignment, Grader, Grader Observation, Eval, and Eval Observation records | -| Browser IndexedDB | 44 | Nineteen canonical entity stores, `transactions`, and disposable `storageShards` accounting | -| Local SQLite projection | IndexedDB 43 | `__idb_databases`, `__idb_stores`, `__idb_indexes`, and `__idb_records` for the same logical stores, plus a `campaigns` table and six transactional relational evidence mirrors without duplicate record documents | -| Go server Postgres sources | Canonical model 18 | Fresh TypeSpec-defined entity and input tables with query-required native columns, compact presence bits, entity-owned relational child values, and transactional diagnostics/revision state; no stored JSON documents or duplicate scalar row formats | +| Canonical model | 35 | Campaign, Repository, Workflow, Run, Domain, Tool, Skill, Friction, Audit, Issue, Operational Value, Operational Value Evidence, Workflow Value Collection, Marketplace Package, Experiment, Experiment Assignment, Grader, Grader Observation, Eval, and Eval Observation records | +| Browser IndexedDB | 45 | Twenty canonical entity stores, `transactions`, and disposable `storageShards` accounting | +| Local SQLite projection | IndexedDB 45 | `__idb_databases`, `__idb_stores`, `__idb_indexes`, and `__idb_records` for the same logical stores, plus a `campaigns` table and six transactional relational evidence mirrors without duplicate record documents | +| Go server Postgres sources | Canonical model 19 | Fresh TypeSpec-defined entity and input tables with query-required native columns, compact presence bits, entity-owned relational child values, and transactional diagnostics/revision state; no stored JSON documents or duplicate scalar row formats | | Static SQL export | 3 | Versioned JSON interchange produced from upstream SQL tables or views | ## 5.2 Go server profile @@ -2614,7 +2614,7 @@ The canonical browser database SHALL use: ```js const DATABASE_NAME = "gh-aw-cao-dashboard-data"; -const DATABASE_VERSION = 44; +const DATABASE_VERSION = 45; ``` The name MAY be scoped by deployment path to prevent unrelated dashboard @@ -2626,7 +2626,7 @@ rows. # 27. Object Stores -IndexedDB version 44 SHALL define: +IndexedDB version 45 SHALL define: ```text campaigns @@ -2641,6 +2641,7 @@ audits issues operationalValues operationalValueEvidence +workflowValueCollections marketplacePackages experiments experimentAssignments @@ -2964,6 +2965,9 @@ No health observation promotes outcome completeness or freshness. Explicit disables without a collector path SHALL remain disabled, not unconfigured. Newer decisions MUST NOT discard or regress a known attempt clock; conflicting decisions at the same observation time SHALL fail. +An absent attempt is unknown, not proof that collection never ran. Merging a +newer decision after cache loss SHALL retain an already known actual attempt; +it MUST NOT synthesize one from the new decision time. Optional Value acquisition MUST NOT delay ordinary Activity publication, consume its protected API headroom, or hold the hosted projection lease. A separate job diff --git a/tests/unit/activity-cache-recycling.test.mjs b/tests/unit/activity-cache-recycling.test.mjs index 0d1145b51..f4eda6f2c 100644 --- a/tests/unit/activity-cache-recycling.test.mjs +++ b/tests/unit/activity-cache-recycling.test.mjs @@ -267,6 +267,25 @@ test('fragment merging moves authoritative shards and removes superseded restore assert.equal(await readFile(path.join(root, 'workflow-value-workspaces', 'octo', 'identity', 'proof.json'), 'utf8'), '{"original":true}\n'); }); +test('optional local request corruption does not block fragments or discard accepted local evidence', async (t) => { + const { root, shards } = await fixture(t); + const fragments = path.join(root, 'fragments'); + const first = await fragment(fragments, 'octo', 'one.jsonl', [run(1)]); + const second = await fragment(fragments, 'other', 'two.jsonl', [run(2)]); + const request = { schemaVersion: 1, snapshot: '1-1', eligible: false, repositories: ['octo/api'] }; + await writeFile(path.join(path.dirname(first), 'workflow-value-local.json'), JSON.stringify([request])); + await writeFile(path.join(path.dirname(second), 'workflow-value-local.json'), '{interrupted'); + const retained = jsonl([{ kind: 'operational_value', operational_value: { + campaign: 'example', repository: 'octo/api', value_id: 'worker.count', value: 0, + timestamp: '2026-10-20T12:00:00Z', + } }]); + await writeFile(path.join(shards, 'operational-values-local.jsonl'), retained); + assert.deepEqual(await mergeActivityFragments(fragments, root), { fragments: 2, shards: 2 }); + assert.deepEqual(JSON.parse(await readFile(path.join(shards, 'workflow-value-local.json'), 'utf8')), [request]); + assert.equal(await readFile(path.join(shards, 'operational-values-local.jsonl'), 'utf8'), retained); + assert.ok((await readdir(shards)).includes('two.jsonl')); +}); + test('fragment merging accepts a direct single-owner layout and an explicitly empty snapshot', async (t) => { const { root, shards } = await fixture(t); const first = await fragment(root, 'direct', 'one.jsonl', [run(1)]); diff --git a/tests/unit/cao-operational-value-file-diet-replay.test.mjs b/tests/unit/cao-operational-value-file-diet-replay.test.mjs index a69b22108..9db556964 100644 --- a/tests/unit/cao-operational-value-file-diet-replay.test.mjs +++ b/tests/unit/cao-operational-value-file-diet-replay.test.mjs @@ -100,7 +100,7 @@ test("the real reviewed File Diet collector loads in the isolated worker and reu repositories: [definition.repository], output, workspace: path.join(directory, "proofs"), observedAt: ledger.window.endAt, }); - assert.deepEqual(result, { collected: 0, skipped: 1, warnings: [] }); + assert.deepEqual(result, { collected: 0, skipped: 1, deferred: 0, failed: 0, warnings: [] }); }); test("cold-start proof is pinned, evidence-only, bounded and validated before reuse", async t => { diff --git a/tests/unit/cao-runtime-artifact.test.mjs b/tests/unit/cao-runtime-artifact.test.mjs index 97304ad38..a69a9e9e6 100644 --- a/tests/unit/cao-runtime-artifact.test.mjs +++ b/tests/unit/cao-runtime-artifact.test.mjs @@ -47,6 +47,37 @@ test("the installed runtime rejects unknown commands before filesystem or databa assertUnknownCommandsRejectBeforeIO(unpack(t), t); }); +test("the installed runtime publishes reviewed collection health without a collector or credentials", t => { + const root = unpack(t); + for (const { source, destination } of parse(readFileSync(path.join(catalog, "aw.yml"), "utf8")).resources) { + const target = path.join(root, destination); + mkdirSync(path.dirname(target), { recursive: true }); + cpSync(path.join(catalog, source), target, { recursive: true }); + } + const policy = path.join(root, "health-policy.json"); + writeFileSync(policy, JSON.stringify({ version: 1, "gh-aw-version": "v0.93.1", "control-plane": { + scope: { "allowed-repositories": ["org/repo"] }, activity: { repositories: ["org/repo"] }, + campaigns: { activity: { "workflow-values": [ + { repository: "org/repo", workflow: "worker", collector: "not-installed.mjs" }, + ] } }, + } })); + const output = path.join(root, "health-evidence.jsonl"); + const result = JSON.parse(execFileSync(process.execPath, [ + "activity/workflow-values.mjs", "--root", root, "--policy", policy, "--repository", "org/repo", + "--output", output, "--workspace", path.join(root, "proofs"), "--defer", "api-budget", + ], { cwd: root, env: { PATH: "", NODE_OPTIONS: "" }, encoding: "utf8", timeout: 30000 })); + assert.equal(result.deferred, 1); + assert.equal(result.failed, 0); + const { workflow_value_collection: health } = JSON.parse(readFileSync( + path.join(root, "health-evidence-collections.jsonl"), "utf8", + )); + assert.equal(health.registration, "enabled"); + assert.equal(health.reasonCode, "api-budget"); + assert.equal(health.lastAttemptAt, undefined); + assert.equal(existsSync(output), false); + assert.equal(existsSync(path.join(root, "proofs")), false); +}); + test("the installed runtime retains explicit ingestion and downloadable queryable evidence", async (t) => { const root = unpack(t); const database = path.join(root, "snapshot.sqlite"); diff --git a/tests/unit/workflow-contract-activity-dispatch.test.mjs b/tests/unit/workflow-contract-activity-dispatch.test.mjs index c7e2adfb9..57797f61a 100644 --- a/tests/unit/workflow-contract-activity-dispatch.test.mjs +++ b/tests/unit/workflow-contract-activity-dispatch.test.mjs @@ -31,21 +31,38 @@ test('manual fast collection narrows download budgets without changing scope or }); }); -test('fast collection preserves the history restore and exits before operational-value computation', (t) => { +test('fast collection preserves Value history and publishes a deferred decision without acquisition', (t) => { const directory = mkdtempSync(path.join(tmpdir(), 'activity-fast-')); t.after(() => rmSync(directory, { recursive: true, force: true })); - const computation = step('collect', 'Compute owner-scoped operational value'); + const computation = step('collect', 'Retain Value evidence and publish collection health'); assert.equal(computation.env.REPORT_FAST_MODE, '${{ inputs.fast == true }}'); - assert.match(computation.run, /cp "\$retained_values" "\$value_output"[\s\S]*?ingest-jsonl[\s\S]*?if \[\[ "\$REPORT_FAST_MODE" == "true" \|\| "\$REPORT_RATE_LIMITED" == "true" \|\| "\$REPORT_PUBLIC_ONLY" == "true" \]\]/); + const seed = path.join(directory, 'seed'); + const shards = path.join(directory, 'shards'); + mkdirSync(seed); + mkdirSync(shards); + writeFileSync(path.join(seed, 'operational-values-example.jsonl'), 'retained evidence\n'); + const inventory = path.join(directory, 'inventory.json'); + writeFileSync(inventory, JSON.stringify({ repositories: { rows: [] }, workflows: { rows: [] } })); + assert.match(computation.run, /cp "\$retained_values" "\$value_output"[\s\S]*?REPORT_FAST_MODE" == "true" \]\]; then reason=fast-mode/); + assert.equal(computation['continue-on-error'], true); + assert.equal(computation['timeout-minutes'], 1); const output = execFileSync('bash', ['-euc', computation.run], { cwd: root, encoding: 'utf8', env: { ...process.env, REPORT_FAST_MODE: 'true', ACTIVITY_ARTIFACT: 'example', - RUNNER_TEMP: directory, - REPORT_VALUE_SEED_SHARDS: directory, REPORT_GH_AW_LOGS_SHARDS: directory + RUNNER_TEMP: directory, REPORT_PUBLIC_ONLY: 'false', REPORT_RATE_LIMITED: 'false', + ACTIVITY_OWNER: 'github', REPORT_TARGET_REPOSITORIES_JSON: '["gh-aw"]', + ACTIVITY_DATABASE: path.join(directory, 'unused.sqlite'), REPORT_INVENTORY_SOURCES: inventory, + GITHUB_RUN_ID: '1', GITHUB_RUN_ATTEMPT: '1', GH_TOKEN: '', GITHUB_TOKEN: '', + REPORT_VALUE_SEED_SHARDS: seed, REPORT_GH_AW_LOGS_SHARDS: shards, } }); - assert.match(output, /skipping new computation/); + assert.equal(JSON.parse(output).deferred, 1); + assert.equal(readFileSync(path.join(shards, 'operational-values-example.jsonl'), 'utf8'), 'retained evidence\n'); + const health = JSON.parse(readFileSync(path.join(shards, 'workflow-values-example-collections.jsonl'), 'utf8')); + assert.equal(health.workflow_value_collection.reasonCode, 'fast-mode'); + assert.equal(health.workflow_value_collection.lastAttemptAt, undefined); + assert.equal(JSON.parse(readFileSync(path.join(shards, 'workflow-value-local.json'), 'utf8'))[0].eligible, false); }); test('forced recycling runs before new downloads and safely clears only disposable payloads', (t) => { diff --git a/tests/unit/workflow-contract-authentication.test.mjs b/tests/unit/workflow-contract-authentication.test.mjs index f4522d3b0..6845fff13 100644 --- a/tests/unit/workflow-contract-authentication.test.mjs +++ b/tests/unit/workflow-contract-authentication.test.mjs @@ -473,15 +473,19 @@ test("CAO Activity workflow-token API reserves fit its standard 1000-request quo const steps = activity.jobs.collect.steps; const logs = steps.find(({ name }) => name === "Download owner-scoped agentic workflow logs"); const inventory = steps.find(({ name }) => name === "Collect owner-scoped dashboard inventory"); - const value = steps.find(({ name }) => name === "Compute owner-scoped operational value"); - for (const [step, appPatReserve] of [[inventory, 2000], [logs, 2000], [value, 2000]]) { + const value = steps.find(({ name }) => name === "Retain Value evidence and publish collection health"); + for (const [step, appPatReserve] of [[inventory, 2000], [logs, 2000]]) { assert.equal( step.env.REPORT_MAX_GITHUB_API_RATE_LIMIT, "${{ (vars.GH_AW_GITHUB_AUTH_MODE == '' || vars.GH_AW_GITHUB_AUTH_MODE == 'workflow-token') && '-100' || '-" + appPatReserve + "' }}", ); } - assert.match(value.run, /--max-github-api-rate-limit "\$REPORT_MAX_GITHUB_API_RATE_LIMIT"/); + assert.equal(value.env.GH_TOKEN, ""); + assert.equal(value.env.CAO_OPERATIONAL_VALUE_GH_TOKEN, ""); + assert.match(value.run, /reason=shared-budget-unavailable/); + assert.match(value.run, /REPORT_RATE_LIMITED" == "true" \]\]; then reason=api-budget/); + assert.doesNotMatch(value.run, /gh api|--max-github-api-rate-limit|cao\.mjs operational-value/); assert.ok(inventory.run.indexOf('github-telemetry.mjs capacity "$REPORT_MAX_GITHUB_API_RATE_LIMIT"') < inventory.run.indexOf("cao.mjs discover-workflows")); }); From de369231f944d10cd96891ca63f17888159b0051 Mon Sep 17 00:00:00 2001 From: Mara Nikola Kiefer <8320933+mnkiefer@users.noreply.github.com> Date: Fri, 23 Oct 2026 19:40:38 +0200 Subject: [PATCH 3/5] Make Value health replay-independent and guard optional publication Reconcile decision and actual-attempt facts independently, preserving known history across reordered imports and cache loss. Fence local results against changed input, policy and accepted evidence; verify the transitions in browser, SQLite and PostgreSQL without changing acquisition authority. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: e45b84aa-0ee5-49c3-8eea-a54a5eb80b03 --- ARCHITECTURE.md | 9 +- CODEBASE.yml | 6 +- activity/local-values.mjs | 26 ++-- .../data/model/workflow-value-collection.js | 47 ++++--- .../test/unit/data-sqlite-indexeddb.test.js | 29 +++- .../unit/workflow-value-collection.test.js | 58 +++++++- docs/operational-value.md | 10 +- server/README.md | 12 +- .../collect/projector_local_value_test.go | 102 ++++++++++++++ .../collect/projector_workflow_values.go | 59 +++++++- .../postgresx/workflow_value_collection.go | 60 +++++---- .../workflow_value_collection_test.go | 126 ++++++++++++++---- specs/dashboard-data.md | 29 +++- tests/unit/workflow-values-recurring.test.mjs | 10 ++ 14 files changed, 485 insertions(+), 98 deletions(-) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 07e6c350f..1fb15fb61 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -741,7 +741,9 @@ records through `cao operational-value`. Automatic remote acquisition remains deferred until shared per-request API admission can protect ordinary Activity against concurrent credential consumers; separate workers are not separate quota. Activity publishes health and retains accepted packets/proof without remote -Value acquisition. Bounded cache-only/local computation remains independent: +Value acquisition. Health reconciles the latest decision and actual attempt +independently of arrival order; unknown attempts never erase known history. +Bounded cache-only/local computation remains independent: Actions runs it only after a successful eligible Activity snapshot, while the hosted worker uses its own single-owner lease and verified private snapshot. Both use the reviewed local-only standard adapter, explicit local-capability @@ -750,7 +752,10 @@ backfill, and a two-minute batch/thirty-second adapter budget. Scope, explicit disables, fast, public-only and API-limited gates remain enforced. A later ordinary snapshot imports completed results; optional work does not acquire the projection lease, hold a long core evidence lock, or initiate a -compute/publication retry loop. Normalized timestamped records then rebuild +compute/publication retry loop. Hosted final publication rechecks enrollment +and the starting generation, manifest, policy and retained-result identities; +changed inputs defer publication rather than overwrite concurrent evidence. +Normalized timestamped records then rebuild the canonical Operational Value collection in every storage profile. Package-level `problem-clustering.mjs` programs read a private Activity SQLite snapshot and emit bounded problem records with actionable fix prompts through diff --git a/CODEBASE.yml b/CODEBASE.yml index a48a999da..642b98a7a 100644 --- a/CODEBASE.yml +++ b/CODEBASE.yml @@ -283,10 +283,10 @@ components: responsibility: authenticate explicit administrator publication of original bounded evidence through POST /api/v1/value, with PostgreSQL namespace-locked atomic packet/fact ownership preserved across snapshot replacement, idempotent exact retries, frozen contracts and immutable historical measurements; never register or execute uploaded code workflow_value_collection: path: activity/workflow-values.mjs - responsibility: publish reviewed exact-registration collection health through the canonical browser/SQLite/PostgreSQL pipeline independently of accepted evidence; preserve actual-attempt and capture/cutoff clocks, explicit disables, scope and proof; defer recurring remote acquisition pending enforceable shared per-request budgets rather than spending ordinary Activity headroom + responsibility: publish reviewed exact-registration collection health through the canonical browser/SQLite/PostgreSQL pipeline independently of accepted evidence; reconcile decision and actual-attempt clocks independently of arrival order without erasing known attempts; preserve capture/cutoff clocks, explicit disables, scope and proof; defer recurring remote acquisition pending enforceable shared per-request budgets rather than spending ordinary Activity headroom local_value_computation: path: activity/local-values.mjs - responsibility: compute bounded local values only after eligible policy-matched Activity publication, using the reviewed local-only standard adapter, explicit local-capability modules or exact versioned cache reuse; no target credentials or automatic backfill; two-minute batch and thirty-second adapter limits; hosted work owns a separate lease and verified snapshot without the projection lease or long evidence lock; a later ordinary snapshot publishes results without a compute/publication retry loop + responsibility: compute bounded local values only after eligible policy-matched Activity publication, using the reviewed local-only standard adapter, explicit local-capability modules or exact versioned cache reuse; no target credentials or automatic backfill; two-minute batch and thirty-second adapter limits; hosted work owns a separate lease and verified snapshot without the projection lease or long evidence lock; final publication rechecks enrollment and starting generation, manifest, policy and retained-result identities, deferring changed inputs; a later ordinary snapshot publishes results without a compute/publication retry loop package_problem_clustering: path: /problem-clustering.mjs responsibility: compute bounded package problem rows from a private Activity SQLite snapshot through the cao cluster-problems command @@ -628,7 +628,7 @@ invariants: - "Browsers and external clients MUST NOT receive Redis or Postgres endpoints, credentials, keys, or storage-specific representations." - "Computations MUST consume canonical evidence, preserve evidence quality and provenance, and emit bounded, versioned results." - "Operational Value evidence MUST retain one bounded current packet per target repository, workflow and frozen contribution metric/version, with acquired contract, output, acceptance, lineage, independent snapshot, quality and coverage facts as typed relational children. Atomic packet replacement MUST preserve one coherent evidence revision independently of seven-day Run-detail retention. Retained source identity MUST materialize observed Repository and Workflow parents without inferring registration or activation. Packet cutoff/capture provenance MUST supply metadata without asserting complete coverage or current freshness. The operational-value-evidence logical source MUST only normalize facts; counts, comparisons, movement and report presentation belong to declarative queries. Import MUST NOT grant target authority and navigation MUST NOT acquire evidence." - - "Workflow Value collection decisions MUST remain separate canonical facts, visible before a report and without inventing attempts or capture/cutoff freshness. Stale/conflicting decisions and regressed attempt history MUST fail closed. Recurring remote acquisition MUST defer until enforceable shared per-request admission protects core Activity; a separate worker is not separate quota. Bounded local-only work MUST remain independent of ordinary publication, preserve scope, disables and existing fast/public-only/API-limited gates, and retain accepted evidence on failure." + - "Workflow Value collection decisions MUST remain separate canonical facts, visible before a report and without inventing attempts or capture/cutoff freshness. Decision and attempt facts MUST independently retain their latest clocks regardless of arrival order, never erase known attempts, and reject same-clock conflicts. Recurring remote acquisition MUST defer until enforceable shared per-request admission protects core Activity; a separate worker is not separate quota. Bounded local-only work MUST remain independent of ordinary publication, preserve scope, disables and existing fast/public-only/API-limited gates, and retain accepted evidence on failure; hosted publication MUST recheck enrollment and starting generation, manifest, policy and retained-result identities." - "Direct value publication MUST require PostgreSQL, existing observed parents, hosted administrator step-up and CSRF or local loopback bearer. Publication MUST atomically preserve owned packet/fact rows and required structural parents across Activity replacement, reject stale/conflicting captures, frozen-contract drift and immutable-history rewrites, and leave exact retries revision-neutral. No uploaded evaluator code, PAT fallback, enrollment or implicit collection is permitted." - "Recurring workflow-value collection MUST require exact reviewed opt-in under control-plane.campaigns.activity.workflow-values and a confined local collector deployed with policy. Existing Activity and hosted collection cycles MUST intersect effective collection scope and frozen cadence; failed refreshes MUST retain the original accepted capture without invented freshness or zeros. Disable MUST stop future collection without deleting history. Navigation, upload and discovery MUST NOT enable collection or introduce a new schedule or model call." - "Computation results MUST NOT grant authority or turn runtime success into verification, accepted outcomes, or operational value." diff --git a/activity/local-values.mjs b/activity/local-values.mjs index 139ad803a..85e9bf23a 100644 --- a/activity/local-values.mjs +++ b/activity/local-values.mjs @@ -1,6 +1,7 @@ import { readFile, stat } from 'node:fs/promises'; import path from 'node:path'; import { pathToFileURL } from 'node:url'; +import { isDeepStrictEqual } from 'node:util'; import { loadPolicyFile } from '../.github/workflows/shared/policy.mjs'; import { MAX_LOCAL_VALUE_BYTES as MAX_BYTES, runOperationalValue } from './operational-value.mjs'; import { adaptCachedGhAwJsonl } from '../dashboard/site/src/data/adapters/gh-aw-logs.js'; @@ -72,18 +73,25 @@ export async function retainLocalValues({ policy, input, output }) { return envelopes; }; const retained = await readValues(output); - let incoming = []; + const key = value => JSON.stringify([value.campaign, value.repository.toLowerCase(), value.value_id, value.timestamp]); + let accepted = new Map(retained.flatMap(envelope => { + const value = envelope.operational_value; + return valueRepositoryInScope(document, [value.repository], value.repository, true) ? [[key(value), envelope]] : []; + })); try { - incoming = await readValues(input); + const merged = new Map(accepted); + for (const envelope of await readValues(input)) { + const value = envelope.operational_value; + if (!valueRepositoryInScope(document, [value.repository], value.repository, true)) continue; + const previous = merged.get(key(value)); + if (previous && !isDeepStrictEqual(previous, envelope)) { + throw new Error('Conflicting completed local Value evidence at the same observation identity'); + } + merged.set(key(value), envelope); + } + accepted = merged; } catch (error) { console.warn(`Local Value import deferred: ${error.message}; retained evidence is unchanged`); - incoming = []; - } - const accepted = new Map(); - for (const envelope of [...retained, ...incoming]) { - const value = envelope.operational_value; - if (!valueRepositoryInScope(document, [value.repository], value.repository, true)) continue; - accepted.set(JSON.stringify([value.campaign, value.repository.toLowerCase(), value.value_id, value.timestamp]), envelope); } const envelopes = [...accepted.values()]; if (Buffer.byteLength(envelopes.map(envelope => JSON.stringify(envelope)).join('\n')) + envelopes.length > MAX_BYTES) { diff --git a/dashboard/site/src/data/model/workflow-value-collection.js b/dashboard/site/src/data/model/workflow-value-collection.js index a84cd19f8..7d4863588 100644 --- a/dashboard/site/src/data/model/workflow-value-collection.js +++ b/dashboard/site/src/data/model/workflow-value-collection.js @@ -26,6 +26,13 @@ const STATE_REASONS = { available: ['captured', 'not-due'] }; +/** @param {unknown} value */ +function collectionTime(value) { + if (typeof value !== 'string' || !value.endsWith('Z')) return null; + const fraction = /\.(\d+)Z$/.exec(value)?.[1] ?? ''; + return /[1-9]/.test(fraction.slice(3)) ? null : timestampMilliseconds(value); +} + /** @param {string} repository @param {string} workflow */ export function workflowValueCollectionId(repository, workflow) { return `workflow-value-collection:${encodeURIComponent(`${repository.toLowerCase()}:${workflow}`)}`; @@ -41,7 +48,7 @@ export function validateWorkflowValueCollection(record) { || !/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(record.workflow) || record.sourcePath !== `.github/workflows/${record.workflow}.md` || record.id !== workflowValueCollectionId(record.repository, record.workflow) - || timestampMilliseconds(record.observedAt) === null + || collectionTime(record.observedAt) === null || !/^[a-f0-9]{64}$/.test(record.policyDigest) || !['enabled', 'disabled', 'unconfigured'].includes(record.registration) || !['unconfigured', 'disabled', 'never-captured', 'deferred', 'failed', 'available'].includes(record.state) @@ -61,7 +68,7 @@ export function validateWorkflowValueCollection(record) { || record.registration === 'disabled' && record.state !== 'disabled' || record.registration === 'enabled' && record.state === 'unconfigured') fail(); if (record.lastAttemptAt !== undefined || record.lastAttemptOutcome !== undefined) { - if (timestampMilliseconds(record.lastAttemptAt) === null + if (collectionTime(record.lastAttemptAt) === null || Date.parse(record.lastAttemptAt) > Date.parse(record.observedAt) || !['available', 'failed'].includes(record.lastAttemptOutcome)) fail(); } @@ -71,22 +78,32 @@ export function validateWorkflowValueCollection(record) { return record; } -/** Replace a complete decision without rolling back its independent attempt clock. - * @param {Record | undefined} previous @param {Record} incoming */ +/** Reconcile the decision and actual attempt independently of arrival order. + * @param {Record | undefined} previous @param {Record} incoming + * @returns {Record} */ export function mergeWorkflowValueCollection(previous, incoming) { validateWorkflowValueCollection(incoming); - if (!previous) return incoming; - const before = Date.parse(previous.observedAt), after = Date.parse(incoming.observedAt); - if (before > after) return previous; - const next = previous.lastAttemptAt && !incoming.lastAttemptAt ? { - ...incoming, lastAttemptAt: previous.lastAttemptAt, lastAttemptOutcome: previous.lastAttemptOutcome, - } : incoming; - const fields = ['registration', 'collector', 'state', 'reasonCode', 'policyDigest', 'lastAttemptAt', 'lastAttemptOutcome']; - if (before === after && fields.some(field => previous[field] !== next[field])) { + if (previous && previous.id !== incoming.id) throw new TypeError('Cannot merge different workflow Value collection identities'); + const before = previous ? Date.parse(previous.observedAt) : -Infinity; + const after = Date.parse(incoming.observedAt); + const fields = ['registration', 'collector', 'state', 'reasonCode', 'policyDigest']; + if (before === after && fields.some(field => previous?.[field] !== incoming[field])) { throw new TypeError('Conflicting workflow Value collection decisions at the same time'); } - if (previous.lastAttemptAt && Date.parse(next.lastAttemptAt) < Date.parse(previous.lastAttemptAt)) { - throw new TypeError('Workflow Value collection attempt history regressed'); + const previousAttempt = timestampMilliseconds(previous?.lastAttemptAt); + const incomingAttempt = timestampMilliseconds(incoming.lastAttemptAt); + if (previousAttempt !== null && previousAttempt === incomingAttempt + && previous?.lastAttemptOutcome !== incoming.lastAttemptOutcome) { + throw new TypeError('Conflicting workflow Value collection outcomes for the same attempt'); } - return next; + const decision = before > after ? previous : incoming; + const attempt = (previousAttempt ?? -Infinity) > (incomingAttempt ?? -Infinity) ? previous : incoming; + return { + ...decision, + observedAt: new Date(Math.max(before, after)).toISOString(), + ...(attempt?.lastAttemptAt ? { + lastAttemptAt: new Date(attempt.lastAttemptAt).toISOString(), + lastAttemptOutcome: attempt.lastAttemptOutcome, + } : {}), + }; } diff --git a/dashboard/site/test/unit/data-sqlite-indexeddb.test.js b/dashboard/site/test/unit/data-sqlite-indexeddb.test.js index eea379810..b0cda798f 100644 --- a/dashboard/site/test/unit/data-sqlite-indexeddb.test.js +++ b/dashboard/site/test/unit/data-sqlite-indexeddb.test.js @@ -19,7 +19,7 @@ import { upsertCanonicalBatch } from '../../src/data/storage/indexeddb.js'; import { normalize } from '../../src/data/normalize/index.js'; -import { NORMALIZED_JSONL_INGESTION_VERSION } from '../../src/data/ingest/coordinator.js'; +import { ingestCachedGhAwJsonl, NORMALIZED_JSONL_INGESTION_VERSION } from '../../src/data/ingest/coordinator.js'; import { doctorSqliteDatabase } from '../../src/data/storage/sqlite-doctor.js'; import { createSqliteIndexedDB, @@ -61,6 +61,33 @@ function batch() { return canonical; } +it('reconciles independent Value decision and attempt clocks across SQLite reopen and replay order', async () => { + const older = JSON.parse(readFileSync(resolve('test/fixtures/workflow-value-collection.jsonl'), 'utf8')); + const newer = structuredClone(older); + newer.workflow_value_collection.observedAt = '2026-10-24T14:00:00.000Z'; + delete newer.workflow_value_collection.lastAttemptAt; + delete newer.workflow_value_collection.lastAttemptOutcome; + const results = []; + for (const records of [[older, newer], [newer, older]]) { + const filename = temporaryDatabase(); + for (const [index, envelope] of [...records, ...records].entries()) { + const database = installSqliteIndexedDB(filename); + await ingestCachedGhAwJsonl(database, JSON.stringify(envelope), { + now: Date.parse('2026-10-25T00:00:00Z'), payloadScope: `health-${index}`, + }); + } + results.push(await readCollection(installSqliteIndexedDB(filename), 'workflowValueCollections')); + } + expect(results[0]).toEqual(results[1]); + expect(results[0]).toHaveLength(1); + expect(results[0][0]).toMatchObject({ + observedAt: newer.workflow_value_collection.observedAt, + lastAttemptAt: older.workflow_value_collection.lastAttemptAt, + lastAttemptOutcome: older.workflow_value_collection.lastAttemptOutcome, + registration: 'enabled', state: 'deferred', reasonCode: 'api-budget', + }); +}); + it('keeps a year of outcome history through ingestion and doctor independently of run and detail TTLs', async () => { const filename = temporaryDatabase(); const indexedDB = installSqliteIndexedDB(filename); diff --git a/dashboard/site/test/unit/workflow-value-collection.test.js b/dashboard/site/test/unit/workflow-value-collection.test.js index bcf0698e9..f503a5a32 100644 --- a/dashboard/site/test/unit/workflow-value-collection.test.js +++ b/dashboard/site/test/unit/workflow-value-collection.test.js @@ -4,11 +4,12 @@ import { IDBFactory } from 'fake-indexeddb'; import { describe, expect, it } from 'vitest'; import { adaptCachedGhAwJsonl } from '../../src/data/adapters/gh-aw-logs.js'; import { ingestCachedGhAwJsonl } from '../../src/data/ingest/coordinator.js'; -import { validateWorkflowValueCollection } from '../../src/data/model/workflow-value-collection.js'; +import { mergeWorkflowValueCollection, validateWorkflowValueCollection } from '../../src/data/model/workflow-value-collection.js'; import { maintainCanonicalDatabase, readCollection } from '../../src/data/storage/indexeddb.js'; const source = readFileSync(new URL('../fixtures/workflow-value-collection.jsonl', import.meta.url), 'utf8'); const fixture = JSON.parse(source); +const orders = [[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]]; describe('canonical workflow Value collection facts', () => { it('fails closed on contradictory states, clocks, identities and measurements disguised as health', () => { @@ -18,7 +19,9 @@ describe('canonical workflow Value collection facts', () => { { registration: 'disabled' }, { state: 'available' }, { reason: 'invented' }, { lastAttemptAt: '2026-10-24T12:00:00Z' }, { lastAttemptOutcome: 'deferred' }, { id: 'wrong' }, { collector: '../escape.mjs' }, { value: 0 }, { capturedAt: record.observedAt }, - { workflowId: 'workflow:other' }, { schemaVersion: '1' } + { workflowId: 'workflow:other' }, { schemaVersion: '1' }, + { observedAt: '2026-10-23T14:00:00.000001Z' }, { observedAt: '2026-10-23T14:00:00+00:00' }, + { lastAttemptAt: '2026-10-22T12:00:00.000001Z' } ]) expect(() => validateWorkflowValueCollection({ ...record, ...changes })).toThrow(); expect(adaptCachedGhAwJsonl(source).observations.map(item => item.kind)) .toEqual(['repository', 'workflow', 'workflow-value-collection']); @@ -39,14 +42,16 @@ describe('canonical workflow Value collection facts', () => { const regressed = structuredClone(fixture); regressed.workflow_value_collection.observedAt = '2026-10-24T00:00:00Z'; regressed.workflow_value_collection.lastAttemptAt = '2026-10-21T12:00:00Z'; - await expect(ingestCachedGhAwJsonl(database, JSON.stringify(regressed), { now, payloadScope: 'regression' })).rejects.toThrow(); + await ingestCachedGhAwJsonl(database, JSON.stringify(regressed), { now, payloadScope: 'regression' }); + expect((await readCollection(database, 'workflowValueCollections'))[0].lastAttemptAt) + .toBe(fixture.workflow_value_collection.lastAttemptAt); const unknown = structuredClone(fixture); unknown.workflow_value_collection.observedAt = '2026-10-24T00:00:00Z'; delete unknown.workflow_value_collection.lastAttemptAt; delete unknown.workflow_value_collection.lastAttemptOutcome; await ingestCachedGhAwJsonl(database, JSON.stringify(unknown), { now, payloadScope: 'unknown-attempt' }); const [preserved] = await readCollection(database, 'workflowValueCollections'); - expect(preserved.observedAt).toBe(unknown.workflow_value_collection.observedAt); + expect(preserved.observedAt).toBe(new Date(unknown.workflow_value_collection.observedAt).toISOString()); expect(preserved.lastAttemptAt).toBe(fixture.workflow_value_collection.lastAttemptAt); expect(preserved.lastAttemptOutcome).toBe(fixture.workflow_value_collection.lastAttemptOutcome); await maintainCanonicalDatabase(database, { @@ -57,4 +62,49 @@ describe('canonical workflow Value collection facts', () => { expect(await readCollection(database, 'workflows')).toHaveLength(1); expect(await readCollection(database, 'runs')).toEqual([]); }); + + it('converges across ordering, duplicates, batch grouping and cache-loss decisions', async () => { + const older = fixture.workflow_value_collection; + const attempted = { ...older, observedAt: '2026-10-23T15:00:00.000Z', + lastAttemptAt: '2026-10-23T14:30:00.000Z', lastAttemptOutcome: 'available' }; + const deferred = { ...older, observedAt: '2026-10-24T14:00:00.000Z' }; + delete deferred.lastAttemptAt; + delete deferred.lastAttemptOutcome; + const records = [older, attempted, deferred]; + const expected = { ...deferred, lastAttemptAt: attempted.lastAttemptAt, lastAttemptOutcome: attempted.lastAttemptOutcome }; + const envelope = (/** @type {Record} */ record) => JSON.stringify({ ...fixture, workflow_value_collection: record }); + for (const order of orders) { + const [a, b, c] = order.map(index => records[index]); + const forward = mergeWorkflowValueCollection(mergeWorkflowValueCollection(a, b), c); + expect(forward).toEqual(expected); + expect(mergeWorkflowValueCollection(a, mergeWorkflowValueCollection(b, c))).toEqual(expected); + expect(mergeWorkflowValueCollection(forward, forward)).toEqual(expected); + const database = new IDBFactory(); + for (const [index, record] of [...order, ...order].map(index => records[index]).entries()) { + await ingestCachedGhAwJsonl(database, envelope(record), { + now: Date.parse('2026-10-25T00:00:00Z'), payloadScope: `permutation-${index}`, + }); + } + expect((await readCollection(database, 'workflowValueCollections'))[0]).toMatchObject(expected); + const grouped = new IDBFactory(); + await ingestCachedGhAwJsonl(grouped, order.map(index => envelope(records[index])).join('\n'), { + now: Date.parse('2026-10-25T00:00:00Z'), payloadScope: 'grouped', + }); + expect((await readCollection(grouped, 'workflowValueCollections'))[0]).toMatchObject(expected); + } + }); + + it('rejects contradictory decision or attempt revisions in either order and normalizes equivalent clocks', () => { + const original = fixture.workflow_value_collection; + const conflict = { ...original, observedAt: '2026-10-24T14:00:00.000Z', lastAttemptOutcome: 'available' }; + for (const [left, right] of [[original, conflict], [conflict, original]]) { + expect(() => mergeWorkflowValueCollection(left, right)).toThrow(/same attempt/); + } + const equivalent = { ...original, observedAt: '2026-10-23T14:00:00Z', lastAttemptAt: '2026-10-22T12:00:00Z' }; + expect(mergeWorkflowValueCollection(original, equivalent)).toEqual(original); + expect(mergeWorkflowValueCollection(equivalent, original)).toEqual(original); + const decision = { ...original, policyDigest: 'c'.repeat(64) }; + expect(() => mergeWorkflowValueCollection(original, decision)).toThrow(/decisions/); + expect(() => mergeWorkflowValueCollection(decision, original)).toThrow(/decisions/); + }); }); diff --git a/docs/operational-value.md b/docs/operational-value.md index e2fa02ed6..f6a23bd2c 100644 --- a/docs/operational-value.md +++ b/docs/operational-value.md @@ -101,7 +101,15 @@ five-minute ceiling, with two minutes per computation batch and thirty seconds per adapter; it does not backfill history. Existing fast, public-only and API-limited gates remain. A later Activity snapshot imports completed results. The hosted collector uses the same local runtime under a separate lease and -private snapshot, never the core projection lease. +private snapshot, never the core projection lease. Publication rechecks enrollment +and the starting input, policy and retained evidence; a concurrent change defers +the result rather than overwriting newer evidence. Completed-cache imports reject +conflicting measurements at an identical observation identity. + +Collection decisions and actual attempts retain independent clocks. Reordered +or repeated health observations cannot erase a known attempt or restore an older +registration. A missing attempt remains unknown; accepted capture and cutoff +dates still come only from measurement evidence. Opening a report does not trigger collection. A failed acquisition, timeout or invalid result leaves previous evidence and its capture/cutoff timestamps intact; diff --git a/server/README.md b/server/README.md index 7781bc4f2..2d221abe2 100644 --- a/server/README.md +++ b/server/README.md @@ -2863,13 +2863,21 @@ It does not mint a token or treat a quota preflight as a shared reservation. Bounded local-only computation has its own `value-local` lease, a verified private Activity snapshot and one attempt per completed projection generation. It does not hold the projection lease or evidence lock while computing. The two-minute -batch/30-second adapter budgets cancel the owned process tree; final publication -uses a short evidence lock and rechecks enrollment. Completed output waits for +batch/30-second adapter budgets cancel the owned process tree. Computation uses +a frozen policy copy; final publication uses a short evidence lock, rechecks +enrollment, and compares the input generation, manifest, policy and retained +evidence with its starting state. A changed precondition defers the result +rather than overwriting newer accepted evidence. Completed output waits for the next ordinary projection, avoiding a Value-generated retry loop. An unsupported adapter, missing input, timeout or failure preserves accepted history. This improves health visibility and core isolation, not guaranteed fresh Value collection or separate capacity for external consumers. +Health reconciliation keeps the newest decision and newest actual attempt +independently, so replay order and missing attempt metadata cannot erase known +history or revive an older registration. Same-clock contradictions fail closed; +measurement capture/cutoff dates remain exclusively those of accepted evidence. + The hosted dashboard shows a user icon at the lower left of the navigation. It appears only after the server confirms an authenticated GitHub session and opens a user view with account switching and logout. Logout remains on a diff --git a/server/internal/collect/projector_local_value_test.go b/server/internal/collect/projector_local_value_test.go index aef6bf239..656e815cf 100644 --- a/server/internal/collect/projector_local_value_test.go +++ b/server/internal/collect/projector_local_value_test.go @@ -70,6 +70,18 @@ func TestLocalValueSnapshotIsPrivateVerifiedAndBounded(t *testing.T) { if err := copyLocalValueSnapshot(t.Context(), lake, destination); err != nil { t.Fatal(err) } + policy := filepath.Join(t.TempDir(), "cao.json") + if err := os.WriteFile(policy, []byte(`{"version":1}`), 0o600); err != nil { + t.Fatal(err) + } + liveRevision, err := readLocalValueRevision(t.Context(), lake.Directory, policy, lake.operationalValuesPath()) + if err != nil { + t.Fatal(err) + } + copiedRevision, err := readLocalValueRevision(t.Context(), destination, policy, filepath.Join(destination, "operational-values.jsonl")) + if err != nil || copiedRevision != liveRevision { + t.Fatalf("snapshot changed its publication precondition: %v", err) + } if _, _, _, err := ingest.ValidateManifest(destination); err != nil { t.Fatal(err) } @@ -91,3 +103,93 @@ func TestLocalValueSnapshotIsPrivateVerifiedAndBounded(t *testing.T) { t.Fatal("a failed disposable snapshot changed accepted evidence") } } + +func localValuePublicationFixture(t *testing.T) (Projector, string, localValueRevision) { + t.Helper() + lake := Lake{Directory: t.TempDir()} + if err := lake.Prepare(); err != nil { + t.Fatal(err) + } + policy, output := filepath.Join(t.TempDir(), "cao.json"), filepath.Join(t.TempDir(), "computed.jsonl") + for filename, content := range map[string]string{ + lake.ManifestPath(): "{}", + policy: `{"version":1}`, + lake.operationalValuesPath(): retainedValueLine("octo/api", "worker.retained"), + output: retainedValueLine("octo/api", "worker.retained") + retainedValueLine("octo/api", "worker.new"), + } { + if err := os.WriteFile(filename, []byte(content), 0o600); err != nil { + t.Fatal(err) + } + } + revision, err := readLocalValueRevision(t.Context(), lake.Directory, policy, lake.operationalValuesPath()) + if err != nil { + t.Fatal(err) + } + return Projector{ + Lake: lake, PolicyPath: policy, + State: &localValueAttemptState{values: map[string][]byte{projectionCompletedKey: []byte("generation-1")}}, + }, output, revision +} + +func TestLocalValuePublicationRejectsSupersededInputs(t *testing.T) { + for _, changed := range []string{"generation", "policy", "manifest", "accepted-evidence", "cancelled"} { + t.Run(changed, func(t *testing.T) { + projector, output, revision := localValuePublicationFixture(t) + ctx := t.Context() + switch changed { + case "generation": + if err := projector.State.SetOperationalState(ctx, projectionCompletedKey, []byte("generation-2")); err != nil { + t.Fatal(err) + } + case "policy", "manifest", "accepted-evidence": + filename := map[string]string{ + "policy": projector.PolicyPath, "manifest": projector.Lake.ManifestPath(), + "accepted-evidence": projector.Lake.operationalValuesPath(), + }[changed] + if err := os.WriteFile(filename, []byte(retainedValueLine("octo/api", "worker.newer")), 0o600); err != nil { + t.Fatal(err) + } + case "cancelled": + var cancel context.CancelFunc + ctx, cancel = context.WithCancel(ctx) + cancel() + } + before, err := os.ReadFile(projector.Lake.operationalValuesPath()) + if err != nil { + t.Fatal(err) + } + if err := projector.publishLocalValues(ctx, output, []byte("generation-1"), revision); err == nil { + t.Fatalf("%s allowed stale publication", changed) + } + after, err := os.ReadFile(projector.Lake.operationalValuesPath()) + if err != nil || string(after) != string(before) { + t.Fatalf("%s changed accepted evidence: %v", changed, err) + } + }) + } +} + +func TestLocalValuePublicationRechecksEnrollmentAndDoesNotRequestProjection(t *testing.T) { + store, ctx := integrationStore(t) + for _, enrolled := range []bool{true, false} { + projector, output, revision := localValuePublicationFixture(t) + projector.Enrollment = Enrollment{Metadata: store, Leases: store} + if enrolled { + if err := projector.Enrollment.AddRepositories(ctx, 7, []string{"octo/api"}); err != nil { + t.Fatal(err) + } + } else if _, err := projector.Enrollment.RemoveRepositories(ctx, 7, []string{"octo/api"}); err != nil { + t.Fatal(err) + } + if err := projector.publishLocalValues(ctx, output, []byte("generation-1"), revision); err != nil { + t.Fatal(err) + } + content, err := os.ReadFile(projector.Lake.operationalValuesPath()) + if err != nil || strings.Contains(string(content), "worker.new") != enrolled { + t.Fatalf("publication bypassed current enrollment: %q, %v", content, err) + } + if pending, err := projector.PendingProjection(ctx); pending || err != nil { + t.Fatalf("optional publication created a projection loop: %t, %v", pending, err) + } + } +} diff --git a/server/internal/collect/projector_workflow_values.go b/server/internal/collect/projector_workflow_values.go index 30c18df3f..21f2bb6ed 100644 --- a/server/internal/collect/projector_workflow_values.go +++ b/server/internal/collect/projector_workflow_values.go @@ -3,6 +3,7 @@ package collect import ( "bytes" "context" + "crypto/sha256" "encoding/json" "errors" "fmt" @@ -85,15 +86,31 @@ func (p Projector) CollectLocalValues(ctx context.Context) error { if err := copyLocalValueSnapshot(ctx, p.Lake, workspace); err != nil { return err } + policy, err := readLocalValueFile(ctx, p.PolicyPath, 1<<20) + if err != nil { + return err + } + policyPath := filepath.Join(workspace, "cao.json") + if err := os.WriteFile(policyPath, policy, 0o600); err != nil { + return err + } output := filepath.Join(workspace, "operational-values.jsonl") + revision, err := readLocalValueRevision(ctx, workspace, policyPath, output) + if err != nil { + return err + } config := operationalvalue.Config{ Root: p.CatalogRoot, NodeBinary: p.node(), Output: output, Database: filepath.Join(workspace, "activity.sqlite"), Environment: collectionEnvironment(p.GitHubAPIURL), WorkerTimeout: 2 * time.Minute, } - if err := operationalvalue.ComputeLocalSnapshot(ctx, config, p.PolicyPath, workspace, strconv.Itoa(p.windowDays())); err != nil { + if err := operationalvalue.ComputeLocalSnapshot(ctx, config, policyPath, workspace, strconv.Itoa(p.windowDays())); err != nil { return err } + return p.publishLocalValues(ctx, output, generation, revision) +} + +func (p Projector) publishLocalValues(ctx context.Context, output string, generation []byte, revision localValueRevision) error { content, err := readLocalValueFile(ctx, output, 16<<20) if errors.Is(err, os.ErrNotExist) { return nil @@ -108,6 +125,17 @@ func (p Projector) CollectLocalValues(ctx context.Context) error { return err } defer unlock() + currentGeneration, err := p.State.OperationalState(publication, projectionCompletedKey) + if err != nil { + return err + } + current, err := readLocalValueRevision(publication, p.Lake.Directory, p.PolicyPath, p.Lake.operationalValuesPath()) + if err != nil { + return err + } + if !bytes.Equal(generation, currentGeneration) || current != revision { + return errors.New("local Value publication deferred: its input, policy, or accepted evidence changed") + } repositories, err := p.enrolledRepositories(publication) if err != nil { return err @@ -135,6 +163,31 @@ func (p Projector) CollectLocalValues(ctx context.Context) error { return WriteFileAtomic(p.Lake.operationalValuesPath(), content) } +type localValueRevision struct { + policy, manifest, values [sha256.Size]byte +} + +func readLocalValueRevision(ctx context.Context, directory, policy, values string) (localValueRevision, error) { + var revision localValueRevision + for _, input := range []struct { + filename string + limit int64 + optional bool + digest *[sha256.Size]byte + }{ + {policy, 1 << 20, false, &revision.policy}, + {filepath.Join(directory, "payload-hashes.json"), 1 << 20, false, &revision.manifest}, + {values, 16 << 20, true, &revision.values}, + } { + content, err := readLocalValueFile(ctx, input.filename, input.limit) + if err != nil && (!input.optional || !errors.Is(err, os.ErrNotExist)) { + return revision, err + } + *input.digest = sha256.Sum256(content) + } + return revision, nil +} + func copyLocalValueSnapshot(ctx context.Context, lake Lake, destination string) error { content, err := readLocalValueFile(ctx, lake.ManifestPath(), 1<<20) if err != nil { @@ -182,10 +235,6 @@ func copyLocalValueSnapshot(ctx context.Context, lake Lake, destination string) return err } } - content, err = json.Marshal(manifest) - if err != nil { - return err - } if err := os.WriteFile(filepath.Join(destination, "payload-hashes.json"), content, 0o600); err != nil { return err } diff --git a/server/internal/postgresx/workflow_value_collection.go b/server/internal/postgresx/workflow_value_collection.go index c21f61e64..2f04ac252 100644 --- a/server/internal/postgresx/workflow_value_collection.go +++ b/server/internal/postgresx/workflow_value_collection.go @@ -7,56 +7,64 @@ import ( "regexp" "slices" "strings" + "time" "github.com/githubnext/gh-cao/server/internal/model" ) func (w *Writer) preserveCollectionDecisions(ctx context.Context) error { _, err := w.tx.Exec(ctx, `CREATE TEMP TABLE workflow_value_collections_previous ON COMMIT DROP AS - SELECT id, observed_at, registration, collector, state, reason_code, policy_digest, + SELECT id, present_fields, observed_at, registration, collector, state, reason_code, reason, policy_digest, last_attempt_at, last_attempt_outcome FROM workflow_value_collections WHERE namespace=$1`, w.store.namespace) return err } func (w *Writer) reconcileCollectionDecisions(ctx context.Context) error { - presence := "incoming.present_fields" - for index, column := range entityTables["$workflowValueCollections"].columns { - if column.field == "lastAttemptAt" || column.field == "lastAttemptOutcome" { - presence = fmt.Sprintf("set_bit(%s,%d,1)", presence, index) - } - } - // An absent attempt means unknown, including after a local cache loss. - if _, err := w.tx.Exec(ctx, `UPDATE workflow_value_collections incoming SET - last_attempt_at=previous.last_attempt_at, last_attempt_outcome=previous.last_attempt_outcome, - present_fields=`+presence+` FROM workflow_value_collections_previous previous - WHERE incoming.namespace=$1 AND incoming.id=previous.id - AND incoming.observed_at>=previous.observed_at - AND incoming.last_attempt_at IS NULL AND previous.last_attempt_at IS NOT NULL`, w.store.namespace); err != nil { - return err - } var invalid bool err := w.tx.QueryRow(ctx, `SELECT EXISTS ( SELECT 1 FROM workflow_value_collections incoming JOIN workflow_value_collections_previous previous USING (id) WHERE incoming.namespace=$1 AND ( - incoming.observed_at < previous.observed_at OR (incoming.observed_at = previous.observed_at AND ROW(incoming.registration, incoming.collector, incoming.state, incoming.reason_code, - incoming.policy_digest, incoming.last_attempt_at, incoming.last_attempt_outcome) + incoming.policy_digest) IS DISTINCT FROM ROW(previous.registration, previous.collector, previous.state, previous.reason_code, - previous.policy_digest, previous.last_attempt_at, previous.last_attempt_outcome)) OR - (previous.last_attempt_at IS NOT NULL AND - (incoming.last_attempt_at IS NULL OR incoming.last_attempt_at < previous.last_attempt_at)) + previous.policy_digest)) OR + (incoming.last_attempt_at = previous.last_attempt_at AND + incoming.last_attempt_outcome IS DISTINCT FROM previous.last_attempt_outcome) ))`, w.store.namespace).Scan(&invalid) if err != nil { return err } if invalid { - return errors.New("workflow Value collection decision regressed or conflicts with accepted history") + return errors.New("workflow Value collection decision or attempt conflicts with accepted history") } - return nil + decisionPresence, attemptPresence := "incoming.present_fields", "incoming.present_fields" + for index, column := range entityTables["$workflowValueCollections"].columns { + if column.field == "collector" { + decisionPresence = fmt.Sprintf("set_bit(%s,%d,get_bit(previous.present_fields,%d))", decisionPresence, index, index) + } + if column.field == "lastAttemptAt" || column.field == "lastAttemptOutcome" { + attemptPresence = fmt.Sprintf("set_bit(%s,%d,1)", attemptPresence, index) + } + } + if _, err := w.tx.Exec(ctx, `UPDATE workflow_value_collections incoming SET + observed_at=previous.observed_at, registration=previous.registration, collector=previous.collector, + state=previous.state, reason_code=previous.reason_code, reason=previous.reason, policy_digest=previous.policy_digest, + present_fields=`+decisionPresence+` FROM workflow_value_collections_previous previous + WHERE incoming.namespace=$1 AND incoming.id=previous.id + AND incoming.observed_at JSON.stringify(record)).join('\n')); + await retainLocalValues({ policy: options.policy, input, output }); + assert.deepEqual(JSON.parse(await readFile(output, 'utf8')), original); + await writeFile(input, [original, later, original].map(record => JSON.stringify(record)).join('\n')); + await retainLocalValues({ policy: options.policy, input, output }); + assert.deepEqual((await readFile(output, 'utf8')).trim().split('\n').map(line => JSON.parse(line)), [original, later]); }); From 5cf6400dd1cda774102c94fc1db3d5a21fd6d64d Mon Sep 17 00:00:00 2001 From: Mara Nikola Kiefer <8320933+mnkiefer@users.noreply.github.com> Date: Fri, 23 Oct 2026 20:05:39 +0200 Subject: [PATCH 4/5] Align Activity cache contract with Value health isolation Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: e45b84aa-0ee5-49c3-8eea-a54a5eb80b03 --- tests/integration/activity-cache.test.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/activity-cache.test.mjs b/tests/integration/activity-cache.test.mjs index b7d09b8ac..d4b299973 100644 --- a/tests/integration/activity-cache.test.mjs +++ b/tests/integration/activity-cache.test.mjs @@ -171,7 +171,7 @@ test("activity workflow caches gh-aw logs and their SQLite projection", async () for (const [name, variable] of [ ["Download owner-scoped agentic workflow logs", "REPORT_ACTIVITY_DATABASE"], ["Enrich owner-scoped issue statuses", "ACTIVITY_DATABASE"], - ["Compute owner-scoped operational value", "ACTIVITY_DATABASE"], + ["Retain Value evidence and publish collection health", "ACTIVITY_DATABASE"], ]) { assert.equal(collectSteps.find((step) => step.name === name).env[variable], "${{ runner.temp }}/cao-activity/collection.sqlite", From 2efffc4ab9e24b1fcb26ce7569b9d2b511c422dd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 23 Oct 2026 19:17:12 +0000 Subject: [PATCH 5/5] Register Value health collection in native queries Co-authored-by: mnkiefer <8320933+mnkiefer@users.noreply.github.com> --- internal/cli/native_snapshot.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/cli/native_snapshot.go b/internal/cli/native_snapshot.go index b551c526a..e43c4f1f9 100644 --- a/internal/cli/native_snapshot.go +++ b/internal/cli/native_snapshot.go @@ -23,7 +23,8 @@ const nativeDatabaseName = dashboardquery.DatabaseName var nativeCollections = []string{ "repositories", "workflows", "runs", "domains", "tools", "skills", "friction", "audits", "issues", - "operationalValues", "operationalValueEvidence", "experiments", "experimentAssignments", "graders", "graderObservations", "evals", "evalObservations", "transactions", + "operationalValues", "operationalValueEvidence", "workflowValueCollections", + "experiments", "experimentAssignments", "graders", "graderObservations", "evals", "evalObservations", "transactions", } func nativeString(cmd *cobra.Command, name string) string {