Skip to content

Commit 3d32cd5

Browse files
authored
feat: surface lifecycle artifacts on run detail (#74)
1 parent 74738ce commit 3d32cd5

2 files changed

Lines changed: 30 additions & 1 deletion

File tree

apps/dashboard/components/run-detail/RunDetailStatusContractCard.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,25 @@ export default function RunDetailStatusContractCard({
7575
const allowedPaths = toArray(run.allowed_paths);
7676
const evidenceEntries = Object.entries(toObject(evidenceHashes));
7777
const artifactList = toArray(manifestArtifacts);
78+
const artifactNames = artifactList
79+
.map((item) => {
80+
const record = toObject(item);
81+
const artifactName = typeof record.name === "string" ? record.name : typeof record.path === "string" ? record.path : "";
82+
return artifactName.trim();
83+
})
84+
.filter(Boolean);
85+
const lifecycleArtifactLabels = [
86+
artifactNames.includes("prompt_artifact") || artifactNames.includes("artifacts/prompt_artifact.json")
87+
? "Prompt artifact"
88+
: "",
89+
artifactNames.includes("planning_wave_plan") || artifactNames.includes("artifacts/planning_wave_plan.json")
90+
? "Wave plan"
91+
: "",
92+
artifactNames.includes("planning_worker_prompt_contracts") ||
93+
artifactNames.includes("artifacts/planning_worker_prompt_contracts.json")
94+
? "Worker prompt contracts"
95+
: "",
96+
].filter(Boolean);
7897
const roleBindingReadModel = run.role_binding_read_model;
7998

8099
return (
@@ -221,6 +240,9 @@ export default function RunDetailStatusContractCard({
221240
) : null}
222241
<div className="mono">Manifest artifacts:</div>
223242
<div className="mono muted">{artifactList.length} artifact{artifactList.length === 1 ? "" : "s"}</div>
243+
{lifecycleArtifactLabels.length > 0 ? (
244+
<div className="mono">Lifecycle artifacts: {lifecycleArtifactLabels.join(" / ")}</div>
245+
) : null}
224246
<details>
225247
<summary className="mono">Expand artifact list</summary>
226248
<pre className="mono">{JSON.stringify(artifactList, null, 2)}</pre>

apps/dashboard/tests/rundetail_core.suite.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,6 @@ describe("RunDetail core flows", () => {
167167
status: "RUNNING",
168168
allowed_paths: ["apps/dashboard"],
169169
contract: {},
170-
manifest: {},
171170
role_binding_read_model: {
172171
authority: "contract-derived-read-model",
173172
source: "persisted from contract",
@@ -208,6 +207,13 @@ describe("RunDetail core flows", () => {
208207
},
209208
},
210209
},
210+
manifest: {
211+
artifacts: [
212+
{ name: "prompt_artifact", path: "artifacts/prompt_artifact.json" },
213+
{ name: "planning_wave_plan", path: "artifacts/planning_wave_plan.json" },
214+
{ name: "planning_worker_prompt_contracts", path: "artifacts/planning_worker_prompt_contracts.json" },
215+
],
216+
},
211217
};
212218
const fetchMock = mockFetchFactory({ events: [], reports: [], availableRuns: [] });
213219
// @ts-expect-error test override
@@ -226,6 +232,7 @@ describe("RunDetail core flows", () => {
226232
expect(screen.getByText("Runtime binding: agents / cliproxyapi / gpt-5.4")).toBeInTheDocument();
227233
expect(screen.getByText("Runtime capability: standard-provider-path")).toBeInTheDocument();
228234
expect(screen.getByText("Tool execution: standard-provider-path / provider-path-required")).toBeInTheDocument();
235+
expect(screen.getByText("Lifecycle artifacts: Prompt artifact / Wave plan / Worker prompt contracts")).toBeInTheDocument();
229236
expect(
230237
screen.getByText(
231238
"Read-only note: this mirrors the persisted binding summary. task_contract still owns execution authority.",

0 commit comments

Comments
 (0)