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.
Files changed (169) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/README.md +28 -16
  3. package/RELEASE.md +35 -27
  4. package/SKILL.md +26 -3
  5. package/agents/god-debugger.md +44 -8
  6. package/agents/god-executor.md +28 -0
  7. package/agents/god-quality-reviewer.md +23 -1
  8. package/agents/god-spec-reviewer.md +6 -0
  9. package/bin/install.js +6 -0
  10. package/lib/README.md +5 -2
  11. package/lib/agent-cache.js +25 -3
  12. package/lib/code-intelligence.js +161 -0
  13. package/lib/command-families.js +375 -0
  14. package/lib/dashboard.js +54 -20
  15. package/lib/extensions.js +6 -13
  16. package/lib/feature-awareness.js +2 -2
  17. package/lib/host-capabilities.js +4 -0
  18. package/lib/install-profiles.js +1 -0
  19. package/lib/planning-systems.js +7 -4
  20. package/lib/quick-proof.js +5 -2
  21. package/lib/release-surface-sync.js +4 -1
  22. package/lib/route-quality-sync.js +42 -12
  23. package/lib/router.js +32 -0
  24. package/lib/workflow-helper-groups.js +50 -0
  25. package/lib/workflow-runner.js +6 -1
  26. package/package.json +2 -2
  27. package/routing/god-add-backlog.yaml +1 -0
  28. package/routing/god-add-tests.yaml +1 -0
  29. package/routing/god-add-todo.yaml +1 -0
  30. package/routing/god-agent-audit.yaml +6 -0
  31. package/routing/god-arch.yaml +1 -0
  32. package/routing/god-archaeology.yaml +1 -0
  33. package/routing/god-audit.yaml +1 -0
  34. package/routing/god-automation-setup.yaml +1 -0
  35. package/routing/god-automation-status.yaml +1 -0
  36. package/routing/god-budget.yaml +6 -0
  37. package/routing/god-build-agent.yaml +1 -0
  38. package/routing/god-build.yaml +1 -0
  39. package/routing/god-cache-clear.yaml +6 -0
  40. package/routing/god-check-todos.yaml +6 -0
  41. package/routing/god-context-scan.yaml +6 -0
  42. package/routing/god-context.yaml +1 -0
  43. package/routing/god-cost.yaml +6 -0
  44. package/routing/god-debug.yaml +1 -0
  45. package/routing/god-deploy.yaml +1 -0
  46. package/routing/god-design-impact.yaml +6 -0
  47. package/routing/god-design.yaml +1 -0
  48. package/routing/god-discuss.yaml +12 -0
  49. package/routing/god-docs.yaml +1 -0
  50. package/routing/god-doctor.yaml +6 -0
  51. package/routing/god-dogfood.yaml +1 -0
  52. package/routing/god-explore.yaml +1 -0
  53. package/routing/god-export-otel.yaml +1 -0
  54. package/routing/god-extension-add.yaml +6 -0
  55. package/routing/god-extension-info.yaml +6 -0
  56. package/routing/god-extension-list.yaml +6 -0
  57. package/routing/god-extension-remove.yaml +6 -0
  58. package/routing/god-extension-scaffold.yaml +26 -0
  59. package/routing/god-extract-learnings.yaml +1 -0
  60. package/routing/god-fast.yaml +1 -0
  61. package/routing/god-feature.yaml +1 -0
  62. package/routing/god-graph.yaml +6 -0
  63. package/routing/god-harden.yaml +1 -0
  64. package/routing/god-help.yaml +6 -0
  65. package/routing/god-hotfix.yaml +1 -0
  66. package/routing/god-hygiene.yaml +1 -0
  67. package/routing/god-init.yaml +1 -0
  68. package/routing/god-intel.yaml +1 -0
  69. package/routing/god-launch.yaml +6 -0
  70. package/routing/god-lifecycle.yaml +12 -0
  71. package/routing/god-link.yaml +1 -0
  72. package/routing/god-lint.yaml +1 -0
  73. package/routing/god-list-assumptions.yaml +6 -0
  74. package/routing/god-locate.yaml +6 -0
  75. package/routing/god-logs.yaml +12 -0
  76. package/routing/god-map-codebase.yaml +1 -0
  77. package/routing/god-metrics.yaml +6 -0
  78. package/routing/god-migrate.yaml +1 -0
  79. package/routing/god-mode.yaml +6 -0
  80. package/routing/god-next.yaml +12 -0
  81. package/routing/god-note.yaml +1 -0
  82. package/routing/god-observe.yaml +1 -0
  83. package/routing/god-org-context.yaml +1 -0
  84. package/routing/god-party.yaml +1 -0
  85. package/routing/god-pause-work.yaml +6 -0
  86. package/routing/god-plant-seed.yaml +1 -0
  87. package/routing/god-postmortem.yaml +1 -0
  88. package/routing/god-pr-branch.yaml +1 -0
  89. package/routing/god-prd.yaml +1 -0
  90. package/routing/god-preflight.yaml +1 -0
  91. package/routing/god-progress.yaml +7 -0
  92. package/routing/god-quick.yaml +1 -0
  93. package/routing/god-reconcile.yaml +6 -0
  94. package/routing/god-reconstruct.yaml +1 -0
  95. package/routing/god-redo.yaml +6 -0
  96. package/routing/god-refactor.yaml +1 -0
  97. package/routing/god-repair.yaml +1 -0
  98. package/routing/god-repo.yaml +1 -0
  99. package/routing/god-restore.yaml +1 -0
  100. package/routing/god-resume-work.yaml +6 -0
  101. package/routing/god-review-changes.yaml +1 -0
  102. package/routing/god-review.yaml +1 -0
  103. package/routing/god-roadmap-check.yaml +6 -0
  104. package/routing/god-roadmap-update.yaml +1 -0
  105. package/routing/god-roadmap.yaml +1 -0
  106. package/routing/god-rollback.yaml +1 -0
  107. package/routing/god-scan.yaml +1 -0
  108. package/routing/god-set-profile.yaml +1 -0
  109. package/routing/god-settings.yaml +1 -0
  110. package/routing/god-skip.yaml +1 -0
  111. package/routing/god-smite.yaml +1 -0
  112. package/routing/god-spike.yaml +1 -0
  113. package/routing/god-sprint.yaml +6 -0
  114. package/routing/god-stack.yaml +2 -1
  115. package/routing/god-standards.yaml +1 -0
  116. package/routing/god-status.yaml +1 -0
  117. package/routing/god-stories.yaml +1 -0
  118. package/routing/god-story-build.yaml +1 -0
  119. package/routing/god-story-close.yaml +1 -0
  120. package/routing/god-story-verify.yaml +1 -0
  121. package/routing/god-story.yaml +1 -0
  122. package/routing/god-suite-init.yaml +1 -0
  123. package/routing/god-suite-patch.yaml +1 -0
  124. package/routing/god-suite-release.yaml +1 -0
  125. package/routing/god-suite-status.yaml +6 -0
  126. package/routing/god-suite-sync.yaml +1 -0
  127. package/routing/god-sync.yaml +1 -0
  128. package/routing/god-tech-debt.yaml +1 -0
  129. package/routing/god-test-extension.yaml +6 -0
  130. package/routing/god-test-runtime.yaml +1 -0
  131. package/routing/god-thread.yaml +6 -0
  132. package/routing/god-trace.yaml +6 -0
  133. package/routing/god-undo.yaml +1 -0
  134. package/routing/god-update-deps.yaml +1 -0
  135. package/routing/god-upgrade.yaml +1 -0
  136. package/routing/god-version.yaml +1 -0
  137. package/routing/god-workstream.yaml +6 -0
  138. package/routing/god.yaml +6 -0
  139. package/routing/recipes/add-feature-mid-arc-pause.yaml +6 -0
  140. package/routing/recipes/brownfield-onboarding.yaml +5 -2
  141. package/routing/recipes/extension-authoring.yaml +32 -0
  142. package/routing/recipes/greenfield-fast.yaml +3 -0
  143. package/routing/recipes/production-broken.yaml +4 -0
  144. package/routing/recipes/release-maintenance.yaml +3 -0
  145. package/routing/recipes/returning-after-break.yaml +3 -0
  146. package/routing/recipes/weekly-health-check.yaml +2 -0
  147. package/schema/routing.v1.json +62 -4
  148. package/schema/workflow.v1.json +14 -0
  149. package/skills/god-discuss.md +10 -5
  150. package/skills/god-doctor.md +9 -3
  151. package/skills/god-extension-scaffold.md +66 -0
  152. package/skills/god-help.md +38 -3
  153. package/skills/god-next.md +19 -2
  154. package/skills/god-status.md +13 -0
  155. package/skills/god-sync.md +1 -1
  156. package/skills/god-version.md +2 -2
  157. package/skills/god.md +61 -12
  158. package/workflows/audit-only.yaml +2 -2
  159. package/workflows/bluefield-arc.yaml +3 -7
  160. package/workflows/brownfield-arc.yaml +4 -8
  161. package/workflows/deps-audit.yaml +2 -5
  162. package/workflows/docs-arc.yaml +2 -2
  163. package/workflows/feature-arc.yaml +3 -6
  164. package/workflows/full-arc.yaml +5 -11
  165. package/workflows/hotfix-arc.yaml +3 -6
  166. package/workflows/hygiene.yaml +2 -2
  167. package/workflows/migration-arc.yaml +3 -5
  168. package/workflows/postmortem.yaml +2 -5
  169. 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 proactiveChecks(projectRoot, changedFiles = []) {
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 = exists(projectRoot, CHECKPOINT_PATH)
142
- ? (hasRecentPath(projectRoot, CHECKPOINT_PATH, oneDay) ? 'fresh' : 'stale')
143
- : 'missing';
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 = exists(projectRoot, SYNC_LOG_PATH)
146
- ? (hasRecentPath(projectRoot, SYNC_LOG_PATH, oneDay) ? 'fresh' : 'stale, suggest /god-sync')
147
- : 'missing, suggest /god-sync';
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 = exists(projectRoot, CHECKPOINT_PATH)
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 repoDocs = repoDocSync.detect(projectRoot, { changedFiles });
166
- const repoDocsStatus = repoDocs.status === 'fresh'
167
- ? 'fresh'
168
- : `${repoDocs.stale.length} stale, suggest /god-docs`;
169
- const repoSurface = repoSurfaceSync.detect(projectRoot);
170
- const repoSurfaceStatus = repoSurface.status === 'fresh'
171
- ? 'fresh'
172
- : `${repoSurface.stale.length} stale, suggest /god-doctor`;
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
  };