@wrongstack/core 0.308.0 → 0.308.2
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/dist/coordination/agents/index.js +4 -4
- package/dist/coordination/index.d.ts +1 -0
- package/dist/coordination/index.js +113 -15
- package/dist/coordination/task-boundary.d.ts +64 -0
- package/dist/core/index.js +1 -1
- package/dist/defaults/index.js +116 -19
- package/dist/execution/index.js +11 -8
- package/dist/index.d.ts +1 -1
- package/dist/index.js +127 -20
- package/dist/infrastructure/index.js +1 -1
- package/dist/storage/index.js +2 -1
- package/dist/tools/index.js +4 -4
- package/dist/types/config/ui.d.ts +1 -1
- package/dist/types/context-window.d.ts +18 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.js +11 -4
- package/dist/types/runtime-capability-manifest.d.ts +1 -1
- package/instructions/agents/backend.md +3 -0
- package/instructions/agents/bug-hunter.md +3 -0
- package/instructions/agents/code-reviewer.md +1 -0
- package/instructions/agents/frontend.md +2 -0
- package/instructions/agents/test.md +2 -0
- package/instructions/coordination/director-preamble.md +9 -1
- package/instructions/coordination/subagent-baseline.md +4 -0
- package/instructions/modes/code-reviewer.md +1 -1
- package/instructions/modes/debugger.md +2 -2
- package/instructions/modes/refactorer.md +2 -2
- package/instructions/modes/tester.md +2 -2
- package/instructions/system-lite.md +37 -33
- package/instructions/system-pro.md +23 -7
- package/instructions/system.md +33 -11
- package/package.json +6 -4
- package/skills/api-design/SKILL.md +26 -1
- package/skills/audit-log/SKILL.md +22 -1
- package/skills/auto-review/SKILL.md +21 -1
- package/skills/bug-hunter/SKILL.md +8 -0
- package/skills/chimera/SKILL.md +9 -0
- package/skills/data-governance/SKILL.md +25 -1
- package/skills/design-system/SKILL.md +19 -1
- package/skills/docker-deploy/SKILL.md +26 -1
- package/skills/git-flow/SKILL.md +26 -1
- package/skills/mailbox-bridge/SKILL.md +25 -1
- package/skills/mnemosyne/SKILL.md +25 -2
- package/skills/multi-agent/SKILL.md +12 -0
- package/skills/node-modern/SKILL.md +28 -1
- package/skills/observability/SKILL.md +25 -1
- package/skills/output-standards/SKILL.md +28 -1
- package/skills/plugin-author/SKILL.md +31 -1
- package/skills/prompt-engineering/SKILL.md +27 -1
- package/skills/react-modern/SKILL.md +29 -1
- package/skills/refactor-planner/SKILL.md +10 -0
- package/skills/research-web/SKILL.md +28 -1
- package/skills/sdd/SKILL.md +18 -0
- package/skills/security-scanner/SKILL.md +25 -1
- package/skills/skill-creator/SKILL.md +25 -1
- package/skills/tech-stack/SKILL.md +25 -1
- package/skills/testing/SKILL.md +25 -1
- package/skills/typescript-strict/SKILL.md +30 -1
- package/skills/wrongstack-kanban/SKILL.md +24 -0
- package/skills/wrongstack-mailbox/SKILL.md +29 -1
- package/skills/wrongstack-mailbox-mcp/SKILL.md +30 -3
|
@@ -1378,7 +1378,7 @@ var RUNTIME_CAPABILITY_MANIFEST = [
|
|
|
1378
1378
|
id: "execution.shell",
|
|
1379
1379
|
pack: "development",
|
|
1380
1380
|
exposure: "direct",
|
|
1381
|
-
tools: ["bash", "exec", "language", "language_info", "language_package"]
|
|
1381
|
+
tools: ["bash", "exec", "pwsh", "language", "language_info", "language_package"]
|
|
1382
1382
|
},
|
|
1383
1383
|
{
|
|
1384
1384
|
id: "verification.run",
|
|
@@ -3337,7 +3337,7 @@ ${identity}`);
|
|
|
3337
3337
|
splitLearnedEntries(rawLearned)
|
|
3338
3338
|
);
|
|
3339
3339
|
const rawBytes = Buffer.byteLength(rawLearned, "utf8");
|
|
3340
|
-
const freshEntries = meta === void 0 ? [] : rawEntries.filter((entry) => entry.capturedAt
|
|
3340
|
+
const freshEntries = meta === void 0 ? [] : rawEntries.filter((entry) => entry.capturedAt >= meta.consolidatedAt);
|
|
3341
3341
|
const stale = meta === void 0 || freshEntries.length > 0 || rawEntries.length > meta.sourceEntryCount || rawBytes > meta.sourceBytes;
|
|
3342
3342
|
if (!stale) {
|
|
3343
3343
|
learnedContent = consolidated;
|
|
@@ -4934,7 +4934,7 @@ var VERIFY_AGENTS = [
|
|
|
4934
4934
|
id: "bug-hunter",
|
|
4935
4935
|
name: "Bug Hunter",
|
|
4936
4936
|
role: "bug-hunter",
|
|
4937
|
-
tools: [...TOOLS.inspect],
|
|
4937
|
+
tools: [...TOOLS.inspect, "dead-code-scan"],
|
|
4938
4938
|
prompt: agentPrompt("bug-hunter")
|
|
4939
4939
|
},
|
|
4940
4940
|
budget: HEAVY_BUDGET,
|
|
@@ -5024,7 +5024,7 @@ var REVIEW_AGENTS = [
|
|
|
5024
5024
|
id: "code-reviewer",
|
|
5025
5025
|
name: "Code Reviewer",
|
|
5026
5026
|
role: "code-reviewer",
|
|
5027
|
-
tools: [...TOOLS.inspect, "git"],
|
|
5027
|
+
tools: [...TOOLS.inspect, "git", "codebase-impact-analysis", "codebase-invariant-check"],
|
|
5028
5028
|
prompt: agentPrompt("code-reviewer")
|
|
5029
5029
|
},
|
|
5030
5030
|
budget: MEDIUM_BUDGET,
|
|
@@ -69,6 +69,7 @@ TIMEOUT_PREEMPT_FRACTION, } from './subagent-budget.js';
|
|
|
69
69
|
export { assignNickname } from './subagent-nicknames.js';
|
|
70
70
|
export { formatSubagentStructuredReport, MAX_SUBAGENT_STRUCTURED_REPORT_CHARS, makeSubagentResultTool, normalizeSubagentStructuredReport, readSubagentStructuredReport, SUBAGENT_STRUCTURED_REPORT_META_KEY, } from './subagent-result-tool.js';
|
|
71
71
|
export { startTechStackConsumer, type TechStackConsumerOptions, } from './techstack-mailbox-consumer.js';
|
|
72
|
+
export { composeBoundedTaskDescription, type TaskBoundary, parseTaskBoundary, renderTaskBoundaryBlock, taskBoundarySchemaProperties, } from './task-boundary.js';
|
|
72
73
|
export { type FleetWorktreePolicy, resolveSubagentWorktreeDecision, subagentNeedsWorktree, WorktreeIntegrationError, type WorktreeIsolationDecision, type WorktreeTaskRunnerOptions, type WorktreeTaskStateUpdate, wrapSubagentRunnerWithWorktrees, } from './worktree-task-runner.js';
|
|
73
74
|
export { collabInjectMiddleware, collabPauseMiddleware, } from '../middleware/collab-pause.js';
|
|
74
75
|
export { AdaptiveConcurrencyController, type AdaptiveConcurrencyState, } from './adaptive-concurrency.js';
|
|
@@ -2643,7 +2643,7 @@ var RUNTIME_CAPABILITY_MANIFEST = [
|
|
|
2643
2643
|
id: "execution.shell",
|
|
2644
2644
|
pack: "development",
|
|
2645
2645
|
exposure: "direct",
|
|
2646
|
-
tools: ["bash", "exec", "language", "language_info", "language_package"]
|
|
2646
|
+
tools: ["bash", "exec", "pwsh", "language", "language_info", "language_package"]
|
|
2647
2647
|
},
|
|
2648
2648
|
{
|
|
2649
2649
|
id: "verification.run",
|
|
@@ -4435,7 +4435,7 @@ ${identity}`);
|
|
|
4435
4435
|
splitLearnedEntries(rawLearned)
|
|
4436
4436
|
);
|
|
4437
4437
|
const rawBytes = Buffer.byteLength(rawLearned, "utf8");
|
|
4438
|
-
const freshEntries = meta === void 0 ? [] : rawEntries.filter((entry) => entry.capturedAt
|
|
4438
|
+
const freshEntries = meta === void 0 ? [] : rawEntries.filter((entry) => entry.capturedAt >= meta.consolidatedAt);
|
|
4439
4439
|
const stale = meta === void 0 || freshEntries.length > 0 || rawEntries.length > meta.sourceEntryCount || rawBytes > meta.sourceBytes;
|
|
4440
4440
|
if (!stale) {
|
|
4441
4441
|
learnedContent = consolidated;
|
|
@@ -6032,7 +6032,7 @@ var VERIFY_AGENTS = [
|
|
|
6032
6032
|
id: "bug-hunter",
|
|
6033
6033
|
name: "Bug Hunter",
|
|
6034
6034
|
role: "bug-hunter",
|
|
6035
|
-
tools: [...TOOLS.inspect],
|
|
6035
|
+
tools: [...TOOLS.inspect, "dead-code-scan"],
|
|
6036
6036
|
prompt: agentPrompt("bug-hunter")
|
|
6037
6037
|
},
|
|
6038
6038
|
budget: HEAVY_BUDGET,
|
|
@@ -6122,7 +6122,7 @@ var REVIEW_AGENTS = [
|
|
|
6122
6122
|
id: "code-reviewer",
|
|
6123
6123
|
name: "Code Reviewer",
|
|
6124
6124
|
role: "code-reviewer",
|
|
6125
|
-
tools: [...TOOLS.inspect, "git"],
|
|
6125
|
+
tools: [...TOOLS.inspect, "git", "codebase-impact-analysis", "codebase-invariant-check"],
|
|
6126
6126
|
prompt: agentPrompt("code-reviewer")
|
|
6127
6127
|
},
|
|
6128
6128
|
budget: MEDIUM_BUDGET,
|
|
@@ -10481,6 +10481,80 @@ var FLEET_ROSTER_WITHACP = {
|
|
|
10481
10481
|
...Object.fromEntries(ACP_AGENTS.map((a) => [a.role, a]))
|
|
10482
10482
|
};
|
|
10483
10483
|
|
|
10484
|
+
// src/coordination/task-boundary.ts
|
|
10485
|
+
var PLACEHOLDER_VALUES = /* @__PURE__ */ new Set([
|
|
10486
|
+
"n/a",
|
|
10487
|
+
"na",
|
|
10488
|
+
"none",
|
|
10489
|
+
"nothing",
|
|
10490
|
+
"tbd",
|
|
10491
|
+
"todo",
|
|
10492
|
+
"unknown",
|
|
10493
|
+
"unspecified",
|
|
10494
|
+
"-",
|
|
10495
|
+
"\u2014",
|
|
10496
|
+
".",
|
|
10497
|
+
"as above",
|
|
10498
|
+
"same as above",
|
|
10499
|
+
"see above",
|
|
10500
|
+
"see task",
|
|
10501
|
+
"same as task"
|
|
10502
|
+
]);
|
|
10503
|
+
var isPlaceholder = (value) => PLACEHOLDER_VALUES.has(value.trim().toLowerCase());
|
|
10504
|
+
var MIN_SCOPE_CHARS = 8;
|
|
10505
|
+
var MIN_NON_GOAL_CHARS = 3;
|
|
10506
|
+
function parseTaskBoundary(raw) {
|
|
10507
|
+
const scope = typeof raw.scope === "string" ? raw.scope.trim() : "";
|
|
10508
|
+
if (scope.length < MIN_SCOPE_CHARS) {
|
|
10509
|
+
return {
|
|
10510
|
+
ok: false,
|
|
10511
|
+
error: `\`scope\` is missing or too vague \u2014 state in one concrete sentence what work this task covers (files, components, or commands in-bounds).`,
|
|
10512
|
+
hint: 'Example \u2014 scope: "Audit packages/core/src/parser/*.ts for unhandled token errors and report findings."'
|
|
10513
|
+
};
|
|
10514
|
+
}
|
|
10515
|
+
if (!Array.isArray(raw.outOfScope) || raw.outOfScope.length === 0) {
|
|
10516
|
+
return {
|
|
10517
|
+
ok: false,
|
|
10518
|
+
error: "`outOfScope` must be an array with at least one explicit non-goal \u2014 things the worker must NOT do.",
|
|
10519
|
+
hint: 'Example \u2014 outOfScope: ["Do not modify files outside packages/core", "Do not fix the bugs you find, only report them"].'
|
|
10520
|
+
};
|
|
10521
|
+
}
|
|
10522
|
+
const concrete = raw.outOfScope.filter((item) => typeof item === "string").map((item) => item.trim()).filter((item) => item.length >= MIN_NON_GOAL_CHARS && !isPlaceholder(item));
|
|
10523
|
+
if (concrete.length === 0) {
|
|
10524
|
+
return {
|
|
10525
|
+
ok: false,
|
|
10526
|
+
error: 'Every `outOfScope` entry was a placeholder ("none", "n/a", \u2026). Name at least one concrete non-goal: files or areas not to touch, changes not to make, features not to add.',
|
|
10527
|
+
hint: 'There is always an edge worth stating \u2014 "read-only, no edits", "no dependency changes", "do not touch other packages". If truly nothing comes to mind, the task is not decomposed enough yet.'
|
|
10528
|
+
};
|
|
10529
|
+
}
|
|
10530
|
+
return { ok: true, boundary: { scope, outOfScope: concrete } };
|
|
10531
|
+
}
|
|
10532
|
+
function renderTaskBoundaryBlock(boundary) {
|
|
10533
|
+
return [
|
|
10534
|
+
"\u2500\u2500 TASK BOUNDARY (hard contract \u2014 these lines define your edges) \u2500\u2500",
|
|
10535
|
+
`Scope (what this task covers):
|
|
10536
|
+
${boundary.scope}`,
|
|
10537
|
+
`Out of scope (explicit non-goals \u2014 do NOT do any of these):
|
|
10538
|
+
${boundary.outOfScope.map((item) => `- ${item}`).join("\n")}`
|
|
10539
|
+
].join("\n");
|
|
10540
|
+
}
|
|
10541
|
+
function composeBoundedTaskDescription(objective, boundary) {
|
|
10542
|
+
return `${objective.trim()}
|
|
10543
|
+
|
|
10544
|
+
${renderTaskBoundaryBlock(boundary)}`;
|
|
10545
|
+
}
|
|
10546
|
+
var taskBoundarySchemaProperties = {
|
|
10547
|
+
scope: {
|
|
10548
|
+
type: "string",
|
|
10549
|
+
description: "REQUIRED. One concrete sentence stating what work this task covers \u2014 the in-bounds. The call is rejected without it."
|
|
10550
|
+
},
|
|
10551
|
+
outOfScope: {
|
|
10552
|
+
type: "array",
|
|
10553
|
+
items: { type: "string", minLength: 1 },
|
|
10554
|
+
description: 'REQUIRED. At least one explicit non-goal the worker must NOT do (files/areas not to touch, changes not to make, features not to add). Placeholders like "none" are rejected.'
|
|
10555
|
+
}
|
|
10556
|
+
};
|
|
10557
|
+
|
|
10484
10558
|
// src/coordination/delegate-tool.ts
|
|
10485
10559
|
function createDelegateTool(opts) {
|
|
10486
10560
|
const defaultTimeoutMs = opts.defaultTimeoutMs ?? 4 * 60 * 60 * 1e3;
|
|
@@ -10490,8 +10564,9 @@ function createDelegateTool(opts) {
|
|
|
10490
10564
|
properties: {
|
|
10491
10565
|
task: {
|
|
10492
10566
|
type: "string",
|
|
10493
|
-
description: "
|
|
10567
|
+
description: "The objective \u2014 what the subagent should do, natural language, complete sentence(s). Pair it with the required `scope` and `outOfScope` boundary fields."
|
|
10494
10568
|
},
|
|
10569
|
+
...taskBoundarySchemaProperties,
|
|
10495
10570
|
role: {
|
|
10496
10571
|
type: "string",
|
|
10497
10572
|
description: rosterIds.length > 0 ? "Roster role id. Common: bug-hunter, security-scanner, refactor-planner, critic, audit-log, executor, shadow-agent, architect." : "No roster configured \u2014 pass `name` instead."
|
|
@@ -10549,12 +10624,12 @@ function createDelegateTool(opts) {
|
|
|
10549
10624
|
description: "Max fresh-worker continuations after budget exhaustion. Default 1. Each gets the prior partial report."
|
|
10550
10625
|
}
|
|
10551
10626
|
},
|
|
10552
|
-
required: ["task"]
|
|
10627
|
+
required: ["task", "scope", "outOfScope"]
|
|
10553
10628
|
};
|
|
10554
10629
|
return {
|
|
10555
10630
|
name: "delegate",
|
|
10556
10631
|
description: "Hand a piece of work to a subagent and block until it returns. This call is synchronous: the leader's iteration pauses for the full duration of the subagent's run. (Multiple `delegate` calls fired in the same assistant turn still parallelize through the provider's parallel-tool-call surface, but each one eats wall-clock time \u2014 so for fan-out you actually control, reach for the async path below.) Use `delegate` when your next step genuinely needs the subagent's verdict \u2014 a review, a fact-check, a sign-off. Has own context, own LLM call, auto-extending budget, and a partial-completion handoff path (maxHandoffs, default 1). Workers cannot recursively spawn.\n\n**Do NOT use `delegate` for long-running work.** While `delegate` is in flight, the leader is fully blocked \u2014 it cannot act on other tools, read mail, or react to the user. If the work might run for tens of minutes or hours (multi-file refactor, monorepo audit, long-running build/test, sweeping migration), the blocking call wastes the leader's time. Use the async tool family instead: `spawn_subagent` to create each worker (returns a `subagentId` immediately), `assign_task` to queue work on it (returns a `taskId` immediately), then `await_tasks` to retrieve results later. The leader keeps doing other work while the worker churns, and a worker that realizes its task will run long can mail the leader (type `steer` or `ask` via `mail_send`) saying *\"my task is going to run long, please spawn a subagent instead\"* so the leader re-dispatches asynchronously instead of waiting.\n\n**Do NOT use `delegate` for fan-out you control.** Multiple sequential `delegate` calls each block the leader, wasting wall-clock time. For independent investigations you want to run in parallel \u2014 security scan + bug hunt + perf review on the same PR \u2014 use the async tool family: `spawn_subagent` to create each worker (returns a `subagentId` immediately), `assign_task` to queue work on it (returns a `taskId` immediately), then the `await_tasks` tool with `{mode: 'any'}` to fold the first useful result into the next decision while the rest keep churning. Reach for `delegate` only when the result gates your next move AND the work is short enough that blocking the leader is acceptable.",
|
|
10557
|
-
usageHint: "Set `task` to a
|
|
10632
|
+
usageHint: "Set `task` to the objective, then make the edges explicit: `scope` (what the work covers) and `outOfScope` (at least one concrete non-goal) are REQUIRED \u2014 the call is rejected without them, and the worker treats the rendered boundary block as a hard contract. Pick `role` from roster or pass `name` for free-form. Reach for `delegate` only when the result gates your next move AND the work is short enough that blocking the leader is acceptable (minutes, not hours). For long-running work or fan-out you control, use `spawn_subagent` + `assign_task` + `await_tasks` instead. Raise `maxHandoffs` (default 1, cap 8) for multi-day or multi-refactor tasks; pass larger `timeoutMs`/`maxIterations`/`maxToolCalls` only when needed.",
|
|
10558
10633
|
permission: "auto",
|
|
10559
10634
|
mutating: false,
|
|
10560
10635
|
managesOwnTimeout: true,
|
|
@@ -10574,6 +10649,14 @@ function createDelegateTool(opts) {
|
|
|
10574
10649
|
error: "Delegation cancelled before spawn \u2014 the run was interrupted."
|
|
10575
10650
|
};
|
|
10576
10651
|
}
|
|
10652
|
+
const boundary = parseTaskBoundary(i);
|
|
10653
|
+
if (!boundary.ok) {
|
|
10654
|
+
return {
|
|
10655
|
+
ok: false,
|
|
10656
|
+
error: `delegate rejected \u2014 task boundary incomplete: ${boundary.error}`,
|
|
10657
|
+
hint: boundary.hint
|
|
10658
|
+
};
|
|
10659
|
+
}
|
|
10577
10660
|
const target = i.role ?? i.name ?? "subagent";
|
|
10578
10661
|
const launchModePreface = [
|
|
10579
10662
|
"Launch-mode guidance (delegate): you were launched via the synchronous `delegate` tool, so the leader is blocked on this call for the full duration of your run.",
|
|
@@ -10644,7 +10727,8 @@ function createDelegateTool(opts) {
|
|
|
10644
10727
|
const dir = director;
|
|
10645
10728
|
const maxHandoffs = Math.min(8, Math.max(0, Math.floor(i.maxHandoffs ?? 1)));
|
|
10646
10729
|
const handoffs = [];
|
|
10647
|
-
|
|
10730
|
+
const baseBrief = composeBoundedTaskDescription(i.task, boundary.boundary);
|
|
10731
|
+
let delegatedTask = baseBrief;
|
|
10648
10732
|
let handoffCount = 0;
|
|
10649
10733
|
for (; ; ) {
|
|
10650
10734
|
const attemptConfig = (() => {
|
|
@@ -10784,7 +10868,7 @@ function createDelegateTool(opts) {
|
|
|
10784
10868
|
remainingWork: continuation.remainingWork
|
|
10785
10869
|
});
|
|
10786
10870
|
handoffCount += 1;
|
|
10787
|
-
delegatedTask = buildHandoffTask(
|
|
10871
|
+
delegatedTask = buildHandoffTask(baseBrief, continuation, handoffCount, maxHandoffs);
|
|
10788
10872
|
continue;
|
|
10789
10873
|
}
|
|
10790
10874
|
const incomplete = result.report?.completion === "partial";
|
|
@@ -12688,8 +12772,9 @@ function makeAssignTool(director) {
|
|
|
12688
12772
|
description: {
|
|
12689
12773
|
type: "string",
|
|
12690
12774
|
minLength: 1,
|
|
12691
|
-
description: "The
|
|
12775
|
+
description: "The objective in natural language \u2014 what you want this subagent to do. Pair it with the required `scope` and `outOfScope` boundary fields."
|
|
12692
12776
|
},
|
|
12777
|
+
...taskBoundarySchemaProperties,
|
|
12693
12778
|
maxToolCalls: {
|
|
12694
12779
|
type: "number",
|
|
12695
12780
|
minimum: 1,
|
|
@@ -12697,20 +12782,28 @@ function makeAssignTool(director) {
|
|
|
12697
12782
|
},
|
|
12698
12783
|
timeoutMs: { type: "number", minimum: 1, description: "Optional per-task timeout in ms." }
|
|
12699
12784
|
},
|
|
12700
|
-
required: ["subagentId", "description"]
|
|
12785
|
+
required: ["subagentId", "description", "scope", "outOfScope"]
|
|
12701
12786
|
};
|
|
12702
12787
|
return {
|
|
12703
12788
|
name: "assign_task",
|
|
12704
|
-
description: "Queue a task on a previously spawned subagent. NON-BLOCKING: returns a `taskId` IMMEDIATELY \u2014 the subagent processes the task on its next iteration with its own LLM budget. The `taskId` is the durable handle for retrieving the result later via `await_tasks`, `roll_up`, or `ask_result`. Many `assign_task` calls can be in flight in parallel against the same or different subagents. This is the primary tool for fan-out work; do NOT use `delegate` to spawn multiple investigations sequentially.",
|
|
12789
|
+
description: "Queue a task on a previously spawned subagent. NON-BLOCKING: returns a `taskId` IMMEDIATELY \u2014 the subagent processes the task on its next iteration with its own LLM budget. The `taskId` is the durable handle for retrieving the result later via `await_tasks`, `roll_up`, or `ask_result`. Every assignment MUST carry an explicit boundary: `scope` (what the work covers) and `outOfScope` (at least one concrete non-goal) \u2014 the call is rejected without them, and the worker treats the rendered boundary block as a hard contract. Many `assign_task` calls can be in flight in parallel against the same or different subagents. This is the primary tool for fan-out work; do NOT use `delegate` to spawn multiple investigations sequentially.",
|
|
12705
12790
|
permission: "auto",
|
|
12706
12791
|
mutating: false,
|
|
12707
12792
|
capabilities: [ToolCapabilities.SUBAGENT_SPAWN],
|
|
12708
12793
|
inputSchema,
|
|
12709
12794
|
async execute(input) {
|
|
12710
12795
|
const i = input;
|
|
12796
|
+
const boundary = parseTaskBoundary(i);
|
|
12797
|
+
if (!boundary.ok) {
|
|
12798
|
+
return {
|
|
12799
|
+
ok: false,
|
|
12800
|
+
error: `assign_task rejected \u2014 task boundary incomplete: ${boundary.error}`,
|
|
12801
|
+
hint: boundary.hint
|
|
12802
|
+
};
|
|
12803
|
+
}
|
|
12711
12804
|
const task = {
|
|
12712
12805
|
id: randomUUID8(),
|
|
12713
|
-
description: i.description,
|
|
12806
|
+
description: composeBoundedTaskDescription(i.description, boundary.boundary),
|
|
12714
12807
|
subagentId: i.subagentId,
|
|
12715
12808
|
maxToolCalls: i.maxToolCalls,
|
|
12716
12809
|
timeoutMs: i.timeoutMs
|
|
@@ -18543,6 +18636,7 @@ var DefaultSessionStore = class _DefaultSessionStore {
|
|
|
18543
18636
|
sessionPath: (sid, ext) => this.sessionPath(sid, ext)
|
|
18544
18637
|
});
|
|
18545
18638
|
this.clearLoadCache(canonical);
|
|
18639
|
+
if (id !== canonical) this.clearLoadCache(id);
|
|
18546
18640
|
}
|
|
18547
18641
|
async summarize(id, mtime) {
|
|
18548
18642
|
return summarizeSessionFile({
|
|
@@ -20502,8 +20596,8 @@ var DefaultMultiAgentCoordinator = class _DefaultMultiAgentCoordinator extends E
|
|
|
20502
20596
|
withNickname(subagent, subagentId) {
|
|
20503
20597
|
const role = subagent.role ?? "subagent";
|
|
20504
20598
|
const name = subagent.name?.trim() ?? "";
|
|
20505
|
-
const
|
|
20506
|
-
if (!
|
|
20599
|
+
const isPlaceholder2 = name === "" || name.toLowerCase() === role.toLowerCase() || name === "subagent" || name === "adhoc" || name === "generic" || /^slot-/.test(name);
|
|
20600
|
+
if (!isPlaceholder2) return subagent;
|
|
20507
20601
|
const { key, display } = assignNickname(role, this.usedNicknames);
|
|
20508
20602
|
this.usedNicknames.add(key);
|
|
20509
20603
|
this.subagentNicknames.set(subagentId, key);
|
|
@@ -31366,6 +31460,7 @@ export {
|
|
|
31366
31460
|
clearProjectSkillAugmentation,
|
|
31367
31461
|
collabInjectMiddleware,
|
|
31368
31462
|
collabPauseMiddleware,
|
|
31463
|
+
composeBoundedTaskDescription,
|
|
31369
31464
|
composeDirectorPrompt,
|
|
31370
31465
|
composeSubagentPrompt,
|
|
31371
31466
|
consolidatedDocumentPath,
|
|
@@ -31450,6 +31545,7 @@ export {
|
|
|
31450
31545
|
parseMailboxAckInput,
|
|
31451
31546
|
parseMailboxQueryInput,
|
|
31452
31547
|
parseMailboxSendInput,
|
|
31548
|
+
parseTaskBoundary,
|
|
31453
31549
|
phaseForRole,
|
|
31454
31550
|
quarantinePath,
|
|
31455
31551
|
rankRoleSkills,
|
|
@@ -31466,6 +31562,7 @@ export {
|
|
|
31466
31562
|
refreshProjectAgentIdentity,
|
|
31467
31563
|
release,
|
|
31468
31564
|
renderSkillAugmentation,
|
|
31565
|
+
renderTaskBoundaryBlock,
|
|
31469
31566
|
resetCaptureWindow,
|
|
31470
31567
|
resetCaptureWindows,
|
|
31471
31568
|
resetProjectAgentIdentity,
|
|
@@ -31496,6 +31593,7 @@ export {
|
|
|
31496
31593
|
startPackageOutdatedWatcher,
|
|
31497
31594
|
startTechStackConsumer,
|
|
31498
31595
|
subagentNeedsWorktree,
|
|
31596
|
+
taskBoundarySchemaProperties,
|
|
31499
31597
|
terminalPolicyDecision,
|
|
31500
31598
|
unwrapWholeDocumentFence,
|
|
31501
31599
|
updatePackageOutdatedStatus,
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hard task-boundary contract for leader → subagent assignment tools.
|
|
3
|
+
*
|
|
4
|
+
* `delegate` and `assign_task` reject any assignment that does not carry an
|
|
5
|
+
* explicit in-bounds `scope` and at least one concrete out-of-scope non-goal.
|
|
6
|
+
* Prompt-only guidance ("state the scope and non-goals") degrades under
|
|
7
|
+
* pressure: a rushed leader writes "fix it", the worker guesses the edges, and
|
|
8
|
+
* the drift only surfaces at review time — the most expensive place to find
|
|
9
|
+
* it. Forcing the boundary into structured fields makes the edges
|
|
10
|
+
* machine-checkable at assignment time and lets the tool return a teaching
|
|
11
|
+
* error that names exactly what is missing, so the leader self-corrects on
|
|
12
|
+
* the next call instead of shipping a vague brief.
|
|
13
|
+
*
|
|
14
|
+
* The parsed boundary is composed into `TaskSpec.description` as a clearly
|
|
15
|
+
* delimited block. That is deliberate: the description is the canonical brief
|
|
16
|
+
* every runner, transcript, handoff continuation, and roll-up already
|
|
17
|
+
* consumes, so the boundary travels with the task everywhere without new
|
|
18
|
+
* plumbing (and `buildHandoffTask`'s "Original task:" carry-over preserves it
|
|
19
|
+
* into fresh workers for free).
|
|
20
|
+
*/
|
|
21
|
+
import type { JSONSchema } from '../types/tool.js';
|
|
22
|
+
export interface TaskBoundary {
|
|
23
|
+
/** What the work covers — the in-bounds statement. */
|
|
24
|
+
scope: string;
|
|
25
|
+
/** Explicit non-goals: things the worker must NOT do. */
|
|
26
|
+
outOfScope: string[];
|
|
27
|
+
}
|
|
28
|
+
export type TaskBoundaryParseResult = {
|
|
29
|
+
ok: true;
|
|
30
|
+
boundary: TaskBoundary;
|
|
31
|
+
} | {
|
|
32
|
+
ok: false;
|
|
33
|
+
error: string;
|
|
34
|
+
hint: string;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Validate and normalize the `scope` / `outOfScope` pair from a tool input.
|
|
38
|
+
* Returns the cleaned boundary, or an error + hint pair worded so the calling
|
|
39
|
+
* leader can fix the call in one retry.
|
|
40
|
+
*/
|
|
41
|
+
export declare function parseTaskBoundary(raw: {
|
|
42
|
+
scope?: unknown;
|
|
43
|
+
outOfScope?: unknown;
|
|
44
|
+
}): TaskBoundaryParseResult;
|
|
45
|
+
/**
|
|
46
|
+
* Render the boundary as the block appended to `TaskSpec.description`. The
|
|
47
|
+
* heading is loud on purpose: the worker treats these lines as hard edges,
|
|
48
|
+
* and review-time drift checks quote them verbatim.
|
|
49
|
+
*/
|
|
50
|
+
export declare function renderTaskBoundaryBlock(boundary: TaskBoundary): string;
|
|
51
|
+
/**
|
|
52
|
+
* Compose the leader's objective with its boundary into the canonical brief
|
|
53
|
+
* delivered to the runner. The objective stays verbatim and first; the
|
|
54
|
+
* boundary block follows so handoffs, transcripts, and roll-ups that quote
|
|
55
|
+
* the description carry the edges with them.
|
|
56
|
+
*/
|
|
57
|
+
export declare function composeBoundedTaskDescription(objective: string, boundary: TaskBoundary): string;
|
|
58
|
+
/**
|
|
59
|
+
* Shared schema property definitions so `delegate` and `assign_task` state
|
|
60
|
+
* the identical contract. Declaring the fields here (rather than inline per
|
|
61
|
+
* tool) keeps the required-field teaching text single-sourced.
|
|
62
|
+
*/
|
|
63
|
+
export declare const taskBoundarySchemaProperties: Record<string, JSONSchema>;
|
|
64
|
+
//# sourceMappingURL=task-boundary.d.ts.map
|
package/dist/core/index.js
CHANGED
|
@@ -7920,7 +7920,7 @@ var RUNTIME_CAPABILITY_MANIFEST = [
|
|
|
7920
7920
|
id: "execution.shell",
|
|
7921
7921
|
pack: "development",
|
|
7922
7922
|
exposure: "direct",
|
|
7923
|
-
tools: ["bash", "exec", "language", "language_info", "language_package"]
|
|
7923
|
+
tools: ["bash", "exec", "pwsh", "language", "language_info", "language_package"]
|
|
7924
7924
|
},
|
|
7925
7925
|
{
|
|
7926
7926
|
id: "verification.run",
|