godpowers 2.3.0 → 2.4.0
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 +28 -16
- package/RELEASE.md +35 -27
- package/SKILL.md +26 -3
- package/agents/god-debugger.md +44 -8
- package/agents/god-executor.md +28 -0
- package/agents/god-quality-reviewer.md +23 -1
- package/agents/god-spec-reviewer.md +6 -0
- package/bin/install.js +6 -0
- package/lib/README.md +5 -2
- package/lib/agent-cache.js +25 -3
- package/lib/code-intelligence.js +161 -0
- package/lib/command-families.js +375 -0
- package/lib/dashboard.js +54 -20
- package/lib/extensions.js +6 -13
- package/lib/feature-awareness.js +2 -2
- package/lib/host-capabilities.js +4 -0
- package/lib/install-profiles.js +1 -0
- package/lib/planning-systems.js +7 -4
- package/lib/quick-proof.js +5 -2
- package/lib/release-surface-sync.js +4 -1
- package/lib/route-quality-sync.js +42 -12
- package/lib/router.js +32 -0
- package/lib/workflow-helper-groups.js +50 -0
- package/lib/workflow-runner.js +6 -1
- package/package.json +2 -2
- package/routing/god-add-backlog.yaml +1 -0
- package/routing/god-add-tests.yaml +1 -0
- package/routing/god-add-todo.yaml +1 -0
- package/routing/god-agent-audit.yaml +6 -0
- package/routing/god-arch.yaml +1 -0
- package/routing/god-archaeology.yaml +1 -0
- package/routing/god-audit.yaml +1 -0
- package/routing/god-automation-setup.yaml +1 -0
- package/routing/god-automation-status.yaml +1 -0
- package/routing/god-budget.yaml +6 -0
- package/routing/god-build-agent.yaml +1 -0
- package/routing/god-build.yaml +1 -0
- package/routing/god-cache-clear.yaml +6 -0
- package/routing/god-check-todos.yaml +6 -0
- package/routing/god-context-scan.yaml +6 -0
- package/routing/god-context.yaml +1 -0
- package/routing/god-cost.yaml +6 -0
- package/routing/god-debug.yaml +1 -0
- package/routing/god-deploy.yaml +1 -0
- package/routing/god-design-impact.yaml +6 -0
- package/routing/god-design.yaml +1 -0
- package/routing/god-discuss.yaml +12 -0
- package/routing/god-docs.yaml +1 -0
- package/routing/god-doctor.yaml +6 -0
- package/routing/god-dogfood.yaml +1 -0
- package/routing/god-explore.yaml +1 -0
- package/routing/god-export-otel.yaml +1 -0
- package/routing/god-extension-add.yaml +6 -0
- package/routing/god-extension-info.yaml +6 -0
- package/routing/god-extension-list.yaml +6 -0
- package/routing/god-extension-remove.yaml +6 -0
- package/routing/god-extension-scaffold.yaml +26 -0
- package/routing/god-extract-learnings.yaml +1 -0
- package/routing/god-fast.yaml +1 -0
- package/routing/god-feature.yaml +1 -0
- package/routing/god-graph.yaml +6 -0
- package/routing/god-harden.yaml +1 -0
- package/routing/god-help.yaml +6 -0
- package/routing/god-hotfix.yaml +1 -0
- package/routing/god-hygiene.yaml +1 -0
- package/routing/god-init.yaml +1 -0
- package/routing/god-intel.yaml +1 -0
- package/routing/god-launch.yaml +6 -0
- package/routing/god-lifecycle.yaml +12 -0
- package/routing/god-link.yaml +1 -0
- package/routing/god-lint.yaml +1 -0
- package/routing/god-list-assumptions.yaml +6 -0
- package/routing/god-locate.yaml +6 -0
- package/routing/god-logs.yaml +12 -0
- package/routing/god-map-codebase.yaml +1 -0
- package/routing/god-metrics.yaml +6 -0
- package/routing/god-migrate.yaml +1 -0
- package/routing/god-mode.yaml +6 -0
- package/routing/god-next.yaml +12 -0
- package/routing/god-note.yaml +1 -0
- package/routing/god-observe.yaml +1 -0
- package/routing/god-org-context.yaml +1 -0
- package/routing/god-party.yaml +1 -0
- package/routing/god-pause-work.yaml +6 -0
- package/routing/god-plant-seed.yaml +1 -0
- package/routing/god-postmortem.yaml +1 -0
- package/routing/god-pr-branch.yaml +1 -0
- package/routing/god-prd.yaml +1 -0
- package/routing/god-preflight.yaml +1 -0
- package/routing/god-progress.yaml +7 -0
- package/routing/god-quick.yaml +1 -0
- package/routing/god-reconcile.yaml +6 -0
- package/routing/god-reconstruct.yaml +1 -0
- package/routing/god-redo.yaml +6 -0
- package/routing/god-refactor.yaml +1 -0
- package/routing/god-repair.yaml +1 -0
- package/routing/god-repo.yaml +1 -0
- package/routing/god-restore.yaml +1 -0
- package/routing/god-resume-work.yaml +6 -0
- package/routing/god-review-changes.yaml +1 -0
- package/routing/god-review.yaml +1 -0
- package/routing/god-roadmap-check.yaml +6 -0
- package/routing/god-roadmap-update.yaml +1 -0
- package/routing/god-roadmap.yaml +1 -0
- package/routing/god-rollback.yaml +1 -0
- package/routing/god-scan.yaml +1 -0
- package/routing/god-set-profile.yaml +1 -0
- package/routing/god-settings.yaml +1 -0
- package/routing/god-skip.yaml +1 -0
- package/routing/god-smite.yaml +1 -0
- package/routing/god-spike.yaml +1 -0
- package/routing/god-sprint.yaml +6 -0
- package/routing/god-stack.yaml +2 -1
- package/routing/god-standards.yaml +1 -0
- package/routing/god-status.yaml +1 -0
- package/routing/god-stories.yaml +1 -0
- package/routing/god-story-build.yaml +1 -0
- package/routing/god-story-close.yaml +1 -0
- package/routing/god-story-verify.yaml +1 -0
- package/routing/god-story.yaml +1 -0
- package/routing/god-suite-init.yaml +1 -0
- package/routing/god-suite-patch.yaml +1 -0
- package/routing/god-suite-release.yaml +1 -0
- package/routing/god-suite-status.yaml +6 -0
- package/routing/god-suite-sync.yaml +1 -0
- package/routing/god-sync.yaml +1 -0
- package/routing/god-tech-debt.yaml +1 -0
- package/routing/god-test-extension.yaml +6 -0
- package/routing/god-test-runtime.yaml +1 -0
- package/routing/god-thread.yaml +6 -0
- package/routing/god-trace.yaml +6 -0
- package/routing/god-undo.yaml +1 -0
- package/routing/god-update-deps.yaml +1 -0
- package/routing/god-upgrade.yaml +1 -0
- package/routing/god-version.yaml +1 -0
- package/routing/god-workstream.yaml +6 -0
- package/routing/god.yaml +6 -0
- package/routing/recipes/add-feature-mid-arc-pause.yaml +6 -0
- package/routing/recipes/brownfield-onboarding.yaml +5 -2
- package/routing/recipes/extension-authoring.yaml +32 -0
- package/routing/recipes/greenfield-fast.yaml +3 -0
- package/routing/recipes/production-broken.yaml +4 -0
- package/routing/recipes/release-maintenance.yaml +3 -0
- package/routing/recipes/returning-after-break.yaml +3 -0
- package/routing/recipes/weekly-health-check.yaml +2 -0
- package/schema/routing.v1.json +62 -4
- package/schema/workflow.v1.json +14 -0
- package/skills/god-discuss.md +10 -5
- package/skills/god-doctor.md +9 -3
- package/skills/god-extension-scaffold.md +66 -0
- package/skills/god-help.md +38 -3
- package/skills/god-next.md +19 -2
- package/skills/god-status.md +13 -0
- package/skills/god-sync.md +1 -1
- package/skills/god-version.md +2 -2
- package/skills/god.md +61 -12
- package/workflows/audit-only.yaml +2 -2
- package/workflows/bluefield-arc.yaml +3 -7
- package/workflows/brownfield-arc.yaml +4 -8
- package/workflows/deps-audit.yaml +2 -5
- package/workflows/docs-arc.yaml +2 -2
- package/workflows/feature-arc.yaml +3 -6
- package/workflows/full-arc.yaml +5 -11
- package/workflows/hotfix-arc.yaml +3 -6
- package/workflows/hygiene.yaml +2 -2
- package/workflows/migration-arc.yaml +3 -5
- package/workflows/postmortem.yaml +2 -5
- package/workflows/refactor-arc.yaml +3 -6
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Optional code intelligence capability detection.
|
|
3
|
+
*
|
|
4
|
+
* These tools sharpen refactors and reviews when present, but Godpowers must
|
|
5
|
+
* keep working through grep-backed workflows when they are absent.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const cp = require('child_process');
|
|
9
|
+
|
|
10
|
+
const AST_GREP_CANDIDATES = [
|
|
11
|
+
{ id: 'ast-grep', command: 'ast-grep', args: ['--version'], match: /ast-grep/i },
|
|
12
|
+
{ id: 'sg', command: 'sg', args: ['--version'], match: /\b(ast-grep|sg\s+\d)/i }
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
const LSP_CANDIDATES = [
|
|
16
|
+
{ id: 'omo-lsp', command: 'omo-lsp', args: ['--version'], languages: ['multi'] },
|
|
17
|
+
{ id: 'typescript-language-server', command: 'typescript-language-server', args: ['--version'], languages: ['javascript', 'typescript'] },
|
|
18
|
+
{ id: 'vscode-json-language-server', command: 'vscode-json-language-server', args: ['--version'], languages: ['json'] },
|
|
19
|
+
{ id: 'yaml-language-server', command: 'yaml-language-server', args: ['--version'], languages: ['yaml'] },
|
|
20
|
+
{ id: 'pyright-langserver', command: 'pyright-langserver', args: ['--version'], languages: ['python'] },
|
|
21
|
+
{ id: 'pylsp', command: 'pylsp', args: ['--version'], languages: ['python'] },
|
|
22
|
+
{ id: 'gopls', command: 'gopls', args: ['version'], languages: ['go'] },
|
|
23
|
+
{ id: 'rust-analyzer', command: 'rust-analyzer', args: ['--version'], languages: ['rust'] },
|
|
24
|
+
{ id: 'clangd', command: 'clangd', args: ['--version'], languages: ['c', 'cpp'] },
|
|
25
|
+
{ id: 'jdtls', command: 'jdtls', args: ['--version'], languages: ['java'] },
|
|
26
|
+
{ id: 'ruby-lsp', command: 'ruby-lsp', args: ['--version'], languages: ['ruby'] },
|
|
27
|
+
{ id: 'solargraph', command: 'solargraph', args: ['--version'], languages: ['ruby'] },
|
|
28
|
+
{ id: 'terraform-ls', command: 'terraform-ls', args: ['version'], languages: ['terraform'] }
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
function firstLine(value) {
|
|
32
|
+
if (!value) return null;
|
|
33
|
+
const text = String(value).trim();
|
|
34
|
+
if (!text) return null;
|
|
35
|
+
return text.split(/\r?\n/)[0] || 'installed';
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function commandVersion(command, args, opts = {}) {
|
|
39
|
+
try {
|
|
40
|
+
const out = cp.execFileSync(command, args, {
|
|
41
|
+
cwd: opts.cwd || process.cwd(),
|
|
42
|
+
encoding: 'utf8',
|
|
43
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
44
|
+
timeout: opts.timeout || 800
|
|
45
|
+
});
|
|
46
|
+
return firstLine(out) || 'installed';
|
|
47
|
+
} catch (err) {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function checkCandidate(candidate, opts) {
|
|
53
|
+
const version = firstLine(opts.commandVersion(candidate.command, candidate.args, {
|
|
54
|
+
cwd: opts.cwd,
|
|
55
|
+
timeout: opts.timeout
|
|
56
|
+
}));
|
|
57
|
+
if (!version) return null;
|
|
58
|
+
if (candidate.match && !candidate.match.test(version)) return null;
|
|
59
|
+
return {
|
|
60
|
+
id: candidate.id,
|
|
61
|
+
command: candidate.command,
|
|
62
|
+
version,
|
|
63
|
+
languages: candidate.languages || []
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function detectFirst(candidates, opts) {
|
|
68
|
+
for (const candidate of candidates) {
|
|
69
|
+
const found = checkCandidate(candidate, opts);
|
|
70
|
+
if (found) return found;
|
|
71
|
+
}
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function detectAll(candidates, opts) {
|
|
76
|
+
const found = [];
|
|
77
|
+
const limit = opts.maxTools || 5;
|
|
78
|
+
for (const candidate of candidates) {
|
|
79
|
+
const result = checkCandidate(candidate, opts);
|
|
80
|
+
if (result) found.push(result);
|
|
81
|
+
if (found.length >= limit) break;
|
|
82
|
+
}
|
|
83
|
+
return found;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function detect(projectRoot, opts = {}) {
|
|
87
|
+
const root = projectRoot || process.cwd();
|
|
88
|
+
const probe = opts.commandVersion || commandVersion;
|
|
89
|
+
const probeOpts = {
|
|
90
|
+
cwd: root,
|
|
91
|
+
commandVersion: probe,
|
|
92
|
+
timeout: opts.timeout || 800,
|
|
93
|
+
maxTools: opts.maxTools || 5
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
const astGrep = detectFirst(opts.astGrepCandidates || AST_GREP_CANDIDATES, probeOpts);
|
|
97
|
+
const lspTools = detectAll(opts.lspCandidates || LSP_CANDIDATES, probeOpts);
|
|
98
|
+
const gaps = [];
|
|
99
|
+
if (!astGrep) gaps.push('ast-grep not detected');
|
|
100
|
+
if (lspTools.length === 0) gaps.push('LSP tools not detected');
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
level: astGrep || lspTools.length > 0 ? 'available' : 'not-detected',
|
|
104
|
+
astGrep: astGrep
|
|
105
|
+
? { available: true, command: astGrep.command, version: astGrep.version }
|
|
106
|
+
: { available: false, command: null, version: null },
|
|
107
|
+
lsp: {
|
|
108
|
+
available: lspTools.length > 0,
|
|
109
|
+
primary: lspTools[0] || null,
|
|
110
|
+
tools: lspTools
|
|
111
|
+
},
|
|
112
|
+
gaps
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function lspSummary(lsp) {
|
|
117
|
+
if (!lsp || !lsp.available) return 'not detected';
|
|
118
|
+
return lsp.tools.map(tool => tool.command).join(', ');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function summary(report) {
|
|
122
|
+
if (!report) return 'not detected';
|
|
123
|
+
const parts = [];
|
|
124
|
+
if (report.astGrep && report.astGrep.available) {
|
|
125
|
+
parts.push(`ast-grep via ${report.astGrep.command}`);
|
|
126
|
+
}
|
|
127
|
+
if (report.lsp && report.lsp.available) {
|
|
128
|
+
parts.push(`LSP via ${lspSummary(report.lsp)}`);
|
|
129
|
+
}
|
|
130
|
+
return parts.length > 0 ? parts.join('; ') : 'not detected';
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function render(report) {
|
|
134
|
+
const ast = report && report.astGrep && report.astGrep.available
|
|
135
|
+
? `${report.astGrep.command} (${report.astGrep.version})`
|
|
136
|
+
: 'not detected';
|
|
137
|
+
const lsp = report && report.lsp && report.lsp.available
|
|
138
|
+
? lspSummary(report.lsp)
|
|
139
|
+
: 'not detected';
|
|
140
|
+
const gaps = report && report.gaps && report.gaps.length > 0
|
|
141
|
+
? report.gaps.join('; ')
|
|
142
|
+
: 'none';
|
|
143
|
+
return [
|
|
144
|
+
'Code intelligence:',
|
|
145
|
+
` Structural search: ${ast}`,
|
|
146
|
+
` LSP tools: ${lsp}`,
|
|
147
|
+
` Gaps: ${gaps}`
|
|
148
|
+
].join('\n');
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
module.exports = {
|
|
152
|
+
detect,
|
|
153
|
+
summary,
|
|
154
|
+
render,
|
|
155
|
+
_private: {
|
|
156
|
+
AST_GREP_CANDIDATES,
|
|
157
|
+
LSP_CANDIDATES,
|
|
158
|
+
commandVersion,
|
|
159
|
+
firstLine
|
|
160
|
+
}
|
|
161
|
+
};
|
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command family metadata.
|
|
3
|
+
*
|
|
4
|
+
* Keeps the user-facing command catalog small without removing leaf commands.
|
|
5
|
+
* These groupings are used by help, routing, docs, and UX audits.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
|
|
11
|
+
const COMMAND_FAMILIES = [
|
|
12
|
+
{
|
|
13
|
+
id: 'start',
|
|
14
|
+
label: 'Start',
|
|
15
|
+
purpose: 'Start or import a project.',
|
|
16
|
+
commands: [
|
|
17
|
+
'/god',
|
|
18
|
+
'/god-init',
|
|
19
|
+
'/god-mode',
|
|
20
|
+
'/god-explore',
|
|
21
|
+
'/god-discuss',
|
|
22
|
+
'/god-list-assumptions',
|
|
23
|
+
'/god-prd',
|
|
24
|
+
'/god-design',
|
|
25
|
+
'/god-design-impact',
|
|
26
|
+
'/god-arch',
|
|
27
|
+
'/god-roadmap',
|
|
28
|
+
'/god-stack',
|
|
29
|
+
'/god-repo',
|
|
30
|
+
'/god-preflight',
|
|
31
|
+
'/god-map-codebase',
|
|
32
|
+
'/god-archaeology',
|
|
33
|
+
'/god-org-context',
|
|
34
|
+
'/god-migrate'
|
|
35
|
+
]
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
id: 'continue',
|
|
39
|
+
label: 'Continue',
|
|
40
|
+
purpose: 'Understand state and choose the next move.',
|
|
41
|
+
commands: [
|
|
42
|
+
'/god-status',
|
|
43
|
+
'/god-next',
|
|
44
|
+
'/god-progress',
|
|
45
|
+
'/god-lifecycle',
|
|
46
|
+
'/god-locate',
|
|
47
|
+
'/god-resume-work',
|
|
48
|
+
'/god-pause-work'
|
|
49
|
+
]
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
id: 'build',
|
|
53
|
+
label: 'Build',
|
|
54
|
+
purpose: 'Plan, implement, test, and ship product work.',
|
|
55
|
+
commands: [
|
|
56
|
+
'/god-build',
|
|
57
|
+
'/god-feature',
|
|
58
|
+
'/god-story',
|
|
59
|
+
'/god-stories',
|
|
60
|
+
'/god-story-build',
|
|
61
|
+
'/god-story-verify',
|
|
62
|
+
'/god-story-close',
|
|
63
|
+
'/god-fast',
|
|
64
|
+
'/god-quick',
|
|
65
|
+
'/god-debug',
|
|
66
|
+
'/god-add-tests',
|
|
67
|
+
'/god-refactor',
|
|
68
|
+
'/god-spike'
|
|
69
|
+
]
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
id: 'verify',
|
|
73
|
+
label: 'Verify',
|
|
74
|
+
purpose: 'Check artifacts, code, runtime behavior, and release readiness.',
|
|
75
|
+
commands: [
|
|
76
|
+
'/god-lint',
|
|
77
|
+
'/god-standards',
|
|
78
|
+
'/god-review',
|
|
79
|
+
'/god-review-changes',
|
|
80
|
+
'/god-test-runtime',
|
|
81
|
+
'/god-audit',
|
|
82
|
+
'/god-agent-audit',
|
|
83
|
+
'/god-hygiene',
|
|
84
|
+
'/god-dogfood',
|
|
85
|
+
'/god-preflight'
|
|
86
|
+
]
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
id: 'operate',
|
|
90
|
+
label: 'Operate',
|
|
91
|
+
purpose: 'Deploy, observe, harden, launch, and respond in production.',
|
|
92
|
+
commands: [
|
|
93
|
+
'/god-deploy',
|
|
94
|
+
'/god-observe',
|
|
95
|
+
'/god-harden',
|
|
96
|
+
'/god-launch',
|
|
97
|
+
'/god-hotfix',
|
|
98
|
+
'/god-postmortem',
|
|
99
|
+
'/god-logs',
|
|
100
|
+
'/god-metrics',
|
|
101
|
+
'/god-trace',
|
|
102
|
+
'/god-export-otel'
|
|
103
|
+
]
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
id: 'maintain',
|
|
107
|
+
label: 'Maintain',
|
|
108
|
+
purpose: 'Keep artifacts, docs, dependencies, context, and repo surfaces current.',
|
|
109
|
+
commands: [
|
|
110
|
+
'/god-docs',
|
|
111
|
+
'/god-sync',
|
|
112
|
+
'/god-scan',
|
|
113
|
+
'/god-link',
|
|
114
|
+
'/god-reconcile',
|
|
115
|
+
'/god-reconstruct',
|
|
116
|
+
'/god-intel',
|
|
117
|
+
'/god-tech-debt',
|
|
118
|
+
'/god-update-deps',
|
|
119
|
+
'/god-upgrade',
|
|
120
|
+
'/god-context',
|
|
121
|
+
'/god-context-scan',
|
|
122
|
+
'/god-roadmap-check',
|
|
123
|
+
'/god-roadmap-update'
|
|
124
|
+
]
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
id: 'capture',
|
|
128
|
+
label: 'Capture',
|
|
129
|
+
purpose: 'Save thoughts, tasks, backlog items, seeds, and learnings.',
|
|
130
|
+
commands: [
|
|
131
|
+
'/god-note',
|
|
132
|
+
'/god-add-todo',
|
|
133
|
+
'/god-check-todos',
|
|
134
|
+
'/god-add-backlog',
|
|
135
|
+
'/god-plant-seed',
|
|
136
|
+
'/god-extract-learnings',
|
|
137
|
+
'/god-thread',
|
|
138
|
+
'/god-graph'
|
|
139
|
+
]
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
id: 'recover',
|
|
143
|
+
label: 'Recover',
|
|
144
|
+
purpose: 'Undo, repair, restore, skip, or diagnose broken state.',
|
|
145
|
+
commands: [
|
|
146
|
+
'/god-undo',
|
|
147
|
+
'/god-redo',
|
|
148
|
+
'/god-rollback',
|
|
149
|
+
'/god-restore',
|
|
150
|
+
'/god-repair',
|
|
151
|
+
'/god-skip',
|
|
152
|
+
'/god-smite',
|
|
153
|
+
'/god-doctor'
|
|
154
|
+
]
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
id: 'extend',
|
|
158
|
+
label: 'Extend',
|
|
159
|
+
purpose: 'Install, inspect, test, remove, or author extension packs.',
|
|
160
|
+
commands: [
|
|
161
|
+
'/god-extension-scaffold',
|
|
162
|
+
'/god-extension-add',
|
|
163
|
+
'/god-extension-list',
|
|
164
|
+
'/god-extension-info',
|
|
165
|
+
'/god-extension-remove',
|
|
166
|
+
'/god-test-extension',
|
|
167
|
+
'/god-build-agent'
|
|
168
|
+
]
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
id: 'collaborate',
|
|
172
|
+
label: 'Collaborate',
|
|
173
|
+
purpose: 'Coordinate people, workstreams, suites, sprints, and pull requests.',
|
|
174
|
+
commands: [
|
|
175
|
+
'/god-workstream',
|
|
176
|
+
'/god-suite-init',
|
|
177
|
+
'/god-suite-status',
|
|
178
|
+
'/god-suite-sync',
|
|
179
|
+
'/god-suite-patch',
|
|
180
|
+
'/god-suite-release',
|
|
181
|
+
'/god-party',
|
|
182
|
+
'/god-sprint',
|
|
183
|
+
'/god-pr-branch'
|
|
184
|
+
]
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
id: 'configure',
|
|
188
|
+
label: 'Configure',
|
|
189
|
+
purpose: 'Tune settings, budgets, cache, profiles, help, and version info.',
|
|
190
|
+
commands: [
|
|
191
|
+
'/god-settings',
|
|
192
|
+
'/god-set-profile',
|
|
193
|
+
'/god-budget',
|
|
194
|
+
'/god-cost',
|
|
195
|
+
'/god-cache-clear',
|
|
196
|
+
'/god-automation-status',
|
|
197
|
+
'/god-automation-setup',
|
|
198
|
+
'/god-help',
|
|
199
|
+
'/god-version'
|
|
200
|
+
]
|
|
201
|
+
}
|
|
202
|
+
];
|
|
203
|
+
|
|
204
|
+
const STATUS_VIEWS = [
|
|
205
|
+
{ id: 'overview', command: '/god-status', label: 'Overview', purpose: 'Operational state, proactive checks, and blockers.' },
|
|
206
|
+
{ id: 'progress', command: '/god-progress', label: 'Progress', purpose: 'Requirement and roadmap increment completion.' },
|
|
207
|
+
{ id: 'lifecycle', command: '/god-lifecycle', label: 'Lifecycle', purpose: 'Project phase and fitting workflows.' },
|
|
208
|
+
{ id: 'locate', command: '/god-locate', label: 'Locate', purpose: 'Resume orientation from checkpoint and disk state.' },
|
|
209
|
+
{ id: 'next', command: '/god-next', label: 'Next', purpose: 'Single recommended command with reason.' }
|
|
210
|
+
];
|
|
211
|
+
|
|
212
|
+
const CAPTURE_LADDER = [
|
|
213
|
+
{ id: 'note', command: '/god-note', signal: 'save only', purpose: 'Save a thought without priority or workflow impact.' },
|
|
214
|
+
{ id: 'todo', command: '/god-add-todo', signal: 'actionable soon', purpose: 'Create a prioritized action item.' },
|
|
215
|
+
{ id: 'backlog', command: '/god-add-backlog', signal: 'optional later', purpose: 'Park an idea for future roadmap review.' },
|
|
216
|
+
{ id: 'seed', command: '/god-plant-seed', signal: 'conditional future trigger', purpose: 'Store an idea until a metric, date, or event happens.' }
|
|
217
|
+
];
|
|
218
|
+
|
|
219
|
+
const WORK_SIZE_LADDER = [
|
|
220
|
+
{ id: 'fast', command: '/god-fast', signal: 'trivial direct edit', purpose: 'One tiny edit with existing verification.' },
|
|
221
|
+
{ id: 'quick', command: '/god-quick', signal: 'small TDD task', purpose: 'Small task with TDD and review but no full planning tier.' },
|
|
222
|
+
{ id: 'story', command: '/god-story', signal: 'fine-grained planned slice', purpose: 'Create a STORY.md before implementation.' },
|
|
223
|
+
{ id: 'feature', command: '/god-feature', signal: 'existing-product feature', purpose: 'Feature workflow with mini-PRD, build, harden, and sync.' },
|
|
224
|
+
{ id: 'build', command: '/god-build', signal: 'current milestone work', purpose: 'Build the planned roadmap increment.' },
|
|
225
|
+
{ id: 'debug', command: '/god-debug', signal: 'non-urgent bug', purpose: 'Run the systematic debug loop.' },
|
|
226
|
+
{ id: 'hotfix', command: '/god-hotfix', signal: 'production outage', purpose: 'Expedited production fix and postmortem trigger.' }
|
|
227
|
+
];
|
|
228
|
+
|
|
229
|
+
const VERIFY_LADDER = [
|
|
230
|
+
{ id: 'lint', command: '/god-lint', signal: 'mechanical artifact check', purpose: 'Fast file-level artifact validation.' },
|
|
231
|
+
{ id: 'standards', command: '/god-standards', signal: 'artifact quality gate', purpose: 'Substitution, labels, and have-nots for one artifact.' },
|
|
232
|
+
{ id: 'review', command: '/god-review', signal: 'code diff review', purpose: 'Two-stage spec and quality review.' },
|
|
233
|
+
{ id: 'runtime', command: '/god-test-runtime', signal: 'live behavior check', purpose: 'Browser-backed design and acceptance verification.' },
|
|
234
|
+
{ id: 'audit', command: '/god-audit', signal: 'artifact set score', purpose: 'Score existing Godpowers artifacts.' },
|
|
235
|
+
{ id: 'hygiene', command: '/god-hygiene', signal: 'ongoing project health', purpose: 'Composite audit, dependency, and docs check.' },
|
|
236
|
+
{ id: 'preflight', command: '/god-preflight', signal: 'existing repo intake', purpose: 'Read-only readiness check before stronger workflows.' },
|
|
237
|
+
{ id: 'dogfood', command: '/god-dogfood', signal: 'release fixture readiness', purpose: 'Messy-repo scenarios for release confidence.' }
|
|
238
|
+
];
|
|
239
|
+
|
|
240
|
+
const TRIGGER_PRECEDENCE = {
|
|
241
|
+
continue: {
|
|
242
|
+
default: '/god-next',
|
|
243
|
+
conditional: [
|
|
244
|
+
{ command: '/god-resume-work', when: 'handoff-exists', reason: 'A handoff exists on disk.' }
|
|
245
|
+
],
|
|
246
|
+
reason: 'Continue means resume a handoff when present, otherwise compute the next route.'
|
|
247
|
+
},
|
|
248
|
+
'think through': {
|
|
249
|
+
default: '/god-discuss',
|
|
250
|
+
conditional: [
|
|
251
|
+
{ command: '/god-explore', when: 'broad-idea', reason: 'The request is broad ideation rather than a concrete decision.' }
|
|
252
|
+
],
|
|
253
|
+
reason: 'Discussion handles concrete decisions while exploration handles broad ideation.'
|
|
254
|
+
},
|
|
255
|
+
'what happened': {
|
|
256
|
+
default: '/god-logs',
|
|
257
|
+
conditional: [
|
|
258
|
+
{ command: '/god-postmortem', when: 'post-incident-pending', reason: 'The project is waiting on incident follow-up.' }
|
|
259
|
+
],
|
|
260
|
+
reason: 'Logs answer run history unless an incident loop is open.'
|
|
261
|
+
},
|
|
262
|
+
"what's done": {
|
|
263
|
+
default: '/god-progress',
|
|
264
|
+
conditional: [
|
|
265
|
+
{ command: '/god-status', when: 'operational-status-request', reason: 'The wording asks for operational state, not deliverables.' }
|
|
266
|
+
],
|
|
267
|
+
reason: 'Progress answers deliverables while status answers operational state.'
|
|
268
|
+
},
|
|
269
|
+
'where am i': {
|
|
270
|
+
default: '/god-lifecycle',
|
|
271
|
+
conditional: [
|
|
272
|
+
{ command: '/god-locate', when: 'checkpoint-or-handoff-exists', reason: 'Resume artifacts exist on disk.' }
|
|
273
|
+
],
|
|
274
|
+
reason: 'Lifecycle explains the phase while locate orients a resumed session.'
|
|
275
|
+
}
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
function familyForCommand(command) {
|
|
279
|
+
return COMMAND_FAMILIES.find((family) => family.commands.includes(command)) || null;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function renderFamilyCards(families = COMMAND_FAMILIES) {
|
|
283
|
+
return families.map((family) => (
|
|
284
|
+
`${family.label}: ${family.purpose} (${family.commands.join(', ')})`
|
|
285
|
+
));
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
function renderLadder(ladder) {
|
|
289
|
+
return ladder.map((step) => `${step.command}: ${step.signal} - ${step.purpose}`);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function detectCondition(condition, projectRoot, text = '') {
|
|
293
|
+
if (!condition) return false;
|
|
294
|
+
const root = projectRoot || process.cwd();
|
|
295
|
+
if (condition === 'handoff-exists') {
|
|
296
|
+
return fs.existsSync(path.join(root, '.godpowers', 'HANDOFF.md'));
|
|
297
|
+
}
|
|
298
|
+
if (condition === 'checkpoint-or-handoff-exists') {
|
|
299
|
+
return fs.existsSync(path.join(root, '.godpowers', 'CHECKPOINT.md'))
|
|
300
|
+
|| fs.existsSync(path.join(root, '.godpowers', 'HANDOFF.md'));
|
|
301
|
+
}
|
|
302
|
+
if (condition === 'post-incident-pending') {
|
|
303
|
+
try {
|
|
304
|
+
const statePath = path.join(root, '.godpowers', 'state.json');
|
|
305
|
+
if (!fs.existsSync(statePath)) return false;
|
|
306
|
+
const parsed = JSON.parse(fs.readFileSync(statePath, 'utf8'));
|
|
307
|
+
return parsed['lifecycle-phase'] === 'post-incident-pending';
|
|
308
|
+
} catch (e) {
|
|
309
|
+
return false;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
if (condition === 'broad-idea') {
|
|
313
|
+
return /\b(idea|brainstorm|explore|what if|possibilities|options)\b/i.test(text || '');
|
|
314
|
+
}
|
|
315
|
+
if (condition === 'operational-status-request') {
|
|
316
|
+
return /\b(status|state|blocked|sync|health|where)\b/i.test(text || '');
|
|
317
|
+
}
|
|
318
|
+
return false;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
function resolveTrigger(trigger, opts = {}) {
|
|
322
|
+
const key = String(trigger || '').trim().toLowerCase();
|
|
323
|
+
const rule = TRIGGER_PRECEDENCE[key];
|
|
324
|
+
if (!rule) return null;
|
|
325
|
+
for (const branch of rule.conditional || []) {
|
|
326
|
+
if (detectCondition(branch.when, opts.projectRoot, opts.text)) {
|
|
327
|
+
return { trigger: key, command: branch.command, reason: branch.reason, rule };
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
return { trigger: key, command: rule.default, reason: rule.reason, rule };
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
function classifyCapture(text = '') {
|
|
334
|
+
if (/\b(when|if|after|in \d+|once)\b/i.test(text)) return CAPTURE_LADDER.find((item) => item.id === 'seed');
|
|
335
|
+
if (/\b(todo|task|remind|priority|p[0-3])\b/i.test(text)) return CAPTURE_LADDER.find((item) => item.id === 'todo');
|
|
336
|
+
if (/\b(backlog|later|someday|future)\b/i.test(text)) return CAPTURE_LADDER.find((item) => item.id === 'backlog');
|
|
337
|
+
return CAPTURE_LADDER.find((item) => item.id === 'note');
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
function classifyWorkSize(text = '') {
|
|
341
|
+
if (/\b(production|outage|down|urgent|hotfix)\b/i.test(text)) return WORK_SIZE_LADDER.find((item) => item.id === 'hotfix');
|
|
342
|
+
if (/\b(bug|debug|failing|error|regression)\b/i.test(text)) return WORK_SIZE_LADDER.find((item) => item.id === 'debug');
|
|
343
|
+
if (/\b(story|acceptance criteria)\b/i.test(text)) return WORK_SIZE_LADDER.find((item) => item.id === 'story');
|
|
344
|
+
if (/\b(feature|new capability|enhancement)\b/i.test(text)) return WORK_SIZE_LADDER.find((item) => item.id === 'feature');
|
|
345
|
+
if (/\b(milestone|roadmap|increment)\b/i.test(text)) return WORK_SIZE_LADDER.find((item) => item.id === 'build');
|
|
346
|
+
if (/\b(tiny|typo|one-line|config tweak|trivial)\b/i.test(text)) return WORK_SIZE_LADDER.find((item) => item.id === 'fast');
|
|
347
|
+
return WORK_SIZE_LADDER.find((item) => item.id === 'quick');
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
function classifyVerification(text = '') {
|
|
351
|
+
if (/\b(dogfood|release readiness|fixture)\b/i.test(text)) return VERIFY_LADDER.find((item) => item.id === 'dogfood');
|
|
352
|
+
if (/\b(preflight|intake|existing repo)\b/i.test(text)) return VERIFY_LADDER.find((item) => item.id === 'preflight');
|
|
353
|
+
if (/\b(hygiene|health|weekly|monthly)\b/i.test(text)) return VERIFY_LADDER.find((item) => item.id === 'hygiene');
|
|
354
|
+
if (/\b(audit|score artifacts)\b/i.test(text)) return VERIFY_LADDER.find((item) => item.id === 'audit');
|
|
355
|
+
if (/\b(runtime|browser|e2e|flow|render|design audit)\b/i.test(text)) return VERIFY_LADDER.find((item) => item.id === 'runtime');
|
|
356
|
+
if (/\b(review|diff|code review)\b/i.test(text)) return VERIFY_LADDER.find((item) => item.id === 'review');
|
|
357
|
+
if (/\b(standard|substitution|have-nots)\b/i.test(text)) return VERIFY_LADDER.find((item) => item.id === 'standards');
|
|
358
|
+
return VERIFY_LADDER.find((item) => item.id === 'lint');
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
module.exports = {
|
|
362
|
+
COMMAND_FAMILIES,
|
|
363
|
+
STATUS_VIEWS,
|
|
364
|
+
CAPTURE_LADDER,
|
|
365
|
+
WORK_SIZE_LADDER,
|
|
366
|
+
VERIFY_LADDER,
|
|
367
|
+
TRIGGER_PRECEDENCE,
|
|
368
|
+
familyForCommand,
|
|
369
|
+
renderFamilyCards,
|
|
370
|
+
renderLadder,
|
|
371
|
+
resolveTrigger,
|
|
372
|
+
classifyCapture,
|
|
373
|
+
classifyWorkSize,
|
|
374
|
+
classifyVerification
|
|
375
|
+
};
|
package/lib/dashboard.js
CHANGED
|
@@ -133,20 +133,43 @@ function hasRecentPath(projectRoot, relPath, maxAgeMs) {
|
|
|
133
133
|
return Date.now() - modified <= maxAgeMs;
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
-
function
|
|
136
|
+
function isGodpowersRuntimeRepo(projectRoot) {
|
|
137
|
+
try {
|
|
138
|
+
const pkgPath = path.join(projectRoot, 'package.json');
|
|
139
|
+
if (!fs.existsSync(pkgPath)) return false;
|
|
140
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
141
|
+
return pkg.name === 'godpowers'
|
|
142
|
+
&& exists(projectRoot, 'skills')
|
|
143
|
+
&& exists(projectRoot, 'routing')
|
|
144
|
+
&& exists(projectRoot, 'agents');
|
|
145
|
+
} catch (e) {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function proactiveChecks(projectRoot, changedFiles = [], opts = {}) {
|
|
137
151
|
const oneDay = 24 * 60 * 60 * 1000;
|
|
138
152
|
const thirtyDays = 30 * oneDay;
|
|
153
|
+
const initialized = opts.initialized !== false;
|
|
154
|
+
const runtimeRepo = opts.runtimeRepo !== undefined
|
|
155
|
+
? opts.runtimeRepo
|
|
156
|
+
: isGodpowersRuntimeRepo(projectRoot);
|
|
139
157
|
const reviews = reviewCount(projectRoot);
|
|
140
158
|
|
|
141
|
-
const checkpoint =
|
|
142
|
-
? (
|
|
143
|
-
|
|
159
|
+
const checkpoint = initialized
|
|
160
|
+
? (exists(projectRoot, CHECKPOINT_PATH)
|
|
161
|
+
? (hasRecentPath(projectRoot, CHECKPOINT_PATH, oneDay) ? 'fresh' : 'stale')
|
|
162
|
+
: 'missing')
|
|
163
|
+
: 'not-applicable';
|
|
144
164
|
|
|
145
|
-
const sync =
|
|
146
|
-
? (
|
|
147
|
-
|
|
165
|
+
const sync = initialized
|
|
166
|
+
? (exists(projectRoot, SYNC_LOG_PATH)
|
|
167
|
+
? (hasRecentPath(projectRoot, SYNC_LOG_PATH, oneDay) ? 'fresh' : 'stale, suggest /god-sync')
|
|
168
|
+
: 'missing, suggest /god-sync')
|
|
169
|
+
: 'not-applicable';
|
|
148
170
|
|
|
149
|
-
const hygieneFresh =
|
|
171
|
+
const hygieneFresh = initialized
|
|
172
|
+
&& exists(projectRoot, CHECKPOINT_PATH)
|
|
150
173
|
&& hasRecentPath(projectRoot, CHECKPOINT_PATH, thirtyDays);
|
|
151
174
|
|
|
152
175
|
const pkgChanged = changedFiles.some(file => [
|
|
@@ -162,14 +185,22 @@ function proactiveChecks(projectRoot, changedFiles = []) {
|
|
|
162
185
|
'auth',
|
|
163
186
|
'security'
|
|
164
187
|
]));
|
|
165
|
-
const
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
:
|
|
188
|
+
const repoDocsStatus = runtimeRepo
|
|
189
|
+
? (() => {
|
|
190
|
+
const repoDocs = repoDocSync.detect(projectRoot, { changedFiles });
|
|
191
|
+
return repoDocs.status === 'fresh'
|
|
192
|
+
? 'fresh'
|
|
193
|
+
: `${repoDocs.stale.length} stale, suggest /god-docs`;
|
|
194
|
+
})()
|
|
195
|
+
: 'not-applicable';
|
|
196
|
+
const repoSurfaceStatus = runtimeRepo
|
|
197
|
+
? (() => {
|
|
198
|
+
const repoSurface = repoSurfaceSync.detect(projectRoot);
|
|
199
|
+
return repoSurface.status === 'fresh'
|
|
200
|
+
? 'fresh'
|
|
201
|
+
: `${repoSurface.stale.length} stale, suggest /god-doctor`;
|
|
202
|
+
})()
|
|
203
|
+
: 'not-applicable';
|
|
173
204
|
const host = hostCapabilities.detect(projectRoot);
|
|
174
205
|
|
|
175
206
|
return {
|
|
@@ -183,7 +214,7 @@ function proactiveChecks(projectRoot, changedFiles = []) {
|
|
|
183
214
|
automation: automationSummary(projectRoot),
|
|
184
215
|
security: sensitiveChanged ? 'sensitive files changed, suggest /god-harden' : 'clear',
|
|
185
216
|
dependencies: pkgChanged ? 'dependency files changed, suggest /god-update-deps' : 'clear',
|
|
186
|
-
hygiene: hygieneFresh ? 'fresh' : 'stale, suggest /god-hygiene'
|
|
217
|
+
hygiene: initialized ? (hygieneFresh ? 'fresh' : 'stale, suggest /god-hygiene') : 'not-applicable'
|
|
187
218
|
};
|
|
188
219
|
}
|
|
189
220
|
|
|
@@ -237,7 +268,7 @@ function compute(projectRoot, opts = {}) {
|
|
|
237
268
|
completion: '0% workflow progress because .godpowers/state.json is missing',
|
|
238
269
|
completionBasis: 'missing .godpowers/state.json'
|
|
239
270
|
},
|
|
240
|
-
proactive: proactiveChecks(projectRoot, git.entries.map(statusPath)),
|
|
271
|
+
proactive: proactiveChecks(projectRoot, git.entries.map(statusPath), { initialized: false }),
|
|
241
272
|
host: hostCapabilities.detect(projectRoot, opts.host || {}),
|
|
242
273
|
next,
|
|
243
274
|
deliverables: { hasRequirements: false },
|
|
@@ -276,7 +307,7 @@ function compute(projectRoot, opts = {}) {
|
|
|
276
307
|
worktree: git.worktree,
|
|
277
308
|
index: git.index,
|
|
278
309
|
planning: planningVisibility(projectRoot, progress),
|
|
279
|
-
proactive: proactiveChecks(projectRoot, git.entries.map(statusPath)),
|
|
310
|
+
proactive: proactiveChecks(projectRoot, git.entries.map(statusPath), { initialized: true }),
|
|
280
311
|
host: hostCapabilities.detect(projectRoot, opts.host || {}),
|
|
281
312
|
next,
|
|
282
313
|
deliverables,
|
|
@@ -289,6 +320,7 @@ function compute(projectRoot, opts = {}) {
|
|
|
289
320
|
function actionBrief(dashboard) {
|
|
290
321
|
const proactive = dashboard.proactive || {};
|
|
291
322
|
const next = dashboard.next || {};
|
|
323
|
+
const recommended = next.command || 'describe the next intent';
|
|
292
324
|
const blockers = [];
|
|
293
325
|
for (const [label, value] of [
|
|
294
326
|
['Repo surface', proactive.repoSurface],
|
|
@@ -304,10 +336,11 @@ function actionBrief(dashboard) {
|
|
|
304
336
|
if (value === 'fresh' || value === 'none' || value === 'clear' || value === 'not-applicable') continue;
|
|
305
337
|
if (/^full on /.test(value)) continue;
|
|
306
338
|
if (/^available via /.test(value)) continue;
|
|
339
|
+
if (label === 'Sync' && recommended !== '/god-sync') continue;
|
|
340
|
+
if (label === 'Hygiene' && recommended !== '/god-hygiene') continue;
|
|
307
341
|
blockers.push(`${label}: ${value}`);
|
|
308
342
|
}
|
|
309
343
|
|
|
310
|
-
const recommended = next.command || 'describe the next intent';
|
|
311
344
|
return {
|
|
312
345
|
recommended,
|
|
313
346
|
reason: next.reason || 'No route was computed.',
|
|
@@ -414,6 +447,7 @@ module.exports = {
|
|
|
414
447
|
parseGitStatus,
|
|
415
448
|
proactiveChecks,
|
|
416
449
|
automationSummary,
|
|
450
|
+
isGodpowersRuntimeRepo,
|
|
417
451
|
actionBrief,
|
|
418
452
|
planningVisibility
|
|
419
453
|
};
|