Skip to content

Commit d15e89a

Browse files
ZengWen-DTclaudevincentkoc
authored
fix(workboard): hide archived cards in CLI list by default (#94562)
* fix(workboard): hide archived cards in CLI list by default The `openclaw workboard list` CLI printed soft-archived cards, while the `workboard_list` agent tool and the `/workboard list` command both hide cards with `metadata.archivedAt` set unless archives are requested. Users who archived cards still saw them in CLI output and assumed archive failed. Filter archived cards by default in the CLI list handler and add an `--include-archived` flag mirroring the tool's `includeArchived` option, so all three list surfaces share one default. Docs updated to match. Co-Authored-By: Claude Opus 4.8 <[email protected]> * fix(workboard): preserve json list archive visibility * fix(workboard): preserve json list archive visibility --------- Co-authored-by: Claude Opus 4.8 <[email protected]> Co-authored-by: Vincent Koc <[email protected]>
1 parent 2fc260a commit d15e89a

3 files changed

Lines changed: 66 additions & 13 deletions

File tree

docs/cli/workboard.md

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ openclaw gateway restart
2222
## Usage
2323

2424
```bash
25-
openclaw workboard list [--board <id>] [--status <status>] [--json]
25+
openclaw workboard list [--board <id>] [--status <status>] [--include-archived] [--json]
2626
openclaw workboard create <title...> [--notes <text>] [--status <status>] [--priority <priority>] [--agent <id>] [--board <id>] [--labels <items>] [--json]
2727
openclaw workboard show <id> [--json]
2828
openclaw workboard dispatch [--url <url>] [--token <token>] [--timeout <ms>] [--json]
@@ -50,11 +50,16 @@ Columns are id prefix, status, priority, board id, optional agent id, and title.
5050

5151
Flags:
5252

53-
| Flag | Purpose |
54-
| ------------------- | ---------------------------------------- |
55-
| `--board <id>` | Limit results to one board namespace |
56-
| `--status <status>` | Limit results to one Workboard status |
57-
| `--json` | Print the full card list as machine JSON |
53+
| Flag | Purpose |
54+
| -------------------- | --------------------------------------------- |
55+
| `--board <id>` | Limit results to one board namespace |
56+
| `--status <status>` | Limit results to one Workboard status |
57+
| `--include-archived` | Include archived cards in compact text output |
58+
| `--json` | Print the full card list as machine JSON |
59+
60+
Compact text output hides archived cards by default so the CLI matches the
61+
`/workboard list` command. Pass `--include-archived` to show them. JSON output
62+
keeps the full card list, including archived cards, for existing automation.
5863

5964
## `create`
6065

extensions/workboard/src/cli.test.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,40 @@ describe("registerWorkboardCli", () => {
106106
expect(showOutput).toContain("[redacted]");
107107
});
108108

109+
it("hides archived cards from text output by default and reveals them with --include-archived", async () => {
110+
const store = new WorkboardStore(createMemoryStore());
111+
await store.create({ title: "Active card" });
112+
const archived = await store.create({ title: "Archived card" });
113+
await store.archive(archived.id, true);
114+
const program = createProgram(store);
115+
116+
const defaultOutput = await captureStdout(async () => {
117+
await program.parseAsync(["workboard", "list"], { from: "user" });
118+
});
119+
const includeOutput = await captureStdout(async () => {
120+
await program.parseAsync(["workboard", "list", "--include-archived"], { from: "user" });
121+
});
122+
123+
expect(defaultOutput).toContain("Active card");
124+
expect(defaultOutput).not.toContain("Archived card");
125+
expect(includeOutput).toContain("Active card");
126+
expect(includeOutput).toContain("Archived card");
127+
});
128+
129+
it("preserves archived cards in JSON list output by default", async () => {
130+
const store = new WorkboardStore(createMemoryStore());
131+
const archived = await store.create({ title: "Archived card" });
132+
await store.archive(archived.id, true);
133+
const program = createProgram(store);
134+
135+
const output = await captureStdout(async () => {
136+
await program.parseAsync(["workboard", "list", "--json"], { from: "user" });
137+
});
138+
139+
expect(output).toContain(archived.id);
140+
expect(output).toContain("archivedAt");
141+
});
142+
109143
it("does not fall back to local dispatch for explicit gateway targets", async () => {
110144
const store = new WorkboardStore(createMemoryStore());
111145
const card = await store.create({ title: "Remote target", status: "ready" });

extensions/workboard/src/cli.ts

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -130,14 +130,28 @@ export function registerWorkboardCli(params: { program: Command; store: Workboar
130130
.description("List Workboard cards")
131131
.option("--board <id>", "Board id")
132132
.option("--status <status>", "Filter by status")
133+
.option("--include-archived", "Include archived cards (default false)")
133134
.option("--json", "Print JSON", false)
134-
.action(async (options: JsonOptions & { board?: string; status?: string }) => {
135-
let cards = await params.store.list({ boardId: options.board });
136-
if (options.status) {
137-
cards = cards.filter((card) => card.status === options.status);
138-
}
139-
writeCards(cards, options);
140-
});
135+
.action(
136+
async (
137+
options: JsonOptions & {
138+
board?: string;
139+
status?: string;
140+
includeArchived?: boolean;
141+
},
142+
) => {
143+
// Text output hides archived cards like /workboard list, while --json
144+
// keeps the shipped full-card contract for existing scripts.
145+
let cards = await params.store.list({ boardId: options.board });
146+
if (!options.json && options.includeArchived !== true) {
147+
cards = cards.filter((card) => !card.metadata?.archivedAt);
148+
}
149+
if (options.status) {
150+
cards = cards.filter((card) => card.status === options.status);
151+
}
152+
writeCards(cards, options);
153+
},
154+
);
141155

142156
workboard
143157
.command("create")

0 commit comments

Comments
 (0)