Skip to content

Commit bc631e6

Browse files
committed
fix: unify harness plan readiness display
1 parent 98f0027 commit bc631e6

14 files changed

Lines changed: 107 additions & 19 deletions

File tree

package-lock.json

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/agent-harness-tools/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export { discoverWorkflowDocs, resolveWorkflowPath, type DiscoverDocsOptions } from "./paths.js";
22
export { archivePlan, discoverPlans, openPlanList, parsePlanReadiness } from "./plans.js";
3+
export { comparePlanReadiness, formatPlanReadinessLabel } from "./plan-readiness.js";
34
export type {
45
ArchivePlanOptions,
56
DiscoverPlansOptions,
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { describe, expect, it } from "vitest";
2+
import { comparePlanReadiness, formatPlanReadinessLabel } from "./plan-readiness.js";
3+
4+
describe("plan readiness presentation", () => {
5+
it("adds the plan-viewer checkmark only to ready plans", () => {
6+
expect(formatPlanReadinessLabel("docs/plans/ready.md", "ready")).toBe(
7+
"docs/plans/ready.md ✓"
8+
);
9+
expect(formatPlanReadinessLabel("docs/plans/draft.md", "draft")).toBe(
10+
"docs/plans/draft.md"
11+
);
12+
});
13+
14+
it("sorts ready plans ahead of drafts", () => {
15+
expect(comparePlanReadiness({ readiness: "ready" }, { readiness: "draft" })).toBeLessThan(0);
16+
expect(comparePlanReadiness({ readiness: "draft" }, { readiness: "ready" })).toBeGreaterThan(0);
17+
expect(comparePlanReadiness({ readiness: "ready" }, { readiness: "ready" })).toBe(0);
18+
});
19+
});
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import type { PlanReadiness } from "./plans.js";
2+
3+
export function formatPlanReadinessLabel(label: string, readiness: PlanReadiness): string {
4+
return `${label}${readiness === "ready" ? " ✓" : ""}`;
5+
}
6+
7+
export function comparePlanReadiness(
8+
left: { readiness: PlanReadiness },
9+
right: { readiness: PlanReadiness }
10+
): number {
11+
return Number(right.readiness === "ready") - Number(left.readiness === "ready");
12+
}

packages/agent-harness-tools/src/plans.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import path from "node:path";
33
import { openTaskList, type TaskList, type TaskListFs } from "@poe-code/task-list";
44
import { hasOwnErrorCode } from "./error-codes.js";
55
import { resolveWorkflowPath } from "./paths.js";
6+
import { comparePlanReadiness } from "./plan-readiness.js";
67

78
const PLAN_LIST_NAME = "plans";
89
const MARKDOWN_EXTENSION = ".md";
@@ -171,7 +172,7 @@ export async function discoverPlans(options: DiscoverPlansOptions): Promise<Plan
171172
...plan,
172173
displayPath: displayPlanPath(plan.absolutePath, options.cwd, options.homeDir)
173174
}))
174-
.sort((left, right) => Number(right.readiness === "ready") - Number(left.readiness === "ready"));
175+
.sort(comparePlanReadiness);
175176
}
176177

177178
export const archivePlan = async (options: ArchivePlanOptions): Promise<void> => {

packages/experiment-loop/src/discovery/discovery.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as fsPromises from "node:fs/promises";
2-
import { discoverPlans } from "@poe-code/agent-harness-tools";
2+
import { discoverPlans, formatPlanReadinessLabel } from "@poe-code/agent-harness-tools";
33

44
type DiscoveryFileStat = {
55
isFile(): boolean;
@@ -37,6 +37,6 @@ export const discoverExperimentDocs = async (
3737

3838
return plans.map((plan) => ({
3939
path: plan.displayPath,
40-
displayPath: `${plan.displayPath}${plan.readiness === "ready" ? " ✓" : ""}`
40+
displayPath: formatPlanReadinessLabel(plan.displayPath, plan.readiness)
4141
}));
4242
};

packages/pipeline/src/plan/discovery.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import path from "node:path";
22
import * as fsPromises from "node:fs/promises";
3-
import { discoverPlans } from "@poe-code/agent-harness-tools";
3+
import {
4+
comparePlanReadiness,
5+
discoverPlans,
6+
formatPlanReadinessLabel
7+
} from "@poe-code/agent-harness-tools";
48
import { UserError } from "@poe-code/user-error";
59
import { parsePlan } from "./parser.js";
610
import type { PipelineFileStat, PipelineFileSystem } from "../types.js";
@@ -92,7 +96,13 @@ async function listPlanCandidates(
9296
return countCompletedTasks(plan.displayPath, content, plan.readiness === "ready");
9397
})
9498
);
95-
candidates.sort((left, right) => Number(right.ready) - Number(left.ready) || left.path.localeCompare(right.path));
99+
candidates.sort(
100+
(left, right) =>
101+
comparePlanReadiness(
102+
{ readiness: left.ready ? "ready" : "draft" },
103+
{ readiness: right.ready ? "ready" : "draft" }
104+
) || left.path.localeCompare(right.path)
105+
);
96106
return candidates;
97107
}
98108

@@ -209,7 +219,10 @@ export async function resolvePlanPaths(options: {
209219
return options.selectPlans({
210220
message: "Select pipeline plans to run",
211221
options: candidates.map((candidate) => ({
212-
label: `${candidate.path}${candidate.ready ? " ✓" : ""} (${candidate.done}/${candidate.total})`,
222+
label: `${formatPlanReadinessLabel(
223+
candidate.path,
224+
candidate.ready ? "ready" : "draft"
225+
)} (${candidate.done}/${candidate.total})`,
213226
value: candidate.path
214227
})),
215228
required: true
@@ -221,7 +234,10 @@ export async function resolvePlanPaths(options: {
221234
const selectedPlan = await options.selectPlan({
222235
message: "Select a pipeline plan to run",
223236
options: candidates.map((candidate) => ({
224-
label: `${candidate.path}${candidate.ready ? " ✓" : ""} (${candidate.done}/${candidate.total})`,
237+
label: `${formatPlanReadinessLabel(
238+
candidate.path,
239+
candidate.ready ? "ready" : "draft"
240+
)} (${candidate.done}/${candidate.total})`,
225241
value: candidate.path
226242
}))
227243
});

packages/plan-browser/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"dist"
1919
],
2020
"dependencies": {
21+
"@poe-code/agent-harness-tools": "*",
2122
"toolcraft-design": "*",
2223
"@poe-code/experiment-loop": "*",
2324
"@poe-code/pipeline": "*",

packages/plan-browser/src/discovery.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import path from "node:path";
22
import * as fsPromises from "node:fs/promises";
33
import { parsePlan } from "@poe-code/pipeline";
4+
import { comparePlanReadiness } from "@poe-code/agent-harness-tools";
45
import {
56
planConfigScope,
67
readMergedDocumentReadonly,
@@ -315,7 +316,7 @@ export async function discoverAllPlans(options: {
315316
if (leftSaved !== rightSaved) {
316317
return leftSaved - rightSaved;
317318
}
318-
const readinessOrder = Number(right.readiness === "ready") - Number(left.readiness === "ready");
319+
const readinessOrder = comparePlanReadiness(left, right);
319320
if (readinessOrder !== 0) return readinessOrder;
320321
if (right.updatedAt !== left.updatedAt) {
321322
return right.updatedAt - left.updatedAt;

packages/plan-browser/src/explorer-config.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import path from "node:path";
2+
import { formatPlanReadinessLabel } from "@poe-code/agent-harness-tools";
23
import type { Action, ExplorerConfig, Row } from "toolcraft-design";
34
import { normalizeExplorerConfig } from "toolcraft-design";
45
import {
@@ -221,7 +222,7 @@ function toRows(plans: PlanEntry[]): Row[] {
221222
const rowIds = createRowIds(plans);
222223
return plans.map((entry, index) => ({
223224
id: rowIds[index]!,
224-
title: `${path.basename(entry.path)}${entry.readiness === "ready" ? " ✓" : ""}`,
225+
title: formatPlanReadinessLabel(path.basename(entry.path), entry.readiness),
225226
subtitle: formatSubtitle(entry),
226227
badge: { text: entry.typeLabel },
227228
group: isSavedForLaterEntry(entry) ? "Saved for later" : "Active"

0 commit comments

Comments
 (0)