pi-herdsman 0.20.1 → 0.21.0
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/SKILL.md +12 -11
- package/dist/index.js +107 -44
- package/dist/index.js.map +3 -3
- package/docs/adr/0012-manager-owns-project-assignment-resolution.md +1 -1
- package/docs/adr/0013-use-herdr-worktree-removal-for-project-retirement.md +1 -1
- package/docs/adr/0016-consume-project-messages-after-manager-delivery.md +32 -0
- package/docs/concepts/coordination.md +8 -6
- package/docs/coordination-api.md +8 -5
- package/docs/development/instruction-interface-design.md +6 -4
- package/docs/development/smoke-testing.md +4 -3
- package/docs/guides/agent-definitions.md +5 -0
- package/docs/guides/project-orchestration.md +6 -4
- package/docs/reference/staff.md +8 -5
- package/docs/reference/supervisor.md +17 -16
- package/package.json +5 -3
- package/skills/pi-herdsman-agent-definitions/SKILL.md +60 -0
package/SKILL.md
CHANGED
|
@@ -375,10 +375,10 @@ Chief supervises independent leads and never changes ownership. Use
|
|
|
375
375
|
supervisor's attention, decision, or action, such as a blocker, warning, scope
|
|
376
376
|
change, risk, or important evidence. Ordinary Leads without a verified
|
|
377
377
|
supervisor continue independently; assigned project Leads may message the
|
|
378
|
-
Manager role while its process is unavailable
|
|
379
|
-
|
|
380
|
-
records the Lead's normal response to each project-assignment
|
|
381
|
-
project message for the
|
|
378
|
+
Manager role while its process is unavailable. Messages remain pending during
|
|
379
|
+
Manager absence and are delivered to the next Manager that can receive them. For an assigned project, Herdsman
|
|
380
|
+
automatically records the Lead's normal response to each project-assignment
|
|
381
|
+
delivery as a project message for the Manager role. If the Lead
|
|
382
382
|
successfully delegates or continues managed Agent work, the herd run owns that
|
|
383
383
|
handoff until it settles; summarize the outcome, validation, and important
|
|
384
384
|
unresolved points in the settled response. An unsuccessful delegation leaves
|
|
@@ -389,8 +389,9 @@ Descendants use `ask_owner`, not supervisor tools. Messages are coordination
|
|
|
389
389
|
data, not assignments or terminal project results.
|
|
390
390
|
|
|
391
391
|
`supervisor_message` is available to ordinary Leads and Managers. Assigned Lead
|
|
392
|
-
messages
|
|
393
|
-
Manager
|
|
392
|
+
messages remain pending while Manager is absent and are delivered to the next
|
|
393
|
+
Manager that can receive them; delivered messages are Pi conversation history,
|
|
394
|
+
not pending Herdsman coordination. Manager messages to
|
|
394
395
|
Leads use `staff_message`. For files, these tools accept ordinary paths,
|
|
395
396
|
reusable direct-agent result refs, and already-supplied canonical result refs
|
|
396
397
|
through `files`.
|
|
@@ -451,17 +452,17 @@ Pi Herdsman uses one durable vocabulary:
|
|
|
451
452
|
through implementation and review iterations;
|
|
452
453
|
- `staff_stop` stops an exact Lead and its owned Agent tree while preserving
|
|
453
454
|
the assignment, Pi session, branch, and worktree. Successful Herdr worktree
|
|
454
|
-
removal retires the matching assignment and
|
|
455
|
-
preserving the Git branch. A missing worktree alone does not retire the
|
|
455
|
+
removal retires the matching assignment and any still-pending project
|
|
456
|
+
messages while preserving the Git branch. A missing worktree alone does not retire the
|
|
456
457
|
assignment; `staff_resume` can reconstruct it. Never infer ownership from
|
|
457
458
|
worktree membership or start an overlapping writer beside another Lead;
|
|
458
459
|
- `/manager leave` preserves project work; a later Manager can resume the same
|
|
459
460
|
branch-based assignment;
|
|
460
461
|
- a **herd** is one Lead and the complete Agent tree it owns;
|
|
461
462
|
- a **Lead** owns its Agents. An assigned project Lead sends
|
|
462
|
-
`supervisor_message` to project-scoped storage
|
|
463
|
-
|
|
464
|
-
messages to Chief. An unassigned Lead routes to its active Manager when one
|
|
463
|
+
`supervisor_message` to project-scoped storage; pending messages survive
|
|
464
|
+
Manager absence and go to the next Manager that can receive them. Delivered
|
|
465
|
+
messages are not replayed; messages do not route to Chief. An unassigned Lead routes to its active Manager when one
|
|
465
466
|
exists, otherwise to Chief;
|
|
466
467
|
- an **Agent** handles one bounded assignment and may delegate only when its
|
|
467
468
|
definition allows it;
|
package/dist/index.js
CHANGED
|
@@ -15,7 +15,7 @@ import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
|
15
15
|
// package.json
|
|
16
16
|
var package_default = {
|
|
17
17
|
name: "pi-herdsman",
|
|
18
|
-
version: "0.
|
|
18
|
+
version: "0.21.0",
|
|
19
19
|
type: "module",
|
|
20
20
|
description: "Asynchronous Pi subagents and agent fleet orchestration for parallel coding agents with nested delegation, background work, and supervision in herdr.",
|
|
21
21
|
license: "Apache-2.0",
|
|
@@ -57,7 +57,8 @@ var package_default = {
|
|
|
57
57
|
"./dist/index.js"
|
|
58
58
|
],
|
|
59
59
|
skills: [
|
|
60
|
-
"."
|
|
60
|
+
"./SKILL.md",
|
|
61
|
+
"./skills"
|
|
61
62
|
],
|
|
62
63
|
image: "https://raw.githubusercontent.com/boadij/pi-herdsman/main/docs/assets/thumbnail.webp"
|
|
63
64
|
},
|
|
@@ -106,7 +107,8 @@ var package_default = {
|
|
|
106
107
|
"SKILL.md",
|
|
107
108
|
"LICENSE",
|
|
108
109
|
"docs",
|
|
109
|
-
"dist"
|
|
110
|
+
"dist",
|
|
111
|
+
"skills"
|
|
110
112
|
],
|
|
111
113
|
publishConfig: {
|
|
112
114
|
registry: "https://registry.npmjs.org/"
|
|
@@ -5455,6 +5457,11 @@ function expandedResultLines(tool, action, details, args, theme) {
|
|
|
5455
5457
|
"session",
|
|
5456
5458
|
details.session ?? details.session_id ?? details.pi_session_id ?? details.chiefSessionId
|
|
5457
5459
|
],
|
|
5460
|
+
["branch", tool === "staff" ? details.branch : void 0],
|
|
5461
|
+
[
|
|
5462
|
+
"task",
|
|
5463
|
+
tool === "staff" && action === "resume" ? details.presentation_task : void 0
|
|
5464
|
+
],
|
|
5458
5465
|
["request", details.request_id],
|
|
5459
5466
|
["assignment request", details.assignment_request_id],
|
|
5460
5467
|
["pane", details.pane_id],
|
|
@@ -5511,8 +5518,26 @@ function expandedResultLines(tool, action, details, args, theme) {
|
|
|
5511
5518
|
return lines;
|
|
5512
5519
|
}
|
|
5513
5520
|
const reports = Array.isArray(details.reports) ? details.reports : [];
|
|
5521
|
+
const work = Array.isArray(details.work) ? details.work : [];
|
|
5514
5522
|
lines.push(
|
|
5515
5523
|
"",
|
|
5524
|
+
...work.length ? [
|
|
5525
|
+
"project work:",
|
|
5526
|
+
...work.flatMap((item) => {
|
|
5527
|
+
if (!item || typeof item !== "object") return [];
|
|
5528
|
+
const branch = value(item.branch) || "unknown";
|
|
5529
|
+
const status = value(item.status) || "unknown";
|
|
5530
|
+
const runtime = value(item.runtime_state);
|
|
5531
|
+
const task = value(item.task);
|
|
5532
|
+
const issue = value(item.issue);
|
|
5533
|
+
return [
|
|
5534
|
+
` ${branch} \xB7 ${status}${runtime ? ` \xB7 runtime=${runtime}` : ""}`,
|
|
5535
|
+
...task ? [` task: ${task}`] : [],
|
|
5536
|
+
...issue ? [` issue: ${issue}`] : []
|
|
5537
|
+
];
|
|
5538
|
+
}),
|
|
5539
|
+
""
|
|
5540
|
+
] : [],
|
|
5516
5541
|
...reports.flatMap((lead) => {
|
|
5517
5542
|
if (!lead || typeof lead !== "object") return [];
|
|
5518
5543
|
const counts = lead.agent_counts && typeof lead.agent_counts === "object" ? lead.agent_counts : {};
|
|
@@ -5526,13 +5551,10 @@ function expandedResultLines(tool, action, details, args, theme) {
|
|
|
5526
5551
|
` agent counts: ${Object.entries(counts).filter(([, count]) => count !== void 0).map(([name, count]) => `${name}=${String(count)}`).join(" \xB7 ")}`
|
|
5527
5552
|
] : [],
|
|
5528
5553
|
...Array.isArray(lead.available_tools) ? [
|
|
5529
|
-
` can: ${lead.available_tools.map((tool2) => String(tool2).replace(/^staff_/, "")).join(", ")}`
|
|
5554
|
+
` can: ${lead.available_tools.map((tool2) => String(tool2).replace(/^staff_/, "")).join(", ") || "nothing"}`
|
|
5530
5555
|
] : []
|
|
5531
5556
|
];
|
|
5532
|
-
})
|
|
5533
|
-
...Array.isArray(details.assignments) ? details.assignments.map(
|
|
5534
|
-
(assignment) => `assignment: ${value(assignment?.id)} \xB7 ${value(assignment?.phase)}${value(assignment?.branch) ? ` \xB7 branch: ${value(assignment.branch)}` : ""}${value(assignment?.workspace_id) ? ` \xB7 workspace: ${value(assignment.workspace_id)}` : ""}${value(assignment?.pane_id) ? ` \xB7 pane: ${value(assignment.pane_id)}` : ""}${value(assignment?.session) ? ` \xB7 session: ${value(assignment.session)}` : ""}`
|
|
5535
|
-
) : []
|
|
5557
|
+
})
|
|
5536
5558
|
);
|
|
5537
5559
|
}
|
|
5538
5560
|
if (action === "inspect")
|
|
@@ -6780,6 +6802,8 @@ async function drainCoordinationInbox(options) {
|
|
|
6780
6802
|
}
|
|
6781
6803
|
continue;
|
|
6782
6804
|
}
|
|
6805
|
+
const deliverAs = options.deliveryMode ? options.deliveryMode(record) : "followUp";
|
|
6806
|
+
if (!deliverAs) continue;
|
|
6783
6807
|
let token;
|
|
6784
6808
|
const clearTransaction = async () => {
|
|
6785
6809
|
if (token === void 0) return;
|
|
@@ -6856,7 +6880,7 @@ async function drainCoordinationInbox(options) {
|
|
|
6856
6880
|
...record.branch ? { branch: record.branch } : {}
|
|
6857
6881
|
}
|
|
6858
6882
|
},
|
|
6859
|
-
{ deliverAs
|
|
6883
|
+
{ deliverAs, triggerTurn: true },
|
|
6860
6884
|
record
|
|
6861
6885
|
);
|
|
6862
6886
|
await options.transaction?.revalidate(token, "after-send");
|
|
@@ -7594,6 +7618,16 @@ function listProjectMessages(runtime, repoKey, branch) {
|
|
|
7594
7618
|
}
|
|
7595
7619
|
}).sort((a, b) => a.createdAt - b.createdAt || a.id.localeCompare(b.id));
|
|
7596
7620
|
}
|
|
7621
|
+
function removeProjectMessage(runtime, repoKey, branch, id) {
|
|
7622
|
+
if (!UUID3.test(id)) throw new Error("Invalid project message ID");
|
|
7623
|
+
const directory = projectMessageDirectory(runtime, repoKey, branch);
|
|
7624
|
+
try {
|
|
7625
|
+
unlinkSync6(join8(directory, `${id}.json`));
|
|
7626
|
+
fsyncDirectory(directory);
|
|
7627
|
+
} catch (error2) {
|
|
7628
|
+
if (error2.code !== "ENOENT") throw error2;
|
|
7629
|
+
}
|
|
7630
|
+
}
|
|
7597
7631
|
function removeProjectMessages(runtime, repoKey, branch) {
|
|
7598
7632
|
rmSync(projectMessageDirectory(runtime, repoKey, branch), {
|
|
7599
7633
|
recursive: true,
|
|
@@ -7682,6 +7716,12 @@ guidance: continue independently; do not use supervisor_message until a supervis
|
|
|
7682
7716
|
function supervisorStateMessage(customType, content, latestContent) {
|
|
7683
7717
|
return latestContent === content ? void 0 : { customType, content, display: false };
|
|
7684
7718
|
}
|
|
7719
|
+
function projectTaskSummary(text) {
|
|
7720
|
+
const task = text.replace(/[\u0000-\u001f\u007f]/g, " ").replace(/\s+/gu, " ").trim();
|
|
7721
|
+
if (!task) return void 0;
|
|
7722
|
+
const characters = Array.from(task);
|
|
7723
|
+
return characters.length <= 160 ? task : `${characters.slice(0, 159).join("")}\u2026`;
|
|
7724
|
+
}
|
|
7685
7725
|
function projectWorkSnapshot(options) {
|
|
7686
7726
|
return options.assignments.map((assignment) => {
|
|
7687
7727
|
const worktrees = options.worktrees.filter(
|
|
@@ -7710,16 +7750,13 @@ function projectWorkSnapshot(options) {
|
|
|
7710
7750
|
status = "paused";
|
|
7711
7751
|
}
|
|
7712
7752
|
}
|
|
7713
|
-
const task = assignment.text
|
|
7714
|
-
const characters = Array.from(task);
|
|
7753
|
+
const task = projectTaskSummary(assignment.text);
|
|
7715
7754
|
return {
|
|
7716
7755
|
branch: assignment.branch,
|
|
7717
7756
|
session: assignment.id,
|
|
7718
7757
|
status,
|
|
7719
7758
|
...runtimeState ? { runtimeState } : {},
|
|
7720
|
-
...task ? {
|
|
7721
|
-
task: characters.length <= 160 ? task : `${characters.slice(0, 159).join("")}\u2026`
|
|
7722
|
-
} : {},
|
|
7759
|
+
...task ? { task } : {},
|
|
7723
7760
|
...issue ? { issue } : {}
|
|
7724
7761
|
};
|
|
7725
7762
|
});
|
|
@@ -17803,6 +17840,7 @@ function createLeadProjectRuntime(host) {
|
|
|
17803
17840
|
throw new Error(
|
|
17804
17841
|
`No existing work was found on ${operation.branch}; start it with staff_delegate and a task.`
|
|
17805
17842
|
);
|
|
17843
|
+
const presentationTask = operation.action === "resume" ? projectTaskSummary(existing.text) : void 0;
|
|
17806
17844
|
const id = operation.action === "resume" ? existing.id : operation.id;
|
|
17807
17845
|
const branch = operation.branch;
|
|
17808
17846
|
const topology = await runHerdr2(
|
|
@@ -17870,7 +17908,8 @@ function createLeadProjectRuntime(host) {
|
|
|
17870
17908
|
branch,
|
|
17871
17909
|
session: id,
|
|
17872
17910
|
status: "active",
|
|
17873
|
-
already_running: true
|
|
17911
|
+
already_running: true,
|
|
17912
|
+
...presentationTask ? { presentation_task: presentationTask } : {}
|
|
17874
17913
|
}
|
|
17875
17914
|
};
|
|
17876
17915
|
}
|
|
@@ -18320,7 +18359,8 @@ function createLeadProjectRuntime(host) {
|
|
|
18320
18359
|
session: leadSessionId,
|
|
18321
18360
|
workspace_id: workspaceId,
|
|
18322
18361
|
branch: assignment.branch,
|
|
18323
|
-
...operation.action === "resume" ? { recovered: true } : {}
|
|
18362
|
+
...operation.action === "resume" ? { recovered: true } : {},
|
|
18363
|
+
...presentationTask ? { presentation_task: presentationTask } : {}
|
|
18324
18364
|
}
|
|
18325
18365
|
};
|
|
18326
18366
|
} catch (error2) {
|
|
@@ -18404,7 +18444,9 @@ function createLeadProjectRuntime(host) {
|
|
|
18404
18444
|
lead_counts: "leadCounts" in report ? report.leadCounts : void 0,
|
|
18405
18445
|
leads: "leads" in report ? report.leads : []
|
|
18406
18446
|
} : {},
|
|
18407
|
-
|
|
18447
|
+
available_tools: report.availableActions.map(
|
|
18448
|
+
(action) => `staff_${action}`
|
|
18449
|
+
)
|
|
18408
18450
|
}))
|
|
18409
18451
|
});
|
|
18410
18452
|
}
|
|
@@ -18645,9 +18687,11 @@ function createLeadCoordinationRuntime(host) {
|
|
|
18645
18687
|
quarantineChiefMessage: quarantineChiefMessage2,
|
|
18646
18688
|
listProjectAssignments: listProjectAssignments2,
|
|
18647
18689
|
listProjectMessages: listProjectMessages2,
|
|
18690
|
+
removeProjectMessage: removeProjectMessage2,
|
|
18648
18691
|
readProjectAssignment: readProjectAssignment2,
|
|
18649
18692
|
importResultBindings: importResultBindings2
|
|
18650
18693
|
} = host;
|
|
18694
|
+
const reportedProjectMessageCleanupErrors = /* @__PURE__ */ new Set();
|
|
18651
18695
|
const readLeadSessionIdsFromHost = (inventory, mailboxes, workspaceId) => readLeadSessionIds(inventory, mailboxes, workspaceId, host);
|
|
18652
18696
|
const prepareCoordinationInput = async (ctx, text, files, operation, heading, recordForInput) => {
|
|
18653
18697
|
const limits = await host.messageLimits(ctx);
|
|
@@ -19224,33 +19268,46 @@ function createLeadCoordinationRuntime(host) {
|
|
|
19224
19268
|
const drainProjectMessages = async (ctx) => {
|
|
19225
19269
|
if (activeRole() !== "manager" || leadRuntime.roleSuspended || !ctx.isIdle())
|
|
19226
19270
|
return 0;
|
|
19271
|
+
const runtime = supervisionRuntime2();
|
|
19227
19272
|
const manager = await currentManager(ctx);
|
|
19228
19273
|
if (!manager || !leadRuntime.managerLease || !sameManagerDescriptor2(manager, leadRuntime.managerLease.descriptor))
|
|
19229
19274
|
return 0;
|
|
19230
|
-
|
|
19231
|
-
|
|
19232
|
-
|
|
19233
|
-
)
|
|
19275
|
+
const hasProjectMessageReceipt = (record) => ctx.sessionManager.getEntries().some(
|
|
19276
|
+
(entry) => entry?.customType === "pi-herdsman-project_message" && entry?.details?.id === record.id && entry?.details?.repoKey === record.repoKey && entry?.details?.branch === record.branch && entry?.details?.fromSessionId === record.fromSessionId
|
|
19277
|
+
);
|
|
19278
|
+
const consumeProjectMessage = (record) => {
|
|
19279
|
+
try {
|
|
19280
|
+
removeProjectMessage2(runtime, record.repoKey, record.branch, record.id);
|
|
19281
|
+
reportedProjectMessageCleanupErrors.delete(record.id);
|
|
19282
|
+
} catch (error2) {
|
|
19283
|
+
if (!reportedProjectMessageCleanupErrors.has(record.id)) {
|
|
19284
|
+
reportedProjectMessageCleanupErrors.add(record.id);
|
|
19285
|
+
appendDurableError2(pi, ctx, "pi_herdsman_state_error", error2);
|
|
19286
|
+
}
|
|
19287
|
+
}
|
|
19288
|
+
};
|
|
19289
|
+
for (const assignment of listProjectAssignments2(runtime, manager.repoKey)) {
|
|
19234
19290
|
for (const record of listProjectMessages2(
|
|
19235
|
-
|
|
19291
|
+
runtime,
|
|
19236
19292
|
manager.repoKey,
|
|
19237
19293
|
assignment.branch
|
|
19238
19294
|
)) {
|
|
19239
19295
|
if (record.fromSessionId !== assignment.id) continue;
|
|
19240
|
-
|
|
19241
|
-
(
|
|
19242
|
-
|
|
19243
|
-
|
|
19296
|
+
if (hasProjectMessageReceipt(record)) {
|
|
19297
|
+
consumeProjectMessage(record);
|
|
19298
|
+
continue;
|
|
19299
|
+
}
|
|
19244
19300
|
const current = await currentManager(ctx);
|
|
19245
19301
|
const stillAssigned = readProjectAssignment2(
|
|
19246
|
-
|
|
19302
|
+
runtime,
|
|
19247
19303
|
manager.repoKey,
|
|
19248
19304
|
assignment.branch
|
|
19249
19305
|
);
|
|
19250
19306
|
if (!ctx.isIdle() || !current || !sameManagerDescriptor2(current, manager) || !stillAssigned || stillAssigned.id !== assignment.id)
|
|
19251
19307
|
return 0;
|
|
19252
19308
|
importResultBindings2(pi, ctx, record.resultBindings, "project_message");
|
|
19253
|
-
|
|
19309
|
+
const backlog = record.createdAt < manager.createdAt;
|
|
19310
|
+
pi.sendMessage(
|
|
19254
19311
|
{
|
|
19255
19312
|
customType: "pi-herdsman-project_message",
|
|
19256
19313
|
content: `Project ${record.branch} from lead ${record.fromSessionId}:
|
|
@@ -19264,8 +19321,9 @@ ${record.text}`,
|
|
|
19264
19321
|
fromSessionId: record.fromSessionId
|
|
19265
19322
|
}
|
|
19266
19323
|
},
|
|
19267
|
-
{ deliverAs: "followUp", triggerTurn: true }
|
|
19324
|
+
backlog ? { triggerTurn: false } : { deliverAs: "followUp", triggerTurn: true }
|
|
19268
19325
|
);
|
|
19326
|
+
if (hasProjectMessageReceipt(record)) consumeProjectMessage(record);
|
|
19269
19327
|
return 1;
|
|
19270
19328
|
}
|
|
19271
19329
|
}
|
|
@@ -19306,16 +19364,17 @@ function projectAssignmentInstruction(assignment) {
|
|
|
19306
19364
|
|
|
19307
19365
|
Manager supervises project scope and assignment boundaries; you own technical
|
|
19308
19366
|
decisions and orchestration of execution. Herdsman automatically hands your
|
|
19309
|
-
normal assignment response to the
|
|
19310
|
-
|
|
19311
|
-
|
|
19312
|
-
|
|
19367
|
+
normal assignment response to the Manager role. If no Manager is available,
|
|
19368
|
+
the handoff remains pending until a Manager can receive it. After successfully
|
|
19369
|
+
delegating or continuing managed Agent work, the herd run owns that handoff
|
|
19370
|
+
until it settles; summarize outcome, validation, and important unresolved
|
|
19371
|
+
points in your response. If delegation is unsuccessful, respond
|
|
19313
19372
|
locally. Later conversational replies stay local.
|
|
19314
19373
|
|
|
19315
19374
|
Use supervisor_message only for material coordination requiring Manager
|
|
19316
19375
|
attention, a decision, or action\u2014not routine status or a duplicate handoff.
|
|
19317
|
-
|
|
19318
|
-
nonterminal; do not infer project closure from runtime state.`;
|
|
19376
|
+
Undelivered project handoffs survive Manager absence. Once delivered, they
|
|
19377
|
+
are not automatically replayed to later Managers. Settlement is nonterminal; do not infer project closure from runtime state.`;
|
|
19319
19378
|
}
|
|
19320
19379
|
function createLeadInboxRuntime(host) {
|
|
19321
19380
|
let chiefInboxTimer;
|
|
@@ -19548,6 +19607,12 @@ function createLeadInboxRuntime(host) {
|
|
|
19548
19607
|
managerDiagnostic("inbox_catch", { category: "cleanup" });
|
|
19549
19608
|
appendDurableError2(pi, ctx, "pi_herdsman_state_error", error2);
|
|
19550
19609
|
},
|
|
19610
|
+
deliveryMode: (record) => {
|
|
19611
|
+
const role2 = activeRole();
|
|
19612
|
+
const supervisorDownlink = role2 === "lead" && (record.kind === "chief_message" || record.kind === "manager_message") || role2 === "manager" && record.kind === "chief_message";
|
|
19613
|
+
if (supervisorDownlink) return "steer";
|
|
19614
|
+
return ctx.isIdle() ? "followUp" : void 0;
|
|
19615
|
+
},
|
|
19551
19616
|
isDelivered: (id) => {
|
|
19552
19617
|
const record = transactions.get(id)?.record;
|
|
19553
19618
|
return record ? messageDelivered(ctx, record) : false;
|
|
@@ -19582,10 +19647,6 @@ function createLeadInboxRuntime(host) {
|
|
|
19582
19647
|
sendMessage: async (message, options, record) => {
|
|
19583
19648
|
const projectAssignment = typeof message === "object" && message !== null && "customType" in message && message.customType === "pi-herdsman-project_assignment";
|
|
19584
19649
|
try {
|
|
19585
|
-
if (!ctx.isIdle())
|
|
19586
|
-
throw new Error(
|
|
19587
|
-
"Coordination delivery deferred while recipient is active"
|
|
19588
|
-
);
|
|
19589
19650
|
let payload = message;
|
|
19590
19651
|
let resultBindings = record.resultBindings;
|
|
19591
19652
|
if (record.kind === "project_assignment") {
|
|
@@ -19713,7 +19774,6 @@ function createLeadInboxRuntime(host) {
|
|
|
19713
19774
|
});
|
|
19714
19775
|
return count;
|
|
19715
19776
|
};
|
|
19716
|
-
if (!ctx.isIdle()) return complete(0);
|
|
19717
19777
|
const held = chiefStartPreflightHeld(ctx);
|
|
19718
19778
|
managerDiagnostic("inbox_preflight", { reason: held ? "held" : "pass" });
|
|
19719
19779
|
if (held) return complete(0);
|
|
@@ -20970,14 +21030,16 @@ Lead while preserving its assignment. Project retirement is user-controlled
|
|
|
20970
21030
|
through successful Herdr worktree removal.
|
|
20971
21031
|
|
|
20972
21032
|
Each project-assignment delivery to a Lead is an automatic handoff to you:
|
|
20973
|
-
Herdsman
|
|
20974
|
-
|
|
21033
|
+
Herdsman automatically hands the Lead's normal assignment response to the
|
|
21034
|
+
Manager role. If no Manager is available, the handoff remains pending until a Manager
|
|
21035
|
+
can receive it. If the Lead successfully delegates or
|
|
20975
21036
|
continues managed Agent work, the herd run owns that handoff until it settles,
|
|
20976
21037
|
and the Lead's settled response should summarize the outcome, validation, and
|
|
20977
21038
|
important unresolved points. An unsuccessful delegation leaves the local
|
|
20978
21039
|
assignment-response path available. Later conversational replies, including
|
|
20979
21040
|
routine thanks or acknowledgments, remain local and are not automatically
|
|
20980
|
-
promoted.
|
|
21041
|
+
promoted. Undelivered project handoffs survive Manager absence. Once a handoff
|
|
21042
|
+
has been delivered, it is not automatically replayed to later Managers. Review
|
|
20981
21043
|
received handoffs and request corrections with staff_message when needed.
|
|
20982
21044
|
|
|
20983
21045
|
Project execution belongs to project Leads and their Agent trees. Your role
|
|
@@ -22181,7 +22243,7 @@ ${summary}`,
|
|
|
22181
22243
|
...staffTool,
|
|
22182
22244
|
name: "staff_message",
|
|
22183
22245
|
label: "staff message",
|
|
22184
|
-
description: "Send a durable
|
|
22246
|
+
description: "Send a durable supervisor message to a direct report; active work is steered cooperatively.",
|
|
22185
22247
|
parameters: staffMessageParameters,
|
|
22186
22248
|
promptSnippet: void 0,
|
|
22187
22249
|
promptGuidelines: [FILE_HANDOFF_GUIDANCE],
|
|
@@ -22370,6 +22432,7 @@ ${summary}`,
|
|
|
22370
22432
|
writeChiefMessage,
|
|
22371
22433
|
listProjectAssignments,
|
|
22372
22434
|
listProjectMessages,
|
|
22435
|
+
removeProjectMessage,
|
|
22373
22436
|
readProjectAssignment,
|
|
22374
22437
|
importResultBindings
|
|
22375
22438
|
},
|