godpowers 1.6.11 → 1.6.13
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 +61 -0
- package/README.md +42 -6
- package/RELEASE.md +35 -38
- package/SKILL.md +42 -3
- package/agents/god-orchestrator.md +23 -10
- package/bin/install.js +75 -3
- package/lib/automation-providers.js +411 -0
- package/lib/dashboard.js +311 -0
- package/package.json +3 -3
- package/routing/god-automation-setup.yaml +25 -0
- package/routing/god-automation-status.yaml +24 -0
- package/skills/god-automation-setup.md +105 -0
- package/skills/god-automation-status.md +76 -0
- package/skills/god-doctor.md +1 -1
- package/skills/god-mode.md +9 -8
- package/skills/god-next.md +41 -11
- package/skills/god-status.md +33 -11
- package/skills/god-version.md +1 -1
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Godpowers Automation Providers
|
|
3
|
+
*
|
|
4
|
+
* Detects host-native automation surfaces and renders opt-in setup guidance.
|
|
5
|
+
* This module never creates schedules, routines, background agents, commits,
|
|
6
|
+
* pushes, packages, publishes, deploys, or clears reviews by itself.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const cp = require('child_process');
|
|
12
|
+
const os = require('os');
|
|
13
|
+
|
|
14
|
+
const CONFIG_PATH = '.godpowers/automations.json';
|
|
15
|
+
|
|
16
|
+
const SAFE_TEMPLATES = [
|
|
17
|
+
{
|
|
18
|
+
id: 'daily-status',
|
|
19
|
+
title: 'Daily Godpowers status',
|
|
20
|
+
cadence: 'Daily at 9am local time',
|
|
21
|
+
risk: 'read-only',
|
|
22
|
+
prompt: 'Run godpowers status --project . and summarize current phase, progress, open items, and recommended next action.'
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
id: 'stale-checkpoint',
|
|
26
|
+
title: 'Stale checkpoint watcher',
|
|
27
|
+
cadence: 'Weekdays at 9am local time',
|
|
28
|
+
risk: 'read-only',
|
|
29
|
+
prompt: 'Check .godpowers/CHECKPOINT.md freshness. If stale, report that /god-sync or /god-resume-work should run.'
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
id: 'review-queue',
|
|
33
|
+
title: 'Review queue watcher',
|
|
34
|
+
cadence: 'Daily at 10am local time',
|
|
35
|
+
risk: 'read-only',
|
|
36
|
+
prompt: 'Inspect .godpowers/REVIEW-REQUIRED.md and report unresolved review items without clearing them.'
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
id: 'weekly-hygiene',
|
|
40
|
+
title: 'Weekly hygiene report',
|
|
41
|
+
cadence: 'Monday at 9am local time',
|
|
42
|
+
risk: 'read-only',
|
|
43
|
+
prompt: 'Run a read-only hygiene summary for docs drift, dependency signals, checkpoint age, and pending reviews.'
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
id: 'release-readiness',
|
|
47
|
+
title: 'Release readiness report',
|
|
48
|
+
cadence: 'Manual or before release',
|
|
49
|
+
risk: 'read-only',
|
|
50
|
+
prompt: 'Report release readiness from tests, package metadata, changelog, release notes, and unstaged work. Do not publish.'
|
|
51
|
+
}
|
|
52
|
+
];
|
|
53
|
+
|
|
54
|
+
const PROVIDERS = [
|
|
55
|
+
{
|
|
56
|
+
id: 'codex-app',
|
|
57
|
+
label: 'Codex App automations',
|
|
58
|
+
runtime: 'codex',
|
|
59
|
+
class: 'native-scheduler',
|
|
60
|
+
detect: (ctx) => hasRuntime(ctx, 'codex') || hasEnv(ctx, 'CODEX_HOME'),
|
|
61
|
+
setup: [
|
|
62
|
+
'Use /god-automation-setup inside Codex App so the host can create reviewed automations.',
|
|
63
|
+
'Prefer thread heartbeat for short follow-ups and worktree cron for durable project checks.'
|
|
64
|
+
]
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
id: 'claude-routines',
|
|
68
|
+
label: 'Claude Code routines',
|
|
69
|
+
runtime: 'claude',
|
|
70
|
+
class: 'native-scheduler',
|
|
71
|
+
detect: (ctx) => hasCommand(ctx, 'claude') || hasRuntime(ctx, 'claude'),
|
|
72
|
+
setup: [
|
|
73
|
+
'Run /schedule in Claude Code for scheduled routines.',
|
|
74
|
+
'Use claude.ai/code/routines for API or GitHub triggers.'
|
|
75
|
+
]
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
id: 'cline-schedule',
|
|
79
|
+
label: 'Cline scheduled agents',
|
|
80
|
+
runtime: 'cline',
|
|
81
|
+
class: 'native-scheduler',
|
|
82
|
+
detect: (ctx) => hasCommand(ctx, 'cline') || hasRuntime(ctx, 'cline'),
|
|
83
|
+
setup: [
|
|
84
|
+
'Run cline schedule to create, list, trigger, pause, resume, or delete schedules.',
|
|
85
|
+
'Use read-only prompts unless the user explicitly approves branch or PR automation.'
|
|
86
|
+
]
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
id: 'kilo-scheduled-triggers',
|
|
90
|
+
label: 'Kilo scheduled triggers',
|
|
91
|
+
runtime: 'kilo',
|
|
92
|
+
class: 'native-scheduler',
|
|
93
|
+
detect: (ctx) => hasRuntime(ctx, 'kilo'),
|
|
94
|
+
setup: [
|
|
95
|
+
'Use KiloClaw Scheduled Triggers from Kilo settings.',
|
|
96
|
+
'Limit each trigger to read-only Godpowers reports unless the user approves write scope.'
|
|
97
|
+
]
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
id: 'qwen-loop',
|
|
101
|
+
label: 'Qwen Code /loop',
|
|
102
|
+
runtime: 'qwen',
|
|
103
|
+
class: 'session-scheduler',
|
|
104
|
+
detect: (ctx) => hasCommand(ctx, 'qwen') || hasRuntime(ctx, 'qwen'),
|
|
105
|
+
setup: [
|
|
106
|
+
'Enable Qwen experimental cron support, then use /loop for session-scoped recurring prompts.',
|
|
107
|
+
'Do not treat Qwen loops as durable because they do not persist across restarts.'
|
|
108
|
+
]
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
id: 'cursor-background-agent',
|
|
112
|
+
label: 'Cursor Background Agents',
|
|
113
|
+
runtime: 'cursor',
|
|
114
|
+
class: 'background-agent',
|
|
115
|
+
detect: (ctx) => hasCommand(ctx, 'cursor') || hasRuntime(ctx, 'cursor'),
|
|
116
|
+
setup: [
|
|
117
|
+
'Use Cursor Background Agent mode or Background Agent API for asynchronous branch work.',
|
|
118
|
+
'Prefer issue or branch scoped tasks and require human review before merge.'
|
|
119
|
+
]
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
id: 'github-copilot-cloud-agent',
|
|
123
|
+
label: 'GitHub Copilot cloud agent',
|
|
124
|
+
runtime: 'copilot',
|
|
125
|
+
class: 'background-agent',
|
|
126
|
+
detect: (ctx) => hasGitRemote(ctx) || hasRuntime(ctx, 'copilot'),
|
|
127
|
+
setup: [
|
|
128
|
+
'Use GitHub issues, pull requests, or Copilot chat to delegate work to Copilot cloud agent.',
|
|
129
|
+
'Keep Godpowers automations branch or PR scoped and require human merge authority.'
|
|
130
|
+
]
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
id: 'windsurf-workflows',
|
|
134
|
+
label: 'Windsurf workflows',
|
|
135
|
+
runtime: 'windsurf',
|
|
136
|
+
class: 'manual-workflow',
|
|
137
|
+
detect: (ctx) => hasRuntime(ctx, 'windsurf'),
|
|
138
|
+
setup: [
|
|
139
|
+
'Install reusable workflows under .windsurf/workflows/ or the global Windsurf workflow folder.',
|
|
140
|
+
'Windsurf workflows are manual-only; use Skills when Cascade should discover a procedure.'
|
|
141
|
+
]
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
id: 'gemini-headless',
|
|
145
|
+
label: 'Gemini CLI headless mode',
|
|
146
|
+
runtime: 'gemini',
|
|
147
|
+
class: 'scriptable-headless',
|
|
148
|
+
detect: (ctx) => hasCommand(ctx, 'gemini') || hasRuntime(ctx, 'gemini'),
|
|
149
|
+
setup: [
|
|
150
|
+
'Use gemini -p for non-interactive scripting.',
|
|
151
|
+
'Use an external scheduler only when the user explicitly asks for OS or CI scheduling.'
|
|
152
|
+
]
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
id: 'opencode-run',
|
|
156
|
+
label: 'OpenCode run and serve',
|
|
157
|
+
runtime: 'opencode',
|
|
158
|
+
class: 'scriptable-headless',
|
|
159
|
+
detect: (ctx) => hasCommand(ctx, 'opencode') || hasRuntime(ctx, 'opencode'),
|
|
160
|
+
setup: [
|
|
161
|
+
'Use opencode run for non-interactive prompts or opencode serve for an attachable server.',
|
|
162
|
+
'Use opencode github install when repo-native GitHub automation is preferred.'
|
|
163
|
+
]
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
id: 'augment-subagents',
|
|
167
|
+
label: 'Augment Agent and subagents',
|
|
168
|
+
runtime: 'augment',
|
|
169
|
+
class: 'manual-workflow',
|
|
170
|
+
detect: (ctx) => hasRuntime(ctx, 'augment'),
|
|
171
|
+
setup: [
|
|
172
|
+
'Use Augment Agent or Agent Auto for supervised tasks.',
|
|
173
|
+
'Use Augment subagents for specialized review, test, or docs work.'
|
|
174
|
+
]
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
id: 'codebuddy-sdk',
|
|
178
|
+
label: 'CodeBuddy Agent SDK',
|
|
179
|
+
runtime: 'codebuddy',
|
|
180
|
+
class: 'scriptable-headless',
|
|
181
|
+
detect: (ctx) => hasCommand(ctx, 'codebuddy') || hasRuntime(ctx, 'codebuddy'),
|
|
182
|
+
setup: [
|
|
183
|
+
'Use the CodeBuddy Agent SDK for programmatic automation.',
|
|
184
|
+
'Keep filesystem config loading explicit so automation stays predictable.'
|
|
185
|
+
]
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
id: 'pi-sdk',
|
|
189
|
+
label: 'Pi CLI and SDK',
|
|
190
|
+
runtime: 'pi',
|
|
191
|
+
class: 'scriptable-headless',
|
|
192
|
+
detect: (ctx) => hasCommand(ctx, 'pi') || hasRuntime(ctx, 'pi'),
|
|
193
|
+
setup: [
|
|
194
|
+
'Use Pi CLI or SDK for scriptable coding-agent sessions.',
|
|
195
|
+
'Use host or CI scheduling only after explicit user approval.'
|
|
196
|
+
]
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
id: 'trae',
|
|
200
|
+
label: 'Trae',
|
|
201
|
+
runtime: 'trae',
|
|
202
|
+
class: 'unknown',
|
|
203
|
+
detect: (ctx) => hasRuntime(ctx, 'trae'),
|
|
204
|
+
setup: [
|
|
205
|
+
'No stable scheduled automation provider is documented for Godpowers yet.',
|
|
206
|
+
'Use manual Godpowers commands until a native Trae automation surface is confirmed.'
|
|
207
|
+
]
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
id: 'antigravity',
|
|
211
|
+
label: 'Google Antigravity',
|
|
212
|
+
runtime: 'antigravity',
|
|
213
|
+
class: 'unknown',
|
|
214
|
+
detect: (ctx) => hasRuntime(ctx, 'antigravity'),
|
|
215
|
+
setup: [
|
|
216
|
+
'Agent-first workflows are supported, but scheduled automation is not confirmed for Godpowers yet.',
|
|
217
|
+
'Use manual workflows and require artifact review for autonomous agent work.'
|
|
218
|
+
]
|
|
219
|
+
}
|
|
220
|
+
];
|
|
221
|
+
|
|
222
|
+
function detect(projectRoot = process.cwd(), opts = {}) {
|
|
223
|
+
const ctx = {
|
|
224
|
+
projectRoot,
|
|
225
|
+
home: opts.home || os.homedir(),
|
|
226
|
+
env: opts.env || process.env,
|
|
227
|
+
commands: opts.commands || null,
|
|
228
|
+
gitRemote: opts.gitRemote
|
|
229
|
+
};
|
|
230
|
+
const active = readConfig(projectRoot).automations || [];
|
|
231
|
+
const providers = PROVIDERS.map(provider => {
|
|
232
|
+
const installed = Boolean(provider.detect(ctx));
|
|
233
|
+
return {
|
|
234
|
+
id: provider.id,
|
|
235
|
+
label: provider.label,
|
|
236
|
+
runtime: provider.runtime,
|
|
237
|
+
class: provider.class,
|
|
238
|
+
installed,
|
|
239
|
+
status: providerStatus(provider.class, installed),
|
|
240
|
+
active: active.filter(item => item.provider === provider.id),
|
|
241
|
+
setup: provider.setup.slice()
|
|
242
|
+
};
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
const safeTemplates = SAFE_TEMPLATES.map(template => ({
|
|
246
|
+
...template,
|
|
247
|
+
active: active.some(item => item.id === template.id && item.status !== 'disabled')
|
|
248
|
+
}));
|
|
249
|
+
|
|
250
|
+
return {
|
|
251
|
+
configPath: path.join(projectRoot, CONFIG_PATH),
|
|
252
|
+
providers,
|
|
253
|
+
safeTemplates,
|
|
254
|
+
active,
|
|
255
|
+
recommendedProvider: recommendProvider(providers),
|
|
256
|
+
safety: [
|
|
257
|
+
'Do not create automations during install.',
|
|
258
|
+
'Create schedules, routines, background agents, or API triggers only after explicit user approval.',
|
|
259
|
+
'Default templates are read-only and must not commit, push, publish, deploy, clear reviews, or access provider dashboards.'
|
|
260
|
+
]
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function render(report) {
|
|
265
|
+
const active = report.active && report.active.length > 0
|
|
266
|
+
? report.active.map(item => ` - ${item.id} via ${item.provider}: ${item.status || 'active'}`)
|
|
267
|
+
: [' - none recorded'];
|
|
268
|
+
const providers = report.providers.map(provider => (
|
|
269
|
+
` - ${provider.label}: ${provider.status} (${provider.class})`
|
|
270
|
+
));
|
|
271
|
+
const recommended = report.recommendedProvider
|
|
272
|
+
? `${report.recommendedProvider.label} (${report.recommendedProvider.class})`
|
|
273
|
+
: 'none available';
|
|
274
|
+
const templates = report.safeTemplates.map(template => (
|
|
275
|
+
` - ${template.id}: ${template.title}, ${template.cadence}, ${template.risk}`
|
|
276
|
+
));
|
|
277
|
+
|
|
278
|
+
return [
|
|
279
|
+
'Godpowers Automation Providers',
|
|
280
|
+
'',
|
|
281
|
+
`Config: ${report.configPath}`,
|
|
282
|
+
`Recommended provider: ${recommended}`,
|
|
283
|
+
'',
|
|
284
|
+
'Active automations:',
|
|
285
|
+
...active,
|
|
286
|
+
'',
|
|
287
|
+
'Provider status:',
|
|
288
|
+
...providers,
|
|
289
|
+
'',
|
|
290
|
+
'Safe templates:',
|
|
291
|
+
...templates,
|
|
292
|
+
'',
|
|
293
|
+
'Safety rules:',
|
|
294
|
+
...report.safety.map(rule => ` - ${rule}`)
|
|
295
|
+
].join('\n');
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function setupPlan(projectRoot = process.cwd(), opts = {}) {
|
|
299
|
+
const report = detect(projectRoot, opts);
|
|
300
|
+
const provider = report.recommendedProvider;
|
|
301
|
+
return {
|
|
302
|
+
...report,
|
|
303
|
+
setup: provider ? provider.setup : ['No automation provider is available. Use /god-next or godpowers next --project . manually.']
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function renderSetupPlan(plan) {
|
|
308
|
+
const provider = plan.recommendedProvider
|
|
309
|
+
? `${plan.recommendedProvider.label} (${plan.recommendedProvider.id})`
|
|
310
|
+
: 'none available';
|
|
311
|
+
return [
|
|
312
|
+
'Godpowers Automation Setup Plan',
|
|
313
|
+
'',
|
|
314
|
+
`Recommended provider: ${provider}`,
|
|
315
|
+
'',
|
|
316
|
+
'Setup steps:',
|
|
317
|
+
...plan.setup.map((step, index) => ` ${index + 1}. ${step}`),
|
|
318
|
+
'',
|
|
319
|
+
'Recommended safe templates:',
|
|
320
|
+
...plan.safeTemplates.map(template => ` - ${template.id}: ${template.prompt}`),
|
|
321
|
+
'',
|
|
322
|
+
'Approval required:',
|
|
323
|
+
' - Choose a provider',
|
|
324
|
+
' - Choose one or more templates',
|
|
325
|
+
' - Confirm any host-native schedule, routine, background agent, API trigger, or connector scope'
|
|
326
|
+
].join('\n');
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
function readConfig(projectRoot) {
|
|
330
|
+
const file = path.join(projectRoot, CONFIG_PATH);
|
|
331
|
+
if (!fs.existsSync(file)) return { automations: [] };
|
|
332
|
+
try {
|
|
333
|
+
const parsed = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
334
|
+
return {
|
|
335
|
+
automations: Array.isArray(parsed.automations) ? parsed.automations : []
|
|
336
|
+
};
|
|
337
|
+
} catch (e) {
|
|
338
|
+
return { automations: [] };
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
function providerStatus(providerClass, installed) {
|
|
343
|
+
if (providerClass === 'unknown') return installed ? 'installed, capability unknown' : 'unknown';
|
|
344
|
+
if (providerClass === 'manual-workflow') return installed ? 'manual workflow available' : 'supported, not detected';
|
|
345
|
+
if (providerClass === 'session-scheduler') return installed ? 'session scheduler available' : 'supported, not detected';
|
|
346
|
+
if (providerClass === 'background-agent') return installed ? 'background agent available' : 'supported, not detected';
|
|
347
|
+
if (providerClass === 'scriptable-headless') return installed ? 'scriptable headless available' : 'supported, not detected';
|
|
348
|
+
if (providerClass === 'native-scheduler') return installed ? 'native scheduler available' : 'supported, not detected';
|
|
349
|
+
return installed ? 'available' : 'not detected';
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function recommendProvider(providers) {
|
|
353
|
+
const order = [
|
|
354
|
+
'native-scheduler',
|
|
355
|
+
'background-agent',
|
|
356
|
+
'scriptable-headless',
|
|
357
|
+
'session-scheduler',
|
|
358
|
+
'manual-workflow'
|
|
359
|
+
];
|
|
360
|
+
for (const providerClass of order) {
|
|
361
|
+
const found = providers.find(provider => provider.installed && provider.class === providerClass);
|
|
362
|
+
if (found) return found;
|
|
363
|
+
}
|
|
364
|
+
return null;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
function hasRuntime(ctx, runtime) {
|
|
368
|
+
const homePath = path.join(ctx.home, `.${runtime}`, 'GODPOWERS_VERSION');
|
|
369
|
+
return fs.existsSync(homePath);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
function hasEnv(ctx, key) {
|
|
373
|
+
return Boolean(ctx.env && ctx.env[key]);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
function hasCommand(ctx, command) {
|
|
377
|
+
if (ctx.commands) {
|
|
378
|
+
return Boolean(ctx.commands[command]);
|
|
379
|
+
}
|
|
380
|
+
try {
|
|
381
|
+
cp.execFileSync('which', [command], { stdio: ['ignore', 'ignore', 'ignore'] });
|
|
382
|
+
return true;
|
|
383
|
+
} catch (e) {
|
|
384
|
+
return false;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
function hasGitRemote(ctx) {
|
|
389
|
+
if (ctx.gitRemote !== undefined) return Boolean(ctx.gitRemote);
|
|
390
|
+
try {
|
|
391
|
+
const out = cp.execFileSync('git', ['remote', '-v'], {
|
|
392
|
+
cwd: ctx.projectRoot,
|
|
393
|
+
encoding: 'utf8',
|
|
394
|
+
stdio: ['ignore', 'pipe', 'ignore']
|
|
395
|
+
});
|
|
396
|
+
return /github\.com[:/]/.test(out);
|
|
397
|
+
} catch (e) {
|
|
398
|
+
return false;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
module.exports = {
|
|
403
|
+
CONFIG_PATH,
|
|
404
|
+
SAFE_TEMPLATES,
|
|
405
|
+
PROVIDERS,
|
|
406
|
+
detect,
|
|
407
|
+
render,
|
|
408
|
+
setupPlan,
|
|
409
|
+
renderSetupPlan,
|
|
410
|
+
readConfig
|
|
411
|
+
};
|