@haoyiyin/workflow 0.2.2 → 0.2.4
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/package.json +9 -8
- package/src/agents/contracts.ts +559 -0
- package/src/agents/dispatcher-enhanced.ts +350 -0
- package/src/agents/dispatcher.ts +680 -0
- package/src/agents/index.ts +48 -0
- package/src/agents/resilience.ts +255 -0
- package/src/agents/token-budget.ts +83 -0
- package/src/agents/types.ts +73 -0
- package/src/guard/main-agent.ts +245 -0
- package/src/hooks/builtin/index.ts +8 -0
- package/src/hooks/builtin/on-error.ts +23 -0
- package/src/hooks/builtin/post-execute.ts +40 -0
- package/src/hooks/builtin/post-plan.ts +23 -0
- package/src/hooks/builtin/pre-execute.ts +30 -0
- package/src/hooks/builtin/pre-plan.ts +26 -0
- package/src/hooks/index.ts +7 -0
- package/src/hooks/loader.ts +98 -0
- package/src/hooks/manager.ts +99 -0
- package/src/hooks/types-enhanced.ts +38 -0
- package/src/hooks/types.ts +35 -0
- package/src/index.ts +127 -0
- package/src/persistence/index.ts +17 -0
- package/src/persistence/plan-md.ts +141 -0
- package/src/persistence/state-md.ts +167 -0
- package/src/persistence/types.ts +89 -0
- package/src/router/classifier.ts +610 -0
- package/src/router/guard.ts +483 -0
- package/src/router/index.ts +22 -0
- package/src/router/router.ts +108 -0
- package/src/router/types.ts +127 -0
- package/src/skills/agents-md/SKILL.md +45 -0
- package/src/skills/agents-md/index.ts +33 -0
- package/src/skills/execute-plan/SKILL.md +60 -0
- package/src/skills/execute-plan/index.ts +970 -0
- package/src/skills/index.ts +13 -0
- package/src/skills/quick-task/SKILL.md +54 -0
- package/src/skills/quick-task/index.ts +346 -0
- package/src/skills/registry.ts +59 -0
- package/src/skills/review-diff/SKILL.md +53 -0
- package/src/skills/review-diff/index.ts +394 -0
- package/src/skills/skill.ts +59 -0
- package/src/skills/systematic-debugging/SKILL.md +56 -0
- package/src/skills/systematic-debugging/index.ts +404 -0
- package/src/skills/tdd/SKILL.md +52 -0
- package/src/skills/tdd/index.ts +409 -0
- package/src/skills/to-plan/SKILL.md +56 -0
- package/src/skills/to-plan/index-enhanced.ts +551 -0
- package/src/skills/to-plan/index.ts +586 -0
- package/src/skills/types.ts +47 -0
- package/src/state/cleanup.ts +118 -0
- package/src/state/index.ts +8 -0
- package/src/state/manager.ts +96 -0
- package/src/state/persistence.ts +77 -0
- package/src/state/types.ts +30 -0
- package/src/state/validator.ts +78 -0
- package/src/types.ts +102 -0
- package/src/utils/compress.ts +347 -0
- package/src/utils/git.ts +82 -0
- package/src/utils/index.ts +6 -0
- package/src/utils/logger.ts +23 -0
- package/src/utils/paths.ts +55 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Router system types - Controls all user input routing
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { SubagentConfig, SubagentResult } from '../agents/types.js'
|
|
6
|
+
|
|
7
|
+
/** Classification of user intent */
|
|
8
|
+
export type IntentType =
|
|
9
|
+
| 'plan' // Needs planning (complex, multi-step)
|
|
10
|
+
| 'quick-task' // Small scoped task (trivial edit, small fix)
|
|
11
|
+
| 'execute' // Execute approved plan
|
|
12
|
+
| 'review' // Review code/diff
|
|
13
|
+
| 'debug' // Systematic debugging
|
|
14
|
+
| 'tdd' // Test-driven development
|
|
15
|
+
| 'general' // Catch-all for other queries
|
|
16
|
+
|
|
17
|
+
export interface IntentClassification {
|
|
18
|
+
type: IntentType
|
|
19
|
+
confidence: number // 0-1
|
|
20
|
+
reasoning: string
|
|
21
|
+
suggestedAgent: string
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface RouterConfig {
|
|
25
|
+
/** Default model for subagents */
|
|
26
|
+
defaultModel: string
|
|
27
|
+
/** Threshold for routing to quick-task vs to-plan */
|
|
28
|
+
planningThreshold: number
|
|
29
|
+
/** Max tokens before forcing subagent dispatch */
|
|
30
|
+
maxMainAgentTokens: number
|
|
31
|
+
/** Whether to auto-route based on keywords */
|
|
32
|
+
autoRoute: boolean
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface RoutingDecision {
|
|
36
|
+
/** The subagent to dispatch */
|
|
37
|
+
subagent: SubagentConfig
|
|
38
|
+
/** Contract/prompt for the subagent */
|
|
39
|
+
contract: SubagentContract
|
|
40
|
+
/** Whether to wait for result or stream */
|
|
41
|
+
async: boolean
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface SubagentContract {
|
|
45
|
+
/** What this subagent is allowed to do */
|
|
46
|
+
permissions: PermissionSet
|
|
47
|
+
/** Exact prompt to send */
|
|
48
|
+
prompt: string
|
|
49
|
+
/** Required output format */
|
|
50
|
+
outputSchema?: Record<string, unknown>
|
|
51
|
+
/** Files this subagent owns */
|
|
52
|
+
owns: string[]
|
|
53
|
+
/** Files this subagent may read */
|
|
54
|
+
reads: string[]
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface PermissionSet {
|
|
58
|
+
readFiles: boolean
|
|
59
|
+
searchCode: boolean
|
|
60
|
+
runCommands: boolean
|
|
61
|
+
writeFiles: boolean
|
|
62
|
+
gitOperations: boolean
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface RouterResult {
|
|
66
|
+
decision: RoutingDecision
|
|
67
|
+
/** Estimated token usage */
|
|
68
|
+
estimatedTokens: number
|
|
69
|
+
/** Fallback if subagent fails */
|
|
70
|
+
fallbackStrategy: 'retry' | 'escalate' | 'abort'
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface ExecutionResult {
|
|
74
|
+
success: boolean
|
|
75
|
+
result?: SubagentResult
|
|
76
|
+
error?: string
|
|
77
|
+
/** Tokens used by entire routing chain */
|
|
78
|
+
totalTokens: number
|
|
79
|
+
/** Time taken */
|
|
80
|
+
duration: number
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/** Input to the router: raw request + classification context. */
|
|
84
|
+
export interface RouterInput {
|
|
85
|
+
/** Raw user request text */
|
|
86
|
+
request: string
|
|
87
|
+
/** Whether a plan file already exists */
|
|
88
|
+
planFileExists: boolean
|
|
89
|
+
/** Whether mid-execution of a plan */
|
|
90
|
+
isExecutingPlan: boolean
|
|
91
|
+
/** Whether there are uncommitted changes */
|
|
92
|
+
hasUncommittedChanges: boolean
|
|
93
|
+
/** Current git branch */
|
|
94
|
+
currentBranch?: string
|
|
95
|
+
/** Files mentioned by the user */
|
|
96
|
+
mentionedFiles: string[]
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/** Output from the router: classification + full routing decision. */
|
|
100
|
+
export interface RouterOutput {
|
|
101
|
+
classification: IntentClassification
|
|
102
|
+
routing: RoutingDecision
|
|
103
|
+
confidence: number
|
|
104
|
+
matchedRule: string
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** Main Agent is NEVER allowed to do these */
|
|
108
|
+
export const MAIN_AGENT_PROHIBITED = {
|
|
109
|
+
readSourceFiles: true, // ❌ Cannot read .ts, .js, .py, etc.
|
|
110
|
+
searchCodebase: true, // ❌ Cannot search/grep
|
|
111
|
+
writeFiles: true, // ❌ Cannot write any files
|
|
112
|
+
runBuildCommands: true, // ❌ Cannot npm build, tsc, etc.
|
|
113
|
+
runTests: true, // ❌ Cannot run tests
|
|
114
|
+
editLargeFiles: true, // ❌ Cannot edit >50 lines
|
|
115
|
+
longRunningTasks: true, // ❌ Cannot run >30s tasks
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** Keywords that trigger specific routes */
|
|
119
|
+
export const ROUTE_KEYWORDS: Record<IntentType, string[]> = {
|
|
120
|
+
plan: ['plan', 'implement', 'add feature', 'refactor', 'migrate', 'create'],
|
|
121
|
+
'quick-task': ['fix typo', 'rename', 'small change', 'quick', 'trivial'],
|
|
122
|
+
execute: ['execute', 'run plan', 'do plan', 'implement plan'],
|
|
123
|
+
review: ['review', 'check code', 'audit', 'review diff', 'cr'],
|
|
124
|
+
debug: ['debug', 'fix bug', 'investigate', 'root cause', 'flaky'],
|
|
125
|
+
tdd: ['tdd', 'test first', 'red green', 'write test'],
|
|
126
|
+
general: ['what', 'how', 'explain', 'tell me', 'search', 'find'],
|
|
127
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: agents-md
|
|
3
|
+
description: Create or update agent instruction files (CLAUDE.md, AGENTS.md, CONTEXT.md) from repo evidence.
|
|
4
|
+
requires: []
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## ⛔ MAIN AGENT CONSTRAINT
|
|
8
|
+
|
|
9
|
+
You are a THIN DISPATCHER. Your ONLY job is to dispatch subagents.
|
|
10
|
+
You MUST NOT: read source files, search code, write/edit files, run tests, run git commands.
|
|
11
|
+
You MAY only: read plan/state files, dispatch subagents via Agent tool, relay results.
|
|
12
|
+
For EVERY user request (including this skill), dispatch a subagent. Never execute yourself.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Use/Exclude Matrix
|
|
17
|
+
|
|
18
|
+
| Use When | Exclude When |
|
|
19
|
+
|---|---|
|
|
20
|
+
| Initializing or updating project agent instructions | File already exists and is comprehensive |
|
|
21
|
+
| New project onboarding | Project has no package.json or README |
|
|
22
|
+
| Adding CLAUDE.md to a repo | File was just created and needs no update |
|
|
23
|
+
| Updating after major tech stack change | Minor wording/polish changes |
|
|
24
|
+
|
|
25
|
+
## Workflow
|
|
26
|
+
|
|
27
|
+
1. **Collect Evidence** — Dispatch explorer subagent to read package.json, README, and any existing instruction file.
|
|
28
|
+
2. **Write Instructions** — Dispatch implementer subagent to create/update the target file with Overview, Tech Stack, Commands, and Conventions sections.
|
|
29
|
+
|
|
30
|
+
## Output Spec
|
|
31
|
+
|
|
32
|
+
| Field | Type | Description |
|
|
33
|
+
|---|---|---|
|
|
34
|
+
| `filePath` | string | Name of the created/updated file (CLAUDE.md, AGENTS.md, or CONTEXT.md) |
|
|
35
|
+
| `mode` | enum | `created` or `updated` |
|
|
36
|
+
| `evidence` | string[] | Source files used as evidence |
|
|
37
|
+
| `summary` | string | Human-readable result |
|
|
38
|
+
|
|
39
|
+
## Error Handling
|
|
40
|
+
|
|
41
|
+
| Error | Action |
|
|
42
|
+
|---|---|
|
|
43
|
+
| Explorer fails to read sources | Write instructions based on available evidence only |
|
|
44
|
+
| Implementer fails to write file | Error propagates to caller |
|
|
45
|
+
| Target file type invalid | Zod schema rejects at input validation |
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { z } from 'zod'
|
|
2
|
+
import { Skill } from '../skill.js'
|
|
3
|
+
import type { SkillContext } from '../types.js'
|
|
4
|
+
import { createDispatcher } from '../../agents/dispatcher.js'
|
|
5
|
+
import { createMainAgentGuard } from '../../guard/main-agent.js'
|
|
6
|
+
|
|
7
|
+
const P = { readFiles: true, searchCode: false, runCommands: false, writeFiles: false, gitOperations: false }
|
|
8
|
+
const PRW = { readFiles: true, searchCode: false, runCommands: false, writeFiles: true, gitOperations: false }
|
|
9
|
+
|
|
10
|
+
const AgentsMdInputSchema = z.object({ type: z.enum(['CLAUDE','AGENTS','CONTEXT']).default('CLAUDE'), update: z.boolean().default(false), model: z.string().optional() })
|
|
11
|
+
export class AgentsMdSkill extends Skill<any, any> {
|
|
12
|
+
constructor() { super({ name: 'agents-md', description: 'Create/update agent instructions', requires: [], inputSchema: AgentsMdInputSchema as any }) }
|
|
13
|
+
async execute(input: any, context: SkillContext): Promise<any> {
|
|
14
|
+
const { config, logger } = context
|
|
15
|
+
const dispatcher = createDispatcher(logger)
|
|
16
|
+
const guard = createMainAgentGuard({}, logger)
|
|
17
|
+
const filename = `${input.type}.md`
|
|
18
|
+
guard.activateEmbargo()
|
|
19
|
+
try {
|
|
20
|
+
const explore = await dispatcher.dispatch(
|
|
21
|
+
{ role: 'explorer', model: input.model || config.defaultModel },
|
|
22
|
+
{ permissions: P, prompt: `Collect repo evidence: package.json, README, configs.`, owns: [], reads: ['package.json','README.md',filename] },
|
|
23
|
+
)
|
|
24
|
+
await dispatcher.dispatch(
|
|
25
|
+
{ role: 'implementer', model: input.model || 'sonnet' },
|
|
26
|
+
{ permissions: PRW, prompt: `${input.update?'Update':'Create'} ${filename}. Evidence: ${explore.output.slice(0,3000)}. Include: Overview, Tech Stack, Commands, Conventions.`, owns: [filename], reads: [] },
|
|
27
|
+
)
|
|
28
|
+
return { filePath: filename, mode: input.update?'updated':'created', evidence: ['package.json'], rules: ['Overview'], assumptions: [], summary: `${filename} done` }
|
|
29
|
+
} finally { guard.deactivateEmbargo() }
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export const agentsMdSkill = new AgentsMdSkill()
|
|
33
|
+
export default agentsMdSkill
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: execute-plan
|
|
3
|
+
description: Execute approved plans via 9-step isolated subagent dispatch with review, verification, auto-commit, and auto-merge.
|
|
4
|
+
requires: [to-plan, tdd, review-diff, systematic-debugging]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## ⛔ MAIN AGENT CONSTRAINT
|
|
8
|
+
|
|
9
|
+
You are a THIN DISPATCHER. Your ONLY job is to dispatch subagents.
|
|
10
|
+
You MUST NOT: read source files, search code, write/edit files, run tests, run git commands.
|
|
11
|
+
You MAY only: read plan/state files, dispatch subagents via Agent tool, relay results.
|
|
12
|
+
For EVERY user request (including this skill), dispatch a subagent. Never execute yourself.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Use/Exclude Matrix
|
|
17
|
+
|
|
18
|
+
| Use When | Exclude When |
|
|
19
|
+
|---|---|
|
|
20
|
+
| Approved plan ready for execution | Plan not yet created or approved |
|
|
21
|
+
| Multi-task implementation with dependencies | Single trivial change (use quick-task) |
|
|
22
|
+
| Need review gate per task | No review requirement |
|
|
23
|
+
| Want auto-commit/merge on success | Manual commit workflow preferred |
|
|
24
|
+
|
|
25
|
+
## Workflow
|
|
26
|
+
|
|
27
|
+
1. **Parse Plan** — Read plan file, extract tasks with owns/reads/dependencies metadata.
|
|
28
|
+
2. **Create State** — Build execution state tracking completed, failed, and in-progress tasks.
|
|
29
|
+
3. **Execute Tasks** — Dispatch implementer subagents per task in dependency order, each in isolated worktree.
|
|
30
|
+
4. **Review Each** — Dispatch reviewer subagent per completed task; BLOCKED tasks move to failed.
|
|
31
|
+
5. **Integrate** — Collect approved changes; detect and report file-level conflicts.
|
|
32
|
+
6. **Verify** — Dispatch verifier subagent to run full test suite and goal-backward check.
|
|
33
|
+
7. **Auto-Commit** — If `config.autoMerge` and all tasks pass, commit changes via subagent.
|
|
34
|
+
8. **Auto-Merge** — Detect base branch, merge feature branch back via subagent.
|
|
35
|
+
9. **Cleanup** — If `config.autoCleanup`, archive plan and delete feature branch.
|
|
36
|
+
|
|
37
|
+
## Output Spec
|
|
38
|
+
|
|
39
|
+
| Field | Type | Description |
|
|
40
|
+
|---|---|---|
|
|
41
|
+
| `status` | enum | `success`, `failure`, `partial` |
|
|
42
|
+
| `tasksCompleted` | number | Count of successfully completed tasks |
|
|
43
|
+
| `tasksFailed` | number | Count of failed/blocked tasks |
|
|
44
|
+
| `tasksTotal` | number | Total tasks in the plan |
|
|
45
|
+
| `summary` | string | Human-readable execution summary |
|
|
46
|
+
| `actions` | array | List of actions taken (commit, merge, archive) |
|
|
47
|
+
| `commitSha` | string? | Commit SHA if auto-committed |
|
|
48
|
+
| `baseBranch` | string? | Detected base branch for merge |
|
|
49
|
+
| `tokensUsed` | number | Total tokens consumed |
|
|
50
|
+
|
|
51
|
+
## Error Handling
|
|
52
|
+
|
|
53
|
+
| Error | Action |
|
|
54
|
+
|---|---|
|
|
55
|
+
| Plan file not found | Throw with path; caller must verify path |
|
|
56
|
+
| Plan contains no parseable tasks | Throw; suggest re-running to-plan |
|
|
57
|
+
| Implementer subagent fails | Record in failed map; continue remaining tasks |
|
|
58
|
+
| Reviewer returns BLOCKED | Move task to failed with reviewer feedback |
|
|
59
|
+
| Verifier reports FAIL | Return partial status with failure details |
|
|
60
|
+
| Merge conflict during auto-merge | Report conflict; do NOT force-resolve |
|