Skip to content

Separate dashboard call-table storage from Redis operations - #15567

Closed
pelikhan with Copilot wants to merge 11 commits into
mainfrom
copilot/refactor-call-table-data-abstraction
Closed

pelikhan with Copilot wants to merge 11 commits into
mainfrom
copilot/refactor-call-table-data-abstraction

Conversation

Copilot AI commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Dashboard call-table storage is currently coupled to Redis generation and projection mechanics. This PR introduces a database boundary for ingestion and queries without adding a PostgreSQL backend.

  • Storage contract: Add snapshot publication, query validation, and query execution interfaces without generation requirements.
  • Redis adapter: Keep generation staging, activation, reclamation, and indexes inside Redis; leave operational locks, state, and caches separate.
  • Consistent reads: Pin each query and its response revision to the same published snapshot.
  • Integration: Route ingestion and server queries through the boundary and add focused coverage.

Copilot AI and others added 3 commits October 1, 2026 15:00
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Copilot AI changed the title Introduce a database boundary for dashboard call-table storage Separate dashboard call-table storage from Redis operations Oct 1, 2026
Copilot AI requested a review from pelikhan October 1, 2026 15:08
@pelikhan
pelikhan marked this pull request as ready for review October 1, 2026 15:13
@github-actions

github-actions Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor
Dashboard query cost report

Dashboard query cost (deployed SQLite snapshot)

Measured the 10 most expensive of 164 queries chosen by the static query cost evaluator (normalized-upper-bound, 695 normalized row-read units to materialize all queries).

Canonical projection read 42,194 records across 10 sources in 8813.16 ms.

Canonical projection by source
Source Records
domains 22,258
overview-runs 8,831
runs 8,831
issues 1,100
outcomes 1,100
workflows 71
repositories 3
audits 0
campaigns 0
tools 0

Empty database tables: campaigns, audits, tools.

Computational cost

Rank Query Static rank Input rows Output rows Operations Time (ms)
1 campaign-problem-run-evidence 7 2,211 0 2,211 4.75
2 repository-activity 8 6 3 18 0.83
3 campaign-problem-tab-counts 1 0 0 0 0.32
4 campaign-workflows 9 71 0 142 0.32
5 campaign-workflow-totals 10 71 0 142 0.30
6 campaign-problem-latest-target-runs 6 0 0 0 0.29
7 campaign-inventory 4 1 0 1 0.16
8 campaign-problem-items 2 0 0 0 0.15
9 campaign-problem-error-groups 5 0 0 0 0.15
10 campaign-current-problem-error-groups 3 0 0 0 0.12

Space cost

Rank Query Output rows Result size Bytes/row Retained heap Heap after run
1 repository-activity 3 3.17 KiB 1.06 KiB 7.47 KiB 78.87 KiB
2 campaign-workflows 0 32 B 0 B 2.78 KiB 66.45 KiB
3 campaign-workflow-totals 0 32 B 0 B 2.69 KiB 66.09 KiB
4 campaign-problem-error-groups 0 32 B 0 B 1.38 KiB 12.78 KiB
5 campaign-problem-tab-counts 0 32 B 0 B 1.26 KiB 13.05 KiB
6 campaign-inventory 0 32 B 0 B 976 B 19.04 KiB
7 campaign-problem-latest-target-runs 0 32 B 0 B 592 B 9.82 KiB
8 campaign-current-problem-error-groups 0 32 B 0 B 520 B 14.78 KiB
9 campaign-problem-run-evidence 0 32 B 0 B 520 B 3.89 MiB
10 campaign-problem-items 0 32 B 0 B 448 B 17.80 KiB

Retained heap is measured after collection while the result is held; heap after run is a single post-execution sample, not an exact peak.

Redis native translation

Redis native translation (offline)

185 queries: 9 full candidates, 2 partial candidates, 167 Go fallback, 7 unsupported by Go.

Candidates are not verified native executions: the active Redis generation must have JSON sources and compatible RediSearch indexes. Partial candidates can still execute remaining operations in Go; no Redis connection or runtime row budget was checked.

Query Source Level Redis primitive Limitation
audit-entity-insights audits full candidate FT.AGGREGATE
audit-event-runs audits full candidate FT.AGGREGATE
audit-event-summary-buckets audits fallback none redis query engine does not support this query shape
campaign-active-orchestrator-run-presence workflows fallback none query dependency requires Go execution
campaign-audit-summary-plot-inventory audit-event-summary-buckets fallback none query dependency requires Go execution
campaign-cost-totals workflows fallback none query dependency requires Go execution
campaign-current-problem-error-groups campaign-problem-error-groups fallback none query dependency requires Go execution
campaign-current-runtime-failures campaign-runtime-problem-candidates fallback none query dependency requires Go execution
campaign-dispatch-totals dispatches fallback none query dependency requires Go execution
campaign-insight-plot-inventory campaign-operational-value-plot-inventory fallback none query dependency requires Go execution
campaign-insight-tab-counts campaign-insight-plot-inventory fallback none query dependency requires Go execution
campaign-inventory campaigns fallback none query dependency requires Go execution
campaign-issue-tab-counts campaign-worker-issues fallback none query dependency requires Go execution
campaign-memory-campaigns campaigns fallback none query dependency requires Go execution
campaign-operational-value-evidence-state campaign-operational-value-evidence-state-totals fallback none query dependency requires Go execution
campaign-operational-value-evidence-state-totals operational-values fallback none query dependency requires Go execution
campaign-operational-value-plot-inventory campaign-operational-value-primary-series fallback none query dependency requires Go execution
campaign-operational-value-primary-series operational-values fallback none query dependency requires Go execution
campaign-operational-value-repository-run-day-totals campaign-runs fallback none query dependency requires Go execution
campaign-operational-value-repository-run-days campaign-operational-value-repository-run-day-totals fallback none query dependency requires Go execution
campaign-operational-value-run-day-totals campaign-operational-value-repository-run-days fallback none query dependency requires Go execution
campaign-operational-value-run-days campaign-operational-value-run-day-totals fallback none query dependency requires Go execution
campaign-performance-baseline campaign-performance-baseline-totals fallback none query dependency requires Go execution
campaign-performance-baseline-totals campaign-runs fallback none query dependency requires Go execution
campaign-problem-error-groups campaign-problem-run-evidence fallback none query dependency requires Go execution
campaign-problem-items campaign-current-problem-error-groups fallback none query dependency requires Go execution
campaign-problem-latest-target-runs campaign-problem-run-evidence fallback none query dependency requires Go execution
campaign-problem-run-evidence campaign-problem-runs fallback none query dependency requires Go execution
campaign-problem-runs campaign-runs fallback none query dependency requires Go execution
campaign-problem-tab-counts campaign-problem-items fallback none query dependency requires Go execution
campaign-readme-details campaigns fallback none query dependency requires Go execution
campaign-readme-orchestrators workflows fallback none query dependency requires Go execution
campaign-reports outcomes fallback none query dependency requires Go execution
campaign-repository-coverage runs fallback none query dependency requires Go execution
campaign-runs runs fallback none query dependency requires Go execution
campaign-runtime-health-groups campaign-runtime-health-runs fallback none query dependency requires Go execution
campaign-runtime-health-runs overview-runs fallback none query dependency requires Go execution
campaign-runtime-problem-candidates campaign-runtime-health-groups fallback none query dependency requires Go execution
campaign-runtime-problem-counts campaign-runtime-problems fallback none query dependency requires Go execution
campaign-runtime-problems campaign-current-runtime-failures fallback none query dependency requires Go execution
campaign-unobserved-orchestrator-candidates campaign-active-orchestrator-run-presence fallback none query dependency requires Go execution
campaign-unobserved-orchestrators campaign-unobserved-orchestrator-candidates fallback none query dependency requires Go execution
campaign-worker-issues outcomes fallback none query dependency requires Go execution
campaign-workflow-totals workflow-inventory fallback none query dependency requires Go execution
campaign-workflows workflow-inventory fallback none query dependency requires Go execution
campaigns $campaigns fallback none redis query engine does not support this query shape
cost-by-campaign campaigns fallback none query dependency requires Go execution
cost-by-repository repository-aic-totals fallback none query dependency requires Go execution
cost-by-workflow workflow-aic-totals fallback none query dependency requires Go execution
cost-per-workflow-run workflow-aic-run-totals fallback none query dependency requires Go execution
database-campaign-count campaigns fallback none query dependency requires Go execution
detection-observations $security-findings unsupported none query "detection-observations" computed field "detection-expected" has invalid arity
dispatches campaign-runs fallback none query dependency requires Go execution
domain-entity-insights domains full candidate FT.AGGREGATE
domain-event-runs domains full candidate FT.AGGREGATE
engines-models-usage runs fallback none query dependency requires Go execution
entity-events event-base fallback none query dependency requires Go execution
entity-runs runs fallback none query dependency requires Go execution
entity-workflow-run-totals runs fallback none query dependency requires Go execution
entity-workflows workflows fallback none query dependency requires Go execution
eval-observations $evalObservations fallback none redis query engine does not support this query shape
eval-yes-no-status eval-observations fallback none query dependency requires Go execution
evals $evals fallback none redis query engine does not support this query shape
event-base audits fallback none redis query engine does not support this query shape
event-runs audit-event-runs fallback none query dependency requires Go execution
experiment-assignment-coverage experiment-assignments fallback none query dependency requires Go execution
experiment-assignments $experimentAssignments fallback none redis query engine does not support this query shape
experiments $experiments fallback none redis query engine does not support this query shape
failed-runs failure-run-base fallback none query dependency requires Go execution
failure-run-base runs fallback none query dependency requires Go execution
findings run-records unsupported none query "findings" computed field "finding-kind" has invalid arity
firewall-domain-totals firewall-observations fallback none query dependency requires Go execution
firewall-domain-workflows firewall-observations fallback none query dependency requires Go execution
firewall-most-blocked-domains firewall-domain-totals fallback none query dependency requires Go execution
firewall-observations run-records fallback none query dependency requires Go execution
friction-by-workflow friction fallback none computed field "repository-coordinate": unsupported function "concat"
friction-observations friction fallback none computed field "repository-coordinate": unsupported function "concat"
github-api-usage github-quota-usage fallback none server runtime source is not a RedisJSON index
grader-observations $graderObservations fallback none redis query engine does not support this query shape
grader-status-ledger grader-observations fallback none query dependency requires Go execution
graders $graders fallback none redis query engine does not support this query shape
indexing-audits-table-count audits full candidate FT.AGGREGATE
indexing-campaigns-table-count campaigns fallback none query dependency requires Go execution
indexing-daily-records transactions fallback none query dependency requires Go execution
indexing-daily-workflow-runs transactions fallback none query dependency requires Go execution
indexing-database-table-counts indexing-campaigns-table-count fallback none query dependency requires Go execution
indexing-domains-table-count domains full candidate FT.AGGREGATE
indexing-issues-table-count issues fallback none issue overlays require Go execution
indexing-operational-values-table-count operational-values fallback none query dependency requires Go execution
indexing-repositories-table-count repositories fallback none query dependency requires Go execution
indexing-runs-table-count runs fallback none query dependency requires Go execution
indexing-tools-table-count tools full candidate FT.AGGREGATE
indexing-transactions transactions fallback none query dependency requires Go execution
indexing-transactions-table-count transactions fallback none query dependency requires Go execution
indexing-workflows-table-count workflows fallback none query dependency requires Go execution
ingestion-backfill collection-health fallback none server runtime source is not a RedisJSON index
ingestion-health collection-health fallback none server runtime source is not a RedisJSON index
ingestion-inflight collection-health fallback none server runtime source is not a RedisJSON index
ingestion-queue-sizes ingestion-queued fallback none query dependency requires Go execution
ingestion-queued collection-health fallback none server runtime source is not a RedisJSON index
issue-event-runs issues fallback none issue overlays require Go execution
issue-repository-totals issue-safe-outputs fallback none query dependency requires Go execution
issue-safe-outputs issues fallback none issue overlays require Go execution
maintenance-campaign-updates campaigns fallback none query dependency requires Go execution
maintenance-repositories maintenance-repository-versions fallback none query dependency requires Go execution
maintenance-repository-upgrades maintenance-repositories fallback none query dependency requires Go execution
maintenance-repository-versions workflows fallback none query dependency requires Go execution
marketplace-package-detail marketplace-packages fallback none query dependency requires Go execution
marketplace-packages $marketplacePackages fallback none redis query engine does not support this query shape
mcp-calls run-records fallback none query dependency requires Go execution
mcp-tool-calls mcp-calls fallback none query dependency requires Go execution
mcp-tool-totals mcp-tool-calls fallback none query dependency requires Go execution
mcp-top-tools mcp-tool-totals fallback none query dependency requires Go execution
operational-values $operationalValues fallback none redis query engine does not support this query shape
outcomes run-records unsupported none query "outcomes" has unsupported computed-field function "link"
overview-campaign-count-presentation-input database-campaign-count fallback none query dependency requires Go execution
overview-campaign-health-presentation overview-healthy-campaign-presentation-input fallback none query dependency requires Go execution
overview-campaign-links campaigns fallback none query dependency requires Go execution
overview-campaign-station overview-campaign-health-presentation fallback none query dependency requires Go execution
overview-delivery-coverage-input overview-delivery-summary fallback none query dependency requires Go execution
overview-delivery-summary overview-runs fallback none query dependency requires Go execution
overview-disabled-dispatchers workflows fallback none query dependency requires Go execution
overview-factory-status overview-run-status-input fallback none query dependency requires Go execution
overview-failing-runs failure-run-base fallback none query dependency requires Go execution
overview-failing-workflows overview-failing-runs fallback none query dependency requires Go execution
overview-header-presentation overview-header-status-presentation-input fallback none query dependency requires Go execution
overview-header-status-presentation-input overview-factory-status fallback none query dependency requires Go execution
overview-healthy-campaign-count campaigns fallback none query dependency requires Go execution
overview-healthy-campaign-presentation-input overview-healthy-campaign-count fallback none query dependency requires Go execution
overview-needs-attention overview-repeated-failure-attention fallback none query dependency requires Go execution
overview-registered-repository-coverage-input overview-registered-repository-summary fallback none query dependency requires Go execution
overview-registered-repository-summary repositories fallback none query dependency requires Go execution
overview-repeated-failure-attention overview-repeated-failure-candidates fallback none query dependency requires Go execution
overview-repeated-failure-candidates work-items fallback none redis query engine does not support this query shape
overview-repeated-failure-groups runs fallback none query dependency requires Go execution
overview-repository-coverage overview-repository-coverage-summary fallback none query dependency requires Go execution
overview-repository-coverage-summary overview-delivery-coverage-input fallback none query dependency requires Go execution
overview-repository-station overview-repository-station-presentation-input fallback none query dependency requires Go execution
overview-repository-station-presentation-input overview-repository-coverage fallback none query dependency requires Go execution
overview-review-attention work-items partial candidate FT.SEARCH candidate selection computed field "kind": unsupported function "coalesce"
overview-rhythm overview-runs fallback none query dependency requires Go execution
overview-run-motion-presentation-input overview-run-summary fallback none query dependency requires Go execution
overview-run-status-input overview-run-summary fallback none query dependency requires Go execution
overview-run-summary overview-runs fallback none query dependency requires Go execution
overview-runs $runs unsupported none query "overview-runs" computed field "run" has invalid arity
overview-value-status-input overview-value-summary fallback none query dependency requires Go execution
overview-value-summary grader-observations fallback none query dependency requires Go execution
repositories $repositories fallback none redis query engine does not support this query shape
repository-activity repository-activity-core fallback none query dependency requires Go execution
repository-activity-core repositories fallback none query dependency requires Go execution
repository-aic-totals runs fallback none query dependency requires Go execution
repository-report-totals outcomes fallback none query dependency requires Go execution
repository-run-totals run-import-status fallback none query dependency requires Go execution
repository-runs runs fallback none query dependency requires Go execution
repository-workflow-totals workflows fallback none query dependency requires Go execution
run-import-status runs fallback none query dependency requires Go execution
run-incomplete-outcomes audits partial candidate FT.SEARCH candidate selection unsupported Redis predicate value for "event-type"
run-records $records unsupported none query "run-records" exceeds structural resource limits
runs $runs unsupported none query "runs" computed field "run" has invalid arity
runs-daily-conclusions runs fallback none query dependency requires Go execution
runs-table runs fallback none query dependency requires Go execution
safe-output-performance $outcomes unsupported none query "safe-output-performance" computed field "safe-output-count" has invalid arity
skill-invocations skills full candidate FT.AGGREGATE
skill-invocations-by-skill skill-invocations fallback none query dependency requires Go execution
skill-invocations-by-workflow skill-invocations-by-workflow-totals fallback none query dependency requires Go execution
skill-invocations-by-workflow-totals skill-invocations fallback none query dependency requires Go execution
skill-workflow-inventory skill-workflow-totals fallback none query dependency requires Go execution
skill-workflow-totals skill-invocations fallback none query dependency requires Go execution
steering-events audits fallback none redis query engine does not support this query shape
steering-top-workflows steering-workflows fallback none query dependency requires Go execution
steering-type-totals steering-events fallback none query dependency requires Go execution
steering-workflow-totals steering-events fallback none query dependency requires Go execution
steering-workflows steering-workflow-totals fallback none query dependency requires Go execution
tool-entity-insights mcp-tool-calls fallback none query dependency requires Go execution
tool-event-runs tools full candidate FT.AGGREGATE
transactions $transactions fallback none redis query engine does not support this query shape
workflow-aic-per-run workflows fallback none query dependency requires Go execution
workflow-aic-run-totals runs fallback none query dependency requires Go execution
workflow-aic-totals runs fallback none query dependency requires Go execution
workflow-inventory workflows fallback none query dependency requires Go execution
workflow-reports outcomes fallback none query dependency requires Go execution
workflow-run-observation-counts overview-runs fallback none query dependency requires Go execution
workflow-run-totals run-import-status fallback none query dependency requires Go execution
workflow-runs runs fallback none query dependency requires Go execution
workflows $workflows fallback none redis query engine does not support this query shape

Query cost benchmark passed. Redis translation report compiled.

View the workflow run and query cost artifact.

@github-actions

github-actions Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Dashboard query parity

Status: passed

All 160 dashboard queries matched across 7 backends.

Download the complete parity report artifact.

@github-actions

github-actions Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Dashboard view assessment

No dashboard views were potentially impacted by this pull request.
Ignored views: operations, readiness.
View the workflow run.

@pelikhan

pelikhan commented Oct 1, 2026

Copy link
Copy Markdown
Collaborator

@copilot database snapshoting is a redis internal implementation. Use a "ingest" function that takes a set of transactions and let the impl details out

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Some server reads bypass the new boundary, ingestion results can become inconsistent, and the architecture model omits the new relationships.

Review effort: Balanced
Findings: 2 Medium severity · 1 Low severity

Open (3)
What changed in this PR

Introduces a database abstraction between dashboard ingestion/querying and Redis-backed storage.

Changes:

  • Adds snapshot, reader, validation, and execution contracts.
  • Implements the contract using Redis generations.
  • Routes ingestion and primary query paths through the abstraction with tests and documentation.
File Description
ARCHITECTURE.md Documents the database boundary.
CODEBASE.yml Adds the database component.
server/​README.md Explains storage responsibilities.
server/​internal/​dashboarddb/​database.go Defines storage interfaces and snapshot types.
server/​internal/​ingest/​database_test.go Tests generic snapshot publication and reuse.
server/​internal/​ingest/​ingest.go Publishes ingestion results through the database.
server/​internal/​redisx/​dashboard_database.go Implements the Redis adapter.
server/​internal/​redisx/​dashboard_database_test.go Tests snapshot pinning and validation.
server/​internal/​server/​canonical.go Routes canonical reads through the database.
server/​internal/​server/​server.go Routes dashboard queries through pinned readers.

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +135 to +139
if err == nil {
active, activeErr := store.Active(ctx)
if activeErr == nil {
result.Generation = active.Generation
}

type App struct {
store *redisx.Store
dashboard dashboarddb.Database
Comment thread CODEBASE.yml Outdated
Comment on lines +141 to +143
dashboard_database:
path: server/internal/dashboarddb/
responsibility: expose generation-free snapshot publication, database state, query validation, and query execution for dashboard call-table sources; Redis-specific generation and index management belongs to the Redis adapter, while operational caches and state remain separate
@pelikhan

pelikhan commented Oct 1, 2026

Copy link
Copy Markdown
Collaborator

@copilot database snapshoting is a redis internal implementation. Use a "ingest" function that takes a set of transactions and let the impl details out

@github-actions

github-actions Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Dashboard query performance

Query performance measurements

Population time: 69198.20 ms

IndexedDB count()

Counted 362,374 records across 18 stores in 497.50 ms.

Overview critical path

Initial Overview ready: 3424.70 ms

Settled deployed-data query: 812.80 ms (23,111 records read)

Phase Duration (ms) Share
IndexedDB reads 469.60 57.78%
Canonical projection 200.30 24.64%
Worker messaging 128.40 15.80%
Declarative queries 14.50 1.78%

Slowest standalone Overview sources:

Source First result (ms) Rows
overview-header-presentation 888.90 1
overview-campaign-station 665.60 1
overview-campaign-links 597.80 10
overview-repository-station 533.60 1
overview-rhythm 517.00 1

All dashboard queries

Chunk size: 25 rows

Query Rows Chunks First chunk (ms) Continuation chunk (ms) Fill iteration (ms)
event-base 0 1 9454.90 — 8946.10
audit-event-runs 0 1 3678.50 — 3531.50
domain-event-runs 7731 310 865.80 843.60 887.40
tool-event-runs 0 1 5035.00 — 5127.60
issue-event-runs 1022 41 370.40 384.70 490.40
event-runs 0 1 8967.80 — 9473.80
run-import-status 8831 354 9076.70 9180.50 8842.80
workflow-run-totals 71 3 9281.80 9049.80 8796.30
workflow-aic-totals 71 3 642.70 475.30 474.00
mcp-tool-calls 0 1 5133.00 — 4887.20
issue-safe-outputs 687 28 509.80 525.40 518.40
issue-repository-totals 3 1 524.50 — 532.80
workflow-inventory 635 26 9124.90 9209.30 8643.70
repository-aic-totals 3 1 489.70 — 498.30
maintenance-repository-versions 6 1 29.20 — 27.90
maintenance-repositories 6 1 30.60 — 27.20
maintenance-campaign-updates 1 1 9.30 — 9.00
maintenance-repository-upgrades 1 1 30.60 — 29.30
run-incomplete-outcomes 0 1 3513.60 — 3583.80
campaign-runs 8831 354 4281.20 4057.00 3874.60
campaign-runtime-health-runs 8831 354 525.00 465.90 513.20
campaign-runtime-health-groups 71 3 582.70 490.90 495.90
campaign-runtime-problem-candidates 71 3 547.30 493.20 493.10
campaign-current-runtime-failures 16 1 546.60 — 500.20
workflow-run-observation-counts 71 3 445.40 493.00 454.90
campaign-active-orchestrator-run-presence 10 1 440.50 — 506.80
campaign-unobserved-orchestrator-candidates 10 1 499.30 — 474.40
campaign-unobserved-orchestrators 0 1 490.00 — 482.50
campaign-runtime-problems 16 1 524.00 — 620.80
dispatches 6089 244 4038.90 4119.90 3920.40
campaign-dispatch-totals 11 1 3940.90 — 4058.30
campaign-workflow-totals 10 1 9087.70 — 8883.30
campaign-repository-coverage 9 1 529.70 — 544.40
campaign-inventory 10 1 9381.40 — 9086.70
firewall-domain-totals 85 4 998.30 981.20 1146.40
firewall-most-blocked-domains 10 1 999.70 — 1017.80
firewall-domain-workflows 437 18 1010.10 1105.80 1011.10
mcp-tool-totals 0 1 5064.20 — 4895.30
mcp-top-tools 0 1 4991.70 — 5028.10
steering-events 0 1 3596.80 — 3540.80
steering-type-totals 0 1 3561.40 — 3813.30
steering-workflow-totals 0 1 3615.10 — 3818.90
steering-workflows 0 1 3557.70 — 3550.90
steering-top-workflows 0 1 3644.00 — 3741.90
entity-workflow-run-totals 71 3 564.70 487.30 492.20
entity-workflows 635 26 505.70 501.40 540.90
repository-runs 8831 354 497.50 501.10 529.20
repository-workflow-totals 6 1 28.80 — 24.50
repository-report-totals 3 1 398.40 — 401.60
repository-run-totals 3 1 8791.20 — 8967.60
repository-activity-core 6 1 8909.00 — 9149.80
repository-activity 6 1 8994.30 — 8957.00
entity-runs 8831 354 522.80 518.60 544.50
workflow-runs 8831 354 538.70 535.20 568.50
workflow-reports 1100 44 398.20 394.90 413.20
audit-event-summary-buckets 0 1 6415.20 — 5522.70
campaign-workflows 59 3 6297.90 6433.60 6173.40
campaign-reports 1100 44 268.30 284.80 347.70
campaign-worker-issues 666 27 286.10 276.50 281.60
campaign-issue-tab-counts 8 1 279.50 — 288.90
campaign-readme-orchestrators 10 1 18.40 — 16.90
campaign-readme-details 10 1 16.80 — 17.10
campaign-memory-campaigns 10 1 9.10 — 5.40
campaign-operational-value-repository-run-day-totals 132 6 2832.10 2795.90 2872.40
campaign-operational-value-repository-run-days 132 6 2782.40 2825.30 2791.30
campaign-operational-value-run-day-totals 102 5 2790.50 2799.60 2785.00
campaign-operational-value-run-days 102 5 2855.90 2725.30 2759.20
campaign-performance-baseline-totals 11 1 2772.00 — 2731.60
campaign-performance-baseline 11 1 2804.70 — 2780.80
campaign-problem-runs 2195 88 2708.20 2793.20 2700.70
campaign-problem-run-evidence 1129 46 2774.60 2810.50 2899.50
campaign-problem-latest-target-runs 20 1 2819.70 — 2845.30
campaign-problem-error-groups 53 3 2893.60 2895.60 2849.40
campaign-current-problem-error-groups 20 1 2798.20 — 2831.20
campaign-problem-items 20 1 2858.40 — 2939.80
campaign-problem-tab-counts 5 1 2887.20 — 2917.00
campaign-operational-value-primary-series 12 1 10.30 — 8.20
campaign-operational-value-evidence-state-totals 2 1 8.30 — 10.10
campaign-operational-value-evidence-state 2 1 9.40 — 10.10
campaign-operational-value-plot-inventory 12 1 8.30 — 8.10
campaign-audit-summary-plot-inventory 0 1 5467.20 — 5660.80
campaign-insight-plot-inventory 12 1 5423.00 — 5458.80
campaign-insight-tab-counts 2 1 5614.90 — 5429.00
runs-daily-conclusions 90 4 227.70 6.40 6.20
entity-events 0 1 5790.30 — 5807.40
runs-table 8831 354 404.20 338.50 353.50
workflow-aic-run-totals 71 3 343.90 347.30 320.80
workflow-aic-per-run 71 3 340.50 336.60 360.80
ingestion-queued 0 1 6.10 — 4.50
ingestion-inflight 0 1 5.60 — 4.50
ingestion-backfill 0 1 4.30 — 4.50
ingestion-queue-sizes 0 1 4.50 — 4.40
ingestion-health 0 1 4.50 — 6.70
github-api-usage 0 1 4.50 — 4.30
marketplace-package-detail 7 1 8.00 — 15.30
friction-by-workflow 64 3 361.20 363.20 356.60
friction-observations 4866 195 409.30 585.10 412.20
indexing-daily-records 1 1 7.10 — 7.40
indexing-daily-workflow-runs 1 1 7.10 — 6.00
indexing-campaigns-table-count 1 1 4.70 — 4.80
indexing-repositories-table-count 1 1 5.00 — 4.80
indexing-workflows-table-count 1 1 7.90 — 4.90
indexing-runs-table-count 1 1 4.60 — 4.70
indexing-domains-table-count 1 1 6.10 — 6.00
indexing-tools-table-count 1 1 15.20 — 14.70
indexing-audits-table-count 1 1 15.60 — 11.80
indexing-issues-table-count 1 1 5.00 — 4.70
indexing-operational-values-table-count 1 1 8.00 — 20.70
indexing-transactions-table-count 1 1 11.20 — 6.90
indexing-database-table-counts 10 1 31.60 — 28.40
indexing-transactions 124 5 447.80 20.80 33.50
engines-models-usage 7 1 666.20 — 610.80
skill-invocations 0 1 372.60 — 354.70
skill-invocations-by-skill 0 1 366.40 — 369.20
skill-invocations-by-workflow-totals 0 1 386.50 — 370.20
skill-invocations-by-workflow 0 1 359.60 — 367.20
skill-workflow-totals 0 1 364.90 — 397.10
skill-workflow-inventory 0 1 358.20 — 377.00
experiment-assignment-coverage 1 1 357.60 — 343.90
eval-yes-no-status 0 1 404.60 — 363.50
grader-status-ledger 13581 544 683.50 723.80 814.10
database-campaign-count 1 1 9.40 — 9.00
overview-run-summary 1 1 546.90 — 505.80
overview-delivery-summary 1 1 512.90 — 575.80
overview-value-summary 1 1 647.00 — 642.00
overview-run-status-input 1 1 538.20 — 503.50
overview-value-status-input 1 1 692.70 — 637.20
overview-factory-status 1 1 803.90 — 723.90
overview-registered-repository-summary 1 1 9.90 — 10.10
overview-delivery-coverage-input 1 1 546.60 — 545.70
overview-registered-repository-coverage-input 1 1 14.00 — 10.20
overview-rhythm 1 1 517.00 — 560.10
campaign-runtime-problem-counts 6 1 590.50 — 591.60
overview-repository-coverage-summary 1 1 588.20 — 531.30
overview-repository-coverage 1 1 524.40 — 560.30
overview-healthy-campaign-count 1 1 588.30 — 575.00
overview-campaign-count-presentation-input 1 1 40.10 — 10.80
overview-healthy-campaign-presentation-input 1 1 628.30 — 618.10
overview-campaign-health-presentation 1 1 597.60 — 628.00
overview-header-status-presentation-input 1 1 744.80 — 754.50
overview-header-presentation 1 1 888.90 — 858.20
overview-run-motion-presentation-input 1 1 517.10 — 506.10
overview-campaign-station 1 1 665.60 — 594.00
overview-repository-station-presentation-input 1 1 487.50 — 514.80
overview-repository-station 1 1 533.60 — 526.00
overview-disabled-dispatchers 0 1 44.40 — 29.40
overview-campaign-links 10 1 597.80 — 617.70
campaign-cost-totals 10 1 578.10 — 564.80
cost-by-campaign 10 1 567.00 — 562.90
cost-by-repository 3 1 553.60 — 589.20
cost-by-workflow 71 3 548.40 608.10 555.20
cost-per-workflow-run 71 3 584.50 557.70 645.20
failure-run-base 2195 88 145.80 134.50 154.30
failed-runs 2195 88 217.70 229.60 229.30
overview-failing-runs 2195 88 143.30 137.70 145.20
overview-failing-workflows 51 3 143.50 143.40 153.60
overview-repeated-failure-groups 51 3 826.50 750.80 803.90
overview-repeated-failure-candidates 0 1 754.70 — 718.90
overview-repeated-failure-attention 0 1 786.70 — 736.80
overview-review-attention 0 1 8.30 — 9.60
overview-needs-attention 0 1 713.70 — 788.90
domain-entity-insights 111 5 977.30 960.10 984.30
tool-entity-insights 0 1 5704.60 — 5596.60
audit-entity-insights 0 1 4122.50 — 3870.70

View the workflow run and performance artifact.

@github-actions

github-actions Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Go Redis dashboard integration: PASSED

Per-page results

Go Redis dashboard page checks

PASSED — 57/57 pages passed.

Page Status Queries Errors
steering PASSED 3 —
firewall PASSED 2 —
firewall-domain-workflows PASSED 1 —
mcps PASSED 2 —
repositories PASSED 2 —
repository-workflows PASSED 1 —
repository-detail PASSED 4 —
repository-insights PASSED 1 —
repository-workflow-inventory PASSED 1 —
repository-runs PASSED 1 —
repository-settings PASSED 1 —
workflow-detail PASSED 3 —
workflow-runs PASSED 4 —
workflow-run-cards PASSED 1 —
workflow-runtime PASSED 2 —
outcome-detail PASSED 4 —
campaigns PASSED 3 —
memory PASSED 1 —
campaign-detail PASSED 3 —
campaign-workflows PASSED 3 —
campaign-issues PASSED 3 —
campaign-repositories PASSED 4 —
campaign-reports PASSED 4 —
campaign-memory PASSED 1 —
campaign-runs PASSED 5 —
campaign-problems PASSED 2 —
campaign-problem-detail PASSED 1 —
campaign-insights PASSED 3 —
workflows PASSED 2 —
runs PASSED 2 —
issues PASSED 3 —
run-events PASSED 1 —
marketplace PASSED 1 —
marketplace-package PASSED 3 —
indexing PASSED 7 —
skills PASSED 3 —
engines-models PASSED 3 —
friction PASSED 2 —
operational-value PASSED 2 —
maintenance PASSED 2 —
experiments PASSED 2 —
evals PASSED 1 —
graders PASSED 1 —
configuration PASSED 1 —
overview PASSED 4 —
cost PASSED 5 —
notifications PASSED 1 —
overview-failed-runs PASSED 1 —
overview-blocked-work PASSED 1 —
overview-awaiting-review PASSED 1 —
overview-security-findings PASSED 1 —
domain-insights PASSED 2 —
domain-runs PASSED 2 —
tool-insights PASSED 2 —
tool-runs PASSED 2 —
audit-insights PASSED 2 —
audit-runs PASSED 2 —

View the workflow run and integration artifact.

Copilot AI and others added 2 commits October 1, 2026 15:31
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>

Copilot AI commented Oct 1, 2026

Copy link
Copy Markdown
Contributor Author

@copilot database snapshoting is a redis internal implementation. Use a "ingest" function that takes a set of transactions and let the impl details out

Changed the database boundary to Ingest(ctx, Transactions), keeping Redis generation staging inside the Redis adapter. Updated callers, tests, and boundary docs; focused Go tests pass. Commit: 25763aa.

Copilot AI commented Oct 1, 2026

Copy link
Copy Markdown
Contributor Author

@copilot database snapshoting is a redis internal implementation. Use a "ingest" function that takes a set of transactions and let the impl details out

This request is already implemented: the boundary exposes Ingest(ctx, Transactions), and Redis generation staging remains internal to the adapter. The update is in commit 25763aa (with boundary documentation in fcf0bd0); no additional code change is needed.

Comment thread server/internal/server/canonical.go Outdated
active, err := service.store.Active(ctx)
database := service.dashboard
if database == nil {
database = &redisx.DashboardDatabase{Store: service.store}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot avoid pollution of concepts here. Service should have database field pre populated.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated canonicalService to require its database dependency explicitly, removed its lazy Redis adapter construction, and initialized one shared adapter in New. Commit: bfff24b.

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>

Copilot AI commented Oct 1, 2026

Copy link
Copy Markdown
Contributor Author

@copilot generate an ADR of the abstraction layer.

Added an accepted ADR documenting the database boundary, why Redis generation and indexing remain adapter details, reader consistency, alternatives, and consequences. Commit: 2748889.

@pelikhan

pelikhan commented Oct 1, 2026

Copy link
Copy Markdown
Collaborator

@copilot make adr self contained with description of the database interface

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>

Copilot AI commented Oct 1, 2026

Copy link
Copy Markdown
Contributor Author

@copilot make adr self contained with description of the database interface

Expanded the ADR with the complete Transactions, State, RuntimeSource, Database, and Reader contract, including method behavior and consistency guarantees. Commit: c52a550.

@pelikhan

pelikhan commented Oct 1, 2026

Copy link
Copy Markdown
Collaborator

/matt review design abstraction, clean up and prepare for Postgres migration

@github-actions

github-actions Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

✅ Matt Pocock Skills Reviewer completed successfully!

Generated by Matt Pocock Skills Reviewer

Comment thread server/internal/dashboarddb/database.go Outdated
type Database interface {
Current(context.Context) (Reader, error)
Ingest(context.Context, Transactions) (State, error)
Validate([]query.Definition) error

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot should take a context as well

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added context.Context to Database.Validate, passed the request context through, and made the Redis adapter return pre-canceled context errors. Added a cancellation test and updated the ADR. Commit: 1c9f822.

@pelikhan

pelikhan commented Oct 1, 2026

Copy link
Copy Markdown
Collaborator

@copilot issue state updates must also be intergrate in the abstraction layer.

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

codebase-design review

Applied skills: codebase-design (database boundary/seam correctness) and tdd (coverage of the new contract).

This PR establishes a clean dashboarddb.Database/Reader seam and the Redis adapter implements it well, with the canonical.go pollution issue from @pelikhan's earlier comment already resolved in bfff24b (service now takes database as a required constructor dependency, no lazy adapter). Good test coverage of the new boundary in database_test.go and dashboard_database_test.go.

However, three defects already flagged by the automated Copilot review remain unresolved in the current diff and block merge:

  1. server/internal/ingest/ingest.go (around line 139): Run silently swallows store.Active errors when populating the legacy Generation field, which can attach a later generation's name to an earlier result's Revision/DataRevision/Counts. This breaks the new Reader consistency guarantee this PR's ADR explicitly promises (pinned revision/response agreement).

  2. server/internal/server/server.go (around line 81 / the App struct and /api/v1/refresh handler): The dashboard database is not yet the sole source of truth — refresh, diagnostics, and repository-memory handlers still read a.store.Active / redisx.Store directly instead of going through a.dashboard. This leaves two divergent read paths for the same generation state, undermining the boundary this PR's ADR claims to establish.

  3. CODEBASE.yml (around line 143): dashboard_database is declared as a component but never appears in dependencies; every server flow still models dashboard_https_server -> redis_projection directly, so the architectural boundary isn't reflected in the dependency graph consumers rely on. Add dashboard_https_server -> dashboard_database (and dashboard_database -> redis_projection if the adapter relationship should be explicit) edges.

None of these are addressed by the latest commits (08d7206, 055b363, bfff24b). Please resolve items 1–3 (or explain why they're out of scope) before merge — items 1 and 2 are correctness/consistency defects that directly contradict the stated goal of pinning queries to one snapshot and making the database the sole source of truth.

Summary table
# Status File Concern
1 Open (pre-existing finding) server/internal/ingest/ingest.go Silently ignored Active error can misattach generation/result data
2 Open (pre-existing finding) server/internal/server/server.go Refresh/diagnostics/memory handlers bypass the new database boundary
3 Open (pre-existing finding) CODEBASE.yml New dashboard_database component missing from dependencies graph
4 Resolved server/internal/server/canonical.go Lazy adapter construction removed per bfff24b; database now required

Generated by Matt Pocock Skills Reviewer · copilot · auto · 54.8 AIC · ⌖ 5.65 AIC · ⊞ 7.3K
Comment /matt to run again

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>

Copilot AI commented Oct 1, 2026

Copy link
Copy Markdown
Contributor Author

@copilot issue state updates must also be intergrate in the abstraction layer.

Added ApplyIssueStatus to dashboarddb.Database with abstract update/result types and ambiguity handling. The verified webhook path now uses the injected database; Redis provides the current atomic implementation, while enrollment and queue admission remain separate. Updated the ADR and tests. Commit: e4d2a21.

@pelikhan

pelikhan commented Oct 1, 2026

Copy link
Copy Markdown
Collaborator

@copilot

Create plan to integrate refactoring in #15576

Improve abstraction with clear ingestion backfill vs webhook updates vs querying

Copilot AI commented Oct 1, 2026

Copy link
Copy Markdown
Contributor Author

@copilot

Create plan to integrate refactoring in #15576...

Plan for integrating the abstraction into #15576:

  1. Set the boundary first: keep the database contract small and storage-neutral: Ingest(ctx, Transactions) for an authoritative complete dataset, Current(ctx) -> Reader for a pinned read view, and Reader.Execute(...) for queries. Move pure query-definition validation to the query layer rather than requiring each database backend to implement it.
  2. Backfill/replay: have Actions snapshot ingestion and evidence-lake replay/backfill both validate and project their artifacts into the same complete Transactions input. PostgreSQL atomically replaces the current dataset and returns its revision; retries of the same data revision are idempotent, and failed writes leave the prior data readable. Keep enumeration, progress, and recovery in the backfill orchestrator, not in the database adapter.
  3. Webhook updates: follow Replace Redis dashboard storage and queries with Postgres #15576’s queued-refresh design. Verify and deduplicate webhooks, check enrollment, and enqueue an issue-status/repository refresh in the operational queue. The worker collects into the evidence lake, then the projector calls the same Ingest path as backfill. Do not also directly mutate issue rows through ApplyIssueStatus; that would create a second writer with competing ordering and consistency rules. If immediate direct issue mutation is still a requirement, decide that separately and specify its transactional/idempotency semantics before retaining such an interface method.
  4. Querying: inject one database implementation into the server. Each request obtains one Reader, uses it for query execution and the response revision, and routes refresh/diagnostics/repository-memory reads through the same database where they represent persisted dashboard data. Keep operational state and queue reads on Redis.
  5. Integrate the Postgres PR: adapt its concrete Store.Replace/state/source calls behind the database adapter; change ingest.Run and Projector to accept the interface rather than *postgresx.Store, and keep Redis dependencies there only for operational coordination. Avoid having ingestion or HTTP handlers branch on the backend.
  6. Acceptance tests: cover backfill and replay parity, idempotent same-revision ingest, atomic failure preserving prior data, duplicate/out-of-order webhook behavior through queue → collect → ingest, and query/state revision consistency. Then remove the superseded Redis overlay path and update the ADR/architecture docs to describe the three distinct flows.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants