@evoclock/pi-agentic-driver 0.8.0 → 0.8.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/extensions/task-board.ts
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
// SPDX-FileCopyrightText: 2026 Julen Gamboa <j.a.r.gamboa@gmail.com>
|
|
2
2
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
3
3
|
|
|
4
|
-
// BOARD-1 provider extension
|
|
5
|
-
//
|
|
6
|
-
// no
|
|
4
|
+
// BOARD-1 provider extension. Both tools register at startup; the board is
|
|
5
|
+
// resolved per tool call from the calling session's working directory. A
|
|
6
|
+
// workspace with no board file gets a structured board-unavailable result —
|
|
7
|
+
// nothing is created and nothing else changes.
|
|
7
8
|
|
|
8
9
|
import { existsSync } from "node:fs";
|
|
9
10
|
import { join } from "node:path";
|
|
10
11
|
|
|
11
|
-
// Documented board locations (design §2): workspace-level Obsidian Kanban
|
|
12
|
-
// Markdown, or vogelkop's simpler TASKS.md shape.
|
|
13
12
|
const BOARD_FILENAMES = ["board.md", "TASKS.md"];
|
|
14
13
|
|
|
15
14
|
export function resolveBoardPath(cwd) {
|
|
@@ -23,9 +22,5 @@ export function resolveBoardPath(cwd) {
|
|
|
23
22
|
|
|
24
23
|
export default async function taskBoardPi(pi) {
|
|
25
24
|
const module = await import(new URL("../scripts/enforcement/task_board_core_pi.js", import.meta.url).href);
|
|
26
|
-
|
|
27
|
-
if (boardPath === null) {
|
|
28
|
-
return { registered: [], observation: { present: false, boardPath: null } };
|
|
29
|
-
}
|
|
30
|
-
return module.registerKanbanBoardTools(pi, { boardPath });
|
|
25
|
+
return module.registerKanbanBoardTools(pi, { resolveBoardPath });
|
|
31
26
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@evoclock/pi-agentic-driver",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"description": "Guardrail extensions for Agentic Driver: advisory review, bounded Herdr communication, and guarded worker lifecycle.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "AGPL-3.0-or-later",
|
|
@@ -988,11 +988,12 @@ export function observeBoardProvider({ boardPath }) {
|
|
|
988
988
|
return { present, boardPath: present ? boardPath : null };
|
|
989
989
|
}
|
|
990
990
|
|
|
991
|
-
export function registerKanbanBoardTools(pi, { boardPath } = {}) {
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
//
|
|
995
|
-
//
|
|
991
|
+
export function registerKanbanBoardTools(pi, { resolveBoardPath, boardPath } = {}) {
|
|
992
|
+
// Tools register unconditionally; the board is resolved per call from the
|
|
993
|
+
// calling session's working directory (Pi extensions have no ctx at
|
|
994
|
+
// registration time). A workspace with no board file gets a structured
|
|
995
|
+
// board-unavailable result per call, so the surface stays reversible (§5):
|
|
996
|
+
// no board, nothing happens.
|
|
996
997
|
const registered = [];
|
|
997
998
|
if (typeof pi?.registerTool === "function") {
|
|
998
999
|
pi.registerTool({
|
|
@@ -1000,25 +1001,25 @@ export function registerKanbanBoardTools(pi, { boardPath } = {}) {
|
|
|
1000
1001
|
label: "Kanban Board",
|
|
1001
1002
|
description: "Read-only view of the validated task board: lanes, flags, priorities, dependencies, and dispatchability. The board is additive and grants no authority; agents read it and act within card states.",
|
|
1002
1003
|
parameters: { type: "object", additionalProperties: false, properties: {} },
|
|
1003
|
-
async execute() {
|
|
1004
|
-
//
|
|
1005
|
-
//
|
|
1006
|
-
//
|
|
1007
|
-
|
|
1008
|
-
if (!existsSync(
|
|
1004
|
+
async execute(_toolCallId, _params, _signal, _onUpdate, ctx) {
|
|
1005
|
+
// The board is resolved per call from the calling session's working
|
|
1006
|
+
// directory. No board in this workspace: structured board-unavailable,
|
|
1007
|
+
// nothing happens.
|
|
1008
|
+
const resolvedBoardPath = (typeof resolveBoardPath === "function" ? resolveBoardPath(ctx?.cwd) : null) ?? boardPath ?? null;
|
|
1009
|
+
if (resolvedBoardPath === null || !existsSync(resolvedBoardPath)) {
|
|
1009
1010
|
const value = {
|
|
1010
1011
|
ok: false,
|
|
1011
1012
|
nonAuthorizing: true,
|
|
1012
1013
|
persisted: false,
|
|
1013
1014
|
boardUnavailable: true,
|
|
1014
1015
|
cards: [],
|
|
1015
|
-
errors: ["board
|
|
1016
|
+
errors: ["no board.md or TASKS.md in this workspace (board-unavailable)"],
|
|
1016
1017
|
};
|
|
1017
1018
|
return { content: [{ type: "text", text: JSON.stringify(value, null, 2) }], details: value };
|
|
1018
1019
|
}
|
|
1019
1020
|
let value;
|
|
1020
1021
|
try {
|
|
1021
|
-
const markdown = readFileSync(
|
|
1022
|
+
const markdown = readFileSync(resolvedBoardPath, "utf8");
|
|
1022
1023
|
const validated = validateBoard(markdown);
|
|
1023
1024
|
value = validated.ok
|
|
1024
1025
|
? { ok: true, nonAuthorizing: true, persisted: false, cards: validated.cards, errors: [] }
|
|
@@ -1075,18 +1076,18 @@ export function registerKanbanBoardTools(pi, { boardPath } = {}) {
|
|
|
1075
1076
|
},
|
|
1076
1077
|
required: ["title", "specification", "definitionOfDone", "stoppingPoint", "scopePaths", "authority"],
|
|
1077
1078
|
},
|
|
1078
|
-
async execute(_toolContext, input) {
|
|
1079
|
-
//
|
|
1080
|
-
//
|
|
1081
|
-
|
|
1082
|
-
if (!existsSync(
|
|
1079
|
+
async execute(_toolContext, input, _signal, _onUpdate, ctx) {
|
|
1080
|
+
// Resolve the board per call from the calling session's working
|
|
1081
|
+
// directory. No board here: structured board-unavailable, no write.
|
|
1082
|
+
const resolvedBoardPath = (typeof resolveBoardPath === "function" ? resolveBoardPath(ctx?.cwd) : null) ?? boardPath ?? null;
|
|
1083
|
+
if (resolvedBoardPath === null || !existsSync(resolvedBoardPath)) {
|
|
1083
1084
|
const value = {
|
|
1084
1085
|
ok: false,
|
|
1085
1086
|
persisted: false,
|
|
1086
1087
|
boardUnavailable: true,
|
|
1087
1088
|
code: "board-unavailable",
|
|
1088
|
-
reason: "board
|
|
1089
|
-
errors: ["board
|
|
1089
|
+
reason: "no board.md or TASKS.md in this workspace (board-unavailable)",
|
|
1090
|
+
errors: ["no board.md or TASKS.md in this workspace (board-unavailable)"],
|
|
1090
1091
|
};
|
|
1091
1092
|
return { content: [{ type: "text", text: JSON.stringify(value, null, 2) }], details: value };
|
|
1092
1093
|
}
|
|
@@ -1132,7 +1133,7 @@ export function registerKanbanBoardTools(pi, { boardPath } = {}) {
|
|
|
1132
1133
|
let result;
|
|
1133
1134
|
try {
|
|
1134
1135
|
result = writeCard({
|
|
1135
|
-
boardPath:
|
|
1136
|
+
boardPath: resolvedBoardPath,
|
|
1136
1137
|
input: writerInput,
|
|
1137
1138
|
authority: input?.authority,
|
|
1138
1139
|
registries: {},
|
|
@@ -1179,5 +1180,5 @@ export function registerKanbanBoardTools(pi, { boardPath } = {}) {
|
|
|
1179
1180
|
});
|
|
1180
1181
|
registered.push("agentic_kanban_board_write");
|
|
1181
1182
|
}
|
|
1182
|
-
return { registered
|
|
1183
|
+
return { registered };
|
|
1183
1184
|
}
|