intentdna 1.5.5 → 1.5.7
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.
|
@@ -42,7 +42,7 @@ export function compileWorkflowToSkill(plan, roles, ir, variables) {
|
|
|
42
42
|
lines.push("</Purpose>");
|
|
43
43
|
lines.push("");
|
|
44
44
|
}
|
|
45
|
-
// Steps
|
|
45
|
+
// Steps — each step MUST be executed via Agent() tool call
|
|
46
46
|
const usedRoles = new Set(plan.steps.map((s) => s.role));
|
|
47
47
|
lines.push("<Steps>");
|
|
48
48
|
let stepNumber = 0;
|
|
@@ -51,24 +51,44 @@ export function compileWorkflowToSkill(plan, roles, ir, variables) {
|
|
|
51
51
|
for (const stepId of group.step_ids) {
|
|
52
52
|
stepNumber++;
|
|
53
53
|
const step = plan.steps.find((s) => s.id === stepId);
|
|
54
|
-
const
|
|
55
|
-
const runIf = step.run_if ?
|
|
54
|
+
const agentType = `dna-${toKebabCase(step.role)}`;
|
|
55
|
+
const runIf = step.run_if ? `\n **Condition**: ${step.run_if}` : "";
|
|
56
56
|
const optional = step.optional ? " (optional)" : "";
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
57
|
+
// Build agent prompt: anti-recursion + role identity + task
|
|
58
|
+
const promptParts = [
|
|
59
|
+
"Do NOT spawn sub-agents.",
|
|
60
|
+
`You are the ${agentType} agent.`,
|
|
61
|
+
step.prompt || step.description,
|
|
62
|
+
];
|
|
63
|
+
const agentPrompt = escapePrompt(promptParts.join(" "));
|
|
64
|
+
lines.push(`${stepNumber}. **${step.id}**${optional}`);
|
|
65
|
+
lines.push(` ${step.description}${runIf}`);
|
|
66
|
+
lines.push("");
|
|
67
|
+
lines.push(` Execute with Agent tool — DO NOT perform this work yourself:`);
|
|
68
|
+
lines.push(` \`\`\``);
|
|
69
|
+
lines.push(` Agent(`);
|
|
70
|
+
lines.push(` subagent_type="${agentType}",`);
|
|
71
|
+
lines.push(` prompt="${agentPrompt}"`);
|
|
72
|
+
lines.push(` )`);
|
|
73
|
+
lines.push(` \`\`\``);
|
|
74
|
+
lines.push(` Wait for agent to complete. Read the output before proceeding.`);
|
|
75
|
+
if (step.handoff?.produces && step.handoff.produces.length > 0) {
|
|
76
|
+
const artifacts = step.handoff.produces.map(p => p.description).join(", ");
|
|
77
|
+
lines.push(` Verify produced artifacts: ${artifacts}`);
|
|
61
78
|
}
|
|
79
|
+
lines.push("");
|
|
62
80
|
}
|
|
63
81
|
}
|
|
64
82
|
lines.push("</Steps>");
|
|
65
83
|
lines.push("");
|
|
66
|
-
// Execution Policy — force
|
|
84
|
+
// Execution Policy — force Agent dispatch
|
|
67
85
|
lines.push("<Execution_Policy>");
|
|
86
|
+
lines.push("- **CRITICAL**: Each step MUST be executed by spawning an Agent using the Agent tool with the specified subagent_type. DO NOT perform any step's work directly in the main session.");
|
|
68
87
|
lines.push("- Use TodoWrite to track each step as pending/in_progress/completed.");
|
|
69
88
|
lines.push("- After completing each step, immediately proceed to the next — do not stop, summarize, or wait for confirmation.");
|
|
70
89
|
lines.push("- If a step fails, mark it as failed in TodoWrite, log the error, and continue to the next non-dependent step.");
|
|
71
90
|
lines.push("- Do not ask the user for permission between steps — the workflow is pre-approved.");
|
|
91
|
+
lines.push("- Wait for each Agent to complete and read its output before proceeding to the next step.");
|
|
72
92
|
lines.push("</Execution_Policy>");
|
|
73
93
|
lines.push("");
|
|
74
94
|
// Tool_Usage — only if roles have permissions or scope
|
|
@@ -232,3 +252,11 @@ export async function removeSkillFiles(outputDir) {
|
|
|
232
252
|
function escapeYaml(s) {
|
|
233
253
|
return s.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
234
254
|
}
|
|
255
|
+
/** Escape prompt text for Agent() call template inside markdown code block. */
|
|
256
|
+
function escapePrompt(s) {
|
|
257
|
+
return s
|
|
258
|
+
.replace(/\\/g, "\\\\")
|
|
259
|
+
.replace(/"/g, '\\"')
|
|
260
|
+
.replace(/`{3,}/g, "` ` `")
|
|
261
|
+
.replace(/\n/g, "\\n");
|
|
262
|
+
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Spec: F5 Agent 调度漏洞修复
|
|
2
|
+
|
|
3
|
+
## 问题(架构级)
|
|
4
|
+
|
|
5
|
+
DNA 的 skill-adapter.ts 生成的 SKILL.md 用文字提示调度 agent:
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
1. **scan** → @dna-frw-scanner
|
|
9
|
+
Prompt: ...
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
LLM 把这当成建议,选择自己做而非 spawn agent。导致:
|
|
13
|
+
|
|
14
|
+
- agent_type 为空 → role scope 不生效
|
|
15
|
+
- tool_permissions deny 不生效(scanner 能写文件)
|
|
16
|
+
- review/verify 步骤在主 session 做 → 自己审自己
|
|
17
|
+
- handoff chain 无意义(没有跨 agent artifact 传递)
|
|
18
|
+
- agent MD 文件从未被加载
|
|
19
|
+
- 所有 role-based 治理形同虚设
|
|
20
|
+
|
|
21
|
+
## 影响范围
|
|
22
|
+
|
|
23
|
+
**以下交付物全部不生效:**
|
|
24
|
+
|
|
25
|
+
| 功能 | 依赖 | 当前状态 |
|
|
26
|
+
|------|------|---------|
|
|
27
|
+
| Role scope (read/write 范围) | agent_type 匹配 | 不生效 |
|
|
28
|
+
| tool_permissions deny | agent_type 匹配 | 不生效 |
|
|
29
|
+
| review 步骤只读约束 | investigator agent spawn | 不生效 |
|
|
30
|
+
| verify 步骤独立验证 | 独立 agent context | 不生效 |
|
|
31
|
+
| merge-time scope gate | worktree + agent 隔离 | 不生效 |
|
|
32
|
+
| handoff consumes/produces | 跨 agent artifact | 不生效 |
|
|
33
|
+
| step enforce rules (G4) | workflow state + agent_type | 不生效 |
|
|
34
|
+
| agent MD 文件加载 | agent spawn 时 CC 自动加载 | 从未加载 |
|
|
35
|
+
|
|
36
|
+
## 根因
|
|
37
|
+
|
|
38
|
+
OMC 用 Claude Code 原生 `Task(subagent_type=...)` API 强制 spawn agent:
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
Task(subagent_type="oh-my-claudecode:executor", prompt="implement caching")
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
这是 API 级调用,LLM 无法绕过。spawn 的 agent 有独立 context、独立 agent_type,hooks 能识别和 enforce。
|
|
45
|
+
|
|
46
|
+
DNA 的 SKILL.md 只是文字提示,不是 API 调用。
|
|
47
|
+
|
|
48
|
+
## 修复方案
|
|
49
|
+
|
|
50
|
+
### skill-adapter.ts 改动
|
|
51
|
+
|
|
52
|
+
生成的 SKILL.md `<Steps>` 部分从:
|
|
53
|
+
|
|
54
|
+
```markdown
|
|
55
|
+
1. **scan** → @dna-frw-scanner
|
|
56
|
+
Prompt: Scan module...
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
改为:
|
|
60
|
+
|
|
61
|
+
```markdown
|
|
62
|
+
1. **scan**
|
|
63
|
+
Execute with Agent tool — DO NOT perform this work in the main session:
|
|
64
|
+
```
|
|
65
|
+
Agent(subagent_type="dna-frw-scanner", prompt="Scan module '$ARGUMENTS' in common/lib/. ...")
|
|
66
|
+
```
|
|
67
|
+
Wait for agent to complete. Read the agent's output before proceeding.
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### 关键设计要点
|
|
71
|
+
|
|
72
|
+
1. **每步必须是 Agent() 调用**,不是文字描述
|
|
73
|
+
2. **明确禁止主 session 做 agent 的工作**:"DO NOT perform this work in the main session"
|
|
74
|
+
3. **Agent 输出要读取**:Agent 完成后读取其 output,作为下一步的 handoff
|
|
75
|
+
4. **Agent 工具参数完整**:subagent_type 用 DNA 编译的 agent 名称,prompt 用编译的步骤 prompt
|
|
76
|
+
5. **参考 OMC 的 preamble 模式**:spawn 的 agent 不应再 spawn 子 agent("Do NOT spawn sub-agents")
|
|
77
|
+
|
|
78
|
+
### 生成模板
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
// skill-adapter.ts — 每个 workflow step 生成:
|
|
82
|
+
function generateStepExecution(step, roleName, prompt) {
|
|
83
|
+
return `
|
|
84
|
+
### Step: ${step.id}
|
|
85
|
+
|
|
86
|
+
Execute with Agent tool — DO NOT perform this work yourself:
|
|
87
|
+
|
|
88
|
+
\`\`\`
|
|
89
|
+
Agent(
|
|
90
|
+
subagent_type="dna-${toKebabCase(roleName)}",
|
|
91
|
+
prompt="${escapePrompt(prompt)}"
|
|
92
|
+
)
|
|
93
|
+
\`\`\`
|
|
94
|
+
|
|
95
|
+
Wait for agent to complete. Read the output.
|
|
96
|
+
${step.handoff?.produces ? `Verify produced artifacts: ${step.handoff.produces.map(p => p.description).join(', ')}` : ''}
|
|
97
|
+
`;
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### 验证方式
|
|
102
|
+
|
|
103
|
+
修复后跑 behavior-lock(home),检查 trace:
|
|
104
|
+
- agent_type 应该有值(dna-frw-scanner, dna-frw-test-writer)
|
|
105
|
+
- 不应该全是 "-"
|
|
106
|
+
|
|
107
|
+
## Acceptance Criteria
|
|
108
|
+
|
|
109
|
+
- [ ] skill-adapter.ts 生成强制 Agent() 调用格式
|
|
110
|
+
- [ ] 每步明确禁止主 session 直接执行
|
|
111
|
+
- [ ] Agent subagent_type 使用编译后的 role 名称
|
|
112
|
+
- [ ] Agent prompt 包含完整步骤 prompt + variables 替换
|
|
113
|
+
- [ ] spawn 的 agent 包含 "Do NOT spawn sub-agents" 约束
|
|
114
|
+
- [ ] handoff produces 在 Agent 完成后验证
|
|
115
|
+
- [ ] 测试:生成的 SKILL.md 包含 Agent() 调用模板
|
|
116
|
+
- [ ] 实战验证:trace 中 agent_type 有值
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Spec: Workflow Pipeline + 状态管理统一
|
|
2
|
+
|
|
3
|
+
## 问题
|
|
4
|
+
|
|
5
|
+
1. **无 workflow 链接**: behavior-lock 完成后不能自动触发 rescue,用户手动跑
|
|
6
|
+
2. **状态管理双路径**: hook CLI 和 MCP server 各自读写同一套文件,重复实现 + 并发风险
|
|
7
|
+
3. **无 pipeline 编排**: 不支持 skill → skill 的串联执行
|
|
8
|
+
|
|
9
|
+
## 一、Workflow Pipeline
|
|
10
|
+
|
|
11
|
+
### 参考 OMC
|
|
12
|
+
|
|
13
|
+
OMC 有两层 pipeline:
|
|
14
|
+
- SKILL.md frontmatter: `next-skill: omc-plan` + `pipeline: [deep-interview, omc-plan, autopilot]`
|
|
15
|
+
- Autopilot 状态机: `STAGE_ORDER: ["ralplan", "execution", "ralph", "qa"]`
|
|
16
|
+
|
|
17
|
+
### DNA 设计
|
|
18
|
+
|
|
19
|
+
在 workflow YAML 层面支持 `next_workflow`:
|
|
20
|
+
|
|
21
|
+
```yaml
|
|
22
|
+
workflows:
|
|
23
|
+
behavior-lock:
|
|
24
|
+
name: Behavior Lock
|
|
25
|
+
next_workflow: rescue # 完成后建议/触发 rescue
|
|
26
|
+
steps: [...]
|
|
27
|
+
|
|
28
|
+
rescue:
|
|
29
|
+
name: Rescue
|
|
30
|
+
max_rounds: 10
|
|
31
|
+
steps: [...]
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
编译到 SKILL.md 的步骤末尾:
|
|
35
|
+
|
|
36
|
+
```markdown
|
|
37
|
+
<Next_Workflow>
|
|
38
|
+
behavior-lock completed. Next recommended workflow:
|
|
39
|
+
Skill("dna-frw-rescue", args="$ARGUMENTS")
|
|
40
|
+
Ask user: "Behavior lock complete. Run rescue to implement? (Y/n)"
|
|
41
|
+
</Next_Workflow>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### 编译器改动
|
|
45
|
+
|
|
46
|
+
`skill-adapter.ts` 新增:
|
|
47
|
+
- 读 `WorkflowDef.next_workflow`
|
|
48
|
+
- 生成 `<Next_Workflow>` section
|
|
49
|
+
- 包含 `Skill()` 调用模板
|
|
50
|
+
|
|
51
|
+
### schema 改动
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
interface WorkflowDef {
|
|
55
|
+
// 现有字段...
|
|
56
|
+
next_workflow?: string; // 完成后推荐的下一个 workflow
|
|
57
|
+
auto_chain?: boolean; // true = 自动执行,false = 提示用户确认(默认 false)
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## 二、状态管理统一
|
|
62
|
+
|
|
63
|
+
### 当前双路径
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
Hook CLI (dna-hook): 读文件 → enforce → 写 trace → 退出
|
|
67
|
+
MCP Server (dna-mcp): 读文件 → 响应工具调用 → 写文件
|
|
68
|
+
两者独立,读写同一套 .dna/state/ 文件
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### 短期方案(不做 IPC)
|
|
72
|
+
|
|
73
|
+
保持双路径,但统一底层:
|
|
74
|
+
1. **hook CLI 和 MCP 共享状态读写模块** — 已经如此(都用 state.ts)
|
|
75
|
+
2. **trace 写入加 session 隔离** — 已实现(G1)
|
|
76
|
+
3. **workflow state 原子写入** — 已实现(R4)
|
|
77
|
+
4. 当前无需改动,架构够用
|
|
78
|
+
|
|
79
|
+
### 长期方案(等 CC 支持 MCP hooks)
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
Claude Code → hook 事件 → 调用 MCP tool `dna_enforce` → 常驻进程
|
|
83
|
+
- 零冷启动(IR 已缓存)
|
|
84
|
+
- 单点状态管理
|
|
85
|
+
- 无并发写入
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
等 Claude Code hook 系统支持 MCP tool 调用时迁移。
|
|
89
|
+
|
|
90
|
+
## Acceptance Criteria
|
|
91
|
+
|
|
92
|
+
### Pipeline
|
|
93
|
+
- [ ] WorkflowDef 支持 `next_workflow` 字段
|
|
94
|
+
- [ ] Schema 验证 next_workflow 引用存在
|
|
95
|
+
- [ ] skill-adapter.ts 生成 `<Next_Workflow>` section
|
|
96
|
+
- [ ] 默认提示用户确认,`auto_chain: true` 自动执行
|
|
97
|
+
- [ ] flutter-rewrite: behavior-lock → rescue 链接
|
|
98
|
+
|
|
99
|
+
### 状态统一
|
|
100
|
+
- [ ] 记录长期方案到 ROADMAP(MCP-based hooks)
|
|
101
|
+
- [ ] 短期无需改动,确认当前架构够用
|