godpowers 3.13.1 → 3.14.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/lib/evidence.js CHANGED
@@ -195,6 +195,10 @@ function appendJsonlAtomic(file, record) {
195
195
  return file;
196
196
  }
197
197
 
198
+ // Reads the whole ledger into memory. This is bounded and acceptable for a CLI:
199
+ // each record caps its stdout/stderr tails (TAIL_CHARS) so growth is slow, and
200
+ // every consumer reads it once per command, never in a loop. If a long-lived
201
+ // project's ledger ever grows large, add an opt-in prune/size cap here (PERF-002).
198
202
  function readJsonl(file) {
199
203
  let raw;
200
204
  try {
@@ -542,11 +546,16 @@ function history(opts = {}) {
542
546
  }
543
547
 
544
548
  /**
545
- * The strict close gate, rebound from Mythify's completion rule (cmd_step):
546
- * a substep may close to done only when evidence bound to it since it went
547
- * in-flight supports the close. This is a read-only predicate. It does NOT
548
- * mutate state and is NOT yet wired into gate.js or the close path; that wiring
549
- * is the deliberate behavior change tracked as the rest of Phase 1.
549
+ * The advisory close-freshness check, rebound from Mythify's completion rule
550
+ * (cmd_step): a substep may close to done only when evidence bound to it since
551
+ * it went in-flight supports the close. This is a read-only predicate. It does
552
+ * NOT mutate state and is NOT wired into gate.js or the close path; that wiring
553
+ * is a deliberate behavior change tracked as the rest of Phase 1. Until then it
554
+ * is advisory discipline the orchestrator runs (via `can-close`), NOT the
555
+ * mechanically enforced gate. The enforced gate is `gate.js`
556
+ * (`npx godpowers gate`), which checks recorded pass/fail evidence but not the
557
+ * since-in-flight freshness this predicate adds. Treat the two as distinct:
558
+ * `gate` is the mechanical boundary, `can-close` is the stricter advisory one.
550
559
  *
551
560
  * Tier-appropriate (docs/FUSION-ARCHITECTURE.md section 4.2):
552
561
  * - Executable-gated substeps (build, deploy, harden) require the latest
@@ -53,9 +53,13 @@ const LABEL_TAGS = ['DECISION', 'HYPOTHESIS', 'OPEN QUESTION', 'OPEN-QUESTION'];
53
53
  function findPositions(content, regex) {
54
54
  const positions = [];
55
55
  const lines = content.split('\n');
56
+ // Compile once and reuse across lines (PERF-001); reset lastIndex per line so
57
+ // matching is identical to a fresh per-line regex.
58
+ const flags = regex.flags.includes('g') ? regex.flags : regex.flags + 'g';
59
+ const localRegex = new RegExp(regex.source, flags);
56
60
  for (let i = 0; i < lines.length; i++) {
61
+ localRegex.lastIndex = 0;
57
62
  let match;
58
- const localRegex = new RegExp(regex.source, regex.flags.includes('g') ? regex.flags : regex.flags + 'g');
59
63
  while ((match = localRegex.exec(lines[i])) !== null) {
60
64
  positions.push({ line: i + 1, column: match.index + 1, matched: match[0] });
61
65
  }
package/lib/intent.js CHANGED
@@ -332,15 +332,20 @@ function splitInlineArray(text) {
332
332
  return parts;
333
333
  }
334
334
 
335
- function cleanArrays(obj) {
336
- if (Array.isArray(obj)) return obj.map(cleanArrays);
335
+ // Far beyond any legitimate config nesting; caps recursion so a hostile,
336
+ // thousands-deep YAML file cannot overflow the stack (SEC-002).
337
+ const MAX_CLEAN_DEPTH = 200;
338
+
339
+ function cleanArrays(obj, depth = 0) {
340
+ if (depth > MAX_CLEAN_DEPTH) return obj;
341
+ if (Array.isArray(obj)) return obj.map((v) => cleanArrays(v, depth + 1));
337
342
  if (obj && typeof obj === 'object') {
338
343
  // Detect array container (legacy or new)
339
- if (obj.__items__) return obj.__items__.map(cleanArrays);
344
+ if (obj.__items__) return obj.__items__.map((v) => cleanArrays(v, depth + 1));
340
345
  if (obj.__pending_array__) return obj.__pending_array__;
341
346
  const cleaned = {};
342
347
  for (const [k, v] of Object.entries(obj)) {
343
- cleaned[k] = cleanArrays(v);
348
+ cleaned[k] = cleanArrays(v, depth + 1);
344
349
  }
345
350
  return cleaned;
346
351
  }
package/lib/pillars.js CHANGED
@@ -114,6 +114,13 @@ const GODPOWERS_ARTIFACTS = [
114
114
  '.godpowers/design/PRODUCT.md'
115
115
  ];
116
116
 
117
+ // ===========================================================================
118
+ // Pillar model: parse pillar files, detect installed pillars, compute the
119
+ // per-task load set, and construct/initialize pillar files. Shared with the
120
+ // artifact-sync workflow below (init/ensurePillar/pillarStub/detect are also
121
+ // part of the public API).
122
+ // ===========================================================================
123
+
117
124
  function stripQuotes(value) {
118
125
  return String(value).trim().replace(/^['"]|['"]$/g, '');
119
126
  }
@@ -401,6 +408,12 @@ function writeFenced(filePath, begin, end, content) {
401
408
  fs.writeFileSync(filePath, next);
402
409
  }
403
410
 
411
+ // ===========================================================================
412
+ // Artifact-sync workflow: turn Godpowers artifacts (PRD/ARCH/...) into durable
413
+ // pillar signals and write them into the routed pillar files. Builds on the
414
+ // model above (init/ensurePillar/pillarStub/detect/buildProtocolContent).
415
+ // ===========================================================================
416
+
404
417
  function artifactToPillars(artifactPath) {
405
418
  const normalized = artifactPath.replace(/\\/g, '/');
406
419
  const pillars = [];
@@ -100,10 +100,6 @@ function ensureDir(filePath) {
100
100
  fs.mkdirSync(path.dirname(filePath), { recursive: true });
101
101
  }
102
102
 
103
- function sha(input) {
104
- return crypto.createHash('sha256').update(input).digest('hex');
105
- }
106
-
107
103
  function hashFiles(projectRoot, files) {
108
104
  const h = crypto.createHash('sha256');
109
105
  for (const file of files.map((f) => f.path).sort()) {
@@ -473,7 +469,6 @@ module.exports = {
473
469
  _private: {
474
470
  classifyFile,
475
471
  extractSignals,
476
- filesForKinds,
477
- sha
472
+ filesForKinds
478
473
  }
479
474
  };
@@ -10,6 +10,9 @@ const path = require('path');
10
10
 
11
11
  const recipes = require('./recipes');
12
12
  const { read, write } = require('./sync-fs');
13
+ const { makeAddCheck } = require('./sync-check');
14
+
15
+ const addCheck = makeAddCheck('recipe-coverage');
13
16
 
14
17
  const LOG_PATH = '.godpowers/surface/RECIPE-COVERAGE-SYNC.md';
15
18
 
@@ -42,18 +45,6 @@ const REQUIRED_COVERAGE = [
42
45
  ];
43
46
 
44
47
 
45
- function addCheck(checks, id, status, relPath, message, opts = {}) {
46
- checks.push({
47
- area: 'recipe-coverage',
48
- id,
49
- status,
50
- path: relPath,
51
- message,
52
- severity: opts.severity || (status === 'fresh' ? 'info' : 'warning'),
53
- spawn: opts.spawn || null
54
- });
55
- }
56
-
57
48
  function recipePath(projectRoot, name) {
58
49
  const rel = `routing/recipes/${name}.yaml`;
59
50
  return fs.existsSync(path.join(projectRoot, rel)) ? rel : 'routing/recipes/';
@@ -10,6 +10,9 @@ const fs = require('fs');
10
10
  const path = require('path');
11
11
 
12
12
  const { read, write, readJson } = require('./sync-fs');
13
+ const { makeAddCheck } = require('./sync-check');
14
+
15
+ const addCheck = makeAddCheck('release-surface');
13
16
 
14
17
  const LOG_PATH = '.godpowers/surface/RELEASE-SURFACE-SYNC.md';
15
18
 
@@ -46,18 +49,6 @@ function releaseGateText(projectRoot, pkg) {
46
49
  ].join('\n');
47
50
  }
48
51
 
49
- function addCheck(checks, id, status, relPath, message, opts = {}) {
50
- checks.push({
51
- area: 'release-surface',
52
- id,
53
- status,
54
- path: relPath,
55
- message,
56
- severity: opts.severity || (status === 'fresh' ? 'info' : 'warning'),
57
- spawn: opts.spawn || null
58
- });
59
- }
60
-
61
52
  function detect(projectRoot) {
62
53
  const checks = [];
63
54
  const pkg = readJson(projectRoot, 'package.json') || {};
@@ -12,6 +12,7 @@ const path = require('path');
12
12
 
13
13
  const { parseSimpleYaml } = require('./intent');
14
14
  const { read, write, exists, readJson } = require('./sync-fs');
15
+ const { addCheck, listFiles } = require('./sync-check');
15
16
  const extensions = require('./extensions');
16
17
  const repoDocSync = require('./repo-doc-sync');
17
18
  const routeQualitySync = require('./route-quality-sync');
@@ -52,19 +53,6 @@ const REQUIRED_PACKAGE_CHECKS = [
52
53
  'routing/god-export-otel.yaml'
53
54
  ];
54
55
 
55
- function rel(projectRoot, absPath) {
56
- return path.relative(projectRoot, absPath).split(path.sep).join('/');
57
- }
58
-
59
- function listFiles(projectRoot, relDir, pattern) {
60
- const dir = path.join(projectRoot, relDir);
61
- if (!fs.existsSync(dir)) return [];
62
- return fs.readdirSync(dir)
63
- .filter((name) => pattern.test(name))
64
- .sort()
65
- .map((name) => `${relDir}/${name}`.replace(/\\/g, '/'));
66
- }
67
-
68
56
  function releaseGateText(projectRoot, pkg) {
69
57
  return [
70
58
  JSON.stringify((pkg && pkg.scripts) || {}),
@@ -81,19 +69,6 @@ function commandForSkill(skillPath) {
81
69
  return `/${path.basename(skillPath, '.md')}`;
82
70
  }
83
71
 
84
- function addCheck(checks, area, id, status, relPath, message, opts = {}) {
85
- checks.push({
86
- area,
87
- id,
88
- status,
89
- path: relPath,
90
- message,
91
- severity: opts.severity || (status === 'fresh' ? 'info' : 'warning'),
92
- safeFix: opts.safeFix === true,
93
- spawn: opts.spawn || null
94
- });
95
- }
96
-
97
72
  function routingChecks(projectRoot) {
98
73
  const checks = [];
99
74
  const skills = listFiles(projectRoot, 'skills', /^god.*\.md$/);
@@ -485,15 +460,12 @@ function releasePolicyChecks(projectRoot) {
485
460
  checks,
486
461
  'release',
487
462
  'release-checklist-surface-sync',
488
- read(projectRoot, 'docs/RELEASE-CHECKLIST.md').includes('repo-surface-sync'),
463
+ read(projectRoot, 'docs/RELEASE-CHECKLIST.md').includes('repo-surface-sync') ? 'fresh' : 'stale',
489
464
  'docs/RELEASE-CHECKLIST.md',
490
465
  'Release checklist references repo-surface-sync readiness.',
491
466
  { spawn: 'god-docs-writer' }
492
467
  );
493
- return checks.map((check) => ({
494
- ...check,
495
- status: check.status === true ? 'fresh' : (check.status === false ? 'stale' : check.status)
496
- }));
468
+ return checks;
497
469
  }
498
470
 
499
471
  function detect(projectRoot) {
@@ -33,9 +33,11 @@ const linkage = require('./linkage');
33
33
  const state = require('./state');
34
34
  const atomic = require('./atomic-write');
35
35
  const textUtil = require('./text-util');
36
+ const artifactMap = require('./artifact-map');
37
+ const { readTextOrNull: readText } = require('./sync-fs');
36
38
 
37
- const PRD_PATH = '.godpowers/prd/PRD.md';
38
- const ROADMAP_PATH = '.godpowers/roadmap/ROADMAP.md';
39
+ const PRD_PATH = artifactMap.requiredArtifactsForTier('prd')[0].path;
40
+ const ROADMAP_PATH = artifactMap.requiredArtifactsForTier('roadmap')[0].path;
39
41
  const LEDGER_PATH = '.godpowers/REQUIREMENTS.md';
40
42
 
41
43
  const PRIORITIES = ['MUST', 'SHOULD', 'COULD'];
@@ -44,16 +46,6 @@ const REQ_ID_RE_G = /\bP-(MUST|SHOULD|COULD)-\d+\b/g;
44
46
  const MILESTONE_ID_RE = /\bM-[\w-]+\b/;
45
47
  const LABEL_RE = /\[(?:DECISION|HYPOTHESIS|OPEN QUESTION)\]/g;
46
48
 
47
- function readText(projectRoot, relPath) {
48
- const file = path.join(projectRoot, relPath);
49
- if (!fs.existsSync(file)) return null;
50
- try {
51
- return fs.readFileSync(file, 'utf8');
52
- } catch (e) {
53
- return null;
54
- }
55
- }
56
-
57
49
  function pad2(n) {
58
50
  return String(n).padStart(2, '0');
59
51
  }
@@ -318,23 +318,29 @@ function run(projectRoot, opts = {}) {
318
318
  // write the file when the PRD actually declares requirements, to avoid
319
319
  // littering pre-PRD projects with an empty ledger.
320
320
  let requirementsSummary = null;
321
+ let requirementsError = null;
321
322
  if (opts.runRequirements !== false) {
322
323
  try {
323
324
  const derived = requirements.derive(projectRoot);
324
325
  if (derived.hasRequirements) {
325
- requirements.writeLedger(projectRoot, derived);
326
326
  const currentState = state.read(projectRoot);
327
327
  requirementsSummary = requirements.summarizeForState(
328
328
  derived,
329
329
  currentState && currentState.deliverables
330
330
  );
331
+ // Write state.json first, then the ledger, so a state-write failure
332
+ // cannot leave a REQUIREMENTS.md ledger that state.json never references.
331
333
  if (currentState) {
332
334
  currentState.deliverables = requirementsSummary;
333
335
  state.write(projectRoot, currentState);
334
336
  }
337
+ requirements.writeLedger(projectRoot, derived);
335
338
  }
336
339
  } catch (e) {
340
+ // ERR-001: surface the failure instead of swallowing it, so the caller can
341
+ // tell a genuine requirements-step error apart from "no requirements".
337
342
  requirementsSummary = null;
343
+ requirementsError = e.message;
338
344
  }
339
345
  }
340
346
 
@@ -346,7 +352,8 @@ function run(projectRoot, opts = {}) {
346
352
  footers,
347
353
  sourceSyncResult,
348
354
  reviewItems,
349
- requirements: requirementsSummary
355
+ requirements: requirementsSummary,
356
+ requirementsError
350
357
  };
351
358
  }
352
359
 
@@ -11,6 +11,9 @@ const path = require('path');
11
11
 
12
12
  const { parseSimpleYaml } = require('./intent');
13
13
  const { read, write } = require('./sync-fs');
14
+ const { makeAddCheck, listFiles } = require('./sync-check');
15
+
16
+ const addCheck = makeAddCheck('route-quality');
14
17
 
15
18
  const LOG_PATH = '.godpowers/surface/ROUTE-QUALITY-SYNC.md';
16
19
  const CONTEXTUAL_NEXT_VALUES = new Set([
@@ -101,15 +104,6 @@ const TIER_GATE_COMMANDS = new Set([
101
104
  '/god-harden'
102
105
  ]);
103
106
 
104
- function listFiles(projectRoot, relDir, pattern) {
105
- const dir = path.join(projectRoot, relDir);
106
- if (!fs.existsSync(dir)) return [];
107
- return fs.readdirSync(dir)
108
- .filter((name) => pattern.test(name))
109
- .sort()
110
- .map((name) => `${relDir}/${name}`.replace(/\\/g, '/'));
111
- }
112
-
113
107
  function arr(value) {
114
108
  return Array.isArray(value) ? value : [];
115
109
  }
@@ -122,18 +116,6 @@ function parseRoute(projectRoot, routePath) {
122
116
  }
123
117
  }
124
118
 
125
- function addCheck(checks, id, status, relPath, message, opts = {}) {
126
- checks.push({
127
- area: 'route-quality',
128
- id,
129
- status,
130
- path: relPath,
131
- message,
132
- severity: opts.severity || (status === 'fresh' ? 'info' : 'warning'),
133
- spawn: opts.spawn || null
134
- });
135
- }
136
-
137
119
  function spawnTokens(route) {
138
120
  const execution = route.execution || {};
139
121
  return normalizeSpawnList([
@@ -30,10 +30,6 @@ const SYSTEM_TARGETS = {
30
30
  }
31
31
  };
32
32
 
33
- function rel(projectRoot, absPath) {
34
- return path.relative(projectRoot, absPath).split(path.sep).join('/');
35
- }
36
-
37
33
  function sha(input) {
38
34
  return `sha256:${crypto.createHash('sha256').update(input).digest('hex')}`;
39
35
  }
package/lib/state.js CHANGED
@@ -365,6 +365,11 @@ function progressSummary(state) {
365
365
  const steps = orderedSubSteps(state);
366
366
  const total = steps.length;
367
367
  const completed = steps.filter(step => isCompleteStatus(step.status)).length;
368
+ // JRN-002: skipped/not-required steps count toward `completed` (and therefore
369
+ // the percent), so a run that skipped tiers can show a high percent that
370
+ // overstates how much was actually built. Expose the skipped count so the
371
+ // dashboard can annotate the percent honestly instead of silently inflating.
372
+ const skipped = steps.filter(step => step.status === 'skipped' || step.status === 'not-required').length;
368
373
 
369
374
  let currentIndex = steps.findIndex(step => isActiveStatus(step.status));
370
375
  if (currentIndex < 0) {
@@ -377,6 +382,7 @@ function progressSummary(state) {
377
382
  percent: total === 0 ? 0 : Math.round((completed / total) * 100),
378
383
  completed,
379
384
  total,
385
+ skipped,
380
386
  remaining: Math.max(total - completed, 0),
381
387
  currentStep: current ? current.ordinal : 0,
382
388
  current,
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Shared check-builder and file-lister for the lib/*-sync.js family (ARC-001).
3
+ *
4
+ * The aggregator (repo-surface-sync) passes a per-call `area` and may mark a
5
+ * check `safeFix`, so it uses the full `addCheck`. The single-area sync modules
6
+ * (recipe-coverage, release-surface, route-quality) bind their area once via
7
+ * `makeAddCheck(area)`; their records intentionally omit `safeFix` (none of
8
+ * their checks are auto-fixable), matching the original per-module builders.
9
+ */
10
+
11
+ const fs = require('fs');
12
+ const path = require('path');
13
+
14
+ function severityFor(status, opts) {
15
+ return opts.severity || (status === 'fresh' ? 'info' : 'warning');
16
+ }
17
+
18
+ // Full form: caller supplies `area`; records include the `safeFix` flag.
19
+ function addCheck(checks, area, id, status, relPath, message, opts = {}) {
20
+ checks.push({
21
+ area,
22
+ id,
23
+ status,
24
+ path: relPath,
25
+ message,
26
+ severity: severityFor(status, opts),
27
+ safeFix: opts.safeFix === true,
28
+ spawn: opts.spawn || null
29
+ });
30
+ }
31
+
32
+ // Area-bound form for single-area modules; records omit `safeFix`.
33
+ function makeAddCheck(area) {
34
+ return function (checks, id, status, relPath, message, opts = {}) {
35
+ checks.push({
36
+ area,
37
+ id,
38
+ status,
39
+ path: relPath,
40
+ message,
41
+ severity: severityFor(status, opts),
42
+ spawn: opts.spawn || null
43
+ });
44
+ };
45
+ }
46
+
47
+ function listFiles(projectRoot, relDir, pattern) {
48
+ const dir = path.join(projectRoot, relDir);
49
+ if (!fs.existsSync(dir)) return [];
50
+ return fs.readdirSync(dir)
51
+ .filter((name) => pattern.test(name))
52
+ .sort()
53
+ .map((name) => `${relDir}/${name}`.replace(/\\/g, '/'));
54
+ }
55
+
56
+ module.exports = { addCheck, makeAddCheck, listFiles };
package/lib/sync-fs.js CHANGED
@@ -34,4 +34,16 @@ function readJson(projectRoot, relPath) {
34
34
  }
35
35
  }
36
36
 
37
- module.exports = { read, write, exists, readJson };
37
+ // Like read(), but returns null (not '') when the file is missing or unreadable,
38
+ // for callers that distinguish "absent" from "empty".
39
+ function readTextOrNull(projectRoot, relPath) {
40
+ const file = path.join(projectRoot, relPath);
41
+ if (!fs.existsSync(file)) return null;
42
+ try {
43
+ return fs.readFileSync(file, 'utf8');
44
+ } catch (err) {
45
+ return null;
46
+ }
47
+ }
48
+
49
+ module.exports = { read, write, exists, readJson, readTextOrNull };
@@ -108,6 +108,8 @@ function render(result) {
108
108
  lines.push(result.since === 'all'
109
109
  ? 'No verification records yet.'
110
110
  : 'Nothing new since the last report.');
111
+ // CNT-006: do not dead-end; name what populates the ledger.
112
+ lines.push('Run "npx godpowers verify <command>" or "reflect --action ..." to add records.');
111
113
  return lines.join('\n');
112
114
  }
113
115
  lines.push(`Since: ${result.since}${result.peek ? ' (peek, cursor not advanced)' : ''}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "godpowers",
3
- "version": "3.13.1",
3
+ "version": "3.14.0",
4
4
  "description": "AI-powered development system: 120 slash commands and 40 specialist agents that take a project from raw idea to hardened production. Runs inside Claude Code, Codex, Cursor, Windsurf, Gemini, and 10+ other AI coding tools.",
5
5
  "bin": {
6
6
  "godpowers": "./bin/install.js"
@@ -24,11 +24,11 @@
24
24
  "test:e2e": "node tests/integration/full-arc.test.js",
25
25
  "test:mcp": "npm --workspace @godpowers/mcp test",
26
26
  "coverage": "c8 --reporter=text --reporter=lcov node scripts/run-tests.js",
27
- "coverage:lib": "c8 --include=lib/**/*.js --check-coverage --lines 90 --branches 75 --reporter=text node scripts/run-tests.js",
27
+ "coverage:lib": "c8 --include=lib/**/*.js --check-coverage --lines 90 --branches 75 --reporter=text --reporter=json-summary node scripts/run-tests.js",
28
28
  "test:audit": "npm audit --omit=dev && git diff --check && npm run test:surface",
29
29
  "pack:check": "node scripts/check-package-contents.js",
30
30
  "pack:mcp:check": "npm --workspace @godpowers/mcp run pack:check",
31
- "release:check": "npm run coverage:lib && npm run test:audit && npm run pack:check && npm run pack:mcp:check",
31
+ "release:check": "npm run coverage:lib && node scripts/check-per-file-coverage.js && npm run test:audit && npm run pack:check && npm run pack:mcp:check",
32
32
  "lint": "node scripts/static-check.js"
33
33
  },
34
34
  "workspaces": [
@@ -406,6 +406,9 @@ maker that fixes is never the checker that grades.
406
406
  command and records the iteration. Repeat until the outcome succeeds or the
407
407
  budget is exhausted.
408
408
  - Never mark a finding resolved while `can-close` for its substep is red.
409
+ (`can-close` is the advisory since-in-flight freshness check you run as
410
+ discipline; the mechanically enforced gate is `npx godpowers gate`. Both
411
+ must agree before you close.)
409
412
  4. **Re-audit.** Re-run `god-debt-assessor` and confirm findings are resolved,
410
413
  not relocated, and that no Strength regressed. The loop is done when no
411
414
  Confirmed Critical or High remains (or the agreed bucket is empty).
@@ -535,9 +538,13 @@ requested or final sign-off begins.
535
538
  6. Verify their output exists on disk
536
539
  7. Run have-nots check on the artifact and run `standards.gate-command` when configured
537
540
  8. For an executable-gated sub-step (build, deploy, harden), record executed
538
- evidence with `npx godpowers verify "<cmd>" --substep <tier.substep>` and then
539
- confirm `npx godpowers can-close --substep <tier.substep> --project=.` exits
540
- zero before closing. Never advance the sub-step to done while can-close is red.
541
+ evidence with `npx godpowers verify "<cmd>" --substep <tier.substep>`, confirm
542
+ the enforced gate passes with `npx godpowers gate --tier=<tier> --project=.`,
543
+ and then run the advisory freshness check
544
+ `npx godpowers can-close --substep <tier.substep> --project=.` (it must exit
545
+ zero). The gate is the mechanical boundary; can-close is the stricter
546
+ since-in-flight discipline. Never advance the sub-step to done while either
547
+ is red.
541
548
  9. If pass and can-close is green: advance the sub-step to done via
542
549
  `npx godpowers state advance`, sync CHECKPOINT.md, run the proactive
543
550
  auto-invoke sweep, print the "Step result" card, then move to next sub-step
@@ -10,6 +10,10 @@ triggers:
10
10
  - "bug found"
11
11
  - "broken in dev"
12
12
  - "investigate bug"
13
+ - "fix a bug"
14
+ - "fix bug"
15
+ - "fix the bug"
16
+ - "bug"
13
17
 
14
18
  sequences:
15
19
  default:
@@ -15,6 +15,12 @@ triggers:
15
15
  - "ship a release"
16
16
  - "release the project"
17
17
  - "prepare release"
18
+ - "ship it"
19
+ - "ship"
20
+ - "release"
21
+ - "deploy"
22
+ - "deploy this"
23
+ - "deploy it"
18
24
 
19
25
  sequences:
20
26
  default:
@@ -17,6 +17,9 @@ triggers:
17
17
  - "deliverable progress"
18
18
  - "show the checklist"
19
19
  - "how much is built"
20
+ - "check progress"
21
+ - "progress"
22
+ - "check status"
20
23
 
21
24
  sequences:
22
25
  default:
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: god-org-context
3
3
  description: |
4
- Bluefield support. Set up or read organization-level context: shared
4
+ Set up or read organization-level context (bluefield support): shared
5
5
  standards, conventions, infrastructure, libraries. Constrains downstream
6
6
  agents to respect org-wide decisions when building new code in an
7
7
  established context.
@@ -1,8 +1,10 @@
1
1
  ---
2
2
  name: god-reconcile
3
3
  description: |
4
- Comprehensive reconciliation across all impacted artifacts before doing
5
- feature work. Checks PRD, ARCH, ROADMAP, STACK, REPO, DEPLOY, OBSERVE,
4
+ Check before feature work (read-only): reconcile all impacted artifacts to
5
+ find conflicts before you build. This is the BEFORE half of the pair; its
6
+ write-back counterpart is /god-sync, which updates artifacts AFTER the work.
7
+ Checks PRD, ARCH, ROADMAP, STACK, REPO, DEPLOY, OBSERVE,
6
8
  HARDEN, LAUNCH, BACKLOG, SEEDS, TODOS, THREADS, repository documentation,
7
9
  repository surface, runtime feature awareness, source-system sync-back, and
8
10
  host capabilities in parallel. Replaces /god-roadmap-check (kept for
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: god-smite
3
3
  description: |
4
- Hard reset of the project's node-style dependency cache: delete
4
+ Clear the dependency cache (hard reset of the node-style layer): delete
5
5
  node_modules / .venv / vendor / target / .next / dist / .nuxt /
6
6
  .turbo / .nx as applicable, then reinstall. For when "have you tried
7
7
  turning it off and on again" applies to the dependency layer.
@@ -1,7 +1,10 @@
1
1
  ---
2
2
  name: god-sync
3
3
  description: |
4
- Sync all affected artifacts after feature work. Updates PRD, ARCH, ROADMAP,
4
+ Update after feature work (write-back): sync all affected artifacts to match
5
+ what the work actually touched. This is the AFTER half of the pair; its
6
+ read-only counterpart is /god-reconcile, which checks for conflicts BEFORE
7
+ the work. Updates PRD, ARCH, ROADMAP,
5
8
  STACK, DEPLOY, OBSERVE, HARDEN, LAUNCH, BACKLOG, SEEDS, TODOS, THREADS
6
9
  based on what the work actually touched. Closes the loop after
7
10
  /god-reconcile + feature execution.