@geekbeer/minion 3.53.1 → 3.55.1
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/core/lib/dag-step-poller.js +245 -1
- package/docs/api-reference.md +40 -297
- package/docs/task-guides.md +76 -75
- package/linux/routes/chat.js +1 -16
- package/package.json +1 -1
- package/rules/core.md +6 -9
- package/win/routes/chat.js +1 -14
|
@@ -119,12 +119,15 @@ async function pollOnce() {
|
|
|
119
119
|
|
|
120
120
|
/**
|
|
121
121
|
* Execute a single pending DAG node.
|
|
122
|
-
* Routes to skill
|
|
122
|
+
* Routes to skill / transform / script execution based on node_type.
|
|
123
123
|
*/
|
|
124
124
|
async function executeNode(node) {
|
|
125
125
|
if (node.node_type === 'transform') {
|
|
126
126
|
return executeTransformNode(node)
|
|
127
127
|
}
|
|
128
|
+
if (node.node_type === 'script') {
|
|
129
|
+
return executeScriptNode(node)
|
|
130
|
+
}
|
|
128
131
|
return executeSkillNode(node)
|
|
129
132
|
}
|
|
130
133
|
|
|
@@ -467,6 +470,247 @@ function appendContractTable(lines, fields) {
|
|
|
467
470
|
}
|
|
468
471
|
}
|
|
469
472
|
|
|
473
|
+
/**
|
|
474
|
+
* Execute a script node:
|
|
475
|
+
* 1. Claim the node
|
|
476
|
+
* 2. Spawn python3 / node as a child process
|
|
477
|
+
* 3. Pipe input_data as JSON on stdin
|
|
478
|
+
* 4. Parse stdout as JSON → output_data, report completion
|
|
479
|
+
*
|
|
480
|
+
* Failure modes (all → status 'failed'):
|
|
481
|
+
* - Unsupported runtime
|
|
482
|
+
* - Non-zero exit code (stderr → error_message)
|
|
483
|
+
* - stdout is not parseable as JSON
|
|
484
|
+
* - Wall-clock timeout exceeded (process is SIGKILL'd)
|
|
485
|
+
*
|
|
486
|
+
* No tmux session is involved — this is a synchronous in-process child.
|
|
487
|
+
* The Output Contract on the outgoing edge is enforced by HQ on
|
|
488
|
+
* /node-complete, identical to skill / transform nodes.
|
|
489
|
+
*/
|
|
490
|
+
async function executeScriptNode(node) {
|
|
491
|
+
const {
|
|
492
|
+
node_execution_id,
|
|
493
|
+
node_id,
|
|
494
|
+
dag_workflow_name,
|
|
495
|
+
scope_path,
|
|
496
|
+
assigned_role,
|
|
497
|
+
input_data,
|
|
498
|
+
script_runtime,
|
|
499
|
+
script_source,
|
|
500
|
+
script_timeout_seconds,
|
|
501
|
+
} = node
|
|
502
|
+
|
|
503
|
+
console.log(
|
|
504
|
+
`[DagPoller] Executing script node "${node_id}" of DAG "${dag_workflow_name}" ` +
|
|
505
|
+
`(runtime: ${script_runtime}, scope: "${scope_path || 'root'}", role: ${assigned_role})`
|
|
506
|
+
)
|
|
507
|
+
|
|
508
|
+
try {
|
|
509
|
+
try {
|
|
510
|
+
await dagRequest('/claim-node', {
|
|
511
|
+
method: 'POST',
|
|
512
|
+
body: JSON.stringify({ node_execution_id }),
|
|
513
|
+
})
|
|
514
|
+
} catch (claimErr) {
|
|
515
|
+
if (claimErr.statusCode === 409) {
|
|
516
|
+
console.log(`[DagPoller] Script node ${node_id} already claimed, skipping`)
|
|
517
|
+
return
|
|
518
|
+
}
|
|
519
|
+
throw claimErr
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
if (!script_source || !script_source.trim()) {
|
|
523
|
+
await reportNodeComplete(node_execution_id, 'failed', null, 'Script node has empty script_source')
|
|
524
|
+
return
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
let interpreter
|
|
528
|
+
if (script_runtime === 'python') {
|
|
529
|
+
interpreter = 'python3'
|
|
530
|
+
} else if (script_runtime === 'node') {
|
|
531
|
+
interpreter = 'node'
|
|
532
|
+
} else {
|
|
533
|
+
await reportNodeComplete(
|
|
534
|
+
node_execution_id,
|
|
535
|
+
'failed',
|
|
536
|
+
null,
|
|
537
|
+
`Unsupported script_runtime: ${script_runtime} (allowed: python, node)`,
|
|
538
|
+
)
|
|
539
|
+
return
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
const timeoutMs = clampTimeout(script_timeout_seconds) * 1000
|
|
543
|
+
|
|
544
|
+
const result = await runScriptProcess(interpreter, script_source, input_data || {}, timeoutMs)
|
|
545
|
+
|
|
546
|
+
if (result.timedOut) {
|
|
547
|
+
await reportNodeComplete(
|
|
548
|
+
node_execution_id,
|
|
549
|
+
'failed',
|
|
550
|
+
null,
|
|
551
|
+
`Script timed out after ${timeoutMs / 1000}s. stderr: ${truncate(result.stderr, 2000)}`,
|
|
552
|
+
)
|
|
553
|
+
return
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
if (result.exitCode !== 0) {
|
|
557
|
+
await reportNodeComplete(
|
|
558
|
+
node_execution_id,
|
|
559
|
+
'failed',
|
|
560
|
+
null,
|
|
561
|
+
`Script exited with code ${result.exitCode}. stderr: ${truncate(result.stderr, 2000)}`,
|
|
562
|
+
)
|
|
563
|
+
return
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
let outputData
|
|
567
|
+
try {
|
|
568
|
+
outputData = JSON.parse(result.stdout)
|
|
569
|
+
} catch (parseErr) {
|
|
570
|
+
await reportNodeComplete(
|
|
571
|
+
node_execution_id,
|
|
572
|
+
'failed',
|
|
573
|
+
null,
|
|
574
|
+
`Script stdout is not valid JSON: ${parseErr.message}. stdout (first 500 chars): ${truncate(result.stdout, 500)}`,
|
|
575
|
+
)
|
|
576
|
+
return
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
if (typeof outputData !== 'object' || outputData === null || Array.isArray(outputData)) {
|
|
580
|
+
await reportNodeComplete(
|
|
581
|
+
node_execution_id,
|
|
582
|
+
'failed',
|
|
583
|
+
null,
|
|
584
|
+
`Script output_data must be a JSON object (got ${Array.isArray(outputData) ? 'array' : typeof outputData})`,
|
|
585
|
+
)
|
|
586
|
+
return
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
await reportNodeComplete(
|
|
590
|
+
node_execution_id,
|
|
591
|
+
'completed',
|
|
592
|
+
outputData,
|
|
593
|
+
buildScriptSummary(outputData, result.stderr),
|
|
594
|
+
)
|
|
595
|
+
console.log(`[DagPoller] Script node "${node_id}" completed`)
|
|
596
|
+
|
|
597
|
+
} catch (err) {
|
|
598
|
+
console.error(`[DagPoller] Failed to execute script node ${node_id}: ${err.message}`)
|
|
599
|
+
try {
|
|
600
|
+
await reportNodeComplete(node_execution_id, 'failed', null, err.message)
|
|
601
|
+
} catch {
|
|
602
|
+
// best-effort
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
/**
|
|
608
|
+
* Build the output_summary text shown in the HQ execution detail UI for a
|
|
609
|
+
* successful script node. The UI renders output_summary as a collapsible
|
|
610
|
+
* code block under "Output"; output_data itself is only visible from the
|
|
611
|
+
* Pin-fixture dialog. Always emit at least the JSON output so users can
|
|
612
|
+
* inspect what the script returned without round-tripping through fixtures.
|
|
613
|
+
*/
|
|
614
|
+
function buildScriptSummary(outputData, stderr) {
|
|
615
|
+
const lines = []
|
|
616
|
+
let serialized
|
|
617
|
+
try {
|
|
618
|
+
serialized = JSON.stringify(outputData, null, 2)
|
|
619
|
+
} catch {
|
|
620
|
+
serialized = '(failed to serialize output_data)'
|
|
621
|
+
}
|
|
622
|
+
lines.push('output_data:')
|
|
623
|
+
lines.push('```json')
|
|
624
|
+
lines.push(truncate(serialized, 8000))
|
|
625
|
+
lines.push('```')
|
|
626
|
+
if (stderr && stderr.trim()) {
|
|
627
|
+
lines.push('')
|
|
628
|
+
lines.push('stderr:')
|
|
629
|
+
lines.push(truncate(stderr, 2000))
|
|
630
|
+
}
|
|
631
|
+
return lines.join('\n')
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
function clampTimeout(seconds) {
|
|
635
|
+
const n = typeof seconds === 'number' && Number.isFinite(seconds) ? seconds : 60
|
|
636
|
+
if (n < 1) return 1
|
|
637
|
+
if (n > 600) return 600
|
|
638
|
+
return Math.floor(n)
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
function truncate(str, max) {
|
|
642
|
+
if (!str) return ''
|
|
643
|
+
return str.length > max ? str.slice(0, max) + '…(truncated)' : str
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
/**
|
|
647
|
+
* Spawn the interpreter, write the script to stdin via `-` / `-c` is not
|
|
648
|
+
* portable (python requires `-`, node requires `-e` with the source as an
|
|
649
|
+
* argument and no stdin). Instead we feed the script via stdin for both:
|
|
650
|
+
* - python3 reads source from stdin when invoked with `-`
|
|
651
|
+
* - node reads source from stdin when invoked with no args, but stdin is
|
|
652
|
+
* then consumed by the script — so for node we must use `-e` with the
|
|
653
|
+
* source as a flag value. To keep input_data on stdin for both, we
|
|
654
|
+
* write the script to a temp file and pass the path as argv[1].
|
|
655
|
+
*/
|
|
656
|
+
function runScriptProcess(interpreter, source, inputData, timeoutMs) {
|
|
657
|
+
const { spawn } = require('child_process')
|
|
658
|
+
const fs = require('fs')
|
|
659
|
+
const os = require('os')
|
|
660
|
+
const path = require('path')
|
|
661
|
+
const crypto = require('crypto')
|
|
662
|
+
|
|
663
|
+
const ext = interpreter === 'python3' ? 'py' : 'js'
|
|
664
|
+
const tmpFile = path.join(
|
|
665
|
+
os.tmpdir(),
|
|
666
|
+
`dag-script-${crypto.randomBytes(8).toString('hex')}.${ext}`,
|
|
667
|
+
)
|
|
668
|
+
fs.writeFileSync(tmpFile, source, 'utf-8')
|
|
669
|
+
|
|
670
|
+
return new Promise(resolve => {
|
|
671
|
+
const child = spawn(interpreter, [tmpFile], {
|
|
672
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
673
|
+
})
|
|
674
|
+
|
|
675
|
+
let stdout = ''
|
|
676
|
+
let stderr = ''
|
|
677
|
+
let timedOut = false
|
|
678
|
+
let killed = false
|
|
679
|
+
|
|
680
|
+
const timer = setTimeout(() => {
|
|
681
|
+
timedOut = true
|
|
682
|
+
killed = true
|
|
683
|
+
try { child.kill('SIGKILL') } catch { /* noop */ }
|
|
684
|
+
}, timeoutMs)
|
|
685
|
+
|
|
686
|
+
child.stdout.on('data', chunk => { stdout += chunk.toString('utf-8') })
|
|
687
|
+
child.stderr.on('data', chunk => { stderr += chunk.toString('utf-8') })
|
|
688
|
+
|
|
689
|
+
child.on('error', err => {
|
|
690
|
+
clearTimeout(timer)
|
|
691
|
+
cleanup(tmpFile)
|
|
692
|
+
resolve({ exitCode: -1, stdout, stderr: stderr + `\nspawn error: ${err.message}`, timedOut })
|
|
693
|
+
})
|
|
694
|
+
|
|
695
|
+
child.on('close', code => {
|
|
696
|
+
clearTimeout(timer)
|
|
697
|
+
cleanup(tmpFile)
|
|
698
|
+
resolve({ exitCode: killed ? -1 : (code ?? -1), stdout, stderr, timedOut })
|
|
699
|
+
})
|
|
700
|
+
|
|
701
|
+
try {
|
|
702
|
+
child.stdin.write(JSON.stringify(inputData))
|
|
703
|
+
child.stdin.end()
|
|
704
|
+
} catch (writeErr) {
|
|
705
|
+
stderr += `\nstdin write error: ${writeErr.message}`
|
|
706
|
+
}
|
|
707
|
+
})
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
function cleanup(tmpFile) {
|
|
711
|
+
try { require('fs').unlinkSync(tmpFile) } catch { /* noop */ }
|
|
712
|
+
}
|
|
713
|
+
|
|
470
714
|
/**
|
|
471
715
|
* Resolve skill_version_id to skill name via HQ API.
|
|
472
716
|
*/
|
package/docs/api-reference.md
CHANGED
|
@@ -52,20 +52,6 @@ hq list workspaces
|
|
|
52
52
|
| `POST /api/skills/fetch/:name` | `workspace_id` | クエリパラメータ |
|
|
53
53
|
| `GET /api/skills/remote` | `workspace_id` | クエリパラメータ |
|
|
54
54
|
|
|
55
|
-
### Workflows
|
|
56
|
-
|
|
57
|
-
v3.38.0 以降、workflows はワークスペース単位でスコープされる。各workflowレコードは `workspace_id` を持ち、未指定は `""`(未所属/legacy)として扱われる。
|
|
58
|
-
|
|
59
|
-
| Method | Endpoint | Description |
|
|
60
|
-
|--------|----------|-------------|
|
|
61
|
-
| GET | `/api/workflows` | List local workflows with next_run. Optional `?workspace_id=` filter (omit for cross-workspace view) |
|
|
62
|
-
| POST | `/api/workflows` | Receive/upsert workflows (from HQ). Each incoming workflow should carry `workspace_id` |
|
|
63
|
-
| POST | `/api/workflows/push/:name` | Push local workflow to HQ |
|
|
64
|
-
| POST | `/api/workflows/fetch/:name` | Fetch workflow from HQ and deploy locally (+ pipeline skills). HQ response includes `workspace_id` |
|
|
65
|
-
| GET | `/api/workflows/remote` | List workflows on HQ |
|
|
66
|
-
| DELETE | `/api/workflows/:id` | Remove a local workflow |
|
|
67
|
-
| POST | `/api/workflows/trigger` | Manual trigger. Body: `{workflow_id}` |
|
|
68
|
-
|
|
69
55
|
### Routines
|
|
70
56
|
|
|
71
57
|
v3.38.0 以降、routines はワークスペース単位でスコープされる。各routineレコードは `workspace_id` を持ち、未指定は `""`(未所属/legacy)として扱われる。
|
|
@@ -82,11 +68,11 @@ v3.38.0 以降、routines はワークスペース単位でスコープされる
|
|
|
82
68
|
|
|
83
69
|
### Executions
|
|
84
70
|
|
|
85
|
-
v3.38.0 以降、executions は親
|
|
71
|
+
v3.38.0 以降、executions は親 routine から `workspace_id` を継承する。
|
|
86
72
|
|
|
87
73
|
| Method | Endpoint | Description |
|
|
88
74
|
|--------|----------|-------------|
|
|
89
|
-
| GET | `/api/executions` | List execution history (`?limit=50`,
|
|
75
|
+
| GET | `/api/executions` | List execution history (`?limit=50`, optional `?workspace_id=`) |
|
|
90
76
|
| GET | `/api/executions/:id` | Get single execution (includes `workspace_id`) |
|
|
91
77
|
| GET | `/api/executions/:id/log` | Get execution log content (`?tail=N`) |
|
|
92
78
|
| POST | `/api/executions/:id/outcome` | Report outcome (no auth). Body: `{outcome, summary?, details?}` |
|
|
@@ -429,6 +415,8 @@ GET `/api/daemons/status` response:
|
|
|
429
415
|
"success": true,
|
|
430
416
|
"daemons": {
|
|
431
417
|
"step_poller": { "running": true, "last_poll_at": "2026-03-19T15:30:00.000Z" },
|
|
418
|
+
"dag_step_poller": { "running": true, "last_poll_at": "2026-03-19T15:30:02.000Z" },
|
|
419
|
+
"board_task_poller": { "running": true, "last_poll_at": "2026-03-19T15:30:08.000Z" },
|
|
432
420
|
"revision_watcher": { "running": true, "last_poll_at": "2026-03-19T15:30:05.000Z" },
|
|
433
421
|
"thread_watcher": { "running": true, "last_poll_at": "2026-03-19T15:29:52.000Z" },
|
|
434
422
|
"reflection_scheduler": { "running": true, "next_run": "2026-03-20T03:00:00.000Z" },
|
|
@@ -439,12 +427,16 @@ GET `/api/daemons/status` response:
|
|
|
439
427
|
|
|
440
428
|
| Daemon | 概要 |
|
|
441
429
|
|--------|------|
|
|
442
|
-
| `
|
|
443
|
-
| `
|
|
430
|
+
| `dag_step_poller` | DAGノード(skill/transform/script)の取得・claim・実行(30秒間隔) |
|
|
431
|
+
| `board_task_poller` | アクティブスプリント内のボードタスク自動着手(30秒間隔、v3.46.0〜) |
|
|
432
|
+
| `step_poller` | 旧式ワークフローステップ用ポーラー(30秒間隔。サポート打ち切り後はpending返却なし、互換目的で稼働) |
|
|
433
|
+
| `revision_watcher` | 旧式ワークフローのリビジョン要求検知(30秒間隔、PMのみ。DAGの差し戻しはサーバ側カスケードで処理) |
|
|
444
434
|
| `thread_watcher` | プロジェクト・ワークスペーススレッドの監視・LLM評価(15秒間隔) |
|
|
445
435
|
| `reflection_scheduler` | 1日1回の振り返り(cron) |
|
|
446
436
|
| `heartbeat` | HQへのハートビート(30秒間隔) |
|
|
447
437
|
|
|
438
|
+
> Note: `dag_cron_poller`(v3.51.0〜、PMロールがcron-enabled DAGを発火する)は内部的には起動しているが、`/api/daemons/status` のレスポンスには含まれていない(既知のギャップ)。稼働確認は `~/.minion/logs/agent.log` を grep する。
|
|
439
|
+
|
|
448
440
|
### Threads (スレッド)
|
|
449
441
|
|
|
450
442
|
ワークスペースレベルのコミュニケーションチャネル。ブロッカー共有やチーム議論に使う。
|
|
@@ -513,7 +505,7 @@ POST `/api/threads` body (プロジェクト紐づきディスカッション):
|
|
|
513
505
|
| `title` | string | Yes | スレッドの要約 |
|
|
514
506
|
| `content` | string | Yes | スレッド本文(thread_messagesの最初のメッセージとして保存) |
|
|
515
507
|
| `mentions` | string[] | No | メンション対象。形式: `role:engineer`, `role:pm`, `minion:<minion_id>`, `user` |
|
|
516
|
-
| `context` | object | No | 任意のメタデータ(category, urgency,
|
|
508
|
+
| `context` | object | No | 任意のメタデータ(category, urgency, dag_execution_id等) |
|
|
517
509
|
|
|
518
510
|
**プロジェクト紐づけの使い分け:**
|
|
519
511
|
- ワークフロー実行中(プロジェクトあり)→ `project_ids: ["uuid"]`
|
|
@@ -817,7 +809,7 @@ Response:
|
|
|
817
809
|
]
|
|
818
810
|
```
|
|
819
811
|
|
|
820
|
-
`role` is
|
|
812
|
+
`role` is one of `"pm"` (project manager), `"engineer"`, or `"accountant"`.
|
|
821
813
|
|
|
822
814
|
### Project Context
|
|
823
815
|
|
|
@@ -855,6 +847,18 @@ Response:
|
|
|
855
847
|
|
|
856
848
|
プロジェクト変数はワークフロー実行時に `template_vars` としてミニオンに渡され、スキルの `{{VAR_NAME}}` テンプレートを展開する。
|
|
857
849
|
|
|
850
|
+
#### 変数とシークレットの違い
|
|
851
|
+
|
|
852
|
+
**変数**(ミニオン変数・プロジェクト変数)はスキル本文の `{{VAR_NAME}}` テンプレートとして実行時に展開される。スキル作成時にパラメータ化したい値は `{{変数名}}` で記述する。
|
|
853
|
+
|
|
854
|
+
**シークレット**(ミニオンシークレット)は環境変数 `$SECRET_NAME` としてプロセスに注入される。APIキーやパスワード等の機密情報に使用する。テンプレート展開は行われない。
|
|
855
|
+
|
|
856
|
+
#### テンプレート変数の展開優先順位
|
|
857
|
+
|
|
858
|
+
同名の変数が複数のスコープで定義されている場合、以下の順序で上書きされる:
|
|
859
|
+
1. ミニオン変数(最低優先)
|
|
860
|
+
2. プロジェクト変数(最優先)
|
|
861
|
+
|
|
858
862
|
### Project Tasks
|
|
859
863
|
|
|
860
864
|
タスクは5段階Kanban (`backlog`/`todo`/`doing`/`review`/`done`)で管理される。親子関係は2階層まで(孫タスク禁止)。担当は **ミニオンか人間の二択**(両方は不可、後勝ち null)。
|
|
@@ -1046,282 +1050,11 @@ Response:
|
|
|
1046
1050
|
- 子タスクが `milestone_id=null` でも、親 EPIC の `milestone_id` を継承して集計される(effective milestone)。つまり「親に MVP を付ければ配下の子タスクも MVP 進捗に含まれる」。
|
|
1047
1051
|
- `summary.by_status` は従来どおり全タスク(親含む)で計上する。
|
|
1048
1052
|
|
|
1049
|
-
### Workflow Variables (PM only)
|
|
1050
|
-
|
|
1051
|
-
| Method | Endpoint | Description |
|
|
1052
|
-
|--------|----------|-------------|
|
|
1053
|
-
| POST | `/api/minion/me/project/[id]/workflows/[wfId]/variables/[key]` | ワークフロー変数を設定(upsert) |
|
|
1054
|
-
| DELETE | `/api/minion/me/project/[id]/workflows/[wfId]/variables/[key]` | ワークフロー変数を削除 |
|
|
1055
|
-
|
|
1056
|
-
POST body:
|
|
1057
|
-
```json
|
|
1058
|
-
{
|
|
1059
|
-
"value": "variable value (max 2000 chars)"
|
|
1060
|
-
}
|
|
1061
|
-
```
|
|
1062
|
-
|
|
1063
|
-
Key format: `/^[A-Za-z_][A-Za-z0-9_]{0,99}$/`
|
|
1064
|
-
|
|
1065
|
-
Response:
|
|
1066
|
-
```json
|
|
1067
|
-
{
|
|
1068
|
-
"success": true,
|
|
1069
|
-
"key": "MY_VAR",
|
|
1070
|
-
"value": "variable value"
|
|
1071
|
-
}
|
|
1072
|
-
```
|
|
1073
|
-
|
|
1074
|
-
ワークフロー変数はプロジェクト変数を上書きする(同名キーの場合)。
|
|
1075
|
-
|
|
1076
|
-
#### 変数とシークレットの違い
|
|
1077
|
-
|
|
1078
|
-
**変数**(ミニオン変数・プロジェクト変数・ワークフロー変数)はスキル本文の `{{VAR_NAME}}` テンプレートとして実行時に展開される。スキル作成時にパラメータ化したい値は `{{変数名}}` で記述する。
|
|
1079
|
-
|
|
1080
|
-
**シークレット**(ミニオンシークレット)は環境変数 `$SECRET_NAME` としてプロセスに注入される。APIキーやパスワード等の機密情報に使用する。テンプレート展開は行われない。
|
|
1081
|
-
|
|
1082
|
-
#### テンプレート変数の展開優先順位
|
|
1083
|
-
|
|
1084
|
-
同名の変数が複数のスコープで定義されている場合、以下の順序で上書きされる:
|
|
1085
|
-
1. ミニオン変数(最低優先)
|
|
1086
|
-
2. プロジェクト変数
|
|
1087
|
-
3. ワークフロー変数(最優先)
|
|
1088
|
-
|
|
1089
|
-
### Workflows (project-scoped, versioned)
|
|
1090
|
-
|
|
1091
|
-
| Method | Endpoint | Description |
|
|
1092
|
-
|--------|----------|-------------|
|
|
1093
|
-
| GET | `/api/minion/workflows` | 参加プロジェクトのアクティブなワークフロー一覧 |
|
|
1094
|
-
| POST | `/api/minion/workflows` | ワークフローを push(新規作成 or 新バージョン) |
|
|
1095
|
-
|
|
1096
|
-
GET Response:
|
|
1097
|
-
```json
|
|
1098
|
-
{
|
|
1099
|
-
"workflows": [
|
|
1100
|
-
{
|
|
1101
|
-
"name": "daily-check",
|
|
1102
|
-
"pipeline_skill_names": ["skill-1", "skill-2"],
|
|
1103
|
-
"pipeline": [
|
|
1104
|
-
{
|
|
1105
|
-
"skill_version_id": "uuid",
|
|
1106
|
-
"skill_name": "skill-1",
|
|
1107
|
-
"skill_display_name": "Skill One",
|
|
1108
|
-
"skill_version": 3,
|
|
1109
|
-
"assigned_role": "engineer",
|
|
1110
|
-
"requires_review": false,
|
|
1111
|
-
"is_my_step": true
|
|
1112
|
-
}
|
|
1113
|
-
],
|
|
1114
|
-
"content": "...",
|
|
1115
|
-
"version": 3,
|
|
1116
|
-
"cron_expression": "0 9 * * *",
|
|
1117
|
-
"project_id": "uuid",
|
|
1118
|
-
"created_at": "..."
|
|
1119
|
-
}
|
|
1120
|
-
]
|
|
1121
|
-
}
|
|
1122
|
-
```
|
|
1123
|
-
|
|
1124
|
-
各ステップの `is_my_step` はミニオン自身のプロジェクトロールと `assigned_role` の一致を示す。
|
|
1125
|
-
|
|
1126
|
-
POST body (push):
|
|
1127
|
-
```json
|
|
1128
|
-
{
|
|
1129
|
-
"name": "my-workflow",
|
|
1130
|
-
"pipeline_skill_names": ["skill-1", "skill-2"],
|
|
1131
|
-
"content": "Workflow description",
|
|
1132
|
-
"project_id": "uuid",
|
|
1133
|
-
"change_summary": "Added skill-2 to pipeline"
|
|
1134
|
-
}
|
|
1135
|
-
```
|
|
1136
|
-
|
|
1137
|
-
push するとパイプライン内のスキル名が `skill_version_id` に解決され、新バージョンが自動作成される。
|
|
1138
|
-
|
|
1139
|
-
### Workflow Structure
|
|
1140
|
-
|
|
1141
|
-
```json
|
|
1142
|
-
{
|
|
1143
|
-
"name": "my-workflow",
|
|
1144
|
-
"pipeline_skill_names": ["skill-1", "skill-2"],
|
|
1145
|
-
"pipeline": [
|
|
1146
|
-
{
|
|
1147
|
-
"skill_version_id": "uuid",
|
|
1148
|
-
"skill_name": "skill-1",
|
|
1149
|
-
"skill_display_name": "Skill One",
|
|
1150
|
-
"skill_version": 2,
|
|
1151
|
-
"assigned_role": "engineer",
|
|
1152
|
-
"requires_review": false,
|
|
1153
|
-
"is_my_step": true
|
|
1154
|
-
}
|
|
1155
|
-
],
|
|
1156
|
-
"content": "Markdown description of the workflow",
|
|
1157
|
-
"version": 2,
|
|
1158
|
-
"cron_expression": "0 9 * * *",
|
|
1159
|
-
"project_id": "uuid"
|
|
1160
|
-
}
|
|
1161
|
-
```
|
|
1162
|
-
|
|
1163
|
-
| Field | Type | Description |
|
|
1164
|
-
|-------|------|-------------|
|
|
1165
|
-
| `name` | string | Slug identifier (`/^[a-z0-9-]+$/`) |
|
|
1166
|
-
| `pipeline_skill_names` | string[] | Ordered skill names (for display/push) |
|
|
1167
|
-
| `pipeline` | PipelineStep[] | Resolved pipeline with version IDs and roles |
|
|
1168
|
-
| `content` | string | Markdown body describing the workflow |
|
|
1169
|
-
| `version` | number | Current version number (auto-incremented on push) |
|
|
1170
|
-
| `cron_expression` | string\|null | Cron schedule (null = manual/one-shot only) |
|
|
1171
|
-
| `project_id` | string | UUID of the parent project |
|
|
1172
|
-
|
|
1173
|
-
### Pipeline Step Fields
|
|
1174
|
-
|
|
1175
|
-
| Field | Type | Description |
|
|
1176
|
-
|-------|------|-------------|
|
|
1177
|
-
| `skill_version_id` | string | UUID of the specific skill version |
|
|
1178
|
-
| `skill_name` | string | Skill slug name |
|
|
1179
|
-
| `skill_display_name` | string | Human-readable skill name |
|
|
1180
|
-
| `skill_version` | number | Skill version number |
|
|
1181
|
-
| `assigned_role` | string | `"pm"` or `"engineer"` — who executes this step |
|
|
1182
|
-
| `requires_review` | boolean | If true, human review required after completion |
|
|
1183
|
-
| `is_my_step` | boolean | Whether this minion's role matches assigned_role |
|
|
1184
|
-
|
|
1185
|
-
### Syncing Workflows with HQ
|
|
1186
|
-
|
|
1187
|
-
- `POST /api/workflows/push/:name` — Push local workflow to HQ. Pipeline skills are auto-pushed first.
|
|
1188
|
-
- `POST /api/workflows/fetch/:name` — Fetch workflow from HQ. Missing pipeline skills are auto-fetched.
|
|
1189
|
-
- `GET /api/workflows/remote` — List workflows available on HQ.
|
|
1190
|
-
|
|
1191
|
-
Pipeline skills must be deployed locally (in `~/.claude/skills/`) before pushing a workflow.
|
|
1192
|
-
|
|
1193
|
-
### Pending Steps (軽量ポーリング)
|
|
1194
|
-
|
|
1195
|
-
| Method | Endpoint | Description |
|
|
1196
|
-
|--------|----------|-------------|
|
|
1197
|
-
| GET | `/api/minion/pending-steps` | 自分が実行すべき pending ステップ一覧 |
|
|
1198
|
-
|
|
1199
|
-
**このエンドポイントはミニオンエージェント(非AI)による高頻度ポーリング用。**
|
|
1200
|
-
|
|
1201
|
-
Response:
|
|
1202
|
-
```json
|
|
1203
|
-
{
|
|
1204
|
-
"steps": [
|
|
1205
|
-
{
|
|
1206
|
-
"step_execution_id": "uuid",
|
|
1207
|
-
"execution_id": "uuid",
|
|
1208
|
-
"workflow_name": "daily-check",
|
|
1209
|
-
"step_index": 0,
|
|
1210
|
-
"skill_version_id": "uuid",
|
|
1211
|
-
"assigned_role": "engineer"
|
|
1212
|
-
}
|
|
1213
|
-
]
|
|
1214
|
-
}
|
|
1215
|
-
```
|
|
1216
|
-
|
|
1217
|
-
返却条件:
|
|
1218
|
-
- `assigned_role` がミニオンのプロジェクトロールと一致
|
|
1219
|
-
- ステップの `status` が `pending`
|
|
1220
|
-
- 前ステップが全て `completed`(`requires_review` の場合は `approved` も必要)
|
|
1221
|
-
|
|
1222
|
-
### Workflow Execution Recording
|
|
1223
|
-
|
|
1224
|
-
| Method | Endpoint | Description |
|
|
1225
|
-
|--------|----------|-------------|
|
|
1226
|
-
| POST | `/api/minion/workflow-execution` | 新規 execution 開始を記録 |
|
|
1227
|
-
| POST | `/api/minion/execution` | ステップ実行状況を HQ に報告 |
|
|
1228
|
-
|
|
1229
|
-
POST `/api/minion/workflow-execution` body:
|
|
1230
|
-
```json
|
|
1231
|
-
{
|
|
1232
|
-
"workflow_version_id": "uuid"
|
|
1233
|
-
}
|
|
1234
|
-
```
|
|
1235
|
-
|
|
1236
|
-
Response:
|
|
1237
|
-
```json
|
|
1238
|
-
{
|
|
1239
|
-
"execution_id": "uuid",
|
|
1240
|
-
"status": "running",
|
|
1241
|
-
"steps_count": 3
|
|
1242
|
-
}
|
|
1243
|
-
```
|
|
1244
|
-
|
|
1245
|
-
POST `/api/minion/execution` body:
|
|
1246
|
-
```json
|
|
1247
|
-
{
|
|
1248
|
-
"workflow_execution_id": "uuid",
|
|
1249
|
-
"steps": [
|
|
1250
|
-
{
|
|
1251
|
-
"step_index": 0,
|
|
1252
|
-
"skill_version_id": "uuid",
|
|
1253
|
-
"assigned_role": "engineer",
|
|
1254
|
-
"status": "completed",
|
|
1255
|
-
"outcome": "success",
|
|
1256
|
-
"started_at": "...",
|
|
1257
|
-
"completed_at": "..."
|
|
1258
|
-
}
|
|
1259
|
-
],
|
|
1260
|
-
"status": "running",
|
|
1261
|
-
"started_at": "..."
|
|
1262
|
-
}
|
|
1263
|
-
```
|
|
1264
|
-
|
|
1265
|
-
### Pending Revisions (PM のみ)
|
|
1266
|
-
|
|
1267
|
-
レビューで `revision_requested` になったステップを検知する。ミニオンの `revision-watcher` デーモンが30秒ごとにポーリングし、LLM で差し戻し先ステップを判断した上で `/api/minion/revision-reset` を呼び出す。
|
|
1268
|
-
|
|
1269
|
-
| Method | Endpoint | Description |
|
|
1270
|
-
|--------|----------|-------------|
|
|
1271
|
-
| GET | `/api/minion/pending-revisions` | `revision_requested` 状態のステップ一覧(PMのプロジェクトのみ) |
|
|
1272
|
-
| POST | `/api/minion/revision-reset` | 差し戻し対象ステップを `pending` に戻す |
|
|
1273
|
-
|
|
1274
|
-
GET Response:
|
|
1275
|
-
```json
|
|
1276
|
-
{
|
|
1277
|
-
"revisions": [
|
|
1278
|
-
{
|
|
1279
|
-
"execution_id": "uuid",
|
|
1280
|
-
"workflow_name": "daily-check",
|
|
1281
|
-
"revision_step_index": 2,
|
|
1282
|
-
"review_comment": "string (レビュアーのフィードバック)",
|
|
1283
|
-
"pipeline": [
|
|
1284
|
-
{
|
|
1285
|
-
"step_index": 0,
|
|
1286
|
-
"skill_version_id": "uuid",
|
|
1287
|
-
"skill_name": "string|null",
|
|
1288
|
-
"assigned_role": "pm|engineer|accountant"
|
|
1289
|
-
}
|
|
1290
|
-
]
|
|
1291
|
-
}
|
|
1292
|
-
]
|
|
1293
|
-
}
|
|
1294
|
-
```
|
|
1295
|
-
|
|
1296
|
-
POST `/api/minion/revision-reset` body:
|
|
1297
|
-
```json
|
|
1298
|
-
{
|
|
1299
|
-
"execution_id": "uuid",
|
|
1300
|
-
"target_step_index": 0,
|
|
1301
|
-
"revision_step_index": 2,
|
|
1302
|
-
"revision_feedback": "string (省略可、target step の review_comment に保存)"
|
|
1303
|
-
}
|
|
1304
|
-
```
|
|
1305
|
-
|
|
1306
|
-
- `target_step_index` は差し戻し先(やり直し起点)のインデックス
|
|
1307
|
-
- `revision_step_index` は差し戻しを要求されたレビューステップのインデックス(`target_step_index <= revision_step_index`)
|
|
1308
|
-
- target から revision までのステップが `pending` に戻り、`revision_feedback` が再実行時のコンテキストとして注入される
|
|
1309
|
-
|
|
1310
|
-
Response:
|
|
1311
|
-
```json
|
|
1312
|
-
{
|
|
1313
|
-
"success": true,
|
|
1314
|
-
"reset_count": 3,
|
|
1315
|
-
"target_step_index": 0,
|
|
1316
|
-
"revision_step_index": 2
|
|
1317
|
-
}
|
|
1318
|
-
```
|
|
1319
|
-
|
|
1320
1053
|
---
|
|
1321
1054
|
|
|
1322
1055
|
## DAG Workflows (HQ, ノード/エッジ方式)
|
|
1323
1056
|
|
|
1324
|
-
DAG
|
|
1057
|
+
DAG ワークフローは有向非巡回グラフでスキル間の依存関係を表現するワークフローです。HQダッシュボードの DAG エディタで作成・編集できるほか、ミニオンAPI経由でも JSON ベースで編集可能(PMロールのみ)。ミニオンはプルベースのポーリングで pending ノードを検出・実行します。
|
|
1325
1058
|
|
|
1326
1059
|
### 編集エンドポイント (PMロール限定)
|
|
1327
1060
|
|
|
@@ -1407,7 +1140,7 @@ POST `/api/minion/dag-workflows/:id/publish` (body なし):
|
|
|
1407
1140
|
}
|
|
1408
1141
|
```
|
|
1409
1142
|
|
|
1410
|
-
- `type` (必須): `start` | `end` | `skill` | `review` | `fan_out` | `join` | `conditional` | `transform`
|
|
1143
|
+
- `type` (必須): `start` | `end` | `skill` | `review` | `fan_out` | `join` | `conditional` | `transform` | `script`
|
|
1411
1144
|
- `id` (任意): 省略時は `<type>_1`, `<type>_2`, ... で自動採番
|
|
1412
1145
|
- `label` (任意): 省略時は `New <type>`
|
|
1413
1146
|
- `after` (任意): このノードの後ろに挿入。`after` → 新ノード へのエッジを自動生成
|
|
@@ -1425,6 +1158,7 @@ POST `/api/minion/dag-workflows/:id/publish` (body なし):
|
|
|
1425
1158
|
| `join` | `join_mode`, `aggregation` | |
|
|
1426
1159
|
| `conditional` | `condition_type`, `branches` or `default_branch` | |
|
|
1427
1160
|
| `transform` | `assigned_role`, incoming edge 1 本 + outgoing edge 1 本 (両方 `contract` 必須) | `transform_instruction` は optional hint。I/O 型は edge の contract から自動導出される |
|
|
1161
|
+
| `script` | `assigned_role`, `script_runtime` (`'python'` \| `'node'`), `script_source` (非空) | `script_timeout_seconds` (任意, デフォルト 60, 範囲 1-600)。LLM を使わず `python3` / `node` で決定的にスクリプト実行。input_data を stdin で JSON 受信 → output_data を stdout に JSON 出力。outgoing edge に `contract` があれば HQ が output_data を検証 |
|
|
1428
1162
|
|
|
1429
1163
|
**review ノード追加の例:**
|
|
1430
1164
|
```json
|
|
@@ -1683,7 +1417,7 @@ hq dag update-node <wf-id> fan_out_1 /tmp/u.json
|
|
|
1683
1417
|
テンプレート内部のノード/エッジを個別操作するAPIは現在ない。テンプレートは `template` フィールドの全体上書きで更新すること。テンプレートは start/end ノードを持たない sub-graph であり、バリデーション時に再帰的に検証される。
|
|
1684
1418
|
|
|
1685
1419
|
> **⚠️ 重要: テンプレート内に `start` / `end` ノードを配置してはいけない。**
|
|
1686
|
-
> テンプレートのエントリポイントとエグジットポイントは、エッジ構造から自動検出される(incoming edge がないノード = エントリ、outgoing edge がないノード = エグジット)。`start` / `end` はトップレベル DAG 専用のノードタイプであり、テンプレート内に含めるとバリデーションエラーになる。テンプレート内では `skill`, `conditional`, `transform`, `review` 等の実行ノードのみ使用すること。
|
|
1420
|
+
> テンプレートのエントリポイントとエグジットポイントは、エッジ構造から自動検出される(incoming edge がないノード = エントリ、outgoing edge がないノード = エグジット)。`start` / `end` はトップレベル DAG 専用のノードタイプであり、テンプレート内に含めるとバリデーションエラーになる。テンプレート内では `skill`, `conditional`, `transform`, `script`, `review` 等の実行ノードのみ使用すること。
|
|
1687
1421
|
|
|
1688
1422
|
### ミニオン CLI ラッパー
|
|
1689
1423
|
|
|
@@ -1787,7 +1521,9 @@ GET `/api/minion/dag-executions/:id` Response:
|
|
|
1787
1521
|
| POST | `/api/dag/minion/node-complete` | ノード完了を報告し、下流ノードへカスケード |
|
|
1788
1522
|
| POST | `/api/dag/minion/dag-cron-tick` | PMロールのミニオン専用。所属プロジェクトのcron-enabled DAGワークフローを発火 |
|
|
1789
1523
|
|
|
1790
|
-
ミニオンの `dag-step-poller` デーモンが30秒ごとに `pending-nodes` を叩き、最大2並列で claim → skill/transform 実行 → node-complete の流れを回す。`skill`・`transform` 以外のノード(start/end/review/fan_out/join/conditional)はHQ内部のカスケードエンジンが処理するため、ミニオンには返されない。
|
|
1524
|
+
ミニオンの `dag-step-poller` デーモンが30秒ごとに `pending-nodes` を叩き、最大2並列で claim → skill/transform/script 実行 → node-complete の流れを回す。`skill`・`transform`・`script` 以外のノード(start/end/review/fan_out/join/conditional)はHQ内部のカスケードエンジンが処理するため、ミニオンには返されない。
|
|
1525
|
+
|
|
1526
|
+
`script` ノード (v3.54.0〜) は LLM を経由しない決定的な処理用。ミニオン標準搭載の `python3` / `node` で `script_source` を `child_process` 実行し、`input_data` を stdin で JSON 渡し → stdout の JSON を `output_data` として `node-complete` に報告する。タイムアウト超過 (`script_timeout_seconds`、デフォルト60s) / 非0終了 / 不正JSON はいずれも `failed` 扱いで stderr が `output_summary` に格納される。tmux セッションは作らない (専用プロセスのみ)。
|
|
1791
1527
|
|
|
1792
1528
|
`dag-cron-poller` デーモン(v3.51.0〜)は60秒ごとに `dag-cron-tick` を叩く。HQ側で「呼び出しミニオンがPMロールであるプロジェクトのDAGワークフロー」のうち `cron_enabled AND next_run_at <= now()` を atomic claim → triggerDagExecution。Push型ではないので、PMミニオンが offline ならcron発火が遅延する。
|
|
1793
1529
|
|
|
@@ -1809,7 +1545,10 @@ Response:
|
|
|
1809
1545
|
"assigned_role": "pm|engineer|accountant",
|
|
1810
1546
|
"input_data": { "...": "..." },
|
|
1811
1547
|
"revision_feedback": "string|null",
|
|
1812
|
-
"transform_instruction": "string|null"
|
|
1548
|
+
"transform_instruction": "string|null",
|
|
1549
|
+
"script_runtime": "python|node|null",
|
|
1550
|
+
"script_source": "string|null",
|
|
1551
|
+
"script_timeout_seconds": "number|null"
|
|
1813
1552
|
}
|
|
1814
1553
|
]
|
|
1815
1554
|
}
|
|
@@ -1818,7 +1557,7 @@ Response:
|
|
|
1818
1557
|
返却条件:
|
|
1819
1558
|
- `assigned_role` がミニオンのプロジェクトロールと一致
|
|
1820
1559
|
- ノードの `status` が `pending`
|
|
1821
|
-
- `node_type` が `skill
|
|
1560
|
+
- `node_type` が `skill`、`transform`、または `script`
|
|
1822
1561
|
- スコープ内の全依存ノードが `completed`(`requires_review` の場合は `approved` も必要)
|
|
1823
1562
|
|
|
1824
1563
|
`scope_path` は fan-out 内のインスタンスを示す(ルートは空文字列、1段のfan-outでは `fan_out_A:0`、ネストでは `fan_out_A:2/fan_out_B:1`)。依存解決は同じ scope_path 内で閉じる。
|
|
@@ -1946,6 +1685,7 @@ DAG ワークフローの graph は以下の構造で保存される(`dag_work
|
|
|
1946
1685
|
| `end` | 終端 | ❌ (内部) |
|
|
1947
1686
|
| `skill` | スキル実行。`skill_version_id` と `assigned_role` が必須 | ✅ |
|
|
1948
1687
|
| `transform` | contract 同士のブリッジ。I/O 型は incoming/outgoing edge の `contract` から自動導出、出力は HQ が contract validate。`transform_instruction` は optional hint | ✅ |
|
|
1688
|
+
| `script` | LLMを使わず `python3` / `node` でインラインスクリプトを実行 (v3.54.0〜)。input_data を stdin で JSON 受信 → output_data を stdout に JSON 出力。決定的処理向け | ✅ |
|
|
1949
1689
|
| `review` | レビューゲート。`approved` / `revision_requested` で分岐 | ❌ (内部) |
|
|
1950
1690
|
| `fan_out` | 配列入力をテンプレートsub-graphに展開して並列実行。子が全て settle すると自ノードが completed に遷移 | ❌ (内部) |
|
|
1951
1691
|
| `join` | N本の上流エッジを待ち合わせる汎用バリア。fan_out とは独立 | ❌ (内部) |
|
|
@@ -1971,6 +1711,9 @@ DAG ワークフローの graph は以下の構造で保存される(`dag_work
|
|
|
1971
1711
|
| `branches` | Record<string,string> | conditional: 条件出力→遷移先ノードID |
|
|
1972
1712
|
| `default_branch` | string? | conditional: マッチしなかった場合の遷移先 |
|
|
1973
1713
|
| `transform_instruction` | string | transform: LLMへの変換指示 |
|
|
1714
|
+
| `script_runtime` | `python`\|`node` | script: ランタイム指定 |
|
|
1715
|
+
| `script_source` | string | script: インラインスクリプト本文。stdin から JSON を読み、stdout に JSON を出力 |
|
|
1716
|
+
| `script_timeout_seconds` | number? | script: タイムアウト秒数 (デフォルト60、範囲1-600) |
|
|
1974
1717
|
| `review` | object | review: レビュー設定 |
|
|
1975
1718
|
|
|
1976
1719
|
#### DagEdge
|
package/docs/task-guides.md
CHANGED
|
@@ -88,7 +88,7 @@ requires:
|
|
|
88
88
|
---
|
|
89
89
|
|
|
90
90
|
Skill instructions here...
|
|
91
|
-
Use {{PROJECT_VAR}} to reference project
|
|
91
|
+
Use {{PROJECT_VAR}} to reference project variables.
|
|
92
92
|
```
|
|
93
93
|
|
|
94
94
|
フロントマターのフィールド:
|
|
@@ -120,7 +120,7 @@ description: サイトをデプロイする
|
|
|
120
120
|
|
|
121
121
|
- 変数名は英数字とアンダースコアのみ(`\w+`)
|
|
122
122
|
- 未定義の変数は `{{VAR_NAME}}` のまま残る(エラーにはならない)
|
|
123
|
-
- 展開優先順位: ミニオン変数 <
|
|
123
|
+
- 展開優先順位: ミニオン変数 < プロジェクト変数(後者が上書き)
|
|
124
124
|
- ルーティン実行時もミニオン変数による `{{VAR}}` 展開が行われる
|
|
125
125
|
|
|
126
126
|
### 変数とシークレットの使い分け
|
|
@@ -130,7 +130,7 @@ description: サイトをデプロイする
|
|
|
130
130
|
| 変数 | `{{VAR_NAME}}` | 設定・パラメータ(非機密) | デプロイ先、サイトURL、プロジェクト名 |
|
|
131
131
|
| シークレット | `$SECRET_NAME`(環境変数) | 機密情報 | APIキー、パスワード、トークン |
|
|
132
132
|
|
|
133
|
-
-
|
|
133
|
+
- **変数**はスキル本文のテンプレートとして展開される。全スコープ(ミニオン・プロジェクト)で同じ `{{VAR}}` 構文を使用する
|
|
134
134
|
- **シークレット**は環境変数としてプロセスに注入される。テンプレート展開は行われない
|
|
135
135
|
- デイリーログやメモリーから変数・シークレットの値を推測して使用しないこと
|
|
136
136
|
|
|
@@ -154,63 +154,11 @@ minion-cli skill fetch <name>
|
|
|
154
154
|
|
|
155
155
|
---
|
|
156
156
|
|
|
157
|
-
## ワークフローの修正 (PM のみ)
|
|
158
|
-
|
|
159
|
-
### パイプライン構成の変更
|
|
160
|
-
|
|
161
|
-
```bash
|
|
162
|
-
# API経由で push (新バージョン自動作成)
|
|
163
|
-
curl -s -X POST "$HQ_URL/api/minion/workflows" \
|
|
164
|
-
-H "Authorization: Bearer $API_TOKEN" \
|
|
165
|
-
-H "Content-Type: application/json" \
|
|
166
|
-
-d '{
|
|
167
|
-
"name": "my-workflow",
|
|
168
|
-
"pipeline_skill_names": ["skill-1", "skill-2"],
|
|
169
|
-
"content": "Workflow description",
|
|
170
|
-
"project_id": "<project-uuid>",
|
|
171
|
-
"change_summary": "Updated pipeline"
|
|
172
|
-
}'
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
### ステップごとのロール・レビュー設定
|
|
176
|
-
|
|
177
|
-
```bash
|
|
178
|
-
curl -s -X POST "$HQ_URL/api/minion/workflows" \
|
|
179
|
-
-H "Authorization: Bearer $API_TOKEN" \
|
|
180
|
-
-H "Content-Type: application/json" \
|
|
181
|
-
-d '{
|
|
182
|
-
"name": "my-workflow",
|
|
183
|
-
"pipeline_skill_names": ["skill-1", "skill-2"],
|
|
184
|
-
"pipeline_steps": [
|
|
185
|
-
{ "assigned_role": "engineer", "requires_review": false },
|
|
186
|
-
{ "assigned_role": "pm", "requires_review": true }
|
|
187
|
-
],
|
|
188
|
-
"content": "Workflow description",
|
|
189
|
-
"project_id": "<project-uuid>"
|
|
190
|
-
}'
|
|
191
|
-
```
|
|
192
|
-
|
|
193
|
-
### ローカルワークフローの同期
|
|
194
|
-
|
|
195
|
-
```bash
|
|
196
|
-
# HQからワークフローを取得 (不足スキルも自動fetch)
|
|
197
|
-
curl -s -X POST "http://localhost:8080/api/workflows/fetch/<name>" \
|
|
198
|
-
-H "Authorization: Bearer $API_TOKEN"
|
|
199
|
-
|
|
200
|
-
# ローカルワークフローをHQにpush (スキルも自動push)
|
|
201
|
-
curl -s -X POST "http://localhost:8080/api/workflows/push/<name>" \
|
|
202
|
-
-H "Authorization: Bearer $API_TOKEN"
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
> **Note**: `/api/workflows/push|fetch` は線形パイプライン形式(`pipeline_skill_names`)の旧式ワークフロー専用です。DAGワークフロー(ノード/エッジ形式)はHQダッシュボードの DAG エディタで作成・編集します。次節を参照。
|
|
206
|
-
|
|
207
|
-
---
|
|
208
|
-
|
|
209
157
|
## DAG ワークフロー (ノード/エッジ形式)
|
|
210
158
|
|
|
211
|
-
DAG
|
|
159
|
+
DAG ワークフローは有向非巡回グラフでスキル間の依存関係を表現するワークフローです。fan-out による並列展開、join による集約、conditional による分岐、transform による LLM データ変換、script による決定的スクリプト実行 (Python/Node)、review によるゲーティングをサポートします。
|
|
212
160
|
|
|
213
|
-
**HQダッシュボードの DAG
|
|
161
|
+
**HQダッシュボードの DAG エディタ(プロジェクト画面の「DAG」タブ)で GUI 編集**できるほか、**ミニオンからは JSON ベースで編集可能**(PMロールのみ)。ミニオンは実行ランタイムも担当し、`dag-step-poller` デーモンが pending ノードを自動で処理します。
|
|
214
162
|
|
|
215
163
|
**cronスケジュール (v3.51.0〜):** DAGワークフローは cron 式による定期実行をサポート。設定はHQダッシュボードのDAGビューにある SchedulePanel から行う(最小実行間隔 5分)。発火主体はそのプロジェクトのPMロールのミニオンで、`dag-cron-poller` デーモンが60秒間隔で `/api/dag/minion/dag-cron-tick` を叩いて発火させる。PM不在のプロジェクトでは cron は発火しない。
|
|
216
164
|
|
|
@@ -405,7 +353,7 @@ hq dag remove-edge <wf-id> edge_3
|
|
|
405
353
|
|
|
406
354
|
**fan_out テンプレート編集:**
|
|
407
355
|
|
|
408
|
-
> **⚠️ テンプレート内に `start` / `end` ノードを入れないこと。** テンプレートのエントリ/エグジットはエッジ構造から自動検出される。`start` / `end` はトップレベル DAG 専用であり、テンプレート内に含めるとバリデーションエラーになる。`skill`, `conditional`, `transform`, `review` 等の実行ノードのみ使用すること。
|
|
356
|
+
> **⚠️ テンプレート内に `start` / `end` ノードを入れないこと。** テンプレートのエントリ/エグジットはエッジ構造から自動検出される。`start` / `end` はトップレベル DAG 専用であり、テンプレート内に含めるとバリデーションエラーになる。`skill`, `conditional`, `transform`, `script`, `review` 等の実行ノードのみ使用すること。
|
|
409
357
|
|
|
410
358
|
```bash
|
|
411
359
|
# fan_out ノードの template を PATCH で上書き
|
|
@@ -434,7 +382,7 @@ hq dag update-node <wf-id> fan_out_1 /tmp/t.json
|
|
|
434
382
|
- 書き込み(create / put / publish / dag 操作)は **PMロールのみ**。Engineer / accountant では 403 が返る。読み取り(fetch)は全メンバー可。
|
|
435
383
|
- ノード/エッジ操作は各ステップでドラフトに自動保存され、バリデーション結果がレスポンスに含まれる。
|
|
436
384
|
- `hq dag validate` で公開前にフル検証できる。publish 時の想定外エラーを防止できる。
|
|
437
|
-
- 全文 JSON 操作(`hq put dag-workflow`)も引き続き利用可能だが、**ノード/エッジ操作API
|
|
385
|
+
- 全文 JSON 操作(`hq put dag-workflow`)も引き続き利用可能だが、**ノード/エッジ操作APIの方が推奨**(型の取り違えで 400 になりやすい)。
|
|
438
386
|
|
|
439
387
|
### 実行フロー(ランタイム側、参考)
|
|
440
388
|
|
|
@@ -548,6 +496,63 @@ input_data: { "items": [{ "title": "Item A" }, { "title": "Item B" }, { "title":
|
|
|
548
496
|
output_data: { "items": [{ "title": "Item A" }, { "title": "Item C" }] }
|
|
549
497
|
```
|
|
550
498
|
|
|
499
|
+
### Script ノード(決定的処理、LLM不要)v3.54.0〜
|
|
500
|
+
|
|
501
|
+
Script ノードは **LLM を使わない決定的なデータ処理** を DAG 内に挟み込むためのノード。トークンコストもかからず、出力形式のブレも発生しない。ミニオン標準搭載の `python3` または `node` でインラインスクリプトを `child_process` 実行する。
|
|
502
|
+
|
|
503
|
+
**静的バリデーション要件:**
|
|
504
|
+
|
|
505
|
+
- `assigned_role` 必須(pm / engineer / accountant のいずれか)
|
|
506
|
+
- `script_runtime`: `'python'` または `'node'`
|
|
507
|
+
- `script_source`: 非空のスクリプト本文
|
|
508
|
+
- `script_timeout_seconds`: 任意(デフォルト 60、範囲 1–600)
|
|
509
|
+
|
|
510
|
+
**I/O プロトコル(skill / transform と完全に揃う):**
|
|
511
|
+
|
|
512
|
+
- 入力: `input_data` (incoming edge から渡る JSON object) → スクリプトの **stdin に JSON 1 個** として書き込まれる
|
|
513
|
+
- 出力: スクリプトが **stdout に JSON object 1 個を書く** → そのままパースされて `output_data` として `node-complete` に送られる
|
|
514
|
+
- outgoing edge に contract が貼ってあれば HQ が `output_data` を validate(skill / transform と同じ runtime validation 経路)
|
|
515
|
+
|
|
516
|
+
**failure モード(いずれも `status: failed`、stderr が `output_summary` に格納される):**
|
|
517
|
+
|
|
518
|
+
- 非 0 終了
|
|
519
|
+
- stdout が JSON parse 不能 / object でない(配列・プリミティブは不可)
|
|
520
|
+
- `script_timeout_seconds` 超過(プロセスは SIGKILL)
|
|
521
|
+
- `script_runtime` が unsupported
|
|
522
|
+
|
|
523
|
+
**典型用途:**
|
|
524
|
+
|
|
525
|
+
```python
|
|
526
|
+
# script_runtime: "python", input edge contract: { items: array<item> }
|
|
527
|
+
# output edge contract: { items: array<item>, total: number }
|
|
528
|
+
import sys, json
|
|
529
|
+
|
|
530
|
+
data = json.load(sys.stdin)
|
|
531
|
+
items = [it for it in data["items"] if it.get("score", 0) >= 0.8]
|
|
532
|
+
json.dump({"items": items, "total": len(items)}, sys.stdout)
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
```javascript
|
|
536
|
+
// script_runtime: "node", URL 一覧から domain ごとにグルーピング
|
|
537
|
+
let raw = ''
|
|
538
|
+
process.stdin.on('data', c => raw += c)
|
|
539
|
+
process.stdin.on('end', () => {
|
|
540
|
+
const data = JSON.parse(raw)
|
|
541
|
+
const groups = {}
|
|
542
|
+
for (const url of data.urls) {
|
|
543
|
+
const host = new URL(url).host
|
|
544
|
+
;(groups[host] ||= []).push(url)
|
|
545
|
+
}
|
|
546
|
+
process.stdout.write(JSON.stringify({ groups }))
|
|
547
|
+
})
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
**制約:**
|
|
551
|
+
|
|
552
|
+
- 追加ライブラリのインストール(pip / npm install)は未対応。ミニオン標準搭載のもののみ使用可能
|
|
553
|
+
- tmux セッションは作らず、ミニオンのエージェントプロセス内で `child_process.spawn` する
|
|
554
|
+
- 並列実行上限は skill / transform と共通(`concurrency-manager` の `MAX_CONCURRENT=2`)
|
|
555
|
+
|
|
551
556
|
### DAG 構築時のノード選定フロー
|
|
552
557
|
|
|
553
558
|
スキルは汎用的で再利用可能な資産であり、ワークフロー固有の contract に合わせて SKILL.md を改修することは原則行わない。代わりに以下のフローで判断する:
|
|
@@ -579,7 +584,7 @@ Review ノードはレビューゲート。`review_status=review_pending` で下
|
|
|
579
584
|
- `approved` にすると `approved` 種別のエッジで下流に進む
|
|
580
585
|
- `revision_requested` にすると `revision` 種別のエッジで差し戻し先に戻る
|
|
581
586
|
|
|
582
|
-
|
|
587
|
+
差し戻しはサーバ側のカスケードで自動処理される(`revision` 種別のエッジが指す上流ノード以降が `pending` に戻り再実行される)。
|
|
583
588
|
|
|
584
589
|
### デバッグ
|
|
585
590
|
|
|
@@ -714,17 +719,14 @@ curl -X PATCH "$HQ_URL/api/minion/projects/<project-id>/tasks/<task-id>" \
|
|
|
714
719
|
-H "Authorization: Bearer $API_TOKEN" -H "Content-Type: application/json" \
|
|
715
720
|
-d '{"status":"doing"}'
|
|
716
721
|
|
|
717
|
-
#
|
|
722
|
+
# レビュー依頼(acceptance_criteria を全て満たした後)
|
|
718
723
|
curl -X PATCH "$HQ_URL/api/minion/projects/<project-id>/tasks/<task-id>" \
|
|
719
724
|
-H "Authorization: Bearer $API_TOKEN" -H "Content-Type: application/json" \
|
|
720
725
|
-d '{"status":"review"}'
|
|
721
|
-
|
|
722
|
-
# 完了
|
|
723
|
-
curl -X PATCH "$HQ_URL/api/minion/projects/<project-id>/tasks/<task-id>" \
|
|
724
|
-
-H "Authorization: Bearer $API_TOKEN" -H "Content-Type: application/json" \
|
|
725
|
-
-d '{"status":"done"}'
|
|
726
726
|
```
|
|
727
727
|
|
|
728
|
+
> **重要**: ミニオン自身は `done` へ直接遷移してはいけない。`done` 遷移はレビュアー(人間または別のミニオン)の責務。受け入れ要件達成後は `review` で停止し、承認を待つこと。
|
|
729
|
+
|
|
728
730
|
### 共通の注意
|
|
729
731
|
|
|
730
732
|
- **`status_changed_at` を手動で渡してはならない**。サーバ側で自動更新される(stalled 検出に使われる)。
|
|
@@ -821,20 +823,19 @@ minion-cli skill list --local
|
|
|
821
823
|
minion-cli skill fetch <name>
|
|
822
824
|
```
|
|
823
825
|
|
|
824
|
-
### ワークフローが実行されない
|
|
826
|
+
### DAG ワークフローが実行されない
|
|
825
827
|
|
|
826
828
|
```bash
|
|
827
|
-
#
|
|
828
|
-
curl -s "
|
|
829
|
-
-H "Authorization: Bearer $API_TOKEN"
|
|
829
|
+
# pending ノードが自分に割り当てられているか確認
|
|
830
|
+
curl -s "$HQ_URL/api/dag/minion/pending-nodes" \
|
|
831
|
+
-H "Authorization: Bearer $API_TOKEN" | jq
|
|
830
832
|
|
|
831
|
-
#
|
|
832
|
-
|
|
833
|
-
-H "Authorization: Bearer $API_TOKEN" \
|
|
834
|
-
-H "Content-Type: application/json" \
|
|
835
|
-
-d '{ "workflow_id": "<workflow-uuid>" }'
|
|
833
|
+
# dag-step-poller のログを確認
|
|
834
|
+
tail -f ~/.minion/logs/agent.log | grep '\[DAG'
|
|
836
835
|
```
|
|
837
836
|
|
|
837
|
+
PMロールが不在のプロジェクトでは cron 発火が行われない。`hq list dag-workflows <project-id>` の `my_role` を確認すること。
|
|
838
|
+
|
|
838
839
|
### エージェントの状態確認
|
|
839
840
|
|
|
840
841
|
```bash
|
package/linux/routes/chat.js
CHANGED
|
@@ -464,26 +464,11 @@ async function buildContextPrefix(message, context, sessionId, workspaceId, refe
|
|
|
464
464
|
)
|
|
465
465
|
}
|
|
466
466
|
break
|
|
467
|
-
case 'workflow':
|
|
468
|
-
if (context.projectId) {
|
|
469
|
-
const label = context.workflowName
|
|
470
|
-
? `ワークフロー「${context.workflowName}」`
|
|
471
|
-
: 'ワークフロー'
|
|
472
|
-
parts.push(
|
|
473
|
-
`ユーザーはHQダッシュボードで${label}を閲覧しています。`,
|
|
474
|
-
`ワークフロー情報を取得するには以下を実行してください:`,
|
|
475
|
-
` hq fetch workflow ${context.workflowName || context.workflowId}`,
|
|
476
|
-
`プロジェクトコンテキスト:`,
|
|
477
|
-
` hq fetch project-context ${context.projectId}`,
|
|
478
|
-
`取得した内容をもとに回答してください。`
|
|
479
|
-
)
|
|
480
|
-
}
|
|
481
|
-
break
|
|
482
467
|
case 'dag-workflow':
|
|
483
468
|
if (context.projectId && context.dagWorkflowId) {
|
|
484
469
|
parts.push(
|
|
485
470
|
`ユーザーはHQダッシュボードで DAG ワークフロー (ID: ${context.dagWorkflowId}) のエディタ/詳細を閲覧しています。`,
|
|
486
|
-
`DAG ワークフローはノード/エッジ形式でスキル間の依存関係を表現し、fan-out / join / conditional / transform / review をサポートします。`,
|
|
471
|
+
`DAG ワークフローはノード/エッジ形式でスキル間の依存関係を表現し、fan-out / join / conditional / transform / script / review をサポートします。`,
|
|
487
472
|
`DAG ワークフロー情報を取得するには以下を実行してください:`,
|
|
488
473
|
` hq fetch dag-workflow ${context.dagWorkflowId}`,
|
|
489
474
|
`プロジェクトコンテキスト:`,
|
package/package.json
CHANGED
package/rules/core.md
CHANGED
|
@@ -15,10 +15,7 @@ You are an AI agent running on a Minion VPS, managed by @geekbeer/minion.
|
|
|
15
15
|
Project (組織・課金単位)
|
|
16
16
|
├── Context (markdown, PMが更新)
|
|
17
17
|
├── Members (minion + role: pm | engineer | accountant)
|
|
18
|
-
|
|
19
|
-
│ ├── Versions (pipeline の不変スナップショット)
|
|
20
|
-
│ └── Executions (実行履歴, ステップごとの進捗)
|
|
21
|
-
└── DAG Workflows (ノード/エッジ形式のワークフロー, beta)
|
|
18
|
+
└── DAG Workflows (ノード/エッジ形式のワークフロー)
|
|
22
19
|
├── Versions (graph の不変スナップショット)
|
|
23
20
|
└── Executions (node_executions の集合, scope-aware)
|
|
24
21
|
|
|
@@ -26,14 +23,14 @@ Minion
|
|
|
26
23
|
└── Routines (ミニオンローカルの定期タスク, cron付き)
|
|
27
24
|
```
|
|
28
25
|
|
|
29
|
-
- **Workflow**:
|
|
30
|
-
- **DAG Workflow**: プロジェクトスコープ。ノード/エッジで依存関係を表現する新方式。fan-out / join / conditional / transform / review をサポート。作成・編集はHQダッシュボードのみ、ミニオンは `dag-step-poller` で自動実行。詳細は `~/.minion/docs/api-reference.md` の「DAG Workflows」と `~/.minion/docs/task-guides.md` の「DAG ワークフロー」を参照。
|
|
26
|
+
- **DAG Workflow**: プロジェクトスコープ。ノード/エッジで依存関係を表現するワークフロー。fan-out / join / conditional / transform / script / review をサポート。作成・編集はHQダッシュボードまたはミニオンAPI、ランタイムは `dag-step-poller` が自動実行。詳細は `~/.minion/docs/api-reference.md` の「DAG Workflows」と `~/.minion/docs/task-guides.md` の「DAG ワークフロー」を参照。
|
|
31
27
|
- **PMロールで編集する場合の重要な規則**:
|
|
32
28
|
- ノード/エッジ/contract の追加・更新は**個別API** (`/nodes` `/edges` `/contracts`) を使うこと。`PUT /dag-workflows/:id` による graph 全文PUTは型の取り違えが起きやすく、バリデーションエラーで 400 が返る
|
|
33
29
|
- `edge.contract` は**単一のContract名(string)**のみ。配列は不可。複数の型構造を束ねたい場合は、それらを内包する複合Contractを1つ定義する
|
|
34
30
|
- Contract内で `List<別Contract>` を表現するには `type: 'array'` + `items: "別Contract名"` を使う(詳細は `~/.minion/docs/api-reference.md` の「Contracts API」を参照)
|
|
35
31
|
- **Contract はランタイムで強制される型定義**。`node-complete` 報告時に outgoing edge の contract で `output_data` が検証され、違反はノード `failed` 扱い。スキルが contract に沿った `## Output Data` を出せない場合は **transform ノードをスキルと下流の間に挟んで整形**すること。スキル側の SKILL.md を各ワークフロー専用に改修するのは原則 NG(スキルは汎用資産)
|
|
36
32
|
- **transform ノードの I/O 型は edge の contract から自動導出**。incoming edge と outgoing edge にそれぞれ contract を必ず貼ること。`transform_instruction` は contract だけで意図が伝わらない場合の補足ヒント(任意)
|
|
33
|
+
- **script ノード (v3.54.0〜)** は LLM を使わない決定的処理用。`script_runtime` (`'python'` or `'node'`) と `script_source` を指定。input_data を stdin で JSON 受け取り → output_data を stdout に JSON 出力する規約。outgoing edge に contract を貼れば transform と同じ runtime validation が走る。LLMトークンを節約したい・出力ブレを許容できない定型処理に使う。詳細は `~/.minion/docs/task-guides.md` の「Script ノード」を参照
|
|
37
34
|
- **fan_out の incoming edge に contract を貼る場合**、`fan_out_source` が指すフィールドが contract 内に `type='array'` として宣言されている必要がある(静的検証で弾かれる)
|
|
38
35
|
- **Routine**: ミニオンスコープ。ミニオンローカルの定期タスク。
|
|
39
36
|
- **Project Tasks / Milestones**: プロジェクトスコープ。**人間+ミニオンが共有するタスクボード**(5段階Kanban: `backlog`→`todo`→`doing`→`review`→`done`)とロードマップ(マイルストーン)。ミニオンは `/api/minion/projects/:projectId/{tasks,milestones,health}` で操作可能。
|
|
@@ -103,7 +100,7 @@ minion-cli --version # バージョン確認
|
|
|
103
100
|
|
|
104
101
|
`http://localhost:8080` — 認証: `Authorization: Bearer $API_TOKEN`
|
|
105
102
|
|
|
106
|
-
主なカテゴリ: Health, Skills,
|
|
103
|
+
主なカテゴリ: Health, Skills, Executions, Terminal, Files, Commands, Permissions, Admin (HQ-pushed freeze), Web Extraction (experimental)
|
|
107
104
|
|
|
108
105
|
#### Web Page Extraction 🧪 (experimental, v3.53.0〜)
|
|
109
106
|
|
|
@@ -202,7 +199,7 @@ Note: Codex CLI の `.codex/` ディレクトリはLLMからの直接編集が
|
|
|
202
199
|
|
|
203
200
|
`$HQ_URL/api/minion/*` — 認証: `Authorization: Bearer $API_TOKEN`
|
|
204
201
|
|
|
205
|
-
主なカテゴリ: Projects, Context,
|
|
202
|
+
主なカテゴリ: Projects, Context, DAG Workflows, Skills, Executions, Routines, Reports
|
|
206
203
|
|
|
207
204
|
DAG ワークフローのランタイム API は `$HQ_URL/api/dag/minion/*`(pending-nodes / claim-node / node-complete / dag-cron-tick)。`dag-step-poller` と `dag-cron-poller` デーモンが自動でポーリングするため、通常ミニオンのAI側から直接叩くことは無い。
|
|
208
205
|
|
|
@@ -224,7 +221,7 @@ Routine 実行中は以下もtmuxセッション環境で利用可能:
|
|
|
224
221
|
- `MINION_ROUTINE_ID` — ルーティンUUID
|
|
225
222
|
- `MINION_ROUTINE_NAME` — ルーティン名
|
|
226
223
|
|
|
227
|
-
|
|
224
|
+
**変数**(ミニオン変数・プロジェクト変数)はスキル本文の `{{VAR_NAME}}` テンプレートとして実行時に展開される。スキル作成時にパラメータ化したい値は `{{変数名}}` で記述すること。展開優先順位: ミニオン変数 < プロジェクト変数(後者が優先)。
|
|
228
225
|
|
|
229
226
|
**シークレット**(ミニオンシークレット)はサーバー起動時に `process.env` にロードされ、全子プロセスで環境変数 `$SECRET_NAME` として利用可能。APIキーやパスワード等の機密情報に使用する。シークレットは `{{VAR}}` テンプレートでは展開されない。
|
|
230
227
|
|
package/win/routes/chat.js
CHANGED
|
@@ -525,24 +525,11 @@ async function buildContextPrefix(message, context, sessionId, workspaceId, refe
|
|
|
525
525
|
)
|
|
526
526
|
}
|
|
527
527
|
break
|
|
528
|
-
case 'workflow':
|
|
529
|
-
if (context.projectId) {
|
|
530
|
-
const label = context.workflowName ? `ワークフロー「${context.workflowName}」` : 'ワークフロー'
|
|
531
|
-
parts.push(
|
|
532
|
-
`ユーザーはHQダッシュボードで${label}を閲覧しています。`,
|
|
533
|
-
`ワークフロー情報を取得するには以下を実行してください:`,
|
|
534
|
-
` hq fetch workflow ${context.workflowName || context.workflowId}`,
|
|
535
|
-
`プロジェクトコンテキスト:`,
|
|
536
|
-
` hq fetch project-context ${context.projectId}`,
|
|
537
|
-
`取得した内容をもとに回答してください。`
|
|
538
|
-
)
|
|
539
|
-
}
|
|
540
|
-
break
|
|
541
528
|
case 'dag-workflow':
|
|
542
529
|
if (context.projectId && context.dagWorkflowId) {
|
|
543
530
|
parts.push(
|
|
544
531
|
`ユーザーはHQダッシュボードで DAG ワークフロー (ID: ${context.dagWorkflowId}) のエディタ/詳細を閲覧しています。`,
|
|
545
|
-
`DAG ワークフローはノード/エッジ形式でスキル間の依存関係を表現し、fan-out / join / conditional / transform / review をサポートします。`,
|
|
532
|
+
`DAG ワークフローはノード/エッジ形式でスキル間の依存関係を表現し、fan-out / join / conditional / transform / script / review をサポートします。`,
|
|
546
533
|
`DAG ワークフロー情報を取得するには以下を実行してください:`,
|
|
547
534
|
` hq fetch dag-workflow ${context.dagWorkflowId}`,
|
|
548
535
|
`プロジェクトコンテキスト:`,
|