From 52b364f88121e93dc56fc8c7f58bf01351e7d747 Mon Sep 17 00:00:00 2001 From: RainMona <316033127+RainMona@users.noreply.github.com> Date: Wed, 19 Aug 2026 10:22:54 +0000 Subject: [PATCH 1/3] Show execution profile identity on Agents capability rows. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue #32: Execution capability listed only runtime · model, so ~42 CODEX rows were indistinguishable. Each row now shows the same rN as the Prepare work picker, plus profileKey and a short executionProfileId. Preflight stays a recheck. Tasks / runs is untouched. (cherry picked from commit 82428d5f46ae300f38c68a80576efda15aed0fcf) --- apps/studio/src/App.tsx | 4 +- .../execution-profile-row-identity.test.ts | 51 +++++++++++++++++++ .../src/lib/execution-profile-row-identity.ts | 20 ++++++++ 3 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 apps/studio/src/lib/execution-profile-row-identity.test.ts create mode 100644 apps/studio/src/lib/execution-profile-row-identity.ts diff --git a/apps/studio/src/App.tsx b/apps/studio/src/App.tsx index e5271375..c9d4f3b9 100644 --- a/apps/studio/src/App.tsx +++ b/apps/studio/src/App.tsx @@ -70,6 +70,7 @@ import { type StandingRouteState, type StandingRouteUsage, } from "@/data/standing-routes"; +import { executionProfileRowIdentity } from "@/lib/execution-profile-row-identity"; import { cn } from "@/lib/utils"; import { parseWorkspaceRoute, @@ -5790,6 +5791,7 @@ function AgentOperationsView() {
{runtime?.kind ?? "runtime"} · {model?.model ?? "model"} + {executionProfileRowIdentity(profile)} {capability?.serviceCapability ?? "UNVERIFIED"} · {capability?.diagnostic ?? "not checked"}
diff --git a/apps/studio/src/lib/execution-profile-row-identity.test.ts b/apps/studio/src/lib/execution-profile-row-identity.test.ts new file mode 100644 index 00000000..4b7dba18 --- /dev/null +++ b/apps/studio/src/lib/execution-profile-row-identity.test.ts @@ -0,0 +1,51 @@ +import { describe, expect, it } from "vitest"; + +import { executionProfileRowIdentity } from "./execution-profile-row-identity.js"; + +const terraCodex = { + executionProfileId: `sha256:${"a".repeat(64)}`, + profileKey: "rule-evidence-codex-app-server", + revision: 1006, +} as const; + +const terraOntology = { + executionProfileId: `sha256:${"b".repeat(64)}`, + profileKey: "ontology-codex-app-server", + revision: 1002, +} as const; + +describe("execution profile row identity", () => { + it("shows the picker rN plus profileKey and a short id", () => { + expect(executionProfileRowIdentity(terraCodex)).toBe( + "r1006 · rule-evidence-codex-app-server · aaaaaaaaaa", + ); + }); + + it("distinguishes same-runtime same-model rows the picker would otherwise collapse", () => { + const left = executionProfileRowIdentity(terraCodex); + const right = executionProfileRowIdentity(terraOntology); + expect(left).not.toBe(right); + expect(left).toContain("r1006"); + expect(right).toContain("r1002"); + expect(left).toContain("rule-evidence-codex-app-server"); + expect(right).toContain("ontology-codex-app-server"); + expect(left).toContain("aaaaaaaaaa"); + expect(right).toContain("bbbbbbbbbb"); + }); + + it("keeps later revisions of the same profileKey distinct", () => { + expect(executionProfileRowIdentity({ + ...terraCodex, + executionProfileId: `sha256:${"c".repeat(64)}`, + revision: 2006, + })).toBe("r2006 · rule-evidence-codex-app-server · cccccccccc"); + }); + + it("does not turn the capability list into a run or campaign control", () => { + const label = executionProfileRowIdentity(terraCodex).toLowerCase(); + expect(label).not.toContain("preflight"); + expect(label).not.toContain("run"); + expect(label).not.toContain("campaign"); + expect(label).not.toContain("spend"); + }); +}); diff --git a/apps/studio/src/lib/execution-profile-row-identity.ts b/apps/studio/src/lib/execution-profile-row-identity.ts new file mode 100644 index 00000000..fddc46df --- /dev/null +++ b/apps/studio/src/lib/execution-profile-row-identity.ts @@ -0,0 +1,20 @@ +const HASH_PREFIX = "sha256:"; +const SHORT_ID_LENGTH = 10; + +export type ExecutionProfileRowIdentityInput = Readonly<{ + executionProfileId: string; + profileKey: string; + revision: number; +}>; + +function shortExecutionProfileId(executionProfileId: string): string { + return executionProfileId.startsWith(HASH_PREFIX) + ? executionProfileId.slice(HASH_PREFIX.length, HASH_PREFIX.length + SHORT_ID_LENGTH) + : executionProfileId.slice(0, SHORT_ID_LENGTH); +} + +export function executionProfileRowIdentity( + profile: ExecutionProfileRowIdentityInput, +): string { + return `r${profile.revision} · ${profile.profileKey} · ${shortExecutionProfileId(profile.executionProfileId)}`; +} From 0c683886d46cb7d7e9d491bf6212f0903df97f7c Mon Sep 17 00:00:00 2001 From: RainMona <316033127+RainMona@users.noreply.github.com> Date: Thu, 20 Aug 2026 02:11:07 +0000 Subject: [PATCH 2/3] Scope Preflight stage circle to the step index only. Issue #37: .preflight-stage > span also hit Badge (a span), crushing PASS / REJECTED / NOT_RUN into a 22px circle. The index class keeps the step number round; the verdict badge stays a normal pill. (cherry picked from commit a0d78a09f1e36c77c03da78011fa005dff6c7d99) --- apps/studio/src/App.tsx | 2 +- apps/studio/src/index.css | 4 ++-- .../src/lib/preflight-stage-index.test.ts | 21 +++++++++++++++++++ 3 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 apps/studio/src/lib/preflight-stage-index.test.ts diff --git a/apps/studio/src/App.tsx b/apps/studio/src/App.tsx index c9d4f3b9..f92cca3e 100644 --- a/apps/studio/src/App.tsx +++ b/apps/studio/src/App.tsx @@ -6891,7 +6891,7 @@ function RealCandidatePreflightView() { {currentStages.map((stage, index) => (
- + {stage.status === "PASS" ? index + 1 : }
diff --git a/apps/studio/src/index.css b/apps/studio/src/index.css index 21281c5f..2ec38f95 100644 --- a/apps/studio/src/index.css +++ b/apps/studio/src/index.css @@ -6006,7 +6006,7 @@ footer span:first-child { padding-bottom: 0; } -.preflight-stage > span { +.preflight-stage-index { display: grid; width: 22px; height: 22px; @@ -6018,7 +6018,7 @@ footer span:first-child { font-size: 12px; } -.preflight-stage > span.is-blocked { +.preflight-stage-index.is-blocked { border-color: rgba(213, 161, 110, 0.18); color: #d5a16e; } diff --git a/apps/studio/src/lib/preflight-stage-index.test.ts b/apps/studio/src/lib/preflight-stage-index.test.ts new file mode 100644 index 00000000..94847a64 --- /dev/null +++ b/apps/studio/src/lib/preflight-stage-index.test.ts @@ -0,0 +1,21 @@ +import { readFileSync } from "node:fs"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; +import { describe, expect, it } from "vitest"; + +const studioRoot = join(dirname(fileURLToPath(import.meta.url)), ".."); + +describe("preflight stage index circle", () => { + it("scopes the 22px circle to the step index, not every child span", () => { + const css = readFileSync(join(studioRoot, "index.css"), "utf8"); + expect(css).toContain(".preflight-stage-index {"); + expect(css).toContain("width: 22px;"); + expect(css).not.toMatch(/\.preflight-stage\s*>\s*span\s*\{/); + }); + + it("marks the step index with preflight-stage-index so Badge stays a pill", () => { + const app = readFileSync(join(studioRoot, "App.tsx"), "utf8"); + expect(app).toContain('className={stage.status === "PASS" ? "preflight-stage-index" : "preflight-stage-index is-blocked"}'); + expect(app).toContain(""); + }); +}); From 1678d677b6482b94738060e2479d7bf48bdcce33 Mon Sep 17 00:00:00 2001 From: RainMona <316033127+RainMona@users.noreply.github.com> Date: Thu, 20 Aug 2026 02:24:23 +0000 Subject: [PATCH 3/3] Let Preflight post-fee upper bound show its full name. Issue #40: the current-snapshot fact labels used nowrap + ellipsis on three equal columns, so POST-FEE UPPER BOUND became POST-FEE UPPER BO... next to a 0.0000. Labels wrap; values can still ellipsize. (cherry picked from commit 3388db82bf17569d2d8cd4f17460d5105ec6a2bf) --- apps/studio/src/index.css | 8 ++++--- .../lib/preflight-disposition-facts.test.ts | 24 +++++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 apps/studio/src/lib/preflight-disposition-facts.test.ts diff --git a/apps/studio/src/index.css b/apps/studio/src/index.css index 2ec38f95..837e171f 100644 --- a/apps/studio/src/index.css +++ b/apps/studio/src/index.css @@ -5506,22 +5506,24 @@ footer span:first-child { .preflight-disposition-facts span, .preflight-disposition-facts strong { display: block; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; } .preflight-disposition-facts span { color: #685c51; font-size: 12px; text-transform: uppercase; + overflow: visible; + white-space: normal; } .preflight-disposition-facts strong { margin-top: 5px; + overflow: hidden; color: #c28f62; font-family: inherit; font-size: 12px; + text-overflow: ellipsis; + white-space: nowrap; } .preflight-disposition > code { diff --git a/apps/studio/src/lib/preflight-disposition-facts.test.ts b/apps/studio/src/lib/preflight-disposition-facts.test.ts new file mode 100644 index 00000000..50b60f41 --- /dev/null +++ b/apps/studio/src/lib/preflight-disposition-facts.test.ts @@ -0,0 +1,24 @@ +import { readFileSync } from "node:fs"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; +import { describe, expect, it } from "vitest"; + +const studioRoot = join(dirname(fileURLToPath(import.meta.url)), ".."); + +describe("preflight disposition fact labels", () => { + it("does not ellipsize POST-FEE UPPER BOUND", () => { + const css = readFileSync(join(studioRoot, "index.css"), "utf8"); + const start = css.indexOf(".preflight-disposition-facts span {"); + expect(start).toBeGreaterThan(-1); + const block = css.slice(start, css.indexOf("}", start) + 1); + expect(block).toContain("white-space: normal"); + expect(block).not.toContain("ellipsis"); + expect(block).not.toContain("nowrap"); + }); + + it("keeps the Post-fee upper bound copy on the current-snapshot row", () => { + const app = readFileSync(join(studioRoot, "App.tsx"), "utf8"); + expect(app).toContain("Post-fee upper bound"); + expect(app).toContain("className=\"preflight-disposition-facts\""); + }); +});