@geekbeer/minion 3.40.1 → 3.40.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -49,7 +49,7 @@ function parseFrontmatter(content) {
49
49
  * written to every enabled plugin's directory so switching Primary doesn't
50
50
  * break skill availability.
51
51
  *
52
- * @param {string} name - Skill slug (e.g. "execution-report")
52
+ * @param {string} name - Skill slug (e.g. "daily-check")
53
53
  * @param {object} opts
54
54
  * @param {string} opts.content - Skill body (markdown without frontmatter)
55
55
  * @param {string} [opts.description] - Skill description for frontmatter
@@ -103,7 +103,7 @@ async function writeSkillToLocal(name, { content, description, display_name, typ
103
103
  * Read a local skill and push it to HQ.
104
104
  * Reusable by workflow push to auto-sync pipeline skills.
105
105
  *
106
- * @param {string} name - Skill slug (e.g. "execution-report")
106
+ * @param {string} name - Skill slug (e.g. "daily-check")
107
107
  * @param {object} [opts]
108
108
  * @param {string} [opts.workspaceId] - Target workspace ID (overrides WORKSPACE_ID env var)
109
109
  * @returns {Promise<object>} HQ response
@@ -391,8 +391,9 @@ async function skillRoutes(fastify, opts) {
391
391
  log_file: logFile,
392
392
  })
393
393
 
394
- // Dispatched steps also run /execution-report so the post-execution hook
395
- // can read back the structured output and forward it to HQ for review.
394
+ // For dispatched steps, the post-execution hook reads the outcome record
395
+ // (set by workflow-runner from the CLI exit code via the local outcome API)
396
+ // and forwards the summary to HQ so reviewers can see the step's report.
396
397
  const isDispatchedStep = execution_id && step_index != null
397
398
  const runOptions = {}
398
399
  if (role) runOptions.role = role
@@ -437,7 +438,7 @@ async function skillRoutes(fastify, opts) {
437
438
  // Post-execution hook: report step completion to HQ
438
439
  if (isDispatchedStep) {
439
440
  try {
440
- // Read execution report generated by /execution-report skill
441
+ // Read the outcome record saved by workflow-runner
441
442
  let outputSummary = null
442
443
  try {
443
444
  const execRecord = await executionStore.getById(effectiveExecutionId)
@@ -867,7 +867,7 @@ push するとパイプライン内のスキル名が `skill_version_id` に解
867
867
  ```json
868
868
  {
869
869
  "name": "my-workflow",
870
- "pipeline_skill_names": ["skill-1", "skill-2", "execution-report"],
870
+ "pipeline_skill_names": ["skill-1", "skill-2"],
871
871
  "pipeline": [
872
872
  {
873
873
  "skill_version_id": "uuid",
@@ -1748,7 +1748,7 @@ Response:
1748
1748
  {
1749
1749
  "id": "uuid",
1750
1750
  "name": "routine-name",
1751
- "pipeline_skill_names": ["skill-1", "execution-report"],
1751
+ "pipeline_skill_names": ["skill-1"],
1752
1752
  "content": "...",
1753
1753
  "is_active": true,
1754
1754
  "cron_expression": "0 9 * * 1-5",
@@ -112,15 +112,12 @@ async function directiveRoutes(fastify) {
112
112
 
113
113
  try {
114
114
  // Execute as a single-skill workflow
115
- // skipExecutionReport: the orchestration template has its own
116
- // completion report (section 5), so /execution-report is redundant
117
- // and would use the wrong (local) execution ID.
118
115
  const result = await workflowRunner.runWorkflow({
119
116
  id: effectiveExecutionId,
120
117
  name: workflowName,
121
118
  pipeline_skill_names: [skill_name],
122
119
  workspace_id: workspaceId,
123
- }, { skipExecutionReport: true })
120
+ })
124
121
 
125
122
  console.log(`[Directive] Execution completed: ${skill_name} (success: ${result.execution_id ? 'yes' : 'no'})`)
126
123
  } catch (err) {
@@ -5,8 +5,7 @@
5
5
  *
6
6
  * Key design:
7
7
  * - All skills in a routine run in ONE CLI session (context preserved)
8
- * - /execution-report is automatically appended to report outcome
9
- * - Marker file written before session start for skill-to-execution mapping
8
+ * - Outcome is reported to the local API by the runner itself based on CLI exit code
10
9
  * - Same tmux execution model as workflow-runner
11
10
  */
12
11
 
@@ -66,7 +65,7 @@ async function executeRoutineSession(routine, executionId, skillNames) {
66
65
  const homeDir = config.HOME_DIR
67
66
  const sessionName = generateSessionName(routine.id, executionId)
68
67
 
69
- // Build prompt: run each skill in sequence, then execution-report
68
+ // Build prompt: run each skill in sequence
70
69
  const primary = getActivePrimary()
71
70
  const formatSkill = primary && typeof primary.formatSkillInvocation === 'function'
72
71
  ? primary.formatSkillInvocation.bind(primary)
@@ -78,8 +77,7 @@ async function executeRoutineSession(routine, executionId, skillNames) {
78
77
  ? `## Context\n\n${routine.context}\n\n---\n\n`
79
78
  : ''
80
79
 
81
- const reportSkill = formatSkill('execution-report')
82
- const prompt = `${contextPrefix}Run the following skills in order: ${skillCommands}. After completing all skills, run ${reportSkill} to report the results.`
80
+ const prompt = `${contextPrefix}Run the following skills in order: ${skillCommands}.`
83
81
 
84
82
  // Exit code file to capture CLI result
85
83
  const exitCodeFile = `/tmp/tmux-exit-${sessionName}`
@@ -88,7 +86,7 @@ async function executeRoutineSession(routine, executionId, skillNames) {
88
86
  const logFile = logManager.getLogPath(executionId)
89
87
 
90
88
  console.log(`[RoutineRunner] Executing routine: ${routine.name}`)
91
- console.log(`[RoutineRunner] Skills: ${skillNames.join(' → ')} → execution-report`)
89
+ console.log(`[RoutineRunner] Skills: ${skillNames.join(' → ')}`)
92
90
  console.log(`[RoutineRunner] tmux session: ${sessionName}`)
93
91
  console.log(`[RoutineRunner] Log file: ${logFile}`)
94
92
 
@@ -281,6 +279,7 @@ async function runRoutine(routine) {
281
279
  const result = await executeRoutineSession(routine, executionId, pipelineSkillNames)
282
280
 
283
281
  const completedAt = new Date().toISOString()
282
+ const outcome = result.success ? 'success' : 'failure'
284
283
 
285
284
  // Save: routine completed
286
285
  await executionStore.save({
@@ -290,7 +289,7 @@ async function runRoutine(routine) {
290
289
  routine_name: routine.name,
291
290
  workspace_id: routine.workspace_id || '',
292
291
  status: result.success ? 'completed' : 'failed',
293
- outcome: result.success ? null : 'failure',
292
+ outcome,
294
293
  started_at: startedAt,
295
294
  completed_at: completedAt,
296
295
  parent_execution_id: null,
@@ -298,6 +297,40 @@ async function runRoutine(routine) {
298
297
  log_file: logFile,
299
298
  })
300
299
 
300
+ // Extract summary from execution log file (captured via tmux pipe-pane)
301
+ let summary = result.success
302
+ ? `All skills completed successfully: ${pipelineSkillNames.join(', ')}`
303
+ : `Routine failed: ${result.error || 'unknown error'}`
304
+ try {
305
+ const logData = await logManager.readLog(executionId, { tail: 200 })
306
+ if (logData && logData.content && logData.content.trim().length > 0) {
307
+ const MAX_SUMMARY_LENGTH = 10000
308
+ const content = logData.content.trim()
309
+ summary = content.length > MAX_SUMMARY_LENGTH
310
+ ? content.slice(-MAX_SUMMARY_LENGTH)
311
+ : content
312
+ }
313
+ } catch (err) {
314
+ console.error(`[RoutineRunner] Failed to read log for summary: ${err.message}`)
315
+ }
316
+
317
+ // Report outcome via local API
318
+ try {
319
+ const resp = await fetch(`http://localhost:${config.AGENT_PORT || 8080}/api/executions/${executionId}/outcome`, {
320
+ method: 'POST',
321
+ headers: { 'Content-Type': 'application/json' },
322
+ body: JSON.stringify({
323
+ outcome,
324
+ summary,
325
+ }),
326
+ })
327
+ if (!resp.ok) {
328
+ console.error(`[RoutineRunner] Failed to report outcome: ${resp.status}`)
329
+ }
330
+ } catch (err) {
331
+ console.error(`[RoutineRunner] Failed to report outcome: ${err.message}`)
332
+ }
333
+
301
334
  // Update last_run in local store
302
335
  await routineStore.updateLastRun(routine.id)
303
336
 
@@ -383,7 +383,7 @@ async function runWorkflow(workflow, options = {}) {
383
383
  console.error(`[WorkflowRunner] Failed to read log for summary: ${err.message}`)
384
384
  }
385
385
 
386
- // Report outcome via local API (same data the execution-report skill used to send)
386
+ // Report outcome via local API
387
387
  try {
388
388
  const resp = await fetch(`http://localhost:${config.AGENT_PORT || 8080}/api/executions/${executionId}/outcome`, {
389
389
  method: 'POST',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geekbeer/minion",
3
- "version": "3.40.1",
3
+ "version": "3.40.2",
4
4
  "description": "AI Agent runtime for Minion - manages status and skill deployment on VPS",
5
5
  "main": "linux/server.js",
6
6
  "bin": {
package/roles/engineer.md CHANGED
@@ -6,7 +6,6 @@
6
6
 
7
7
  - **スキル実行**: 割り当てられたワークフローステップ(スキル)を確実に実行する
8
8
  - **タスク完了**: スキルの指示に従い、成果物を生成する
9
- - **結果報告**: 実行結果を `/execution-report` または API 経由で報告する
10
9
 
11
10
  ## 重要なルール
12
11
 
@@ -94,7 +94,7 @@ async function directiveRoutes(fastify) {
94
94
  name: workflowName,
95
95
  pipeline_skill_names: [skill_name],
96
96
  workspace_id: workspaceId,
97
- }, { skipExecutionReport: true })
97
+ })
98
98
 
99
99
  console.log(`[Directive] Execution completed: ${skill_name} (success: ${result.execution_id ? 'yes' : 'no'})`)
100
100
  } catch (err) {
@@ -58,13 +58,12 @@ async function executeRoutineSession(routine, executionId, skillNames) {
58
58
  const contextPrefix = routine.context
59
59
  ? `## Context\n\n${routine.context}\n\n---\n\n`
60
60
  : ''
61
- const reportSkill = formatSkill('execution-report')
62
- const prompt = `${contextPrefix}Run the following skills in order: ${skillCommands}. After completing all skills, run ${reportSkill} to report the results.`
61
+ const prompt = `${contextPrefix}Run the following skills in order: ${skillCommands}.`
63
62
 
64
63
  const logFile = logManager.getLogPath(executionId)
65
64
 
66
65
  console.log(`[RoutineRunner] Executing routine: ${routine.name}`)
67
- console.log(`[RoutineRunner] Skills: ${skillNames.join(' -> ')} -> execution-report`)
66
+ console.log(`[RoutineRunner] Skills: ${skillNames.join(' -> ')}`)
68
67
  console.log(`[RoutineRunner] Session: ${sessionName}`)
69
68
  console.log(`[RoutineRunner] Log file: ${logFile}`)
70
69
 
@@ -220,6 +219,7 @@ async function runRoutine(routine) {
220
219
 
221
220
  const result = await executeRoutineSession(routine, executionId, pipelineSkillNames)
222
221
  const completedAt = new Date().toISOString()
222
+ const outcome = result.success ? 'success' : 'failure'
223
223
 
224
224
  await executionStore.save({
225
225
  id: executionId,
@@ -228,7 +228,7 @@ async function runRoutine(routine) {
228
228
  routine_name: routine.name,
229
229
  workspace_id: routine.workspace_id || '',
230
230
  status: result.success ? 'completed' : 'failed',
231
- outcome: result.success ? null : 'failure',
231
+ outcome,
232
232
  started_at: startedAt,
233
233
  completed_at: completedAt,
234
234
  parent_execution_id: null,
@@ -236,6 +236,40 @@ async function runRoutine(routine) {
236
236
  log_file: logFile,
237
237
  })
238
238
 
239
+ // Extract summary from execution log file (captured via pty logStream)
240
+ let summary = result.success
241
+ ? `All skills completed successfully: ${pipelineSkillNames.join(', ')}`
242
+ : `Routine failed: ${result.error || 'unknown error'}`
243
+ try {
244
+ const logData = await logManager.readLog(executionId, { tail: 200 })
245
+ if (logData && logData.content && logData.content.trim().length > 0) {
246
+ const MAX_SUMMARY_LENGTH = 10000
247
+ const content = logData.content.trim()
248
+ summary = content.length > MAX_SUMMARY_LENGTH
249
+ ? content.slice(-MAX_SUMMARY_LENGTH)
250
+ : content
251
+ }
252
+ } catch (err) {
253
+ console.error(`[RoutineRunner] Failed to read log for summary: ${err.message}`)
254
+ }
255
+
256
+ // Report outcome via local API
257
+ try {
258
+ const resp = await fetch(`http://localhost:${config.AGENT_PORT || 8080}/api/executions/${executionId}/outcome`, {
259
+ method: 'POST',
260
+ headers: { 'Content-Type': 'application/json' },
261
+ body: JSON.stringify({
262
+ outcome,
263
+ summary,
264
+ }),
265
+ })
266
+ if (!resp.ok) {
267
+ console.error(`[RoutineRunner] Failed to report outcome: ${resp.status}`)
268
+ }
269
+ } catch (err) {
270
+ console.error(`[RoutineRunner] Failed to report outcome: ${err.message}`)
271
+ }
272
+
239
273
  await routineStore.updateLastRun(routine.id)
240
274
 
241
275
  runningExecutions.delete(executionId)