Skip to content

Follow work across the factory

The Factory page brings product projects, their component repositories and recorded runs into one view. Use Browse work below the production floor to choose a product project or return to the factory overview. The model stays above the controls; on a phone it initially focuses the selected station. Show full floor restores the complete model.

Factory overview with the production floor, scope navigation and recorded run countsFactory overview with the production floor, scope navigation and recorded run counts

A controlled Studio walkthrough. Counts describe saved records; the still model does not imply a live worker or deployment.

Choose the right scope

Scope What it includes
Factory overview Product projects and runs available to your current identity. Administrators also see standalone work.
Product project Runs recorded against that product-project ID, across its component repositories.
Standalone work Runs with no recorded product-project association. This requires a factory administrator.
Run One execution, its current plan, recorded component, branch, ticket and pull-request links.

A repository is not a product project. Two products can use the same repository without sharing their run records or permissions. A run whose referenced project is unavailable is not relabeled as standalone work.

Project choices and run records are paged. Searching projects and requesting another page do not change the totals. Counts cover the complete selected scope, including work outside the current page.

Browse work drawer showing a product project and its component and repository countsBrowse work drawer showing a product project and its component and repository counts

Open Browse work, then choose a product. Product membership determines access; sharing a repository does not share its runs.

Read runs and tasks separately

The stage inspector describes tasks at the selected station. Runs in this scope counts executions across the selected factory or product project. Several task records can belong to one run, so these quantities should not be added together.

Recorded running means the stored run state describes work in progress. It does not establish that a worker is currently alive. A task last recorded as running can have unknown current activity while its run still has a running state.

The dashboard can use a separate, current observation of an Engine-owned stage. Execution-request claims alone are retained custody records; a factory-wide advisory lock alone is not a heartbeat for every task. Remote runners own a separate private ledger, which the dashboard does not query by assuming a schema or adding cross-schema privileges. Machinery stays still when current stage activity cannot be established. Aggregate scopes never show a single package as if it represented every run.

Worker liveness, queue-wait duration, deployment health and runtime metrics remain unavailable in this view. Recorded expired or quarantined run states are separate from unknown states; they are not inferred runner-lease diagnoses. Deployment and support evidence have their own views and recorded sources.

Engine stage observations

An observed active stage means the factory's Engine still owns that task and its observation has not expired. The stage may be waiting on a runner or model; the display does not establish that the remote system is using CPU. A missing, expired or inconsistent observation stays unknown. Grouped activity expires when its earliest supporting observation expires.

Signing out does not cancel a queued or running job. Execution uses its retained canonical identity and current grants. Suspend that identity or remove its required project permission to withdraw that authority; use the run's cancellation action when cancellation is intended. The person reading this page still needs current project access and an active browser session. SCM-mapped and personal-token execution actors are not treated as supported activity producers. A personal read token grants observation only.

Administrators can configure these server settings before starting forge:

Setting Default Purpose
FORGE_ACTIVITY_HEARTBEAT_SECONDS 5 Interval between samples for locally owned Engine stages.
FORGE_ACTIVITY_STALE_SECONDS 20 Freshness window; it must exceed the heartbeat interval.
FORGE_ACTIVITY_SAMPLE_TIMEOUT_SECONDS 1 Time allowed for an observation sample before it becomes unavailable.

These intervals govern telemetry, not the time allowed to implement a product. An unavailable observation does not stop or replay productive work. Worker health, external execution and final command outcomes retain their own evidence boundaries.

Inspect a run

  1. Choose a product project, or keep the factory overview.
  2. Use Board to compare recorded run states, or read the run list below the floor. Board totals cover the scope; cards are paged.
  3. Select a run to inspect its plan and source-control links. Only this selected run requests a plan. Aggregate views do not poll one plan per run.
  4. Open the run to inspect its activity, evidence and source changes. A missing plan remains unavailable; the view does not invent a stage sequence or a package position.

Product-project board showing a recorded run that needs attentionProduct-project board showing a recorded run that needs attention

Board groups the product's recorded runs by state. Focus run returns to its floor context; Open run shows the detailed evidence.

Studio refreshes observations while the page is visible. A transient read failure labels the retained observation and suspends motion. An authorization failure discards the prior observation. Changing identity or project clears the previous selection and pending reads.

Read through the API

The authenticated endpoints are:

GET /api/v1/factory-dashboard?kind=factory
GET /api/v1/factory-dashboard/projects?search=customer
GET /api/v1/factory-dashboard?kind=project&project_id=<project-id>
GET /api/v1/factory-dashboard?kind=run&run_id=<run-id>

The snapshot supports bucket, cursor and a per-page limit from 1 to 200. Project choices support search, cursor and the same page-size range. Cursors are bound to the identity, tenant schema, scope and filters; they cannot be reused for another selection. This page-size bound does not cap product projects, runs or aggregate counts.

Personal read tokens can observe an explicitly selected product project or run through their current project grants. They cannot enumerate the factory, standalone work or project choices through these endpoints. Token revocation and current membership are checked before and after the observation. Source-control actor mappings do not automatically become dashboard identities.

The same boundary applies to signed-in users. After the read-only transaction closes, a fresh transaction rechecks the native user, current role audience and expiry, exact cookie session when used, and membership state. Explicit project and run reads also recheck canonical project permission. A concurrent logout, disabled user or changed membership discards the response, including project-choice pages. A fixed-size database witness detects changes without loading a user's complete membership list. It does not grant access: the native identity and project predicates remain authoritative.

These checks use authority already recorded by forge. They do not claim instant revocation of an external identity-provider role that forge has not yet observed; access-token verification, refresh and local session revocation retain their existing behavior.

How the read is built

flowchart LR
    A["Scope and<br/>current identity"] --> B["Read-only<br/>snapshot"]
    B --> C["Projects, runs<br/>counts and tasks"]
    C --> D["Fresh<br/>authority check"]
    D -->|Unchanged| E["Show<br/>observation"]
    D -->|Changed| F["Discard<br/>response"]

Read from left to right. On a narrow screen, focus the diagram and scroll with the arrow keys.

FactoryDashboard uses native pyfly services and repositories over the existing PostgreSQL entities. Visibility predicates, totals and pages share a read-only repeatable-read transaction. SQL aggregates produce counts without loading every run or component into application memory. Reads do not acquire runner invocation locks, renew leases, dispatch work or change execution authority. The database read time is returned as observed_at; it is not a worker heartbeat.