Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 14 additions & 11 deletions docs/engineering/ENGINEERING_REPORTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,11 +213,11 @@ reports never claim successful implementation or delivery.

## Advisory Codex analysis

After a terminal report is written, the runner may request one separate Codex
CLI analysis of that exact local report. The analysis is read-only, bounded and
stored locally per run under `.engineering/report-analysis/<run-id>.md`. It
distils findings, issues, risks, next steps and advice for the Product
Architect. Its output is advisory and redacted before persistence. Every
After a terminal report is written, the lifecycle dispatcher may request one
separate Codex CLI analysis of that exact report. The analysis is read-only,
bounded, redacted before persistence, and registered as an integrity-verified
CENTRAL Markdown artifact for the same `(project_id, run_id)`. It distils
findings, issues, risks, next steps and advice for the Product Architect. Every
analysis also records a bounded **Analyseverwerking** status. If the provider
is unavailable, fails, or returns an invalid structured response, the matching
safe reason is shown there; raw provider output and diagnostics are never
Expand All @@ -230,15 +230,18 @@ and authoritative.

The private Engineering Status dashboard exposes an **AI analysis** column in
Prompt History next to the engineering report. View and download actions are
available only when the analysis file belongs to that exact Run ID; analyses
from another execution are never selected as a fallback.
available only for the matching verified CENTRAL artifact; an older local file
or another run is never selected as a fallback. A response that is unavailable
or is not Markdown is rendered as a localized unavailable message, never as
technical JSON.

For a controlled temporary processing failure (`provider_failed`,
`provider_unavailable` or `invalid_structured_response`), the analysis dialog
also offers **Generate analysis again**. It is bound to that same indexed
terminal report and regenerates only the advisory analysis; it never resumes,
retries or changes the Engineering execution, checkpoint, branch or pull
request. A successfully processed analysis is deliberately not retryable.
also offers **Generate analysis again**. It is bound to that same centrally
indexed terminal report, emits a redacted Console audit event, and regenerates
only the advisory analysis; it never resumes, retries or changes the
Engineering execution, checkpoint, branch or pull request. A successfully
processed analysis is deliberately not retryable.

If a terminal report temporarily cannot be read in its dialog, the dashboard
offers **Reload report**. That action repeats only the read-only retrieval of
Expand Down
2 changes: 1 addition & 1 deletion docs/engineering/P_CENTRAL_CONSOLE_AUTHORITY_MAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ physical execution binding only; it is not Console authority.
| Provider usage | SERVER_PLATFORM_NATIVE | Current single-runtime Codex capacity is a Server/CENTRAL projection. |
| Evidence report downloads | CENTRAL_NATIVE | Report index and artifact path are authorized by `(project_id, run_id)` in CENTRAL. |
| Prompt chat history | CENTRAL_NATIVE (read projection) | Immutable transcript lookup is scoped by CENTRAL project/run lineage. |
| Provider-backed chat mutation and report analysis | RETIRED/UNREACHABLE from migrated routes | No CENTRAL Server authority is invented for historical root-backed mutation. |
| Advisory report analysis and retry | CENTRAL_NATIVE (bounded project mutation) | An exact-run, integrity-verified Markdown artifact is read from CENTRAL. Retry is allowed only for a controlled transient analysis status and uses the matching CENTRAL report; it is audited and cannot change the execution. |
| Configuration | CENTRAL_NATIVE (read projection) | Only CENTRAL maintenance/capacity policy is exposed; old root-local settings fail closed. |
| Component logs | CENTRAL_NATIVE | Server-owned CENTRAL log index, explicitly `PLATFORM` scoped. |
| Worktree, provider-login and update actions | RETIRED/UNREACHABLE | They are not supported installed Console actions in this phase. |
Expand Down
16 changes: 15 additions & 1 deletion docs/engineering/P_TRANSPORT_CONSOLE_ROUTE_OWNERSHIP_MATRIX.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ change authority, select a checkout, or delegate that route.
| PLATFORM | `GET/POST /api/configuration`; `GET /api/central-data/export`; `POST /api/central-data/{relocate,relocate/browse,relocate/discard,import}`; `GET/POST /api/central-database/configuration` | Server settings and Central data operations; paths and imported bytes are never placed in the audit log |
| HOST_ADMIN | `GET /api/host-admin/diagnostics` | Bounded installation-only disk and managed-runtime observation; no project, queue, execution or mutation authority |
| PLATFORM | `GET /v1/operations/projects` | Operations Console platform listing |
| PROJECT | `GET /api/prompt-history`, `/api/prompt-history/{run}/{report,chat,details}`, `/api/telemetry/{date}`; `POST /api/telemetry/clear`, `/api/execution-{dismiss,retry}`, `/api/dashboard-translate` | Project history, telemetry and project actions; no valid selected project returns `409 CONSOLE_PROJECT_UNAVAILABLE` |
| PROJECT | `GET /api/prompt-history`, `/api/prompt-history/{run}/{report,analysis,chat,details}`, `/api/telemetry/{date}`; `POST /api/prompt-history/{run}/analysis-retry`, `/api/telemetry/clear`, `/api/execution-{dismiss,retry}`, `/api/dashboard-translate` | Project history, centrally indexed advisory analysis, telemetry and project actions; no valid selected project returns `409 CONSOLE_PROJECT_UNAVAILABLE` |
| TRANSPORT_INTERNAL | `/diagnostics/topology`, `/healthz`, `/readyz`, `/v1/projects/{project}/submissions`, `/v1/agent/{pair,register,heartbeat,attachment}` | Transport probes and authenticated transport endpoints, not Console delegation |
| HISTORICAL_UNREACHABLE | `POST /api/runtime-directory/open` | Explicitly retired checkout-bound runtime action (`410 RUNTIME_DIRECTORY_RETIRED`) |

Expand All @@ -45,6 +45,11 @@ Mission, Engineering Action, correlation and target repository. For Forge, the
accepted versioned provenance also supplies host, mission/intent revisions,
runtime-prompt identifier and digest, and retry correlation when present.

The active card names two deliberately separate EP states: **EP execution
phase** is the state recorded for the Execution Host run; **EP dispatcher
state** is the FIFO dispatch record's orchestration state. They can both be
`RUNNING` during normal operation, but neither is inferred from the other.

The Console never derives a branch, checkout, tracked-file count, Mission
summary or prompt content. Those remain absent until the Execution Host records
run-specific evidence or Forge supplies a separately versioned context.
Expand All @@ -57,6 +62,15 @@ audited, but the log contains only action, actor, outcome and canonical target
identifiers: no prompt text, AI-chat content, queue reason, local path, import
payload or downloaded bytes.

An advisory AI analysis is a separately indexed, integrity-verified CENTRAL
Markdown artifact for the exact terminal `(project_id, run_id)`. The Console
never falls back to a repository checkout or a legacy local analysis file.
Only the bounded retryable processing states may be regenerated from that
run's CENTRAL report; regeneration records a `dashboard_action_completed`
audit event and cannot change the execution outcome. Document responses that
are absent, malformed, or not Markdown are shown as a localized unavailable
message, never as a JSON payload in the Console.

## Test and qualification coverage

The matrix is not documentation-only. The following checks are the normal
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "engineering-platform-browser-validation",
"private": true,
"version": "2.3.19",
"version": "2.3.20",
"scripts": {
"test:engineering-dashboard": "PYTHONPATH=src python3 -m engineering_platform.dashboard_browser_validation",
"test:engineering-dashboard-logic": "node --test tests/engineering/dashboard_status_store.test.mjs tests/engineering/ui_localization_contract.test.mjs",
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "engineering-platform"
version = "2.3.19"
version = "2.3.20"
description = "Local-first Engineering Platform execution operations runtime"
readme = "README.md"
requires-python = ">=3.11"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"platform": {
"id": "engineering-platform",
"name": "Engineering Platform",
"version": "2.3.19",
"version": "2.3.20",
"generation": 2,
"documentation_namespace": "engineering-platform",
"capability_registry_version": 1
Expand Down
8 changes: 4 additions & 4 deletions src/engineering_platform/ENGINEERING_PLATFORM_VERSION.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
{
"bootstrap_contract": "2026.12",
"checkpoint_format": 1,
"dashboard_version": "2.3.19",
"dashboard_version": "2.3.20",
"handoff_protocol": 1,
"memory_format": 2,
"minimum_codex_cli": "0.146.0",
"inbox_protocol": 1,
"platform_version": "2.3.19",
"platform_version": "2.3.20",
"report_format": 2,
"runner_version": "2.3.19",
"runner_version": "2.3.20",
"status_model": 1,
"storage_schema": 44,
"watcher_version": "2.3.19"
"watcher_version": "2.3.20"
}
2 changes: 1 addition & 1 deletion src/engineering_platform/assets/dashboard.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

54 changes: 26 additions & 28 deletions src/engineering_platform/assets/dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -1618,18 +1618,25 @@ function replaceWithLocalFilesystemLink(element, replacementValue = element?.tex
element.replaceWith(link);
return link;
}
function executionContextField(label, value, badge = false, folder = false) {
function executionContextField(label, value, folder = false) {
const field = document.createElement("p"), caption = document.createElement("span"), content = document.createElement("span");
field.className = "field";
caption.className = "label";
caption.textContent = label;
const supplied = executionContextValue(value);
const output = folder && supplied.startsWith("/") ? localFilesystemLink(supplied) : content;
if (output === content) content.textContent = supplied || t("execution_context.not_supplied");
if (badge) output.classList.add("execution-context__phase");
field.append(caption, output);
return field;
}
function executionContextRuntimeStatus(value) {
const raw = executionContextValue(value);
return raw ? translate(raw) : "";
}
function executionContextTimestamp(value) {
const raw = executionContextValue(value);
return raw ? formatTimestamp(raw) : "";
}
function inheritModalAccent(modal, trigger) {
const source = trigger?.closest(".current-run,[data-modal-accent-source],.dashboard-modal-shell");
const sample = source && document.createElement("span");
Expand Down Expand Up @@ -1683,7 +1690,7 @@ function renderExecutionContext(context, execution = {}) {
if (!context || typeof context !== "object") {
card.replaceChildren(
Object.assign(document.createElement("strong"), { textContent: t("ui.execution_context") }),
...hostFields.map(([label, value, isExecutionMode]) => isExecutionMode ? executionModeField(value) : executionContextField(label, value, false, label === t("detail.target_checkout"))),
...hostFields.map(([label, value, isExecutionMode]) => isExecutionMode ? executionModeField(value) : executionContextField(label, value, label === t("detail.target_checkout"))),
Object.assign(document.createElement("p"), { textContent: t("execution_context.not_supplied") }),
);
return;
Expand All @@ -1696,15 +1703,15 @@ function renderExecutionContext(context, execution = {}) {
[t("execution_context.engineering_summary"), context.engineering_summary],
[t("execution_context.current_intent"), context.current_intent],
[t("execution_context.current_engineering_action"), context.current_engineering_action],
[t("execution_context.execution_phase"), context.execution_phase, true],
[t("execution_context.execution_phase"), executionContextRuntimeStatus(context.execution_phase)],
[t("execution_context.planning_confidence"), context.planning_confidence],
[t("execution_context.current_iteration"), context.current_iteration],
[t("execution_context.mission_progress"), context.mission_progress],
[t("execution_context.last_runtime_update"), context.last_runtime_update || context.last_updated_timestamp],
[t("execution_context.last_runtime_update"), executionContextTimestamp(context.last_runtime_update || context.last_updated_timestamp)],
[t("execution_context.decision_evidence_reference"), context.decision_evidence_reference || context.decision_evidence],
[t("execution_context.decision_type"), context.decision_type],
[t("execution_context.execution_receipt_reference"), context.execution_receipt_reference || context.last_execution_receipt],
[t("execution_context.dispatcher_state"), context.dispatcher_state],
[t("execution_context.dispatcher_state"), executionContextRuntimeStatus(context.dispatcher_state)],
[t("execution_context.approved_mission_queue_state"), context.approved_mission_queue_state],
[t("execution_context.producer_host"), context.producer_host_id],
[t("execution_context.mission_revision"), context.mission_revision],
Expand All @@ -1731,10 +1738,10 @@ function renderExecutionContext(context, execution = {}) {
];
card.replaceChildren(
Object.assign(document.createElement("strong"), { textContent: t("ui.execution_context") }),
...hostFields.map(([label, value, isExecutionMode]) => isExecutionMode ? executionModeField(value) : executionContextField(label, value, false, label === t("detail.target_checkout"))),
...hostFields.map(([label, value, isExecutionMode]) => isExecutionMode ? executionModeField(value) : executionContextField(label, value, label === t("detail.target_checkout"))),
...suppliedFields.map(([label, value]) => executionContextField(label, value)),
...(planningFields.length
? planningFields.map(([label, value, badge]) => executionContextField(label, value, badge))
? planningFields.map(([label, value]) => executionContextField(label, value))
: [Object.assign(document.createElement("p"), {
className: "execution-context__planning-empty",
textContent: t("execution_context.planning_not_supplied"),
Expand Down Expand Up @@ -7313,19 +7320,14 @@ function loadPromptHistoryDocument() {
(promptHistoryDocumentKind === "analysis" ? "/analysis" : "/report"),
{ cache: "no-store" },
)
.then((response) =>
response.ok
.then((response) => {
const markdown = response.headers.get("content-type")?.toLowerCase().includes("text/markdown");
return response.ok && markdown
? response.text()
: Promise.reject(
Error(
t(
promptHistoryDocumentKind === "analysis"
? "history.analysis_unavailable"
: "history.report_unavailable",
),
),
),
)
: Promise.reject(Error(
t(promptHistoryDocumentKind === "analysis" ? "history.analysis_unavailable" : "history.report_unavailable"),
));
})
.then((text) => {
if (!text)
throw Error(
Expand Down Expand Up @@ -7382,19 +7384,15 @@ async function retryPromptHistoryAnalysis() {
"/api/prompt-history/" + encodeURIComponent(promptHistoryReportRun) + "/analysis-retry",
{ method: "POST", headers: { "Content-Type": "application/json" }, body: "{}" },
);
const markdown = response.headers.get("content-type")?.toLowerCase().includes("text/markdown");
const text = await response.text();
if (!response.ok) {
let detail = "";
try { detail = JSON.parse(text).error || ""; } catch { /* controlled fallback below */ }
throw Error(detail || t("history.analysis_retry_failed"));
}
if (!response.ok || !markdown) throw Error(t("history.analysis_retry_failed"));
promptHistoryReportText = text;
renderMarkdownDocument(content, text);
button.hidden = !reportAnalysisCanRetry(text);
void recordUserAction("prompt_history_analysis_regenerated", promptHistoryReportRun);
} catch (error) {
renderMarkdownDocument(content, promptHistoryReportText);
showDashboardError(error instanceof Error ? error.message : "", t("history.analysis_retry_failed"));
showDashboardError(t("history.analysis_retry_failed"), t("history.analysis_retry_failed"));
} finally {
button.disabled = false;
}
Expand Down Expand Up @@ -7532,7 +7530,7 @@ function promptDetailExecutionSections(history) {
detailField(t("detail.mission_id"), executionContextValue(context.mission_id) || t("execution_context.not_supplied")),
detailField(t("execution_context.business_summary"), executionContextValue(context.business_summary) || t("execution_context.not_supplied")),
detailField(t("execution_context.engineering_summary"), executionContextValue(context.engineering_summary) || t("execution_context.not_supplied")),
detailField(t("execution_context.execution_phase"), executionContextValue(context.execution_phase) || t("execution_context.not_supplied")),
detailField(t("execution_context.execution_phase"), executionContextRuntimeStatus(context.execution_phase) || t("execution_context.not_supplied")),
detailField(t("execution_context.mission_lifecycle"), executionContextValue(context.mission_lifecycle) || t("execution_context.not_supplied")),
detailField(t("execution_context.decision_evidence_reference"), executionContextValue(context.decision_evidence_reference || context.decision_evidence) || t("execution_context.not_supplied")),
detailField(t("execution_context.execution_receipt_reference"), executionContextValue(context.execution_receipt_reference || context.last_execution_receipt) || t("execution_context.not_supplied")),
Expand Down
Loading
Loading