@danypops/papyrus 0.30.0 → 0.30.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danypops/papyrus",
3
- "version": "0.30.0",
3
+ "version": "0.30.1",
4
4
  "description": "Daemon-backed graph artifacts, evidence-bearing tasks, rules, skills, and native TUI workflows for Pi",
5
5
  "type": "module",
6
6
  "keywords": ["pi-package"],
package/src/cli.ts CHANGED
@@ -1441,7 +1441,7 @@ export async function runTaskCli(args: string[], client: TaskCliClient, projectR
1441
1441
  case "list": {
1442
1442
  if (id) throw new Error("tasks list accepts no positional arguments");
1443
1443
  const rows = await client.call<Record<string, unknown>, CliArtifact[]>("tasks.list", {
1444
- status, text, limit, project_root: projectRoot, scope: listScope, root_task_id: rootTaskId, ...sessionScope,
1444
+ status, text, limit, labels, project_root: projectRoot, scope: listScope, root_task_id: rootTaskId, ...sessionScope,
1445
1445
  });
1446
1446
  result = rows;
1447
1447
  human = rows.length === 0 ? "No tasks found." : rows.map((row) => artifactLabel(row)).join("\n");
@@ -1571,7 +1571,7 @@ export async function runTaskCli(args: string[], client: TaskCliClient, projectR
1571
1571
  const graph = await client.call<Record<string, unknown>, {
1572
1572
  nodes: Array<{ dependencyIds: string[]; childIds: string[] }>;
1573
1573
  rootIds: string[];
1574
- }>("tasks.graph", { limit: TASK_EXECUTION_MAX_NODES + 1, project_root: projectRoot, ...sessionScope });
1574
+ }>("tasks.graph", { limit: TASK_EXECUTION_MAX_NODES + 1, labels, project_root: projectRoot, scope: listScope, root_task_id: rootTaskId, ...sessionScope });
1575
1575
  result = graph;
1576
1576
  const dependencies = graph.nodes.reduce((count, node) => count + node.dependencyIds.length, 0);
1577
1577
  const children = graph.nodes.reduce((count, node) => count + node.childIds.length, 0);
@@ -74,6 +74,7 @@ const taskFilter = (input: OperationInput) => ({
74
74
  scope: optionalString(input, "scope") as TaskViewMode | undefined,
75
75
  rootTaskId: optionalString(input, "root_task_id"),
76
76
  sessionId: optionalString(input, "session_id") ?? optionalString(input, "sessionId"),
77
+ labels: optionalStringArray(input, "labels"),
77
78
  });
78
79
 
79
80
  /**
@@ -38,6 +38,8 @@ export interface TaskFilter {
38
38
  rootTaskId?: string;
39
39
  /** Requesting agent session id — scopes Task Focus reads so concurrent agents see only their own Focus. Defaults to a shared "global" scope when omitted. */
40
40
  sessionId?: string;
41
+ /** AND semantics: a task must carry every requested label, matching ArtifactStore.query's own labels filter. */
42
+ labels?: string[];
41
43
  }
42
44
 
43
45
  export type TaskStatus = TaskLifecycleStatus;
@@ -225,17 +227,19 @@ export class Tasks {
225
227
  throw new Error(`task list limit must be between 1 and ${TASK_SCOPE_MAX_TASKS + 1}`);
226
228
  }
227
229
  if (selection.mode === "all") {
228
- return this.artifacts.query({ kind: "task", excludeSubtype: DISCUSSION_SUBTYPE, status: filter.status, text: filter.text, limit });
230
+ return this.artifacts.query({ kind: "task", excludeSubtype: DISCUSSION_SUBTYPE, status: filter.status, text: filter.text, labels: filter.labels, limit });
229
231
  }
230
232
  const ids = this.scopes.taskIds(selection.projectRoot, TASK_SCOPE_MAX_TASKS + 1);
231
233
  if (ids.length > TASK_SCOPE_MAX_TASKS) throw new Error(`task project scope exceeds ${TASK_SCOPE_MAX_TASKS} tasks`);
232
234
  const selectedIds = selection.mode === "graph" ? this.descendantIds(selection.rootTaskId!, ids) : new Set(ids);
233
235
  const text = filter.text?.toLowerCase();
236
+ const labels = filter.labels ?? [];
234
237
  return [...selectedIds]
235
238
  .map((id) => this.artifacts.get(id))
236
239
  .filter((task): task is Artifact => task?.kind === "task" && !isDiscussionArtifact(task))
237
240
  .filter((task) => filter.status === undefined || task.status === filter.status)
238
241
  .filter((task) => text === undefined || task.title.toLowerCase().includes(text) || task.body.toLowerCase().includes(text))
242
+ .filter((task) => labels.every((label) => task.labels.includes(label)))
239
243
  .sort((left, right) => right.updated_at.localeCompare(left.updated_at) || left.id.localeCompare(right.id))
240
244
  .slice(0, limit);
241
245
  }