@selesai/code 0.5.29 → 0.6.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/CHANGELOG.md +34 -0
- package/README.md +1 -1
- package/dist/config.d.ts +16 -3
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +106 -5
- package/dist/config.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +18 -0
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/system-prompt.test.d.ts +2 -0
- package/dist/core/system-prompt.test.d.ts.map +1 -0
- package/dist/core/system-prompt.test.js +89 -0
- package/dist/core/system-prompt.test.js.map +1 -0
- package/dist/defaults/models.json +13 -45
- package/dist/defaults/settings.json +5 -7
- package/dist/extensions/copy-turn.test.ts +131 -0
- package/dist/extensions/copy-turn.ts +6 -1
- package/dist/extensions/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -0
- package/dist/extensions/package.json +0 -1
- package/dist/extensions/pi-subagents/CHANGELOG.md +3 -0
- package/dist/extensions/pi-subagents/README.md +27 -32
- package/dist/extensions/pi-subagents/agents/architect.md +4 -4
- package/dist/extensions/pi-subagents/agents/builder.md +5 -4
- package/dist/extensions/pi-subagents/agents/commentator.md +3 -2
- package/dist/extensions/pi-subagents/agents/explorer.md +3 -2
- package/dist/extensions/pi-subagents/agents/recapper.md +3 -2
- package/dist/extensions/pi-subagents/agents/researcher.md +4 -3
- package/dist/extensions/pi-subagents/skills/pi-subagents/SKILL.md +2 -0
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/constraints-and-recipes.md +10 -9
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/execution-controls.md +12 -11
- package/dist/extensions/pi-subagents/skills/pi-subagents/references/prompting-and-roles.md +10 -11
- package/dist/extensions/pi-subagents/src/agents/agent-management.ts +56 -9
- package/dist/extensions/pi-subagents/src/agents/task-aware-routing.ts +125 -0
- package/dist/extensions/pi-subagents/src/api/preflight.ts +1 -1
- package/dist/extensions/pi-subagents/src/extension/index.ts +5 -1
- package/dist/extensions/pi-subagents/src/extension/schemas.ts +2 -2
- package/dist/extensions/pi-subagents/src/extension/tool-description.ts +24 -7
- package/dist/extensions/pi-subagents/src/runs/background/async-execution.ts +23 -5
- package/dist/extensions/pi-subagents/src/runs/background/notify.ts +27 -1
- package/dist/extensions/pi-subagents/src/runs/background/result-watcher.ts +64 -6
- package/dist/extensions/pi-subagents/src/runs/background/subagent-runner.ts +16 -1
- package/dist/extensions/pi-subagents/src/runs/foreground/chain-execution.ts +72 -18
- package/dist/extensions/pi-subagents/src/runs/foreground/execution.ts +19 -5
- package/dist/extensions/pi-subagents/src/runs/foreground/subagent-executor.ts +127 -31
- package/dist/extensions/pi-subagents/src/runs/shared/acceptance.ts +4 -6
- package/dist/extensions/pi-subagents/src/runs/shared/single-output.ts +63 -9
- package/dist/extensions/pi-subagents/src/runs/shared/task-intent.ts +21 -0
- package/dist/extensions/pi-subagents/src/shared/types.ts +41 -2
- package/dist/extensions/pi-subagents/src/shared/utils.ts +29 -1
- package/dist/extensions/pi-subagents/src/slash/delegation-adapters.ts +5 -1
- package/dist/extensions/pi-subagents/src/tui/render.ts +32 -6
- package/dist/extensions/pi-subagents/test/e2e/real-session-subagent.test.ts +111 -6
- package/dist/extensions/pi-subagents/test/integration/async-execution.test.ts +74 -43
- package/dist/extensions/pi-subagents/test/integration/chain-execution.test.ts +36 -21
- package/dist/extensions/pi-subagents/test/integration/fork-context-execution.test.ts +5 -3
- package/dist/extensions/pi-subagents/test/integration/intercom-result-delivery.test.ts +20 -8
- package/dist/extensions/pi-subagents/test/integration/parallel-execution.test.ts +14 -7
- package/dist/extensions/pi-subagents/test/integration/render-fork-badge.test.ts +227 -0
- package/dist/extensions/pi-subagents/test/integration/result-watcher.test.ts +81 -5
- package/dist/extensions/pi-subagents/test/integration/single-execution.test.ts +49 -10
- package/dist/extensions/pi-subagents/test/support/real-session-runner.ts +18 -2
- package/dist/extensions/pi-subagents/test/unit/agent-disabled.test.ts +1 -1
- package/dist/extensions/pi-subagents/test/unit/agent-frontmatter.test.ts +70 -6
- package/dist/extensions/pi-subagents/test/unit/agent-management.test.ts +161 -1
- package/dist/extensions/pi-subagents/test/unit/builtin-agent-documentation.test.ts +63 -0
- package/dist/extensions/pi-subagents/test/unit/capability-ceiling-agent-allowlist.test.ts +34 -0
- package/dist/extensions/pi-subagents/test/unit/delegation-api.test.ts +24 -0
- package/dist/extensions/pi-subagents/test/unit/index-child-registration.test.ts +6 -1
- package/dist/extensions/pi-subagents/test/unit/notify.test.ts +29 -0
- package/dist/extensions/pi-subagents/test/unit/preflight.test.ts +2 -0
- package/dist/extensions/pi-subagents/test/unit/schemas.test.ts +12 -0
- package/dist/extensions/pi-subagents/test/unit/single-output.test.ts +91 -1
- package/dist/extensions/pi-subagents/test/unit/task-aware-routing.test.ts +213 -0
- package/dist/extensions/pi-subagents/test/unit/task-intent.test.ts +23 -1
- package/dist/extensions/pi-subagents/test/unit/tool-description.test.ts +60 -9
- package/dist/extensions/pi-web-agent/package.json +1 -1
- package/dist/skills/pi-subagents/SKILL.md +43 -0
- package/dist/skills/pi-subagents/references/constraints-and-recipes.md +257 -0
- package/dist/skills/pi-subagents/references/execution-controls.md +431 -0
- package/dist/skills/pi-subagents/references/management-authoring-rpc.md +144 -0
- package/dist/skills/pi-subagents/references/prompting-and-roles.md +281 -0
- package/dist/skills/ponytail/SKILL.md +1 -3
- package/docs/plans/subagent-delegation/phase-0-correctness.md +265 -0
- package/docs/plans/subagent-delegation/phase-1-behavioral-contract.md +486 -0
- package/docs/plans/subagent-delegation/phase-2-context-controls.md +282 -0
- package/docs/plans/subagent-delegation/phase-3-advisory-routing.md +362 -0
- package/docs/plans/subagent-delegation/phase-4-optional-enforcement.md +381 -0
- package/package.json +2 -2
- package/dist/extensions/caveman/caveman-instructions.cjs +0 -11
- package/dist/extensions/caveman/index.js +0 -118
- package/dist/extensions/caveman/package.json +0 -8
- package/dist/extensions/caveman/test/extension.test.js +0 -203
- package/dist/extensions/caveman/test/helpers.test.js +0 -58
- package/dist/skills/caveman/SKILL.md +0 -50
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: recapper
|
|
3
|
-
description:
|
|
3
|
+
description: Read-only handoff and context synthesis
|
|
4
4
|
tools: read, grep, find, ls
|
|
5
5
|
systemPromptMode: replace
|
|
6
6
|
inheritProjectContext: true
|
|
7
7
|
inheritSkills: false
|
|
8
|
-
skill: ponytail
|
|
8
|
+
skill: ponytail
|
|
9
9
|
defaultContext: fork
|
|
10
|
+
acceptanceRole: read-only
|
|
10
11
|
---
|
|
11
12
|
|
|
12
13
|
Create a concise, self-contained handoff for a fresh agent. Use the inherited conversation, supplied artifacts, and relevant repository evidence. Do not edit project files, write output files, or launch subagents.
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: researcher
|
|
3
|
-
description:
|
|
4
|
-
tools: read, grep_app_search, grep_app_fetch, web_explore
|
|
3
|
+
description: Read-only external and code-first research
|
|
4
|
+
tools: read, mcp:grep_app_search, mcp:grep_app_fetch, web_explore
|
|
5
5
|
thinking: medium
|
|
6
6
|
systemPromptMode: replace
|
|
7
7
|
inheritProjectContext: false
|
|
8
8
|
inheritSkills: false
|
|
9
9
|
defaultContext: fresh
|
|
10
|
-
skill: ponytail
|
|
10
|
+
skill: ponytail
|
|
11
|
+
acceptanceRole: read-only
|
|
11
12
|
---
|
|
12
13
|
|
|
13
14
|
You are a code-first research subagent. Answer the supplied question with a concise, well-sourced brief. Do not edit project files, write output files, or launch subagents.
|
|
@@ -27,6 +27,8 @@ Read the matching reference file before acting. Paths are relative to this `SKIL
|
|
|
27
27
|
|
|
28
28
|
Selesai default: use Fable-style parent orchestration for complex work (multiple moving parts, unclear acceptance, cross-cutting code, meaningful user impact, expensive validation, or broad review surface). Lightweight one-off delegation stays lightweight.
|
|
29
29
|
|
|
30
|
+
Routing rule: keep tiny targeted reads and simple answers with the parent. For broad local investigation, external research, or mutation work, call `{ action: "list" }`, choose an executable entry from its runtime metadata, then delegate. Treat list output—not hardcoded role names—as the agent-selection authority.
|
|
31
|
+
|
|
30
32
|
For broad or uncertain requests, read more than one reference. For complex work, start with `references/prompting-and-roles.md` and `references/execution-controls.md`, then consult `references/constraints-and-recipes.md` before launching or reviewing child work.
|
|
31
33
|
|
|
32
34
|
## Always-on constraints
|
package/dist/extensions/pi-subagents/skills/pi-subagents/references/constraints-and-recipes.md
CHANGED
|
@@ -5,9 +5,10 @@ This file is a detailed reference loaded from `skills/pi-subagents/SKILL.md`.
|
|
|
5
5
|
## Important Constraints
|
|
6
6
|
|
|
7
7
|
- **Forking requires a persisted parent session.** If the current session does not
|
|
8
|
-
have a persisted session file, forked runs fail. Packaged `architect
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
have a persisted session file, forked runs fail. Packaged `architect` and `recapper`
|
|
9
|
+
default to forked context; `builder`, `commentator`, `explorer`, and `researcher`
|
|
10
|
+
default to fresh context. Use explicit `context: "fork"` or `context: "fresh"` when
|
|
11
|
+
you intentionally want one context for every child.
|
|
11
12
|
- **Forked runs inherit parent history.** They are branched threads, not fresh
|
|
12
13
|
filtered contexts. Use fresh context for adversarial commentators unless the user explicitly asks for forked context.
|
|
13
14
|
- **Default subagent nesting depth is 2.** Deeper recursive delegation is blocked
|
|
@@ -18,7 +19,7 @@ This file is a detailed reference loaded from `skills/pi-subagents/SKILL.md`.
|
|
|
18
19
|
- **Keep conversational authority clear.** Advisory subagents should not silently
|
|
19
20
|
become second decision-makers.
|
|
20
21
|
|
|
21
|
-
Runtime config can change orchestration behavior. `intercomBridge.resultDelivery: false` disables only external acknowledged grouped-result delivery when native parent notifications own completion; supervisor asks/progress stay active, and enabled transport failures are still reported. `asyncByDefault` and `forceTopLevelAsync` affect whether launches detach; `waitTool` can make direct `subagent_wait()` calls return immediately while headless auto-drain remains active, and its effective value is propagated to child runtimes; `globalConcurrencyLimit` bounds concurrent fanout, while a positive `maxSubagentSpawnsPerSession` optionally caps cumulative launches (`0` or unset is unlimited). Status and doctor report the budget; static work preflights declared capacity; only the settled root interactive parent can use `grant-spawn-budget` after native confirmation, with total grants bounded by the original cap. Compaction does not reset usage or grants; `singleRunOutputBaseDir` and `worktreeBaseDir` route outputs and worktrees; `completionBatch` groups async notifications. `artifactDir` is `project` (default), `session`, or `temp` and chooses where subagent artifacts are stored. Set `asyncWidget: false` to hide the above-editor background-run widget when a companion footer or dashboard owns that space (fleet inspector remains available).
|
|
22
|
+
Runtime config can change orchestration behavior. `intercomBridge.resultDelivery: false` disables only external acknowledged grouped-result delivery when native parent notifications own completion; supervisor asks/progress stay active, and enabled transport failures are still reported. `asyncByDefault` and `forceTopLevelAsync` affect whether launches detach; `waitTool` can make direct `subagent_wait()` calls return immediately while headless auto-drain remains active, and its effective value is propagated to child runtimes; `globalConcurrencyLimit` bounds concurrent fanout, while a positive `maxSubagentSpawnsPerSession` optionally caps cumulative launches (`0` or unset is unlimited). Status and doctor report the budget; static work preflights declared capacity; only the settled root interactive parent can use `grant-spawn-budget` after native confirmation, with total grants bounded by the original cap. Compaction does not reset usage or grants; `singleRunOutputBaseDir` and `worktreeBaseDir` route outputs and worktrees; `completionBatch` groups async notifications. `artifactDir` is `project` (default), `session`, or `temp` and chooses where subagent artifacts are stored. Set `asyncWidget: false` to hide the above-editor background-run widget when a companion footer or dashboard owns that space (fleet inspector remains available). Artifact capture is off by default; set per-run `artifacts: true` when debug files are needed. Async status and result artifacts are versioned with fields such as `lifecycleArtifactVersion`, `workflowGraph`, `steps`, `results`, `totalTokens`, `totalCost`, `turnCount`, `toolCount`, and nested `children`. Child protocol failures expose a structured `protocolError`; `protocol_output_limit` means a child emitted a JSONL line above the 4 MiB live-parser cap. Prefer these artifacts and `status` views over scraping terminal output.
|
|
22
23
|
|
|
23
24
|
## Best Practices
|
|
24
25
|
|
|
@@ -91,7 +92,7 @@ Fable mode is the default orchestration posture for complex work. It is not a se
|
|
|
91
92
|
|
|
92
93
|
Run the work through seven gated phases:
|
|
93
94
|
|
|
94
|
-
1. **Understand** — use `explorer`
|
|
95
|
+
1. **Understand** — use `explorer` fanout for breadth, but the parent personally reads the load-bearing files and lets direct source reading decide disagreements. Gate: the parent can quote the exact code or behavior being changed and knows the repo's verification harness.
|
|
95
96
|
2. **Decide** — separate user-owned decisions from implementation judgments. Use `interview` for product, naming, cost, taste, or risk decisions; decide routine engineering details in the parent and state them. Gate: every user-owned decision needed for design is answered.
|
|
96
97
|
3. **Design** — use `architect`, `explorer`, or read-only design/review children for parallel perspectives. Before parallel workstreams, write seam contracts: ownership boundaries, composition points, assumptions, and validation handoffs. Gate: one parent-synthesized plan and written seams for parallel work.
|
|
97
98
|
4. **Implement** — capture a baseline first, then launch one async `builder` as the sole writer for the active worktree unless isolated worktrees were intentionally requested. Break large work into serial milestones instead of concurrent writes. Gate: build/typecheck is green and every output or diff delta is characterized as intended or fixed.
|
|
@@ -103,7 +104,7 @@ Run the work through seven gated phases:
|
|
|
103
104
|
|
|
104
105
|
For straightforward non-trivial work, this sequence is the lightweight version of the parent-owned loop. When the task is complex, use Fable mode above. In either case, factor in the packaged prompt workflows without literally invoking slash commands. Use the same patterns through tools and subagents.
|
|
105
106
|
|
|
106
|
-
Keep builtin agent defaults unless the user explicitly asks for a different model, thinking level, skills, output behavior, context mode, or other override. Do not add overrides just because you are orchestrating; the defaults encode the intended role behavior. In particular, packaged `architect
|
|
107
|
+
Keep builtin agent defaults unless the user explicitly asks for a different model, thinking level, skills, output behavior, context mode, or other override. Do not add overrides just because you are orchestrating; the defaults encode the intended role behavior. In particular, packaged `architect` and `recapper` default to forked context; `builder`, `commentator`, `explorer`, and `researcher` default to fresh context.
|
|
107
108
|
|
|
108
109
|
When the user approves launching a subagent to carry out a plan or workflow, treat that as approval to generate a proper role-specific meta prompt for that subagent. Include the approved plan path or summary, clarified requirements, non-goals, relevant context, role boundaries, files or areas to inspect, acceptance criteria, expected output, and validation expectations. Do not pass vague instructions like “implement the plan fully” or “review this” by themselves.
|
|
109
110
|
|
|
@@ -125,7 +126,7 @@ The validation contract defines acceptance before code is written: expected beha
|
|
|
125
126
|
|
|
126
127
|
Use the structured `acceptance` field when the run should carry an explicit acceptance contract. If omitted, subagents infer an effective policy from role, mode, and risk. Evidence levels end at `verified`: use `level: "checked"` for ordinary writer evidence and `level: "verified"` when the runtime should run explicit validation commands. Independent review is orthogonal; use `review: { required: true, agent: "commentator" }` and orchestrate the commentator separately. `review-required` means evidence passed but review is pending, while `reviewed` means a real independent result found no blockers. For commentator/read-only calls, omit `acceptance`. Never explicitly request `level: "reviewed"`; that value remains recognized only so preflight can return an actionable correction. To disable gates, use `{ level: "none", reason: "..." }`; the bare string `"none"` is rejected, and `false` is accepted only as a deprecated shorthand. Child-reported command success is evidence, not runtime verification.
|
|
127
128
|
|
|
128
|
-
The first `builder` implements the approved plan. The parent continues with independent inspection or validation prep while it runs, not parallel edits to the same worktree. When the async builder completes, treat its handoff as the transition into review, not as final completion, unless the user explicitly asked for builder-only work, review-only output, or to stop after implementation. Parallel commentators inspect the resulting diff from fresh context. Validators check behavior with the best available evidence: commands, tests, browser/CLI interaction, screenshots, logs, or manual reproduction notes. The final `builder` applies synthesized review fixes
|
|
129
|
+
The first `builder` implements the approved plan. The parent continues with independent inspection or validation prep while it runs, not parallel edits to the same worktree. When the async builder completes, treat its handoff as the transition into review, not as final completion, unless the user explicitly asked for builder-only work, review-only output, or to stop after implementation. Parallel commentators inspect the resulting diff from fresh context. Validators check behavior with the best available evidence: commands, tests, browser/CLI interaction, screenshots, logs, or manual reproduction notes. The final `builder` applies synthesized review fixes with an explicit `context: "fork"` when the fix needs inherited parent context, then the parent looks over the final diff before completing. The parent may launch these steps as an initial async chain when the workflow is already clear, or as follow-up subagent runs after each async completion. Initial chains should pass `async: true` so the main chat is unblocked; avoid `clarify: true` unless the user asked for foreground clarification. Do not stop after parallel review unless the user explicitly asked for review-only output or the review surfaced a decision that needs approval first.
|
|
129
130
|
|
|
130
131
|
For complex work, risky changes, broad refactors, or many changed lines, increase review and validation fanout rather than trusting one commentator. Use distinct angles such as correctness/regressions, tests/validation, simplicity/maintainability, security/privacy, performance, docs/API contracts, and user-flow behavior. When commentators find non-trivial issues or the fix builder touches many lines, run another focused review round before final validation.
|
|
131
132
|
|
|
@@ -135,10 +136,10 @@ For very large work, split into serial milestones instead of launching a swarm o
|
|
|
135
136
|
|
|
136
137
|
Keep orchestration authority in the parent session. Child subagents should not launch more subagents, read this skill, or run their own orchestration loops unless the parent intentionally selected a fanout agent whose builtin `tools` includes `subagent`. Spawned subagents do not receive the `pi-subagents` skill, parent-only status/control/slash messages, or prior parent `subagent` tool-call/tool-result artifacts. Ordinary children also do not receive the `subagent` extension tool. Child context filtering strips old hidden orchestration-instruction messages when they appear in inherited history. Every child receives a boundary instruction: ordinary children are told the parent owns orchestration and they must not propose or run subagents; explicit fanout children are told to use `subagent` only for the assigned fanout work, with `maxSubagentDepth` still enforced. Implementation children must call real edit/write tools instead of printing pseudo tool calls. Pass children concrete role-specific work instead.
|
|
137
138
|
|
|
138
|
-
1. Clarify first. This is mandatory. Gather code context with `explorer
|
|
139
|
+
1. Clarify first. This is mandatory. Gather code context with `explorer`, add `researcher` only when external evidence matters, then ask the user clarifying questions with `interview` until scope, acceptance criteria, constraints, and non-goals are clear.
|
|
139
140
|
2. Define the validation contract. State acceptance before implementation: expected behavior, checks to run, user flows to exercise, and evidence required in the builder handoff. For UI, CLI, integration, or workflow changes, include at least one validator angle that uses the product the way a user would rather than only reading code.
|
|
140
141
|
3. Plan when useful. For complex work, call `architect` or write a plan doc yourself and get approval before implementation. For simple work, confirm shared understanding and explicitly note why planning is skipped.
|
|
141
|
-
4. Implement with one writer. After approval, launch `builder` asynchronously with a proper meta prompt that includes clarified requirements, relevant context, plan path or summary, the validation contract, and output expectations. Packaged `builder` defaults to
|
|
142
|
+
4. Implement with one writer. After approval, launch `builder` asynchronously with a proper meta prompt that includes clarified requirements, relevant context, plan path or summary, the validation contract, and output expectations. Packaged `builder` defaults to fresh context; pass `context: "fork"` only when inherited parent context is intentionally required. While it runs, prepare validation or inspect adjacent code instead of editing the same worktree.
|
|
142
143
|
5. Require a useful builder handoff. Ask the builder to report changed files, what was implemented, what was left undone, commands run with exit codes, validation evidence, surprises or new risks, decisions made inside approved scope, and decisions needing parent approval.
|
|
143
144
|
6. Review after implementation. After the builder completes, launch parallel async fresh-context `commentator` agents for correctness/regressions, tests/validation, and simplicity/maintainability. Add security, performance, docs/API, domain-specific, or user-flow validators for complex work, risky changes, broad refactors, or many changed lines. Use `output: false` unless review artifacts are explicitly needed.
|
|
144
145
|
7. Synthesize, then run the fix builder. Separate blockers, fixes worth doing now, optional improvements, and feedback to ignore/defer, then launch an async forked `builder` to apply fixes worth doing now when the workflow is implementation-authorized. If commentators found scope/product/architecture choices that were not approved, ask the user first instead of applying them.
|
|
@@ -6,12 +6,12 @@ This file is a detailed reference loaded from `skills/pi-subagents/SKILL.md`.
|
|
|
6
6
|
|
|
7
7
|
Agent files can live in:
|
|
8
8
|
- `~/.selesai/agent/agents/**/*.md` — user scope
|
|
9
|
-
- `.
|
|
10
|
-
- legacy `.agents/**/*.md` — still read for compatibility, but `.
|
|
9
|
+
- `.selesai/agents/**/*.md` — canonical project scope
|
|
10
|
+
- legacy `.agents/**/*.md` — still read for compatibility, but `.selesai/agents/` wins on conflicts
|
|
11
11
|
|
|
12
12
|
Chains live in:
|
|
13
13
|
- `~/.selesai/agent/chains/**/*.chain.md` and `~/.selesai/agent/chains/**/*.chain.json` — user scope
|
|
14
|
-
- `.
|
|
14
|
+
- `.selesai/chains/**/*.chain.md` and `.selesai/chains/**/*.chain.json` — project scope
|
|
15
15
|
|
|
16
16
|
Discovery is recursive. `.chain.md` files do not define agents. Use `.chain.md` for simple saved chains and `.chain.json` for dynamic fanout or inline schema objects. Agents and chains can set optional frontmatter/package metadata; `name: explorer` plus `package: code-analysis` registers as runtime name `code-analysis.explorer` while serialization keeps `name` and `package` separate.
|
|
17
17
|
|
|
@@ -20,7 +20,7 @@ Precedence is by parsed runtime name:
|
|
|
20
20
|
2. user scope
|
|
21
21
|
3. builtin agents
|
|
22
22
|
|
|
23
|
-
Project settings resolve from the nearest parent directory containing `.
|
|
23
|
+
Project settings resolve from the nearest parent directory containing a `.selesai` config dir or a legacy `.agents` agent dir by default. In monorepos or git worktrees where an incidental nested `.selesai` directory should not shadow the repository config, set `subagents.projectRootResolution: "git-root"` in the repository root `.selesai/settings.json`; a nested project can opt back with `"nearest"` in its own settings.
|
|
24
24
|
|
|
25
25
|
## Running Subagents
|
|
26
26
|
|
|
@@ -88,7 +88,7 @@ subagent({
|
|
|
88
88
|
})
|
|
89
89
|
```
|
|
90
90
|
|
|
91
|
-
Avoid duplicate output paths in parallel tasks. Concurrent children should not write to the same file.
|
|
91
|
+
Avoid duplicate output paths in parallel tasks. Concurrent children should not write to the same file. Delivery is reference-first by default: every child gets a durable saved output unless `output: false`, omitted `output` uses a generated per-run path, omitted `outputMode` resolves to `file-only`, and the parent result contains only a compact reference like `Output saved to: /abs/report.md (48.2 KB, 2847 lines). Read this file if needed.` Inspect full output through the saved path, async status/transcript, or resume. Explicit `outputMode: "inline"` keeps the legacy full inline delivery; `output: false` disables durable result persistence (follow-up visibility falls back to bounded excerpts). Failed runs with a persisted result return the error/status plus the saved-output reference; persistence or read-back failures return only a bounded excerpt (first 80 lines / 4 KiB) together with the error, never raw unbounded output. Do not use `output: false` to get a file-only return; use file-only mode with an output path. In chains, relative `output` paths are chain-artifact paths under `{chain_dir}`, not project CWD paths; use an absolute `output` path or a persistent `chainDir` when a saved artifact must outlive the temp chain directory. Read-only children return the complete artifact in their final response and the runtime persists it, so missing write tools are not a supervisor blocker. Mutation-capable children still receive direct-write instructions.
|
|
92
92
|
|
|
93
93
|
### Chain execution
|
|
94
94
|
|
|
@@ -137,7 +137,7 @@ subagent({
|
|
|
137
137
|
})
|
|
138
138
|
```
|
|
139
139
|
|
|
140
|
-
File-only output mode also works for async single runs, top-level parallel task items, sequential chain steps, and chain parallel task items. In chains, `{previous}` receives the compact saved-file reference when the prior step used file-only mode. Relative chain output paths are resolved under `{chain_dir}`; pass a persistent `chainDir` or an absolute `output` path when a later human or process needs a stable path outside the temp chain run.
|
|
140
|
+
File-only output mode also works for async single runs, top-level parallel task items, sequential chain steps, and chain parallel task items. In chains, `{previous}` receives the compact saved-file reference when the prior step used file-only mode. Relative chain output paths are resolved under `{chain_dir}`; pass a persistent `chainDir` or an absolute `output` path when a later human or process needs a stable path outside the temp chain run. Async completion delivery is reference-first: the completion notification and grouped intercom payload carry per-child saved-output references (or `output-<index>.log` references) plus process status, never full child output. Inspect full output through the saved path, `{ action: "status", id, view: "transcript" }`, or resume.
|
|
141
141
|
|
|
142
142
|
For review fanout where the parent continues a local audit:
|
|
143
143
|
|
|
@@ -353,20 +353,20 @@ worktree, first confirm dependencies were linked, installed, or provisioned by
|
|
|
353
353
|
## The commentator Workflow
|
|
354
354
|
|
|
355
355
|
The intended commentator loop is:
|
|
356
|
-
1. the main agent
|
|
356
|
+
1. the main agent launches `commentator` (fresh context by default; pass `context: "fork"` only when a branched advisory thread that inherits the parent session history is intended)
|
|
357
357
|
2. `commentator` reviews direction, drift, assumptions, and risks
|
|
358
358
|
3. `commentator` can coordinate back through `contact_supervisor` when the bridge injects it
|
|
359
359
|
4. the main agent decides what direction to approve
|
|
360
360
|
5. only then should `builder` implement
|
|
361
361
|
|
|
362
362
|
```typescript
|
|
363
|
-
// Advisory review
|
|
363
|
+
// Advisory review. commentator defaults to fresh context; fork explicitly when a branched advisory thread is intended.
|
|
364
364
|
subagent({
|
|
365
365
|
agent: "commentator",
|
|
366
366
|
task: "Review my current direction, challenge assumptions, and propose the best next move."
|
|
367
367
|
})
|
|
368
368
|
|
|
369
|
-
// Implementation only after explicit approval. builder defaults to
|
|
369
|
+
// Implementation only after explicit approval. builder defaults to fresh context; pass context: "fork" when inherited parent context is intentionally required.
|
|
370
370
|
subagent({
|
|
371
371
|
agent: "builder",
|
|
372
372
|
task: "Implement the approved approach: ..."
|
|
@@ -374,8 +374,9 @@ subagent({
|
|
|
374
374
|
```
|
|
375
375
|
|
|
376
376
|
`commentator` is not a fresh-context commentator in the Cognition article sense. It is
|
|
377
|
-
|
|
378
|
-
|
|
377
|
+
an advisory thread that reviews direction, drift, and risks against the task/plan.
|
|
378
|
+
Pass `context: "fork"` when the review should inherit the parent session history and
|
|
379
|
+
use that history as a baseline contract; otherwise fresh context is the default.
|
|
379
380
|
|
|
380
381
|
Use `commentator` as a smart-friend escalation when the parent needs help with trajectory rather than diff inspection: architectural boundaries, model capability routing, merge conflicts, commentator disagreement, context drift after long work, a builder about to invent a pattern, or fixes that require product/scope tradeoffs. Ask broad questions when the right concern is unclear, and let `commentator` point out missing context or files the parent should inspect before asking again. Keep `commentator` advisory unless it has been explicitly assigned the single writer role.
|
|
381
382
|
|
|
@@ -11,7 +11,7 @@ Parent extensions may register a session-scoped, out-of-band ceiling through `pi
|
|
|
11
11
|
- **Complex work orchestration**: use Fable mode as the default parent-agent loop for complex work. Complex means the task has multiple moving parts, unclear acceptance, cross-cutting code, meaningful user-visible impact, expensive or irreversible validation, broad review surface, or the user asks for orchestration. Lightweight one-off delegation can stay lightweight.
|
|
12
12
|
- **Advisory review**: use fresh-context `commentator` agents for adversarial code review, or fork to `commentator` when inherited decisions and drift matter
|
|
13
13
|
- **Implementation handoff**: have `commentator` advise, then `builder` implement only after an approved direction
|
|
14
|
-
- **Recon and planning**: use `explorer
|
|
14
|
+
- **Recon and planning**: use `explorer`, then `architect`
|
|
15
15
|
- **Parallel exploration**: run multiple non-conflicting tasks concurrently
|
|
16
16
|
- **Regular skill specialists**: when discovery shows proactive skill subagent suggestions and the current work is broad enough, launch a small fresh-context fanout that asks one subagent per relevant regularly used skill to apply that skill's perspective to the task
|
|
17
17
|
- **Long-running work**: launch async/background runs and inspect them later. For mutation-capable work, bound the delivery slice and elapsed runtime, then request checkpoints after active tool work returns. Reserve hard turn and tool-call caps for explicitly read-only children.
|
|
@@ -179,17 +179,16 @@ and user/project agents override builtins with the same name.
|
|
|
179
179
|
|
|
180
180
|
| Agent | Purpose | Model | Typical output / role |
|
|
181
181
|
|-------|---------|-------|------------------------|
|
|
182
|
-
| `
|
|
183
|
-
| `architect` | Creates implementation plans | inherits default | Writes `plan.md` |
|
|
182
|
+
| `architect` | Creates implementation plans | inherits default | Read-only planning; returns the complete plan in its final response |
|
|
184
183
|
| `builder` | Implementation and approved commentator handoffs | inherits default | Single-writer implementation with decision escalation |
|
|
185
|
-
| `commentator` | Review specialist | inherits default |
|
|
186
|
-
| `explorer` |
|
|
187
|
-
| `
|
|
188
|
-
| `
|
|
189
|
-
| `commentator` | Decision-consistency advisory review | inherits default | Advisory review, intercom coordination |
|
|
190
|
-
| `commentator` | Claude Code-compatible alias for `commentator` | inherits default | Same advisory role as `commentator` |
|
|
184
|
+
| `commentator` | Review specialist | inherits default | Review-only findings in its final response; no edit/write tools |
|
|
185
|
+
| `explorer` | Fast codebase recon | inherits default | Read-only recon findings in its final response |
|
|
186
|
+
| `recapper` | Current-state handoff specialist | inherits default | Fork-context handoff; returns a self-contained handoff in its final response |
|
|
187
|
+
| `researcher` | Sourced research brief generator | inherits default | Read-only brief in its final response |
|
|
191
188
|
|
|
192
|
-
|
|
189
|
+
Only `architect` and `recapper` resolve to forked context when a launch omits `context`; `builder`, `commentator`, `explorer`, and `researcher` default to fresh context. Read-only builtins return their output in the final response; output files are written only when the caller configures output persistence.
|
|
190
|
+
|
|
191
|
+
Explicit `tools` is an allowlist, but ambient extension discovery remains possible unless `extensions`, `subagentOnlyExtensions`, or a capability ceiling constrains it; naming a tool alone does not load its provider. To give a child an extension tool, name it in `tools` and load its provider via `extensions`, a path-like `tools` entry, or `subagentOnlyExtensions`. Custom agents without an `extensions` field follow `subagents.defaultExtensions` when set.
|
|
193
192
|
|
|
194
193
|
Builtin agents inherit the current Pi default model unless a run, user setting, project setting, or `subagents.defaultModel` overrides `model`. Set `subagents.defaultModel` when subagents should use a different default model than the parent session. Override builtin defaults before copying full agent files when a small tweak is enough.
|
|
195
194
|
|
|
@@ -266,7 +265,7 @@ agent with the same name only when you want a substantially different agent.
|
|
|
266
265
|
When several providers are available, route agents by task shape instead of one model for everything:
|
|
267
266
|
|
|
268
267
|
1. **Fast workhorse** — cheapest capable model at low thinking for recon, lookups, and mechanical edits (for example on `explorer`).
|
|
269
|
-
2. **Standard well-scoped** — mid-tier model at medium thinking for most delegations: routine multi-file edits, focused reviews, straightforward implementation (for example on `builder
|
|
268
|
+
2. **Standard well-scoped** — mid-tier model at medium thinking for most delegations: routine multi-file edits, focused reviews, straightforward implementation (for example on `builder` and `commentator`).
|
|
270
269
|
3. **Deep but bounded** — top reasoning model at high thinking only for hard tasks that arrive with explicit goals and completion criteria; these models loop on vague goals (for example on `architect` and commentator-style agents).
|
|
271
270
|
4. **Taste and intent** — a model that reads human intent well for ambiguous work: UX/design judgment, product tradeoffs, planning from vague requirements, writing quality.
|
|
272
271
|
|
|
@@ -28,13 +28,14 @@ import { discoverAvailableSkills, resolveSkills } from "./skills.ts";
|
|
|
28
28
|
import {
|
|
29
29
|
buildProactiveSkillSubagentRecommendationLines,
|
|
30
30
|
} from "./proactive-skills.ts";
|
|
31
|
+
import { formatTaskAwareAgentRecommendation, recommendTaskAwareAgent } from "./task-aware-routing.ts";
|
|
31
32
|
import { parseFrontmatter } from "./frontmatter.ts";
|
|
32
33
|
import { toModelInfo } from "../shared/model-info.ts";
|
|
33
34
|
import { resolveSubagentModelOverride, type ParentModel } from "../runs/shared/model-fallback.ts";
|
|
34
35
|
import { validateToolBudgetConfig } from "../runs/shared/tool-budget.ts";
|
|
35
36
|
import { resolveTurnBudgetConfig } from "../runs/shared/turn-budget.ts";
|
|
36
37
|
import { validateAcceptanceInput } from "../runs/shared/acceptance.ts";
|
|
37
|
-
import type { AcceptanceInput, Details, ExtensionConfig, ToolBudgetConfig } from "../shared/types.ts";
|
|
38
|
+
import type { AcceptanceInput, CatalogAgentMetadata, Details, ExtensionConfig, ToolBudgetConfig } from "../shared/types.ts";
|
|
38
39
|
import { getProjectConfigDir } from "../shared/utils.ts";
|
|
39
40
|
import { capabilityCeilingAgentRestrictionSources, isAgentAllowedByCapabilityCeiling, resolveCurrentSubagentCapabilityCeiling } from "../runs/shared/capability-ceiling.ts";
|
|
40
41
|
|
|
@@ -48,10 +49,12 @@ interface ManagementParams {
|
|
|
48
49
|
chainName?: string;
|
|
49
50
|
agentScope?: string;
|
|
50
51
|
config?: unknown;
|
|
52
|
+
/** Optional advisory intent for action:'list' only; never launches work. */
|
|
53
|
+
task?: string;
|
|
51
54
|
}
|
|
52
55
|
|
|
53
|
-
function result(text: string, isError = false): AgentToolResult<Details> {
|
|
54
|
-
return { content: [{ type: "text", text }], isError, details: { mode: "management", results: [] } };
|
|
56
|
+
function result(text: string, isError = false, extraDetails: Partial<Details> = {}): AgentToolResult<Details> {
|
|
57
|
+
return { content: [{ type: "text", text }], isError, details: { mode: "management", results: [], ...extraDetails } };
|
|
55
58
|
}
|
|
56
59
|
|
|
57
60
|
function parseCsv(value: string): string[] {
|
|
@@ -585,8 +588,13 @@ function renamePath(
|
|
|
585
588
|
return { filePath };
|
|
586
589
|
}
|
|
587
590
|
|
|
591
|
+
/** Effective declared tools: normal tools plus mcp:-prefixed direct MCP tools. */
|
|
592
|
+
function effectiveAgentTools(agent: AgentConfig): string[] {
|
|
593
|
+
return [...(agent.tools ?? []), ...(agent.mcpDirectTools ?? []).map((t) => `mcp:${t}`)];
|
|
594
|
+
}
|
|
595
|
+
|
|
588
596
|
function formatAgentDetail(agent: AgentConfig): string {
|
|
589
|
-
const tools =
|
|
597
|
+
const tools = effectiveAgentTools(agent);
|
|
590
598
|
const lines: string[] = [`Agent: ${agent.name} (${agent.source})`, `Path: ${agent.filePath}`, `Description: ${agent.description}`];
|
|
591
599
|
if (agent.packageName) {
|
|
592
600
|
lines.push(`Local name: ${frontmatterNameForConfig(agent)}`);
|
|
@@ -672,6 +680,33 @@ function formatChainDetail(chain: ChainConfig): string {
|
|
|
672
680
|
return lines.join("\n");
|
|
673
681
|
}
|
|
674
682
|
|
|
683
|
+
function formatCatalogAgentLine(agent: AgentConfig): string {
|
|
684
|
+
const parts: string[] = [agent.source, `context: ${agent.defaultContext ?? "fresh"}`];
|
|
685
|
+
if (agent.acceptanceRole) parts.push(`role: ${agent.acceptanceRole}`);
|
|
686
|
+
if (agent.aliases?.length) parts.push(`aliases: ${agent.aliases.join(", ")}`);
|
|
687
|
+
const tools = effectiveAgentTools(agent);
|
|
688
|
+
if (tools.length) parts.push(`tools: ${tools.join(", ")}`);
|
|
689
|
+
return `- ${agent.name} (${parts.join(", ")}): ${agent.description}`;
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
function catalogAgentMetadata(
|
|
693
|
+
agent: AgentConfig,
|
|
694
|
+
executable: boolean,
|
|
695
|
+
restrictionSources: string[] | undefined,
|
|
696
|
+
): CatalogAgentMetadata {
|
|
697
|
+
return {
|
|
698
|
+
name: agent.name,
|
|
699
|
+
source: agent.source,
|
|
700
|
+
description: agent.description,
|
|
701
|
+
executable,
|
|
702
|
+
...(restrictionSources?.length ? { restrictionSources } : {}),
|
|
703
|
+
...(agent.aliases?.length ? { aliases: [...agent.aliases] } : {}),
|
|
704
|
+
defaultContext: agent.defaultContext ?? "fresh",
|
|
705
|
+
...(agent.acceptanceRole ? { acceptanceRole: agent.acceptanceRole } : {}),
|
|
706
|
+
tools: effectiveAgentTools(agent),
|
|
707
|
+
};
|
|
708
|
+
}
|
|
709
|
+
|
|
675
710
|
export function handleList(params: ManagementParams, ctx: ManagementContext): AgentToolResult<Details> {
|
|
676
711
|
const scope = normalizeListScope(params.agentScope) ?? "both";
|
|
677
712
|
const d = discoverAgentsAll(ctx.cwd);
|
|
@@ -690,23 +725,35 @@ export function handleList(params: ManagementParams, ctx: ManagementContext): Ag
|
|
|
690
725
|
config: ctx.config?.proactiveSkillSubagents,
|
|
691
726
|
discoverAvailableSkills: () => discoverAvailableSkills(ctx.cwd),
|
|
692
727
|
});
|
|
728
|
+
const taskAdvice = params.task?.trim()
|
|
729
|
+
? formatTaskAwareAgentRecommendation(recommendTaskAwareAgent({ task: params.task, agents, capabilityCeiling }))
|
|
730
|
+
: [];
|
|
693
731
|
const lines = [
|
|
694
732
|
"Executable agents:",
|
|
695
|
-
...(agents.length
|
|
696
|
-
? agents.map((a) => `- ${a.name} (${a.source}${a.defaultContext ? `, context: ${a.defaultContext}` : ""}${a.aliases?.length ? `, aliases: ${a.aliases.join(", ")}` : ""}): ${a.description}`)
|
|
697
|
-
: ["- (none)"]),
|
|
733
|
+
...(agents.length ? agents.map(formatCatalogAgentLine) : ["- (none)"]),
|
|
698
734
|
...(restrictedAgents.length ? [
|
|
699
735
|
"",
|
|
700
736
|
`Restricted agents (not executable in this session${restrictedSources?.length ? `; capability ceiling: ${restrictedSources.join(", ")}` : ""}):`,
|
|
701
|
-
...restrictedAgents.map(
|
|
737
|
+
...restrictedAgents.map(formatCatalogAgentLine),
|
|
702
738
|
] : []),
|
|
703
739
|
"",
|
|
704
740
|
"Chains:",
|
|
705
741
|
...(chains.length ? chains.map((c) => `- ${c.name} (${c.source}): ${c.description}`) : ["- (none)"]),
|
|
706
742
|
...(proactiveSuggestions.length ? ["", ...proactiveSuggestions] : []),
|
|
743
|
+
...(taskAdvice.length ? ["", ...taskAdvice] : []),
|
|
707
744
|
...(diagnostics.length ? ["", "Chain diagnostics:", ...diagnostics.map((entry) => `- ${entry.filePath}: ${entry.error}`)] : []),
|
|
708
745
|
];
|
|
709
|
-
return result(lines.join("\n")
|
|
746
|
+
return result(lines.join("\n"), false, {
|
|
747
|
+
catalog: {
|
|
748
|
+
version: 1,
|
|
749
|
+
agents: [
|
|
750
|
+
...agents.map((a) => catalogAgentMetadata(a, true, undefined)),
|
|
751
|
+
...restrictedAgents.map((a) => catalogAgentMetadata(a, false, restrictedSources)),
|
|
752
|
+
],
|
|
753
|
+
chains: chains.map((c) => ({ name: c.name, source: c.source, description: c.description })),
|
|
754
|
+
...(restrictedSources?.length ? { capabilityCeilingSources: restrictedSources } : {}),
|
|
755
|
+
},
|
|
756
|
+
});
|
|
710
757
|
}
|
|
711
758
|
|
|
712
759
|
function formatModelSource(agent: AgentConfig, currentModel: ParentModel | undefined): string {
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure task-aware advisory agent recommender.
|
|
3
|
+
*
|
|
4
|
+
* Given an already-discovered, effective agent set and the current capability
|
|
5
|
+
* ceiling, deterministically selects at most one canonical agent to recommend
|
|
6
|
+
* for a task, or returns recovery guidance when intent is unknown or no safe
|
|
7
|
+
* candidate exists. This module is deliberately pure: it performs no
|
|
8
|
+
* filesystem/discovery access, no alias/chains/executor/RPC/preflight/settings
|
|
9
|
+
* access, no mutation, launch, scheduling, or persistence, and never writes to
|
|
10
|
+
* params. Launching stays explicit: the caller must make a separate execution
|
|
11
|
+
* call with the recommended canonical `agent.name`.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import type { AgentConfig, AgentSource } from "./agents.ts";
|
|
15
|
+
import { agentHasWriteTools } from "./agent-memory.ts";
|
|
16
|
+
import { classifyTaskMutationIntent, resolveAgentRoutingRole } from "../runs/shared/task-intent.ts";
|
|
17
|
+
import { isAgentAllowedByCapabilityCeiling, type ResolvedSubagentCapabilityCeiling } from "../runs/shared/capability-ceiling.ts";
|
|
18
|
+
|
|
19
|
+
/** Core tools that make an implementation agent able to write (matches agent-memory). */
|
|
20
|
+
const WRITER_TOOLS = new Set(["edit", "write", "bash"]);
|
|
21
|
+
|
|
22
|
+
/** Source precedence for deterministic ordering: project > user > package > builtin. */
|
|
23
|
+
const AGENT_SOURCE_PRECEDENCE: Record<AgentSource, number> = { builtin: 0, package: 1, user: 2, project: 3 };
|
|
24
|
+
|
|
25
|
+
export type TaskAwareAgentIntent = "implementation" | "read-only" | "unknown";
|
|
26
|
+
|
|
27
|
+
export interface TaskAwareAgentRecommendationAgent {
|
|
28
|
+
/** Canonical runtime agent name accepted by execution; never an alias. */
|
|
29
|
+
name: string;
|
|
30
|
+
source: AgentSource;
|
|
31
|
+
role: "writer" | "read-only";
|
|
32
|
+
roleBasis: "declared" | "inferred";
|
|
33
|
+
reason: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface TaskAwareAgentRecommendation {
|
|
37
|
+
intent: TaskAwareAgentIntent;
|
|
38
|
+
agent?: TaskAwareAgentRecommendationAgent;
|
|
39
|
+
/** Recovery guidance when no safe recommendation exists (unknown intent or no candidate). */
|
|
40
|
+
next?: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Recommend a canonical agent for a trimmed non-empty task, or `undefined` for
|
|
45
|
+
* an empty/whitespace task (no-op). Never recommends disabled or
|
|
46
|
+
* capability-disallowed agents, never guesses for unknown intent, and never
|
|
47
|
+
* outputs an alias or a role-incompatible agent.
|
|
48
|
+
*/
|
|
49
|
+
export function recommendTaskAwareAgent(input: {
|
|
50
|
+
task: string;
|
|
51
|
+
agents: AgentConfig[];
|
|
52
|
+
capabilityCeiling?: ResolvedSubagentCapabilityCeiling;
|
|
53
|
+
}): TaskAwareAgentRecommendation | undefined {
|
|
54
|
+
const task = input.task.trim();
|
|
55
|
+
if (!task) return undefined;
|
|
56
|
+
|
|
57
|
+
const intent = classifyTaskMutationIntent("builder", task).kind;
|
|
58
|
+
if (intent === "unknown") {
|
|
59
|
+
return {
|
|
60
|
+
intent,
|
|
61
|
+
next: "Clarify whether the task is read-only analysis/review or implementation allowed to edit files.",
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const candidates: TaskAwareAgentRecommendationAgent[] = [];
|
|
66
|
+
for (const agent of input.agents) {
|
|
67
|
+
if (agent.disabled) continue;
|
|
68
|
+
if (!isAgentAllowedByCapabilityCeiling(agent.name, input.capabilityCeiling)) continue;
|
|
69
|
+
const role = resolveAgentRoutingRole(agent.name, agent.acceptanceRole);
|
|
70
|
+
if (!role) continue;
|
|
71
|
+
const hasWriteTools = agentHasWriteTools(agent);
|
|
72
|
+
if (intent === "implementation") {
|
|
73
|
+
if (role !== "writer" || !hasWriteTools) continue;
|
|
74
|
+
const allowedTools = input.capabilityCeiling?.allowedTools;
|
|
75
|
+
if (allowedTools !== undefined && !allowedTools.some((tool) => WRITER_TOOLS.has(tool))) continue;
|
|
76
|
+
} else {
|
|
77
|
+
if (role !== "read-only" || hasWriteTools) continue;
|
|
78
|
+
}
|
|
79
|
+
const roleBasis = agent.acceptanceRole !== undefined ? "declared" : "inferred";
|
|
80
|
+
candidates.push({
|
|
81
|
+
name: agent.name,
|
|
82
|
+
source: agent.source,
|
|
83
|
+
role,
|
|
84
|
+
roleBasis,
|
|
85
|
+
reason: intent === "implementation"
|
|
86
|
+
? `${roleBasis} writer role with write tools`
|
|
87
|
+
: `${roleBasis} read-only role without known write tools`,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
candidates.sort((a, b) => {
|
|
92
|
+
const sourceOrder = AGENT_SOURCE_PRECEDENCE[b.source] - AGENT_SOURCE_PRECEDENCE[a.source];
|
|
93
|
+
if (sourceOrder !== 0) return sourceOrder;
|
|
94
|
+
const declaredOrder = (a.roleBasis === "declared" ? 0 : 1) - (b.roleBasis === "declared" ? 0 : 1);
|
|
95
|
+
if (declaredOrder !== 0) return declaredOrder;
|
|
96
|
+
return a.name < b.name ? -1 : a.name > b.name ? 1 : 0;
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
const agent = candidates[0];
|
|
100
|
+
if (!agent) {
|
|
101
|
+
return {
|
|
102
|
+
intent,
|
|
103
|
+
next: intent === "implementation"
|
|
104
|
+
? "No executable agent has a writer role with write tools for this task. Check the executable/restricted sections above or adjust the capability ceiling."
|
|
105
|
+
: "No executable agent has a read-only role without known write tools for this task. Check the executable/restricted sections above.",
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
return { intent, agent };
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/** Text-only advisory lines; `undefined` (empty-task no-op) renders nothing. */
|
|
112
|
+
export function formatTaskAwareAgentRecommendation(recommendation: TaskAwareAgentRecommendation | undefined): string[] {
|
|
113
|
+
if (!recommendation) return [];
|
|
114
|
+
const lines = ["Task-aware advisory routing:", `- Intent: ${recommendation.intent}`];
|
|
115
|
+
if (recommendation.agent) {
|
|
116
|
+
lines.push(`- Recommended: ${recommendation.agent.name} (${recommendation.agent.source})`);
|
|
117
|
+
lines.push(`- Reason: ${recommendation.agent.reason}`);
|
|
118
|
+
lines.push("- Advisory only: no subagent was launched. To proceed, explicitly call subagent with this canonical agent name and the task.");
|
|
119
|
+
} else {
|
|
120
|
+
lines.push("- Recommendation: none");
|
|
121
|
+
lines.push(`- Next: ${recommendation.next ?? "Refine the task wording and retry."}`);
|
|
122
|
+
lines.push("- Advisory only: no subagent was launched.");
|
|
123
|
+
}
|
|
124
|
+
return lines;
|
|
125
|
+
}
|
|
@@ -284,7 +284,7 @@ export async function resolveSubagentLaunchContract(input: SubagentLaunchContrac
|
|
|
284
284
|
diagnostics.push({ code: "denied_required_tool", severity: "error", message });
|
|
285
285
|
return { ok: false, code: "denied_required_tool", message, diagnostics };
|
|
286
286
|
}
|
|
287
|
-
const artifactsEnabled = input.artifacts
|
|
287
|
+
const artifactsEnabled = input.artifacts === true;
|
|
288
288
|
const artifactsDir = artifactsEnabled ? getArtifactsDir(input.parentSessionFile ?? null, effectiveCwd, input.artifactDir ?? "project") : undefined;
|
|
289
289
|
const artifactPaths = artifactsDir ? getArtifactPaths(artifactsDir, runId, agent.name, 0) : undefined;
|
|
290
290
|
const outputPath = resolveSingleOutputPath(behavior.output, effectiveCwd, effectiveCwd, artifactsDir ? path.join(artifactsDir, "outputs", runId) : undefined);
|
|
@@ -51,7 +51,7 @@ import { SUBAGENT_CHILD_ENV, SUBAGENT_PARENT_SESSION_ENV } from "../runs/shared/
|
|
|
51
51
|
import { resolveCurrentSubagentCapabilityCeiling } from "../runs/shared/capability-ceiling.ts";
|
|
52
52
|
import { formatDuration, shortenPath } from "../shared/formatters.ts";
|
|
53
53
|
import { loadConfig } from "./config.ts";
|
|
54
|
-
import { buildSubagentToolDescription } from "./tool-description.ts";
|
|
54
|
+
import { buildSubagentToolDescription, SUBAGENT_PARENT_ROUTING_GUIDANCE } from "./tool-description.ts";
|
|
55
55
|
import {
|
|
56
56
|
type Details,
|
|
57
57
|
type SubagentState,
|
|
@@ -405,6 +405,10 @@ export default function registerSubagentExtension(pi: ExtensionAPI): void {
|
|
|
405
405
|
name: "subagent",
|
|
406
406
|
label: "Subagent",
|
|
407
407
|
description: buildSubagentToolDescription(config),
|
|
408
|
+
// Always-visible active-tool path: rendered into the main system prompt by
|
|
409
|
+
// buildSystemPrompt (default and custom-prompt branches). Parent-only; the
|
|
410
|
+
// child-safe fanout registration must not receive this guidance.
|
|
411
|
+
promptGuidelines: [SUBAGENT_PARENT_ROUTING_GUIDANCE],
|
|
408
412
|
parameters: SubagentParams,
|
|
409
413
|
|
|
410
414
|
prepareArguments(args) {
|
|
@@ -262,7 +262,7 @@ const ControlOverrides = Type.Object({
|
|
|
262
262
|
|
|
263
263
|
const SubagentParamsSchema = Type.Object({
|
|
264
264
|
agent: Type.Optional(Type.String({ description: "Agent name (SINGLE mode) or target for management get/update/delete" })),
|
|
265
|
-
task: Type.Optional(Type.String({ description: "Task
|
|
265
|
+
task: Type.Optional(Type.String({ description: "Task for SINGLE-mode execution, or an optional advisory intent for action:'list' (list only appends a task-aware recommendation and never launches work; explicitly call subagent with the recommended canonical agent name and the task to execute)" })),
|
|
266
266
|
// Management action (when present, tool operates in management mode)
|
|
267
267
|
action: Type.Optional(Type.String({
|
|
268
268
|
description: "Optional management/control action. Omit this field entirely for execution/delegation ({agent, task}, {tasks}, or {chain}); use it only for management/control actions."
|
|
@@ -321,7 +321,7 @@ const SubagentParamsSchema = Type.Object({
|
|
|
321
321
|
usageBudget: Type.Optional(UsageBudgetOverride),
|
|
322
322
|
agentScope: Type.Optional(Type.String({ description: "Agent discovery scope: 'user', 'project', or 'both' (default: 'both'; project wins on name collisions)" })),
|
|
323
323
|
cwd: Type.Optional(Type.String()),
|
|
324
|
-
artifacts: Type.Optional(Type.Boolean({ description: "Write debug artifacts (default:
|
|
324
|
+
artifacts: Type.Optional(Type.Boolean({ description: "Write debug artifacts (default: false)" })),
|
|
325
325
|
includeProgress: Type.Optional(Type.Boolean({ description: "Include full progress in result (default: false)" })),
|
|
326
326
|
share: Type.Optional(Type.Boolean({ description: "Upload session to GitHub Gist for sharing (default: false)" })),
|
|
327
327
|
sessionDir: Type.Optional(
|