mirror of
https://github.com/andrewyng/openworker.git
synced 2026-09-12 15:20:19 +00:00
Tool-request card: separate the product's facts from the coworker's ask
Registry metadata (version, publisher, checksum) moves to a distinct fact strip. Decline button renamed to say the run continues; reason capped to one sentence.
This commit is contained in:
@@ -628,6 +628,7 @@ export async function mockApi(page: import("@playwright/test").Page) {
|
||||
installable: true,
|
||||
version: "8.30.1",
|
||||
summary: "scans git history and the working tree for committed secrets",
|
||||
source: "github.com/gitleaks",
|
||||
});
|
||||
return; // suspended on the tool request
|
||||
}
|
||||
|
||||
@@ -17,10 +17,14 @@ test("request_tool surfaces a card naming the tool, the reason and the pinned ve
|
||||
const card = page.locator(".dirreq-card");
|
||||
await expect(card).toContainText("gitleaks");
|
||||
await expect(card).toContainText("scan the git history for committed secrets");
|
||||
await expect(card).toContainText("8.30.1");
|
||||
await expect(card).toContainText(/checksum-verified/i);
|
||||
// Declining must read as a normal choice, not a failure.
|
||||
await expect(card.getByTestId("toolreq-skip")).toBeVisible();
|
||||
// The fact strip is the product's voice: version, publisher, checksum — kept apart from
|
||||
// the coworker's quoted reason (mixing them is what made the card confusing, 2026-08-14).
|
||||
const facts = card.locator(".toolreq-facts");
|
||||
await expect(facts).toContainText("8.30.1");
|
||||
await expect(facts).toContainText(/checksum-verified/i);
|
||||
await expect(facts).toContainText("from github.com/gitleaks");
|
||||
// Declining must read as a normal choice that continues the run, not a failure.
|
||||
await expect(card.getByTestId("toolreq-skip")).toHaveText("Continue without it");
|
||||
});
|
||||
|
||||
test("an event without install metadata fails CLOSED — Install disabled, skip offered", async ({
|
||||
|
||||
@@ -741,6 +741,7 @@ export function App() {
|
||||
installable: d.installable === true,
|
||||
version: d.version || "",
|
||||
summary: d.summary || "",
|
||||
source: d.source || "",
|
||||
},
|
||||
]);
|
||||
break;
|
||||
|
||||
@@ -22,23 +22,30 @@ export function ToolRequestCard({
|
||||
</span>
|
||||
</div>
|
||||
{item.reason && <div className="dirreq-reason">“{item.reason}”</div>}
|
||||
{/* The fact strip is the PRODUCT speaking (registry metadata), styled apart from the
|
||||
coworker's quoted ask above — mixing the two voices is what made the card confusing. */}
|
||||
{item.installable ? (
|
||||
<div className="dirreq-reason">
|
||||
{item.summary ? `${item.summary}. ` : ""}
|
||||
Installs {item.tool}
|
||||
{item.version ? ` ${item.version}` : ""} — a pinned build, checksum-verified before
|
||||
it runs.
|
||||
<div className="toolreq-facts">
|
||||
<code>
|
||||
{item.tool}
|
||||
{item.version ? ` ${item.version}` : ""}
|
||||
</code>
|
||||
{item.summary && <span className="toolreq-fact">{item.summary}</span>}
|
||||
<span className="toolreq-fact">pinned & checksum-verified</span>
|
||||
{item.source && <span className="toolreq-fact">from {item.source}</span>}
|
||||
</div>
|
||||
) : (
|
||||
<div className="dirreq-reason">
|
||||
No verified build is available for this machine — install it yourself if you want
|
||||
this check, or skip and the coworker will note the gap.
|
||||
<div className="toolreq-facts">
|
||||
<span className="toolreq-fact">
|
||||
No verified build is available for this machine — install it yourself if you want
|
||||
this check, or continue and the coworker will note the gap.
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
<div className="dirreq-actions">
|
||||
<span className="spacer" />
|
||||
<button className="btn" data-testid="toolreq-skip" onClick={() => onRespond(false)}>
|
||||
Skip this check
|
||||
Continue without it
|
||||
</button>
|
||||
<button
|
||||
className="btn primary"
|
||||
|
||||
@@ -794,6 +794,19 @@ button.btn.danger { color: var(--accent); }
|
||||
.dirreq-head { display: flex; align-items: center; gap: 8px; font-weight: 600; font-size: 13.5px; color: var(--ink); }
|
||||
.dirreq-head .ico { color: var(--accent); }
|
||||
.dirreq-reason { font-size: 13px; color: var(--muted); font-style: italic; margin: 6px 0 10px; }
|
||||
/* request_tool fact strip — the product's own metadata (version, publisher, checksum),
|
||||
deliberately NOT italic so it can't be misread as the coworker still talking */
|
||||
.toolreq-facts {
|
||||
display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px;
|
||||
font-size: 12.5px; color: var(--muted); font-style: normal;
|
||||
background: var(--paper); border: 1px solid var(--line); border-radius: 8px;
|
||||
padding: 7px 10px; margin: 2px 0 10px;
|
||||
}
|
||||
.toolreq-facts code { color: var(--ink); font-size: 12.5px; }
|
||||
.toolreq-fact + .toolreq-fact::before,
|
||||
.toolreq-facts code + .toolreq-fact::before { content: "· "; color: var(--muted); }
|
||||
/* a disabled Install must LOOK disabled — the whole card exists to not oversell */
|
||||
.dirreq-actions .btn:disabled { opacity: 0.45; cursor: not-allowed; }
|
||||
.dirreq-pathrow { display: flex; gap: 8px; align-items: center; }
|
||||
.dirreq-path {
|
||||
flex: 1; font: inherit; font-size: 13px; color: var(--ink);
|
||||
|
||||
@@ -136,6 +136,7 @@ export type Item =
|
||||
installable?: boolean;
|
||||
version?: string;
|
||||
summary?: string;
|
||||
source?: string;
|
||||
resolved?: "installed" | "skipped";
|
||||
}
|
||||
| {
|
||||
|
||||
Reference in New Issue
Block a user