@nghyane/arcane 0.1.7 → 0.1.10
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 +6 -0
- package/package.json +6 -6
- package/src/cli/update-cli.ts +2 -1
- package/src/cli.ts +2 -1
- package/src/config/settings-schema.ts +0 -10
- package/src/debug/system-info.ts +2 -1
- package/src/discovery/helpers.ts +1 -6
- package/src/index.ts +3 -1
- package/src/main.ts +2 -1
- package/src/memories/index.ts +3 -3
- package/src/modes/components/settings-defs.ts +0 -8
- package/src/patch/applicator.ts +12 -4
- package/src/prompts/agents/task.md +1 -1
- package/src/prompts/system/subagent-system-prompt.md +2 -14
- package/src/prompts/system/system-prompt.md +12 -14
- package/src/prompts/tools/task.md +49 -178
- package/src/prompts/tools/todo-write.md +4 -4
- package/src/sdk.ts +15 -16
- package/src/session/session-manager.ts +1 -3
- package/src/task/executor.ts +2 -2
- package/src/task/index.ts +5 -5
- package/src/task/types.ts +7 -20
- package/src/tools/index.ts +16 -33
- package/src/tools/subagent-tool.ts +5 -5
- package/src/tools/todo-write.ts +0 -37
- package/src/version.ts +3 -0
- package/src/prompts/system/subagent-submit-reminder.md +0 -11
- package/src/tools/jtd-to-json-schema.ts +0 -247
- package/src/tools/submit-result.ts +0 -152
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@nghyane/arcane",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.10",
|
|
5
5
|
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
|
6
6
|
"homepage": "https://github.com/nghyane/arcane",
|
|
7
7
|
"author": "Can Bölük",
|
|
@@ -44,12 +44,12 @@
|
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@mozilla/readability": "0.6.0",
|
|
47
|
-
"@nghyane/arcane-stats": "^0.1.
|
|
48
|
-
"@nghyane/arcane-agent": "^0.1.
|
|
49
|
-
"@nghyane/arcane-codemode": "^0.1.
|
|
50
|
-
"@nghyane/arcane-ai": "^0.1.
|
|
47
|
+
"@nghyane/arcane-stats": "^0.1.8",
|
|
48
|
+
"@nghyane/arcane-agent": "^0.1.8",
|
|
49
|
+
"@nghyane/arcane-codemode": "^0.1.9",
|
|
50
|
+
"@nghyane/arcane-ai": "^0.1.8",
|
|
51
51
|
"@nghyane/arcane-natives": "^0.1.7",
|
|
52
|
-
"@nghyane/arcane-tui": "^0.1.
|
|
52
|
+
"@nghyane/arcane-tui": "^0.1.8",
|
|
53
53
|
"@nghyane/arcane-utils": "^0.1.6",
|
|
54
54
|
"@sinclair/typebox": "^0.34.48",
|
|
55
55
|
"@xterm/headless": "^6.0.0",
|
package/src/cli/update-cli.ts
CHANGED
|
@@ -8,9 +8,10 @@ import { execSync, spawnSync } from "node:child_process";
|
|
|
8
8
|
import * as fs from "node:fs";
|
|
9
9
|
import { pipeline } from "node:stream/promises";
|
|
10
10
|
import { isEnoent } from "@nghyane/arcane-utils";
|
|
11
|
-
import { APP_NAME
|
|
11
|
+
import { APP_NAME } from "@nghyane/arcane-utils/dirs";
|
|
12
12
|
import chalk from "chalk";
|
|
13
13
|
import { theme } from "../modes/theme/theme";
|
|
14
|
+
import { VERSION } from "../version";
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* Detect if we're running as a Bun compiled binary.
|
package/src/cli.ts
CHANGED
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* lightweight CLI runner from pi-utils.
|
|
5
5
|
*/
|
|
6
6
|
import { type CommandEntry, run } from "@nghyane/arcane-utils/cli";
|
|
7
|
-
import { APP_NAME
|
|
7
|
+
import { APP_NAME } from "@nghyane/arcane-utils/dirs";
|
|
8
|
+
import { VERSION } from "./version";
|
|
8
9
|
|
|
9
10
|
// Detect known Bun errata that cause TUI crashes (e.g. Bun.stringWidth mishandling OSC sequences).
|
|
10
11
|
if (Bun.stringWidth("\x1b[0m\x1b]8;;\x07") !== 0) {
|
|
@@ -548,16 +548,6 @@ export const SETTINGS_SCHEMA = {
|
|
|
548
548
|
submenu: true,
|
|
549
549
|
},
|
|
550
550
|
},
|
|
551
|
-
"task.maxRecursionDepth": {
|
|
552
|
-
type: "number",
|
|
553
|
-
default: 2,
|
|
554
|
-
ui: {
|
|
555
|
-
tab: "tools",
|
|
556
|
-
label: "Task max recursion depth",
|
|
557
|
-
description: "How many levels deep subagents can spawn their own subagents",
|
|
558
|
-
submenu: true,
|
|
559
|
-
},
|
|
560
|
-
},
|
|
561
551
|
"task.disabledAgents": {
|
|
562
552
|
type: "array",
|
|
563
553
|
default: [] as string[],
|
package/src/debug/system-info.ts
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
* System information collection for debug reports.
|
|
3
3
|
*/
|
|
4
4
|
import * as os from "node:os";
|
|
5
|
-
import { getProjectDir
|
|
5
|
+
import { getProjectDir } from "@nghyane/arcane-utils/dirs";
|
|
6
|
+
import { VERSION } from "../version";
|
|
6
7
|
|
|
7
8
|
export interface SystemInfo {
|
|
8
9
|
os: string;
|
package/src/discovery/helpers.ts
CHANGED
|
@@ -232,12 +232,7 @@ export function parseAgentFields(frontmatter: Record<string, unknown>): ParsedAg
|
|
|
232
232
|
return null;
|
|
233
233
|
}
|
|
234
234
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
// Subagents with output schema need submit_result to return structured data
|
|
238
|
-
if (tools && frontmatter.output && !tools.includes("submit_result")) {
|
|
239
|
-
tools = [...tools, "submit_result"];
|
|
240
|
-
}
|
|
235
|
+
const tools = parseArrayOrCSV(frontmatter.tools);
|
|
241
236
|
|
|
242
237
|
const model = parseModelList(frontmatter.model);
|
|
243
238
|
const thinkingLevel = parseThinkingLevel(frontmatter);
|
package/src/index.ts
CHANGED
|
@@ -7,7 +7,7 @@ export { StringEnum } from "@nghyane/arcane-ai";
|
|
|
7
7
|
export { Container, Markdown, Spacer, Text } from "@nghyane/arcane-tui";
|
|
8
8
|
// Logging
|
|
9
9
|
export { logger } from "@nghyane/arcane-utils";
|
|
10
|
-
export { getAgentDir
|
|
10
|
+
export { getAgentDir } from "@nghyane/arcane-utils/dirs";
|
|
11
11
|
export { formatKeyHint, formatKeyHints } from "./config/keybindings";
|
|
12
12
|
export { ModelRegistry } from "./config/model-registry";
|
|
13
13
|
// Prompt templates
|
|
@@ -179,6 +179,7 @@ export {
|
|
|
179
179
|
loadSshTool,
|
|
180
180
|
PythonTool,
|
|
181
181
|
ReadTool,
|
|
182
|
+
type SubagentContext,
|
|
182
183
|
type ToolSession,
|
|
183
184
|
WriteTool,
|
|
184
185
|
} from "./sdk";
|
|
@@ -273,3 +274,4 @@ export {
|
|
|
273
274
|
type WriteToolDetails,
|
|
274
275
|
type WriteToolInput,
|
|
275
276
|
} from "./tools";
|
|
277
|
+
export { VERSION } from "./version";
|
package/src/main.ts
CHANGED
|
@@ -12,7 +12,7 @@ import * as path from "node:path";
|
|
|
12
12
|
import { createInterface } from "node:readline/promises";
|
|
13
13
|
import { type ImageContent, supportsXhigh } from "@nghyane/arcane-ai";
|
|
14
14
|
import { $env, postmortem } from "@nghyane/arcane-utils";
|
|
15
|
-
import { getProjectDir, setProjectDir
|
|
15
|
+
import { getProjectDir, setProjectDir } from "@nghyane/arcane-utils/dirs";
|
|
16
16
|
import chalk from "chalk";
|
|
17
17
|
import type { Args } from "./cli/args";
|
|
18
18
|
import { processFileArguments } from "./cli/file-processor";
|
|
@@ -33,6 +33,7 @@ import { type SessionInfo, SessionManager } from "./session/session-manager";
|
|
|
33
33
|
import { resolvePromptInput } from "./system-prompt";
|
|
34
34
|
import { getChangelogPath, getNewEntries, parseChangelog } from "./utils/changelog";
|
|
35
35
|
import { printTimings, time } from "./utils/timings";
|
|
36
|
+
import { VERSION } from "./version";
|
|
36
37
|
|
|
37
38
|
/** Conditional startup debug prints (stderr) when ARCANE_DEBUG_STARTUP is set */
|
|
38
39
|
const debugStartup = $env.ARCANE_DEBUG_STARTUP
|
package/src/memories/index.ts
CHANGED
|
@@ -121,12 +121,12 @@ export function startMemoryStartupTask(options: {
|
|
|
121
121
|
settings: Settings;
|
|
122
122
|
modelRegistry: ModelRegistry;
|
|
123
123
|
agentDir: string;
|
|
124
|
-
|
|
124
|
+
isSubagent: boolean;
|
|
125
125
|
}): void {
|
|
126
|
-
const { session, settings, modelRegistry, agentDir,
|
|
126
|
+
const { session, settings, modelRegistry, agentDir, isSubagent } = options;
|
|
127
127
|
const cfg = loadMemoryConfig(settings);
|
|
128
128
|
if (!cfg.enabled) return;
|
|
129
|
-
if (
|
|
129
|
+
if (isSubagent) return;
|
|
130
130
|
if (!session.sessionManager.getSessionFile()) return;
|
|
131
131
|
|
|
132
132
|
const dbPath = getAgentDbPath(agentDir);
|
|
@@ -85,14 +85,6 @@ const OPTION_PROVIDERS: Partial<Record<SettingPath, OptionProvider>> = {
|
|
|
85
85
|
{ value: "32", label: "32 tasks" },
|
|
86
86
|
{ value: "64", label: "64 tasks" },
|
|
87
87
|
],
|
|
88
|
-
// Task max recursion depth
|
|
89
|
-
"task.maxRecursionDepth": [
|
|
90
|
-
{ value: "-1", label: "Unlimited" },
|
|
91
|
-
{ value: "0", label: "None" },
|
|
92
|
-
{ value: "1", label: "Single" },
|
|
93
|
-
{ value: "2", label: "Double" },
|
|
94
|
-
{ value: "3", label: "Triple" },
|
|
95
|
-
],
|
|
96
88
|
// Todo max reminders
|
|
97
89
|
"todo.reminders.max": [
|
|
98
90
|
{ value: "1", label: "1 reminder" },
|
package/src/patch/applicator.ts
CHANGED
|
@@ -890,10 +890,11 @@ function applyCharacterMatch(
|
|
|
890
890
|
const adjustedNewText = adjustIndentation(normalizedOldText, matchOutcome.match.actualText, newText);
|
|
891
891
|
|
|
892
892
|
const warnings: string[] = [];
|
|
893
|
-
if (matchOutcome.
|
|
893
|
+
if (matchOutcome.match && matchOutcome.match.confidence < 0.97) {
|
|
894
894
|
const similarity = Math.round(matchOutcome.match.confidence * 100);
|
|
895
|
+
const qualifier = matchOutcome.dominantFuzzy ? "Dominant fuzzy" : "Fuzzy";
|
|
895
896
|
warnings.push(
|
|
896
|
-
|
|
897
|
+
`${qualifier} match applied in ${path} near line ${matchOutcome.match.startLine} (${similarity}% similar).`,
|
|
897
898
|
);
|
|
898
899
|
}
|
|
899
900
|
|
|
@@ -1152,9 +1153,16 @@ function computeReplacements(
|
|
|
1152
1153
|
|
|
1153
1154
|
const found = searchResult.index;
|
|
1154
1155
|
|
|
1155
|
-
if (
|
|
1156
|
+
if (
|
|
1157
|
+
searchResult.strategy === "prefix" ||
|
|
1158
|
+
searchResult.strategy === "substring" ||
|
|
1159
|
+
searchResult.strategy === "fuzzy" ||
|
|
1160
|
+
searchResult.strategy === "fuzzy-dominant"
|
|
1161
|
+
) {
|
|
1156
1162
|
const similarity = Math.round(searchResult.confidence * 100);
|
|
1157
|
-
warnings.push(
|
|
1163
|
+
warnings.push(
|
|
1164
|
+
`Non-exact match applied in ${path} near line ${found + 1} (${similarity}% similar, strategy: ${searchResult.strategy}).`,
|
|
1165
|
+
);
|
|
1158
1166
|
}
|
|
1159
1167
|
|
|
1160
1168
|
// Reject if match is ambiguous (prefix/substring matching found multiple matches)
|
|
@@ -8,7 +8,7 @@ Finish only the assigned work and return the minimum useful result.
|
|
|
8
8
|
- Avoid full-file reads unless necessary.
|
|
9
9
|
- Prefer edits to existing files over creating new ones.
|
|
10
10
|
- NEVER create documentation files (*.md) unless explicitly requested.
|
|
11
|
-
- When
|
|
11
|
+
- When done, write a concise summary of what you did as your final response. This is your output.
|
|
12
12
|
- Include the smallest relevant code snippet when discussing code or config.
|
|
13
13
|
- Follow the main agent's instructions.
|
|
14
14
|
</directives>
|
|
@@ -11,20 +11,8 @@ For additional parent conversation context, check {{contextFile}} (`tail -100` o
|
|
|
11
11
|
{{/if}}
|
|
12
12
|
|
|
13
13
|
<critical>
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
{{#if outputSchema}}
|
|
17
|
-
- If cannot complete, call `submit_result` with `status="aborted"` and error message. Do not provide success result or pretend completion.
|
|
18
|
-
{{else}}
|
|
19
|
-
- If cannot complete, call `submit_result` with `status="aborted"` and error message. Do not claim success.
|
|
20
|
-
{{/if}}
|
|
21
|
-
{{#if outputSchema}}
|
|
22
|
-
- `data` parameter MUST be valid JSON matching TypeScript interface:
|
|
23
|
-
```ts
|
|
24
|
-
{{jtdToTypeScript outputSchema}}
|
|
25
|
-
```
|
|
26
|
-
{{/if}}
|
|
27
|
-
- If cannot complete, call `submit_result` exactly once with result indicating failure/abort status (use failure/notes field if available). Do not claim success.
|
|
14
|
+
- When done, stop. Your final text response is your output — the parent receives it as the task result.
|
|
15
|
+
- If cannot complete, report failure clearly in your final response. Do not claim success.
|
|
28
16
|
- Do NOT abort due to uncertainty or missing info that can be obtained via tools or repo context. Use `find`/`grep`/`read` first, then proceed with reasonable defaults if multiple options are acceptable.
|
|
29
17
|
- Aborting is only acceptable when truly blocked after exhausting tools and reasonable attempts. If you abort, include what you tried and the exact blocker in the result.
|
|
30
18
|
- Keep going until request is fully fulfilled. This matters.
|
|
@@ -115,8 +115,17 @@ The question is not "does this work?" but "under what conditions? What happens o
|
|
|
115
115
|
- Skip entirely for single-step or trivial requests.
|
|
116
116
|
|
|
117
117
|
{{#has tools "task"}}
|
|
118
|
-
###
|
|
119
|
-
|
|
118
|
+
### Delegation
|
|
119
|
+
You have subagents. Pick the right one:
|
|
120
|
+
- "I need to think through architecture/plan" → **Oracle**
|
|
121
|
+
- "I need to understand unfamiliar code" → **Explore / Librarian**
|
|
122
|
+
- "I know what to do, need parallel execution" → **Task tool**
|
|
123
|
+
|
|
124
|
+
Workflow for complex work: Oracle (plan) → Explore (validate scope) → Task (execute).
|
|
125
|
+
|
|
126
|
+
Task tool is a fire-and-forget executor — a productive junior engineer who cannot ask follow-ups once started. Prompt it with detailed instructions, enumerate deliverables, include constraints and verification steps.
|
|
127
|
+
|
|
128
|
+
Use Task tool when work genuinely forks into independent streams:
|
|
120
129
|
- Editing 4+ files with no dependencies between edits
|
|
121
130
|
- Investigating 2+ independent subsystems
|
|
122
131
|
- Work that decomposes into pieces not needing each other's results
|
|
@@ -231,18 +240,7 @@ Current date: {{date}}
|
|
|
231
240
|
|
|
232
241
|
{{#has tools "task"}}
|
|
233
242
|
<parallel_reflex>
|
|
234
|
-
When work forks, you fork.
|
|
235
|
-
|
|
236
|
-
Notice the sequential habit:
|
|
237
|
-
- Comfort in doing one thing at a time
|
|
238
|
-
- Illusion that order = correctness
|
|
239
|
-
- Assumption that B depends on A
|
|
240
|
-
**Use Task tool when:**
|
|
241
|
-
- Editing 4+ files with no dependencies between edits
|
|
242
|
-
- Investigating 2+ independent subsystems
|
|
243
|
-
- Work decomposes into pieces not needing each other's results
|
|
244
|
-
|
|
245
|
-
Sequential work requires justification. If you cannot articulate why B depends on A → parallelize.
|
|
243
|
+
When work forks, you fork. Sequential work requires justification — if you cannot articulate why B depends on A, parallelize via Task tool.
|
|
246
244
|
</parallel_reflex>
|
|
247
245
|
{{/has}}
|
|
248
246
|
|
|
@@ -1,18 +1,12 @@
|
|
|
1
1
|
# Task
|
|
2
2
|
|
|
3
|
-
Launch
|
|
3
|
+
Launch a fire-and-forget subagent to execute well-scoped work. Think of it as a productive junior engineer who cannot ask follow-ups once started.
|
|
4
|
+
- **Use for**: Multi-file implementations, cross-layer refactors, mass migrations, boilerplate generation
|
|
5
|
+
- **Don't use for**: Exploratory work, architectural decisions, single-file edits, reading a file
|
|
4
6
|
|
|
5
|
-
##
|
|
6
|
-
Subagents receive the **full system prompt**, including AGENTS.md, context files, and skills. Do NOT repeat project rules, coding conventions, or style guidelines in `context` — they already have them.
|
|
7
|
+
## Subagent capabilities
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
Subagents have no access to your conversation history. They don't know:
|
|
10
|
-
- Decisions you made but didn't write down
|
|
11
|
-
- Which approach you chose among alternatives
|
|
12
|
-
- What you learned from reading files during this session
|
|
13
|
-
- Requirements the user stated only in conversation
|
|
14
|
-
|
|
15
|
-
Subagents CAN grep the parent conversation file for supplementary details.
|
|
9
|
+
Subagents receive the **full system prompt**, including AGENTS.md, context files, and skills. They have no access to your conversation history — they don't know decisions you made, approaches you chose, or requirements stated only in conversation. Subagents CAN grep the parent conversation file for supplementary details.
|
|
16
10
|
---
|
|
17
11
|
|
|
18
12
|
## Parameters
|
|
@@ -22,35 +16,18 @@ Subagents CAN grep the parent conversation file for supplementary details.
|
|
|
22
16
|
Shared background prepended verbatim to every task `assignment`. Use only for session-specific information subagents lack.
|
|
23
17
|
|
|
24
18
|
<critical>
|
|
25
|
-
Do NOT include project rules, coding conventions, or style guidelines — subagents already have AGENTS.md
|
|
19
|
+
Do NOT include project rules, coding conventions, or style guidelines — subagents already have AGENTS.md. Restating any rule from AGENTS.md in `context` is a bug.
|
|
26
20
|
</critical>
|
|
27
|
-
**Before writing each line of context, ask:** "Would this sentence be true for ANY task in this repo, or only for THIS specific batch?" If it applies to any task →
|
|
28
|
-
|
|
29
|
-
WRONG — restating project rules the subagent already has:
|
|
30
|
-
```
|
|
31
|
-
## Constraints
|
|
32
|
-
- Use X import style, not Y (per AGENTS.md)
|
|
33
|
-
- Use Z for private fields per AGENTS.md
|
|
34
|
-
- Run the formatter after changes
|
|
35
|
-
- Follow the logging convention
|
|
36
|
-
```
|
|
37
|
-
Every line above restates a project convention. The subagent reads AGENTS.md. Delete them all.
|
|
38
|
-
|
|
39
|
-
RIGHT — only session-specific decisions the subagent cannot infer from project files:
|
|
40
|
-
```
|
|
41
|
-
## Constraints
|
|
42
|
-
- We decided to use approach A over B (session decision)
|
|
43
|
-
- The migration target type is `Foo` from `bar` package (looked up this session)
|
|
44
|
-
```
|
|
21
|
+
**Before writing each line of context, ask:** "Would this sentence be true for ANY task in this repo, or only for THIS specific batch?" If it applies to any task → the subagent already has it → delete the line.
|
|
45
22
|
|
|
46
23
|
Use template; omit non-applicable sections:
|
|
47
24
|
|
|
48
25
|
````
|
|
49
26
|
## Goal
|
|
50
|
-
One sentence: batch accomplishes together.
|
|
27
|
+
One sentence: what the batch accomplishes together.
|
|
51
28
|
|
|
52
29
|
## Non-goals
|
|
53
|
-
Explicitly exclude tempting scope — what tasks must not touch
|
|
30
|
+
Explicitly exclude tempting scope — what tasks must not touch.
|
|
54
31
|
|
|
55
32
|
## Constraints
|
|
56
33
|
- Task-specific MUST / MUST NOT rules not already in AGENTS.md
|
|
@@ -58,49 +35,43 @@ Explicitly exclude tempting scope — what tasks must not touch/attempt.
|
|
|
58
35
|
|
|
59
36
|
## Reference Files
|
|
60
37
|
- `path/to/file.ext` — pattern demo
|
|
61
|
-
- `path/to/other.ext` — reuse or avoid
|
|
62
38
|
|
|
63
39
|
## API Contract (if tasks produce/consume shared interface)
|
|
64
40
|
```language
|
|
65
|
-
// Exact type definitions, function signatures
|
|
41
|
+
// Exact type definitions, function signatures
|
|
66
42
|
```
|
|
67
43
|
|
|
68
44
|
## Acceptance (global)
|
|
69
45
|
- Definition of "done" for batch
|
|
70
|
-
-
|
|
46
|
+
- For parallel tasks, build/test/lint verification happens AFTER all tasks complete — not inside tasks. Single tasks may self-verify.
|
|
71
47
|
````
|
|
72
|
-
**Belongs in `context`**:
|
|
73
|
-
**
|
|
74
|
-
**Does NOT belong in `context`**: project rules already in AGENTS.md/context files, per-task file lists, one-off requirements (go in `assignment`), and strict response contracts that only apply to one task.
|
|
48
|
+
**Belongs in `context`**: session decisions, reference paths, shared type definitions, API contracts, global acceptance — anything 2+ tasks need that isn't in AGENTS.md.
|
|
49
|
+
**Does NOT belong**: project rules from AGENTS.md, per-task file lists, one-off requirements (go in `assignment`).
|
|
75
50
|
|
|
76
51
|
### `tasks` (required)
|
|
77
52
|
|
|
78
|
-
Array tasks execute in parallel.
|
|
53
|
+
Array of tasks that execute in parallel.
|
|
79
54
|
|
|
80
55
|
|Field|Required|Purpose|
|
|
81
56
|
|---|---|---|
|
|
82
|
-
|`id
|
|
83
|
-
|`description
|
|
84
|
-
|`assignment
|
|
85
|
-
|`skills`||Skill names preload. Use only when changes correctness
|
|
86
|
-
|
|
87
|
-
Outputs are free-form text/JSON from each subtask. If you need strict structure, define it clearly inside each `assignment` and validate at the caller.
|
|
57
|
+
|`id`|yes|CamelCase identifier, max 32 chars|
|
|
58
|
+
|`description`|yes|Short one-liner for UI display only — not seen by subagent|
|
|
59
|
+
|`assignment`|yes|Complete per-task instructions (see below)|
|
|
60
|
+
|`skills`||Skill names to preload. Use only when it changes correctness.|
|
|
88
61
|
---
|
|
89
62
|
|
|
90
63
|
## Writing an assignment
|
|
91
64
|
|
|
92
|
-
<critical
|
|
93
|
-
|
|
94
|
-
`assignment` must contain enough info for agent to act **without asking a clarifying question**.
|
|
95
|
-
**Minimum bar:** assignment under ~8 lines or missing acceptance criteria = too vague. One-liners guaranteed failure.
|
|
65
|
+
<critical>
|
|
66
|
+
`assignment` must contain enough info for the subagent to act **without asking a clarifying question**. One-liners guarantee failure.
|
|
96
67
|
|
|
97
|
-
Use structure
|
|
68
|
+
Use this structure:
|
|
98
69
|
|
|
99
70
|
```
|
|
100
71
|
## Target
|
|
101
72
|
- Files: exact path(s)
|
|
102
73
|
- Symbols/entrypoints: specific functions, types, exports
|
|
103
|
-
- Non-goals: what task must NOT touch
|
|
74
|
+
- Non-goals: what task must NOT touch
|
|
104
75
|
|
|
105
76
|
## Change
|
|
106
77
|
- Step-by-step: add/remove/rename/restructure
|
|
@@ -108,168 +79,68 @@ Use structure every assignment:
|
|
|
108
79
|
|
|
109
80
|
## Edge Cases / Don't Break
|
|
110
81
|
- Tricky case 1: ...
|
|
111
|
-
-
|
|
112
|
-
- Existing behavior must survive: ...
|
|
82
|
+
- Existing behavior that must survive: ...
|
|
113
83
|
|
|
114
84
|
## Acceptance (task-local)
|
|
115
85
|
- Expected behavior or observable result
|
|
116
|
-
- DO NOT include project-wide build/test/lint commands
|
|
86
|
+
- For parallel tasks: DO NOT include project-wide build/test/lint commands
|
|
117
87
|
```
|
|
118
88
|
|
|
119
|
-
`context` carries shared background. `assignment` carries only delta: file-specific instructions, local edge cases, per-task acceptance
|
|
120
|
-
|
|
121
|
-
### Anti-patterns (ban these)
|
|
122
|
-
**Vague assignments** — agent guesses wrong or stalls:
|
|
123
|
-
- "Refactor this to be cleaner."
|
|
124
|
-
- "Migrate to N-API."
|
|
125
|
-
- "Fix the bug in streaming."
|
|
126
|
-
- "Update all constructors in `src/**/*.ts`."
|
|
127
|
-
**Vague context** — forces agent invent conventions:
|
|
128
|
-
- "Use existing patterns."
|
|
129
|
-
- "Follow conventions."
|
|
130
|
-
- "No WASM."
|
|
131
|
-
**Redundant context** — wastes tokens repeating what subagents already have:
|
|
132
|
-
- Restating AGENTS.md rules (coding style, import conventions, formatting commands, logger usage, etc.)
|
|
133
|
-
- Repeating project constraints from context files
|
|
134
|
-
- Listing tool/framework preferences already documented in the repo
|
|
135
|
-
|
|
136
|
-
If a constraint appears in AGENTS.md, it MUST NOT appear in `context`. The subagent has the full system prompt.
|
|
137
|
-
|
|
138
|
-
If tempted to write above, expand using templates.
|
|
139
|
-
**Test/lint commands in parallel tasks** — edit wars:
|
|
140
|
-
Parallel agents share working tree. If two agents run `bun check` or `bun test` concurrently, they see each other's half-finished edits, "fix" phantom errors, loop. **Never tell parallel tasks run project-wide build/test/lint commands.** Each task edits, stops. Caller verifies after all tasks complete.
|
|
141
|
-
**If you can't specify scope yet**, create **Discovery task** first: enumerate files, find callsites, list candidates. Then fan out with explicit paths.
|
|
89
|
+
`context` carries shared background. `assignment` carries only delta: file-specific instructions, local edge cases, per-task acceptance.
|
|
142
90
|
|
|
143
91
|
### Delegate intent, not keystrokes
|
|
144
92
|
|
|
145
|
-
Your role
|
|
146
|
-
**Be specific about:** constraints, naming
|
|
147
|
-
**Delegate:** code reading, approach selection, exact edit locations, implementation details.
|
|
148
|
-
|
|
149
|
-
Micromanaging (you think, agent types):
|
|
150
|
-
```
|
|
151
|
-
assignment: "In src/api/handler.ts, line 47, change `throw err` to `throw new ApiError(err.message, 500)`.
|
|
152
|
-
On line 63, wrap fetch call try/catch return 502 on failure.
|
|
153
|
-
On line 89, add null check before accessing resp.body..."
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
Delegating (agent thinks within constraints):
|
|
157
|
-
```
|
|
158
|
-
assignment: "## Target\n- Files: src/api/handler.ts\n\n## Change\nImprove error handling: replace raw throws
|
|
159
|
-
with typed ApiError instances, add try/catch around external calls, guard against null responses.\n\n
|
|
160
|
-
## Edge Cases / Don't Break\n- Existing error codes in tests must still match\n
|
|
161
|
-
- Don't change public function signatures"
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
First style wastes your time, brittle if code shifts. Second gives agent room to do work.
|
|
93
|
+
Your role is tech lead: set direction, define boundaries, call out pitfalls — then get out of the way. Don't dictate line-by-line edits.
|
|
94
|
+
**Be specific about:** constraints, naming, API contracts, "don't break" items, acceptance criteria.
|
|
95
|
+
**Delegate:** code reading, approach selection, exact edit locations, implementation details.
|
|
165
96
|
</critical>
|
|
166
97
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
</tasks>
|
|
176
|
-
</example>
|
|
177
|
-
|
|
178
|
-
<example type="good" label="Shared rules in context, only deltas in assignment">
|
|
179
|
-
<context>
|
|
180
|
-
## Goal
|
|
181
|
-
Port WASM modules to N-API, matching existing arcane-natives conventions.
|
|
182
|
-
|
|
183
|
-
## Non-goals
|
|
184
|
-
Do not touch TS bindings or downstream consumers — separate phase.
|
|
185
|
-
|
|
186
|
-
## Constraints
|
|
187
|
-
- MUST use `#[napi]` attribute macro on all exports
|
|
188
|
-
- MUST return `napi::Result<T>` for fallible ops; never panic
|
|
189
|
-
- MUST use `spawn_blocking` for filesystem I/O or >1ms work
|
|
190
|
-
...
|
|
191
|
-
|
|
192
|
-
## Acceptance (global)
|
|
193
|
-
- Caller verifies after all tasks: `cargo test -p arcane-natives` and `cargo build -p arcane-natives` with no warnings
|
|
194
|
-
- Individual tasks must NOT run these commands themselves
|
|
195
|
-
</context>
|
|
196
|
-
|
|
197
|
-
<tasks>
|
|
198
|
-
<task name="PortGrep">
|
|
199
|
-
<description>Port grep module to N-API</description>
|
|
200
|
-
<assignment>
|
|
201
|
-
## Target
|
|
202
|
-
- Files: `src/grep.rs`, `src/lib.rs` (registration only)
|
|
203
|
-
- Symbols: search, search_multi, compile_pattern
|
|
204
|
-
|
|
205
|
-
## Change
|
|
206
|
-
- Implement three N-API exports in grep.rs:
|
|
207
|
-
- `search(pattern: JsString, path: JsString, env: Env) -> napi::Result<Vec<Match>>`
|
|
208
|
-
...
|
|
209
|
-
|
|
210
|
-
## Acceptance (task-local)
|
|
211
|
-
- Three functions exported with correct signatures (caller verifies build after all tasks)
|
|
212
|
-
</assignment>
|
|
213
|
-
</task>
|
|
214
|
-
|
|
215
|
-
<task name="PortHighlight">
|
|
216
|
-
<description>Port highlight module to N-API</description>
|
|
217
|
-
<assignment>
|
|
218
|
-
## Target
|
|
219
|
-
- Files: `src/highlight.rs`, `src/lib.rs` (registration only)
|
|
220
|
-
...
|
|
221
|
-
</assignment>
|
|
222
|
-
</task>
|
|
223
|
-
</tasks>
|
|
224
|
-
</example>
|
|
98
|
+
### Anti-patterns
|
|
99
|
+
**Vague assignments** — subagent guesses wrong or stalls:
|
|
100
|
+
- "Refactor this to be cleaner."
|
|
101
|
+
- "Fix the bug in streaming."
|
|
102
|
+
- "Update all constructors in `src/**/*.ts`."
|
|
103
|
+
**Test/lint in parallel tasks** — edit wars:
|
|
104
|
+
Parallel agents share working tree. If two agents run `bun check` concurrently, they see each other's half-finished edits, "fix" phantom errors, loop. **Never tell parallel tasks to run project-wide build/test/lint.** Each task edits, stops. Caller verifies after all complete. Single-task launches may include verification.
|
|
105
|
+
**If you can't specify scope yet**, create a **Discovery task** first: enumerate files, find callsites, list candidates. Then fan out with explicit paths.
|
|
225
106
|
---
|
|
226
107
|
|
|
227
108
|
## Task scope
|
|
228
109
|
|
|
229
|
-
Each task small, well-defined
|
|
230
|
-
**Signs task too broad:**
|
|
231
|
-
|
|
232
|
-
- Assignment says "update all" / "migrate everything" / "refactor across"
|
|
233
|
-
- Scope covers entire package or directory tree
|
|
234
|
-
**Fix:** enumerate files first (grep/glob discovery), then fan out one task per file or small cluster.
|
|
110
|
+
Each task: small, well-defined — **at most 3-5 files**.
|
|
111
|
+
**Signs task is too broad:** file paths use globs, assignment says "update all" / "migrate everything", scope covers entire package.
|
|
112
|
+
**Fix:** enumerate files first (grep/glob), then fan out one task per file or small cluster.
|
|
235
113
|
---
|
|
236
114
|
|
|
237
115
|
## Parallelization
|
|
238
116
|
**Test:** Can task B produce correct output without seeing task A's result?
|
|
239
117
|
- **Yes** → parallelize
|
|
240
|
-
- **No** →
|
|
118
|
+
- **No** → sequential (A completes, then launch B with A's output in context)
|
|
241
119
|
|
|
242
120
|
### Must be sequential
|
|
243
121
|
|
|
244
122
|
|First|Then|Reason|
|
|
245
123
|
|---|---|---|
|
|
246
124
|
|Define types/interfaces|Implement consumers|Consumers need contract|
|
|
247
|
-
|Create API exports|Write bindings/callers|Callers need
|
|
248
|
-
|Scaffold structure|Implement bodies|Bodies need shape|
|
|
125
|
+
|Create API exports|Write bindings/callers|Callers need signatures|
|
|
249
126
|
|Core module|Dependent modules|Dependents import from core|
|
|
250
|
-
|Schema/DB migration|Application logic|Logic depends on new schema shape|
|
|
251
127
|
|
|
252
128
|
### Safe to parallelize
|
|
253
129
|
- Independent modules, no cross-imports
|
|
254
130
|
- Tests for already-implemented code
|
|
255
131
|
- Isolated file-scoped refactors
|
|
256
|
-
- Documentation for stable APIs
|
|
257
|
-
|
|
258
|
-
### Phased execution
|
|
259
132
|
|
|
260
|
-
|
|
261
|
-
**Phase 1 —
|
|
262
|
-
**Phase 2 — Parallel
|
|
133
|
+
### Multi-phase pattern
|
|
134
|
+
**Phase 1 — Sequential**: define shared contracts (types, interfaces, schemas).
|
|
135
|
+
**Phase 2 — Parallel**: fan out tasks consuming same known interface.
|
|
263
136
|
**Phase 3 — Integration** (do yourself): wire modules, fix mismatches, verify builds.
|
|
264
|
-
**Phase 4 — Dependent layer**: fan out tasks consuming Phase 2 outputs.
|
|
265
137
|
---
|
|
266
138
|
|
|
267
139
|
## Pre-flight checklist
|
|
268
140
|
|
|
269
141
|
Before calling tool, verify:
|
|
270
|
-
- [ ] `context` includes only session-specific info not already in AGENTS.md
|
|
271
|
-
- [ ] Each
|
|
272
|
-
- [ ]
|
|
273
|
-
- [ ]
|
|
274
|
-
- [ ]
|
|
275
|
-
- [ ] No task runs project-wide build/test/lint — you do after all tasks complete
|
|
142
|
+
- [ ] `context` includes only session-specific info not already in AGENTS.md
|
|
143
|
+
- [ ] Each assignment has Target, Change, Edge Cases, Acceptance sections
|
|
144
|
+
- [ ] Assignments reference exact file paths (no globs)
|
|
145
|
+
- [ ] Scope small, file paths explicit
|
|
146
|
+
- [ ] Parallel tasks don't run project-wide build/test/lint — you do after all tasks complete (single tasks may self-verify)
|
|
@@ -18,11 +18,11 @@ Use proactively:
|
|
|
18
18
|
- in_progress: working
|
|
19
19
|
- completed: finished
|
|
20
20
|
2. **Task Management**:
|
|
21
|
-
- Update status
|
|
22
|
-
- Mark
|
|
23
|
-
-
|
|
21
|
+
- Update status each turn
|
|
22
|
+
- Mark completed after each code execution finishes — do not defer to a later turn
|
|
23
|
+
- Multiple tasks may be in_progress simultaneously when working in parallel
|
|
24
24
|
- Remove tasks no longer relevant
|
|
25
|
-
-
|
|
25
|
+
- Mark tasks completed as they finish, regardless of list order
|
|
26
26
|
3. **Task Completion Requirements**:
|
|
27
27
|
- ONLY mark completed when FULLY accomplished
|
|
28
28
|
- On errors/blockers/inability to finish, keep in_progress
|