feat: multi-work is able to delegate to root
CI / verify (pull_request) Successful in 9s

This commit is contained in:
2026-09-18 20:13:54 +02:00
parent 8b6836f5a4
commit 52e98c9d78
9 changed files with 376 additions and 88 deletions
+5 -3
View File
@@ -48,14 +48,16 @@ assignment is accepted for compatibility but deprecated and ignored; orchestrati
## Multi-work
Select `multi-work` in a verified live Herdr root checkout to delegate local retrieval
to `fast-lo` and independent work to `coordinate` children in new Herdr worktrees.
to `fast-lo` and independent work to `coordinate` children in either the current root
checkout or new Herdr worktrees.
It is primary-only and, like `coordinate`, uses the `deep-lo` model and effort,
falling back to `good-lo` when `deep-lo` is unavailable. Clients viewing the
same eligible location can see it; eligibility is revalidated before creation.
Configure `experimental.subagent_depth: 2` at the root and worktree locations.
The native `subagent` tool accepts `worktree: { base: "source-branch" }` for new
coordinate tasks and retains native session/job handling. See [usage, permissions,
For new coordinate tasks, omit `worktree` to share the current root checkout, or pass
`worktree: { base: "source-branch" }` for an isolated checkout. The tool retains native
session/job handling. See [usage, permissions,
failure handling, and verification limits](docs/multi-work.md).
## Playwright
+37 -13
View File
@@ -1,13 +1,15 @@
# Multi-work
`multi-work` is a **primary-only** agent for coordinating independent work in
Herdr-managed Git worktrees. Like `coordinate`, it uses the configured `deep-lo`
model and effort, falling back to `good-lo` when `deep-lo` is unavailable. No
extra custom model assignment is required.
the current Herdr root checkout or new Herdr-managed Git worktrees. Like
`coordinate`, it uses the configured `deep-lo` model and effort, falling back
to `good-lo` when `deep-lo` is unavailable. No extra custom model assignment is
required.
```text
multi-work (root checkout)
├── fast-lo (local retrieval)
├── coordinate (current root checkout)
└── coordinate (new Herdr worktree)
└── existing leaf workers (that worktree)
```
@@ -56,7 +58,24 @@ plugins or project configuration.
## Delegation
Multi-work retains the native tool name, `subagent`. It adds one argument:
Multi-work retains the native tool name, `subagent`. For work in the current root
checkout, omit `worktree`:
```js
subagent({
agent: "coordinate",
description: "Implement local change",
prompt: "Goal, owned files, constraints, and acceptance checks...",
background: true,
});
```
The child is bound to the verified root workspace before its prompt is admitted.
No Herdr workspace is created and neither the child nor parent is moved. Root-local
children share a checkout, so parallel assignments must have disjoint file ownership.
Their placement metadata uses `branch: "root"` to identify the shared root checkout;
it is not a claim about the root's current Git branch.
Use a worktree when edits may overlap or require branch isolation:
```js
subagent({
@@ -86,17 +105,22 @@ checkout path; the tool parses and verifies the returned checkout/workspace.
Creation explicitly preserves focus with `--no-focus`.
For focused retrieval, use native `subagent` with `agent: "fast-lo"` and no
`worktree`. Resume an owned coordinate child with its `sessionID` and **omit**
`worktree`. Resumes verify parent, agent, checkout, branch, and live Herdr ownership.
`worktree`. A new coordinate call without `worktree` means root-local work. Resume
an owned coordinate child with its `sessionID` and **omit**
`worktree`. Resumes verify parent, agent, assigned checkout, and live Herdr ownership;
worktree resumes also verify the branch.
Bound coordinate children cannot be repurposed through native delegation.
Neither multi-work nor coordinate has general shell/edit permissions. Multi-work
also rejects non-reading/non-delegation tools at execution, including Code Mode,
even if a session permission override would expose them. Worktree preparation
requires effective `herdr_worktree: allow`, evaluated against the canonical root
directory using ordered agent and session rules. `ask` fails explicitly because
the public plugin API cannot request custom-tool approval. Native subagent
permissions are still asserted by OpenCode before preparation starts.
even if a session permission override would expose them. Creating or resuming
worktree-backed delegation requires effective `herdr_worktree: allow`, evaluated
against the canonical root directory using ordered agent and session rules. `ask`
fails explicitly because the public plugin API cannot request custom-tool approval.
Native subagent permissions are still asserted by OpenCode before preparation
starts. Root-local delegation performs no Herdr creation and therefore does not
require `herdr_worktree`; worker edit/shell permissions remain inherited and
enforced normally.
Worktree permissions inherit the base plugin's **effective build-permission
snapshot**, including configuration applied after plugin transforms. Its existing
@@ -118,8 +142,8 @@ child ID, and confirm its actual session location before allowing the task promp
A move-request acknowledgement alone is insufficient. Confirmation is bounded to
30 seconds and remains interruptible. The parent session does not move.
Coordinate is child-capable only through an owned, ready worktree binding. Prompt
admission and model-context guards reject unbound or moved coordinate children.
Coordinate is child-capable only through an owned, ready multi-work binding. Prompt
admission and model-context guards reject unbound or relocated coordinate children.
Multi-work cannot be a child, and the existing workers remain leaves.
Normal delegation cards and child navigation recognize the retained `subagent`
+2 -2
View File
@@ -320,7 +320,7 @@ const makeBasePlugin = (permissionsChanged: (permissions: Agent.Info["permission
if (agent === "multi-work") throw new Error("multi-work is primary only");
if (agent === "coordinate" && event.agent !== "multi-work")
throw new Error(
"coordinate cannot run as a subagent without a ready worktree binding",
"coordinate cannot run as a subagent without a ready multi-work binding",
);
if (workerNames.some((name) => name === event.agent))
throw new Error("Workers cannot delegate tasks");
@@ -349,7 +349,7 @@ const makeBasePlugin = (permissionsChanged: (permissions: Agent.Info["permission
parent.location.directory !== binding.data.root.directory
)
throw new Error(
"coordinate cannot run as a subagent without a ready worktree binding",
"coordinate cannot run as a subagent without a ready multi-work binding",
);
}
if (
+65 -29
View File
@@ -9,7 +9,8 @@ import { randomUUID } from "node:crypto";
import { Herdr, rootSchema } from "./herdr.js";
import { multiWorkGuide } from "./routing.js";
export const bindingSchema = z.object({
export const bindingSchema = z
.object({
owner: z.string(),
child: z.string(),
projectID: z.string(),
@@ -18,7 +19,14 @@ export const bindingSchema = z.object({
workspaceID: z.string(),
branch: z.string(),
ready: z.boolean(),
});
})
.refine(
(binding) =>
binding.directory === binding.root.directory
? binding.workspaceID === binding.root.workspaceID && binding.branch === "root"
: binding.workspaceID !== binding.root.workspaceID,
{ message: "Invalid multi-work placement metadata" },
);
export const bindingKey = (id: string) => `multi-work:${id}`;
const inputSchema = z
.object({
@@ -98,7 +106,7 @@ export const installMultiWork = (
agent.name = Agent.Name.make("multi-work");
agent.mode = "primary";
agent.description =
"Coordinate independent tasks in Herdr worktrees; retrieve local facts with fast-lo.";
"Coordinate independent tasks locally or in Herdr worktrees; retrieve local facts with fast-lo.";
agent.system = multiWorkGuide;
agent.permissions = [
...coordinate.permissions.filter((rule) => rule.action !== "subagent"),
@@ -137,14 +145,14 @@ export const installMultiWork = (
child.projectID !== binding.projectID ||
child.location.directory !== binding.directory
)
throw new Error("Coordinate child does not match its ready worktree binding");
throw new Error("Coordinate child does not match its ready multi-work binding");
const parent = yield* context.session.get({ sessionID: child.parentID });
if (
parent.agent !== "multi-work" ||
parent.projectID !== binding.projectID ||
parent.location.directory !== binding.root.directory
)
throw new Error("Worktree owner changed agent or location");
throw new Error("Binding owner changed agent or location");
return binding;
});
@@ -184,7 +192,7 @@ export const installMultiWork = (
agent: { type: "string", enum: ["fast-lo", "coordinate"] },
};
tool.description =
"Delegate to fast-lo locally, or coordinate in a new Herdr worktree using worktree: {base, branch?, label?}. Prefer descriptive human-readable branch and label values, for example {base:'main',branch:'fix/login-timeout',label:'Fix login timeout'}. Continue an owned coordinate child with sessionID and no worktree argument; naming fields are create-only. Native background and results apply.";
"Delegate to fast-lo for retrieval, or coordinate in this root checkout by omitting worktree. To isolate new coordinate work, use worktree: {base, branch?, label?}. Continue an owned coordinate child with sessionID and no worktree argument. Native background and results apply.";
}
}).pipe(Effect.orDie),
);
@@ -208,9 +216,7 @@ export const installMultiWork = (
throw new Error("A bound coordinate child cannot be repurposed");
if (call.agent !== "multi-work") {
if (input.worktree || input.agent === "coordinate")
throw new Error(
"Only multi-work may initialize coordinate worktrees",
);
throw new Error("Only multi-work may delegate to coordinate");
return yield* native.execute(input, call);
}
const parent = yield* context.session.get({ sessionID: call.sessionID });
@@ -240,14 +246,27 @@ export const installMultiWork = (
}
if (input.agent !== "coordinate")
throw new Error("multi-work delegates only to fast-lo or coordinate");
if (
input.sessionID
? input.worktree !== undefined
: input.worktree === undefined
)
if (input.sessionID && input.worktree !== undefined)
throw new Error(
"New coordinate work requires worktree: {base}; resumes require only sessionID",
"Coordinate resumes require only sessionID; worktree is create-only",
);
const lock = input.sessionID ?? `${call.sessionID}:${call.id}`;
if (busy.has(lock)) throw new Error("This delegation is already active");
busy.add(lock);
let childLock: string | undefined;
return yield* Effect.gen(function* () {
let initialized = false;
let placement: z.infer<typeof bindingSchema> | undefined;
if (input.sessionID) {
const binding = yield* validate(Session.ID.make(input.sessionID));
if (binding.owner !== call.sessionID)
throw new Error("Cannot resume another parent's binding");
placement = binding;
}
if (
input.worktree ||
(placement && placement.directory !== placement.root.directory)
) {
const { data: agent } = yield* context.agent.get({
agentID: call.agent,
location: { directory: parent.location.directory },
@@ -264,17 +283,16 @@ export const installMultiWork = (
throw new Error(
`herdr_worktree requires explicit allow; custom approval is unavailable (${permission ?? "ask"})`,
);
const lock = input.sessionID ?? `${call.sessionID}:${call.id}`;
if (busy.has(lock)) throw new Error("This delegation is already active");
busy.add(lock);
let childLock: string | undefined;
return yield* Effect.gen(function* () {
let initialized = false;
let placement: z.infer<typeof bindingSchema> | undefined;
if (input.sessionID) {
const binding = yield* validate(Session.ID.make(input.sessionID));
if (binding.owner !== call.sessionID)
throw new Error("Cannot resume another parent's worktree");
}
if (placement) {
const binding = placement;
if (
root.directory !== binding.root.directory ||
root.workspaceID !== binding.root.workspaceID ||
root.repo !== binding.root.repo
)
throw new Error("Bound Herdr root is no longer available");
if (binding.directory !== binding.root.directory)
yield* Effect.tryPromise((signal) =>
herdr.verify(
binding.directory,
@@ -284,7 +302,6 @@ export const installMultiWork = (
signal,
),
);
placement = binding;
initialized = true;
}
const { worktree, ...args } = input;
@@ -310,8 +327,6 @@ export const installMultiWork = (
);
childLock = id;
busy.add(id);
if (!worktree)
throw new Error("Missing worktree initialization");
const sessionID = Session.ID.make(id);
const child = yield* context.session.get({ sessionID });
if (
@@ -323,6 +338,27 @@ export const installMultiWork = (
throw new Error(
"Native executor returned an unexpected child",
);
if (!worktree) {
const binding = {
owner: call.sessionID,
child: id,
projectID: parent.projectID,
root,
directory: root.directory,
workspaceID: root.workspaceID,
branch: "root",
ready: true,
};
yield* context.storage.set(callKey, {
child: id,
branch: binding.branch,
root,
});
yield* context.storage.set(bindingKey(id), binding);
placement = binding;
initialized = true;
return;
}
const branch =
worktree.branch ?? `multi-work/${randomUUID()}`;
yield* context.storage.set(callKey, {
+6 -4
View File
@@ -16,15 +16,17 @@ export const descriptions = {
export const multiWorkGuide = `You are multi-work, a primary orchestrator in a verified Herdr root checkout.
Read, plan, track todos and delegate; never implement or execute shell commands yourself.
Use native subagent with agent fast-lo for focused local retrieval. Use agent coordinate
for work in a new Herdr worktree, supplying descriptive human-readable names such as
without worktree to edit concurrently in this root checkout, or isolate work in a new
Herdr worktree by supplying descriptive human-readable names such as
worktree: {base: "main", branch: "fix/login-timeout", label: "Fix login timeout"}, plus
description and a complete prompt with scope, constraints and acceptance checks. The tool
uses the requested branch and Herdr workspace label; when omitted, it creates the prior unique
uses the requested branch and Herdr workspace label; when the branch is omitted, it creates the prior unique
multi-work/<uuid> branch and lets Herdr choose its default label. It moves the coordinate child
before its task begins, and preserves your root session. Dirty root changes are not copied.
Resume an owned coordinate child using its sessionID and no worktree argument. Never switch
its agent or location; naming fields are create-only. Only fast-lo and coordinate are permitted. Workers are leaves.
Parallelize independent work with disjoint ownership; serialize dependencies. Native background
its agent or assigned checkout; naming fields are create-only. Only fast-lo and coordinate are permitted. Workers are leaves.
Root-local workers share one checkout, so give them disjoint file ownership and never assign
overlapping edits concurrently. Parallelize independent work; serialize dependencies. Native background
delegation returns immediately and notifies you when complete; do not poll or duplicate work.
Reconcile results and report checkout, branch and child IDs. Retained resources on failure
must not be deleted automatically. Never retry ambiguous creation failures blindly.
+1 -1
View File
@@ -80,7 +80,7 @@ export default Plugin.define({
return (
<Show when={status()}>
<Show when={props.centered} fallback={<Content />}>
<box width="100%" alignItems="center">
<box position="absolute" top={2} left={0} width="100%" alignItems="center">
<Content />
</box>
</Show>
+151 -1
View File
@@ -14,6 +14,8 @@ import { bindingKey, bindingSchema, installMultiWork } from "../src/multi-work.j
class FixtureHerdr extends Herdr {
eligible = true;
rootWorkspaceID = "w1";
rootRepo = "/root/.git";
creations = 0;
verified = 0;
delayCreation = false;
@@ -24,7 +26,7 @@ class FixtureHerdr extends Herdr {
creationStarted = Promise.withResolvers<void>();
override async root(directory: string) {
return this.eligible && directory === "/root"
? { directory, workspaceID: "w1", repo: "/root/.git" }
? { directory, workspaceID: this.rootWorkspaceID, repo: this.rootRepo }
: undefined;
}
override async create(
@@ -366,6 +368,128 @@ test("local fast-lo uses native delegation without a worktree", async () => {
);
});
test("coordinate can create and resume a root-local background child without Herdr creation or movement", async () => {
const f = fixture();
f.parent.permissions = [{ action: "herdr_worktree", resource: "*", effect: "deny" }];
await Effect.runPromise(
Effect.scoped(
Effect.gen(function* () {
yield* f.install;
const created = yield* f.execute({
agent: "coordinate",
description: "local edit",
prompt: "edit assigned files",
background: true,
});
expect(created.metadata).toMatchObject({
sessionID: "ses_child1",
status: "running",
directory: "/root",
workspaceID: "w1",
branch: "root",
});
expect(f.herdr.creations).toBe(0);
expect(f.order).toEqual(["create", "prompt:/root"]);
expect(bindingSchema.parse(f.storage.get(bindingKey("ses_child1")))).toMatchObject({
owner: "ses_parent",
directory: "/root",
workspaceID: "w1",
branch: "root",
ready: true,
});
yield* f.execute({
agent: "coordinate",
description: "resume local",
prompt: "continue",
sessionID: "ses_child1",
});
expect(f.herdr.creations).toBe(0);
expect(f.herdr.verified).toBe(0);
}),
),
);
});
test("root-local resume rejects location, binding, and live-root changes", async () => {
for (const tamper of ["session", "workspace", "root", "branch", "live-root"] as const) {
const f = fixture();
await Effect.runPromise(
Effect.scoped(
Effect.gen(function* () {
yield* f.install;
yield* f.execute({
agent: "coordinate",
description: "local edit",
prompt: "work",
});
if (tamper === "session")
f.sessions.get("ses_child1")!.location.directory = "/other";
else if (tamper === "live-root") f.herdr.rootWorkspaceID = "foreign";
else {
const binding = bindingSchema.parse(
f.storage.get(bindingKey("ses_child1")),
);
const changed = { ...binding };
if (tamper === "workspace") changed.workspaceID = "foreign";
if (tamper === "root") {
changed.root = { ...binding.root, workspaceID: "foreign" };
changed.workspaceID = "foreign";
}
if (tamper === "branch") changed.branch = "main";
f.storage.set(bindingKey("ses_child1"), changed);
}
expect(
(yield* Effect.exit(
f.execute({
agent: "coordinate",
description: "resume",
prompt: "continue",
sessionID: "ses_child1",
}),
))._tag,
).toBe("Failure");
expect(f.prompts).toBe(1);
}),
),
);
}
});
test("interrupted root-local creation retains its binding and cannot be blindly replayed", async () => {
const f = fixture();
f.hold();
const controller = new AbortController();
const running = Effect.runPromise(
Effect.scoped(
Effect.gen(function* () {
yield* f.install;
return yield* f.execute({
agent: "coordinate",
description: "local edit",
prompt: "work",
});
}),
),
{ signal: controller.signal },
);
await f.entered.promise;
controller.abort();
await expect(running).rejects.toBeDefined();
expect(bindingSchema.parse(f.storage.get(bindingKey("ses_child1"))).ready).toBe(true);
expect(f.storage.has(`multi-work-call:${f.call.sessionID}:${f.call.id}`)).toBe(true);
const replay = await Effect.runPromise(
Effect.exit(
f.execute({
agent: "coordinate",
description: "local edit",
prompt: "work",
}),
),
);
expect(replay._tag).toBe("Failure");
expect(f.prompts).toBe(1);
});
test("custom branch and workspace label pass through delegation", async () => {
const f = fixture();
await Effect.runPromise(
@@ -623,6 +747,32 @@ test("configured build restrictions remain effective for worktree preparation",
);
});
test("worktree resumes retain the herdr_worktree permission guard", async () => {
const f = fixture();
await Effect.runPromise(
Effect.scoped(
Effect.gen(function* () {
yield* f.install;
yield* f.invoke();
f.parent.permissions = [
{ action: "herdr_worktree", resource: "*", effect: "deny" },
];
const resumed = yield* Effect.exit(
f.execute({
agent: "coordinate",
description: "resume",
prompt: "continue",
sessionID: "ses_child1",
}),
);
expect(resumed._tag).toBe("Failure");
expect(f.herdr.verified).toBe(0);
expect(f.prompts).toBe(1);
}),
),
);
});
test("failed initialization records the attempt and never blindly recreates on replay", async () => {
const f = fixture();
f.missingDestination();
+13 -10
View File
@@ -306,17 +306,17 @@ async function host(
child = target;
for (const hook of sessionHooks.prompt ?? []) await hook({ sessionID: "child" });
},
bindCoordinate(ready: boolean, moved = true) {
childDirectory = moved ? `${directory}/worktree` : directory;
bindCoordinate(ready: boolean, moved = true, local = false) {
childDirectory = local ? directory : moved ? `${directory}/worktree` : directory;
storage.set(bindingKey("child"), {
owner: "parent",
child: "child",
projectID: "project-fixture",
ready,
root: { directory, workspaceID: "w1", repo: `${directory}/.git` },
directory: `${directory}/worktree`,
workspaceID: "w2",
branch: "multi-work/test",
directory: local ? directory : `${directory}/worktree`,
workspaceID: local ? "w1" : "w2",
branch: local ? "root" : "multi-work/test",
});
},
async tools(caller: string) {
@@ -663,22 +663,25 @@ test("manual calls and command-created child sessions cannot bypass delegation r
expect((await result.tools("build")).subagent?.description).toBe("Native subagents");
});
test("coordinate prompt admission requires both owned provenance and a completed move; multi-work cannot be a child", async () => {
test("coordinate prompt admission requires owned ready placement; local and moved bindings work", async () => {
const result = await host();
await expect(result.command("multi-work", "coordinate")).rejects.toThrow(
"ready worktree binding",
"ready multi-work binding",
);
result.bindCoordinate(false);
await expect(result.command("multi-work", "coordinate")).rejects.toThrow(
"ready worktree binding",
"ready multi-work binding",
);
result.bindCoordinate(true, false);
await expect(result.command("multi-work", "coordinate")).rejects.toThrow(
"ready worktree binding",
"ready multi-work binding",
);
result.bindCoordinate(true);
await result.command("multi-work", "coordinate");
await expect(result.command("build", "coordinate")).rejects.toThrow("ready worktree binding");
result.bindCoordinate(true, true, true);
await result.command("multi-work", "coordinate");
await expect(result.command("build", "coordinate")).rejects.toThrow("ready multi-work binding");
result.bindCoordinate(true);
await expect(result.command("multi-work", "fast-lo")).rejects.toThrow("local fast-lo");
for (const invoke of [result.delegate, result.command])
await expect(invoke("build", "multi-work")).rejects.toThrow("primary only");
+74 -3
View File
@@ -2,6 +2,7 @@ import { expect, test } from "bun:test";
import type { Plugin } from "@opencode/plugin/tui";
import type { Route, SlotMap } from "@opencode/plugin/tui/context";
import { testRender, type JSX } from "@opentui/solid";
import { jsx } from "@opentui/solid/jsx-runtime";
import { createSignal } from "solid-js";
import { build } from "../scripts/build.js";
import type { QuotaStatus } from "../src/quota.js";
@@ -87,12 +88,19 @@ test("built quota slot stays reactive across pending, empty, failure, update, an
const renderHome = homeRender;
const home = await testRender(() => renderHome({ mode: "normal", showDetails: false }), {
width: 40,
height: 5,
height: 6,
});
await home.waitForFrame((frame) => frame.includes("ChatGPT quota (home)"));
const homeFrame = home.captureCharFrame();
expect(homeFrame).toContain(" ChatGPT quota (home)");
expect(homeFrame).toContain(" 5h: 90% · due");
expect(homeFrame.split("\n")).toEqual([
" ",
" ",
" ChatGPT quota (home) ",
" 5h: 90% · due ",
" ",
" ",
"",
]);
expect(statusCalls).toBe(1);
home.renderer.destroy();
@@ -152,3 +160,66 @@ test("built quota slot stays reactive across pending, empty, failure, update, an
if (cleanup) await cleanup();
}
});
test("home quota stays out of the host footer row at wide and narrow widths", async () => {
await build();
const { default: plugin } = await import(new URL("../dist/tui.js", import.meta.url).href);
let homeRender: HomeSlotRender | undefined;
const contextFixture = {
client: {
rpc: () => ({
status: async () => status("home", 90),
events: { on: () => () => undefined },
}),
},
ui: {
slot(claim: { after?: "prompt.footer"; render: HomeSlotRender }) {
if (claim.after === "prompt.footer") homeRender = claim.render;
return () => undefined;
},
router: { current: () => ({ type: "home" as const }) },
},
theme: { text: { default: "#ffffff", muted: "#888888" } },
};
// SAFETY: This focused fixture implements every context member read by slot setup/rendering.
const cleanup = await plugin.setup(Object.assign({} as Plugin.Context, contextFixture));
if (!homeRender) throw new Error("Plugin did not register the home slot");
const renderHome = homeRender;
try {
for (const width of [75, 40]) {
const footer = (quota: boolean) =>
jsx("box", {
flexDirection: "row",
children: [
jsx("text", { children: "/project" }),
jsx("box", { flexGrow: 1 }),
jsx("text", { children: "NORMAL" }),
jsx("text", { children: " ctrl+k commands" }),
quota ? renderHome({ mode: "normal", showDetails: false }) : undefined,
],
});
const baseline = await testRender(() => footer(false), { width, height: 6 });
const rendered = await testRender(() => footer(true), { width, height: 6 });
try {
await baseline.renderOnce();
await rendered.waitForFrame((frame) => frame.includes("ChatGPT quota (home)"));
const baselineRows = baseline.captureCharFrame().split("\n");
const quotaRows = rendered.captureCharFrame().split("\n");
expect(quotaRows[0]).toBe(baselineRows[0]);
expect(quotaRows[0]).toContain("/project");
expect(quotaRows[0]).toContain("NORMAL ctrl+k commands");
expect(quotaRows[1]?.trim()).toBe("");
expect(quotaRows[2]?.trim()).toBe("ChatGPT quota (home)");
expect(quotaRows[3]?.trim()).toBe("5h: 90% · due");
expect(quotaRows[2]?.indexOf("ChatGPT quota (home)")).toBe(
Math.ceil((width - "ChatGPT quota (home)".length) / 2),
);
} finally {
baseline.renderer.destroy();
rendered.renderer.destroy();
}
}
} finally {
if (cleanup) await cleanup();
}
});