godpowers 1.6.6 → 1.6.7
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/AGENTS.md +10 -0
- package/CHANGELOG.md +39 -0
- package/README.md +5 -6
- package/RELEASE.md +36 -30
- package/agents/god-orchestrator.md +57 -7
- package/bin/install.js +22 -12
- package/lib/checkpoint.js +50 -13
- package/lib/state.js +144 -1
- package/package.json +2 -2
- package/skills/god-locate.md +15 -2
- package/skills/god-mode.md +35 -0
- package/skills/god-next.md +17 -0
- package/skills/god-status.md +14 -0
- package/templates/PROGRESS.md +22 -0
package/AGENTS.md
CHANGED
|
@@ -35,3 +35,13 @@ projects from raw idea to hardened production.
|
|
|
35
35
|
- No emojis (use `+`, `-`, `x`, `!` for status indicators)
|
|
36
36
|
- Every sentence in generated artifacts must be labeled: DECISION, HYPOTHESIS, or OPEN QUESTION
|
|
37
37
|
- Every claim must fail the substitution test (swap in a competitor, sentence must break)
|
|
38
|
+
|
|
39
|
+
<!-- pillars:begin -->
|
|
40
|
+
## Godpowers Pillars Protocol
|
|
41
|
+
|
|
42
|
+
- [DECISION] Load `agents/context.md` and `agents/repo.md` before Godpowers commands make durable project decisions.
|
|
43
|
+
- [DECISION] Load additional `agents/*.md` pillar files only when their frontmatter matches the task.
|
|
44
|
+
- [DECISION] Treat `.godpowers/state.json`, `.godpowers/PROGRESS.md`, and `.godpowers/CHECKPOINT.md` as workflow state.
|
|
45
|
+
- [DECISION] Treat Pillars files as portable project context for any coding agent that opens this repository.
|
|
46
|
+
- [DECISION] Disk state wins over conversation memory when these sources disagree.
|
|
47
|
+
<!-- pillars:end -->
|
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,45 @@ All notable changes to Godpowers will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.6.7] - 2026-05-16
|
|
9
|
+
|
|
10
|
+
Progress visibility patch. Makes Godpowers easier to follow while preserving
|
|
11
|
+
the stable 1.6 command surface.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
- Added `lib/state.progressSummary`, `orderedSubSteps`, and
|
|
15
|
+
`renderProgressLine` so commands can report percentage complete, completed
|
|
16
|
+
step count, total step count, and current step number from state.json.
|
|
17
|
+
- Added checkpoint frontmatter fields for `progress-pct`,
|
|
18
|
+
`progress-complete`, `progress-total`, and `current-step`.
|
|
19
|
+
- Added `CHECKPOINT.md` sections for recent work and what happens next.
|
|
20
|
+
- Added a Step Narration Protocol for `god-orchestrator` so visible
|
|
21
|
+
tier/sub-step work gets compact "Next step" and "Step result" cards.
|
|
22
|
+
- Added `/god-mode`, `/god-next`, `/god-status`, and `/god-locate` guidance
|
|
23
|
+
for progress, path-ahead, recent work, and next-action summaries.
|
|
24
|
+
- Added `PROGRESS.md` template sections for the current step plan and recent
|
|
25
|
+
step results.
|
|
26
|
+
- Added root `AGENTS.md` Pillars Protocol guidance so coding agents know which
|
|
27
|
+
project context and workflow-state files are authoritative.
|
|
28
|
+
- Added installer coverage for `--local` Codex installs.
|
|
29
|
+
- Added regression coverage for progress math, checkpoint progress rendering,
|
|
30
|
+
checkpoint progress preservation, and checkpoint step summaries.
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
- Package publication now allowlists `agents/god-*.md` instead of the entire
|
|
34
|
+
`agents/` directory so local Pillars files do not enter the npm payload.
|
|
35
|
+
- Package contents checks now fail when non-specialist files under `agents/`
|
|
36
|
+
would be included in the npm package.
|
|
37
|
+
- The installer now resolves local runtime destinations when `--local` is used
|
|
38
|
+
and only installs specialist agent files matching `god-*.md`.
|
|
39
|
+
|
|
40
|
+
### Guardrails
|
|
41
|
+
- This patch does not add slash commands, specialist agents, workflows,
|
|
42
|
+
recipes, schemas, or public artifact formats.
|
|
43
|
+
- Progress percentages are derived from disk state, not conversation memory.
|
|
44
|
+
- Optional or intentionally skipped steps count as complete when their state
|
|
45
|
+
is `imported`, `skipped`, or `not-required`.
|
|
46
|
+
|
|
8
47
|
## [1.6.6] - 2026-05-16
|
|
9
48
|
|
|
10
49
|
Non-God-Mode handoff privacy patch. Extends the display-safe handoff pattern
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://github.com/aihxp/godpowers/actions/workflows/ci.yml)
|
|
4
4
|
[](LICENSE)
|
|
5
|
-
[](CHANGELOG.md)
|
|
6
6
|
[](https://www.npmjs.com/package/godpowers)
|
|
7
7
|
|
|
8
8
|
**Ship fast. Ship right. Ship everything. Ship accountably.**
|
|
@@ -12,11 +12,10 @@ idea to hardened production. It runs as **slash commands inside your AI coding
|
|
|
12
12
|
tool** (Claude Code, Codex, Cursor, etc.) that orchestrate **specialist agents**
|
|
13
13
|
in fresh contexts to do the work.
|
|
14
14
|
|
|
15
|
-
Version 1.6.
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
Tier 3 commands, `/god-mode`, and `/god-mode --yolo`.
|
|
15
|
+
Version 1.6.7 keeps the stable Godpowers surface while making the live arc
|
|
16
|
+
easier to follow: progress reports now show percent complete, current step,
|
|
17
|
+
recent work, and what happens next. The orchestrator also documents compact
|
|
18
|
+
"Next step" and "Step result" cards around visible tier/sub-step work.
|
|
20
19
|
|
|
21
20
|
It fuses four disciplines into one unified workflow:
|
|
22
21
|
|
package/RELEASE.md
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
# Godpowers 1.6.
|
|
1
|
+
# Godpowers 1.6.7 Release
|
|
2
2
|
|
|
3
3
|
Date: 2026-05-16
|
|
4
4
|
|
|
5
|
-
Godpowers 1.6.
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
orchestrator and coordinator behavior.
|
|
5
|
+
Godpowers 1.6.7 makes the live workflow easier to track. The goal of this
|
|
6
|
+
patch is to answer "what is Godpowers doing, how far along is it, what just
|
|
7
|
+
happened, and what happens next" from disk state.
|
|
9
8
|
|
|
10
9
|
## What is stable
|
|
11
10
|
|
|
@@ -27,29 +26,36 @@ orchestrator and coordinator behavior.
|
|
|
27
26
|
|
|
28
27
|
## What is new
|
|
29
28
|
|
|
30
|
-
-
|
|
31
|
-
|
|
32
|
-
`
|
|
33
|
-
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
29
|
+
- `lib/state.progressSummary` computes percentage complete, completed step
|
|
30
|
+
count, total step count, current step number, and current tier/sub-step from
|
|
31
|
+
`state.json`.
|
|
32
|
+
- `CHECKPOINT.md` can persist progress frontmatter and now includes
|
|
33
|
+
"What happened recently" and "What happens next" sections.
|
|
34
|
+
- `god-orchestrator` now has a Step Narration Protocol for compact
|
|
35
|
+
"Next step" and "Step result" cards around visible tier/sub-step work.
|
|
36
|
+
- `/god-mode`, `/god-next`, `/god-status`, and `/god-locate` now document
|
|
37
|
+
progress, path-ahead, recent-work, and next-action summaries.
|
|
38
|
+
- `templates/PROGRESS.md` now includes a current step plan and recent step
|
|
39
|
+
result shape.
|
|
40
|
+
- Package publication now allowlists `agents/god-*.md`, preventing local
|
|
41
|
+
Pillars files under `agents/` from entering the npm payload.
|
|
42
|
+
- Package contents checks now fail if non-specialist files under `agents/`
|
|
43
|
+
would be published.
|
|
44
|
+
- `AGENTS.md` now includes the Pillars Protocol for loading durable project
|
|
45
|
+
context and workflow-state files.
|
|
46
|
+
- Installer local mode now resolves runtime destinations under the current
|
|
47
|
+
directory and installs only `god-*.md` specialist agent files.
|
|
48
|
+
|
|
49
|
+
## What 1.6.7 means
|
|
50
|
+
|
|
51
|
+
Godpowers 1.6.7 does not expand the public command surface. It makes the
|
|
52
|
+
existing arc more legible by showing a disk-derived progress report, a short
|
|
53
|
+
plan before visible work starts, and a short result after work completes or
|
|
54
|
+
pauses.
|
|
55
|
+
|
|
56
|
+
The release also tightens npm packaging around specialist agents. Local
|
|
57
|
+
project Pillars can live under `agents/` during development, but only
|
|
58
|
+
`agents/god-*.md` files are packaged as Godpowers specialist agents.
|
|
53
59
|
|
|
54
60
|
Safe sync and unresolved Critical harden findings remain release-truth gates.
|
|
55
61
|
Per-repo Quarterback ownership remains intact for Mode D suite work.
|
|
@@ -59,8 +65,8 @@ Per-repo Quarterback ownership remains intact for Mode D suite work.
|
|
|
59
65
|
During the 1.x stability window, do not add broad new command families, change
|
|
60
66
|
schema formats, or rename public artifacts without evidence from real use.
|
|
61
67
|
|
|
62
|
-
The `v1.6.
|
|
63
|
-
`godpowers@1.6.
|
|
68
|
+
The `v1.6.7` git tag points to the release commit that matches the npm
|
|
69
|
+
`godpowers@1.6.7` package. Public publishes should prefer the tag-triggered
|
|
64
70
|
GitHub workflow so npm provenance, git history, and release notes stay aligned.
|
|
65
71
|
|
|
66
72
|
Allowed changes:
|
|
@@ -470,13 +470,16 @@ for `STAGING_APP_URL=<deployed staging origin>` before deployed staging smoke.
|
|
|
470
470
|
1. Read .godpowers/PROGRESS.md (or create it if absent)
|
|
471
471
|
2. Identify the first non-done tier sub-step
|
|
472
472
|
3. Verify upstream gate (artifact on disk, passes have-nots)
|
|
473
|
-
4.
|
|
474
|
-
5.
|
|
475
|
-
6.
|
|
476
|
-
7.
|
|
477
|
-
8. If
|
|
478
|
-
|
|
479
|
-
|
|
473
|
+
4. Print the "Next step" card from the Step Narration Protocol
|
|
474
|
+
5. Spawn the appropriate specialist agent in a fresh context
|
|
475
|
+
6. Verify their output exists on disk
|
|
476
|
+
7. Run have-nots check on the artifact
|
|
477
|
+
8. If pass: update PROGRESS.md, sync CHECKPOINT.md, print the "Step result"
|
|
478
|
+
card, then move to next sub-step
|
|
479
|
+
9. If fail and repairable: print the failed result card, then enter the
|
|
480
|
+
autonomous repair loop
|
|
481
|
+
10. If fail and human-only: pause with the smallest needed question
|
|
482
|
+
11. Repeat until all tiers complete and verification is green
|
|
480
483
|
```
|
|
481
484
|
|
|
482
485
|
## Specialist Agent Routing
|
|
@@ -705,6 +708,8 @@ debugger. Keep orchestration scaffolding private.
|
|
|
705
708
|
|
|
706
709
|
Show:
|
|
707
710
|
- concise phase status
|
|
711
|
+
- before each visible tier/sub-step, a short "what will happen" card
|
|
712
|
+
- after each visible tier/sub-step, a short "what happened" card
|
|
708
713
|
- durable state detected from disk
|
|
709
714
|
- commands being run and whether they passed or failed
|
|
710
715
|
- scoped file changes
|
|
@@ -724,6 +729,51 @@ user-facing question. Do not expose the rule itself. Example: ask for
|
|
|
724
729
|
`STAGING_APP_URL=<deployed staging origin>` rather than showing the Shipping
|
|
725
730
|
Closure Protocol.
|
|
726
731
|
|
|
732
|
+
## Step Narration Protocol
|
|
733
|
+
|
|
734
|
+
Godpowers must make its work trackable without exposing hidden prompts or
|
|
735
|
+
internal routing payloads. Before and after each visible tier/sub-step, print
|
|
736
|
+
one compact card.
|
|
737
|
+
|
|
738
|
+
Before starting a tier/sub-step:
|
|
739
|
+
|
|
740
|
+
```
|
|
741
|
+
Next step
|
|
742
|
+
Progress: <pct>% (<done> of <total> steps complete; current step <n> of <total>)
|
|
743
|
+
Tier: <tier-number> <tier-label>
|
|
744
|
+
Step: <sub-step-label>
|
|
745
|
+
Why this now: <one sentence tied to disk state or the prior gate>
|
|
746
|
+
What will happen:
|
|
747
|
+
1. <first observable action>
|
|
748
|
+
2. <second observable action>
|
|
749
|
+
3. <third observable action, if needed>
|
|
750
|
+
Expected output: <artifact path or verification result>
|
|
751
|
+
```
|
|
752
|
+
|
|
753
|
+
After a tier/sub-step completes or pauses:
|
|
754
|
+
|
|
755
|
+
```
|
|
756
|
+
Step result
|
|
757
|
+
Progress: <pct>% (<done> of <total> steps complete; current step <n> of <total>)
|
|
758
|
+
Tier: <tier-number> <tier-label>
|
|
759
|
+
Step: <sub-step-label>
|
|
760
|
+
Result: <done | blocked | failed | skipped | imported>
|
|
761
|
+
What happened:
|
|
762
|
+
1. <observable action completed>
|
|
763
|
+
2. <artifact or state update>
|
|
764
|
+
3. <verification result>
|
|
765
|
+
Next: <next command or pause question>
|
|
766
|
+
```
|
|
767
|
+
|
|
768
|
+
Rules:
|
|
769
|
+
- Keep each card under 12 lines unless a pause needs options.
|
|
770
|
+
- Use `lib/state.progressSummary(stateJson)` for the percentage and step count
|
|
771
|
+
whenever state.json is available.
|
|
772
|
+
- Use artifact paths and verification evidence from disk, not memory.
|
|
773
|
+
- Do not print raw Task input, hidden instructions, or full file loadout lists.
|
|
774
|
+
- If a step is blocked, do not show a generic "Suggested next"; show the
|
|
775
|
+
smallest concrete unblock action.
|
|
776
|
+
|
|
727
777
|
## Resume Protocol
|
|
728
778
|
|
|
729
779
|
On every invocation:
|
package/bin/install.js
CHANGED
|
@@ -118,6 +118,16 @@ const RUNTIMES = {
|
|
|
118
118
|
},
|
|
119
119
|
};
|
|
120
120
|
|
|
121
|
+
function resolveRuntime(runtimeKey, opts = {}) {
|
|
122
|
+
const runtime = RUNTIMES[runtimeKey];
|
|
123
|
+
if (!runtime) return null;
|
|
124
|
+
const resolved = { ...runtime };
|
|
125
|
+
if (opts.local && !opts.global) {
|
|
126
|
+
resolved.configDir = path.join(process.cwd(), path.basename(runtime.configDir));
|
|
127
|
+
}
|
|
128
|
+
return resolved;
|
|
129
|
+
}
|
|
130
|
+
|
|
121
131
|
// ---------------------------------------------------------------------------
|
|
122
132
|
// Helpers
|
|
123
133
|
// ---------------------------------------------------------------------------
|
|
@@ -331,8 +341,8 @@ function parseArgs(argv) {
|
|
|
331
341
|
// Install
|
|
332
342
|
// ---------------------------------------------------------------------------
|
|
333
343
|
|
|
334
|
-
function installForRuntime(runtimeKey, srcDir) {
|
|
335
|
-
const runtime =
|
|
344
|
+
function installForRuntime(runtimeKey, srcDir, opts = {}) {
|
|
345
|
+
const runtime = resolveRuntime(runtimeKey, opts);
|
|
336
346
|
if (!runtime) {
|
|
337
347
|
error(`Unknown runtime: ${runtimeKey}`);
|
|
338
348
|
return false;
|
|
@@ -367,7 +377,7 @@ function installForRuntime(runtimeKey, srcDir) {
|
|
|
367
377
|
ensureDir(agentsDest);
|
|
368
378
|
let count = 0;
|
|
369
379
|
for (const file of fs.readdirSync(agentsSrc)) {
|
|
370
|
-
if (file
|
|
380
|
+
if (/^god-.*\.md$/.test(file)) {
|
|
371
381
|
const srcFile = path.join(agentsSrc, file);
|
|
372
382
|
installAgentFile(srcFile, agentsDest, runtime);
|
|
373
383
|
count++;
|
|
@@ -456,8 +466,8 @@ function installForRuntime(runtimeKey, srcDir) {
|
|
|
456
466
|
// Uninstall
|
|
457
467
|
// ---------------------------------------------------------------------------
|
|
458
468
|
|
|
459
|
-
function uninstallForRuntime(runtimeKey) {
|
|
460
|
-
const runtime =
|
|
469
|
+
function uninstallForRuntime(runtimeKey, opts = {}) {
|
|
470
|
+
const runtime = resolveRuntime(runtimeKey, opts);
|
|
461
471
|
if (!runtime) {
|
|
462
472
|
error(`Unknown runtime: ${runtimeKey}`);
|
|
463
473
|
return false;
|
|
@@ -580,16 +590,16 @@ function main() {
|
|
|
580
590
|
|
|
581
591
|
const srcDir = path.resolve(__dirname, '..');
|
|
582
592
|
|
|
583
|
-
// Detect non-interactive and default to
|
|
593
|
+
// Detect non-interactive and default to Claude Code.
|
|
584
594
|
if (opts.runtimes.length === 0 && !opts.all) {
|
|
585
595
|
if (!process.stdin.isTTY) {
|
|
586
|
-
warn('Non-interactive terminal detected, defaulting to Claude Code
|
|
596
|
+
warn('Non-interactive terminal detected, defaulting to Claude Code install');
|
|
587
597
|
opts.runtimes = ['claude'];
|
|
588
|
-
opts.global = true;
|
|
598
|
+
if (!opts.local) opts.global = true;
|
|
589
599
|
} else {
|
|
590
600
|
// Interactive mode: default to claude
|
|
591
601
|
opts.runtimes = ['claude'];
|
|
592
|
-
opts.global = true;
|
|
602
|
+
if (!opts.local) opts.global = true;
|
|
593
603
|
}
|
|
594
604
|
}
|
|
595
605
|
|
|
@@ -601,7 +611,7 @@ function main() {
|
|
|
601
611
|
if (opts.uninstall) {
|
|
602
612
|
let removed = 0;
|
|
603
613
|
for (const runtime of opts.runtimes) {
|
|
604
|
-
if (uninstallForRuntime(runtime)) {
|
|
614
|
+
if (uninstallForRuntime(runtime, opts)) {
|
|
605
615
|
removed++;
|
|
606
616
|
}
|
|
607
617
|
}
|
|
@@ -617,7 +627,7 @@ function main() {
|
|
|
617
627
|
|
|
618
628
|
let installed = 0;
|
|
619
629
|
for (const runtime of opts.runtimes) {
|
|
620
|
-
if (installForRuntime(runtime, srcDir)) {
|
|
630
|
+
if (installForRuntime(runtime, srcDir, opts)) {
|
|
621
631
|
installed++;
|
|
622
632
|
}
|
|
623
633
|
}
|
|
@@ -625,7 +635,7 @@ function main() {
|
|
|
625
635
|
if (installed > 0) {
|
|
626
636
|
// Count slash commands for verification message
|
|
627
637
|
const skillsCount = fs.readdirSync(path.join(srcDir, 'skills')).filter(f => f.endsWith('.md')).length;
|
|
628
|
-
const agentsCount = fs.readdirSync(path.join(srcDir, 'agents')).filter(f => f
|
|
638
|
+
const agentsCount = fs.readdirSync(path.join(srcDir, 'agents')).filter(f => /^god-.*\.md$/.test(f)).length;
|
|
629
639
|
|
|
630
640
|
log('');
|
|
631
641
|
log(`\x1b[32mDone!\x1b[0m Installed Godpowers v${VERSION} for ${installed} runtime(s).`);
|
package/lib/checkpoint.js
CHANGED
|
@@ -22,6 +22,10 @@
|
|
|
22
22
|
* lifecycle: {pre-init|in-arc|steady-state-active|...}
|
|
23
23
|
* current-tier: {tier-N}
|
|
24
24
|
* current-substep: {substep-key}
|
|
25
|
+
* progress-pct: {number}
|
|
26
|
+
* progress-complete: {number}
|
|
27
|
+
* progress-total: {number}
|
|
28
|
+
* current-step: {number}
|
|
25
29
|
* last-action: {action-name}
|
|
26
30
|
* last-actor: {agent or user}
|
|
27
31
|
* last-update: {ISO8601}
|
|
@@ -123,6 +127,7 @@ function write(projectRoot, state) {
|
|
|
123
127
|
const actions = (state.actions || []).slice(0, MAX_ACTIONS);
|
|
124
128
|
const facts = (state.facts || []).slice(0, MAX_FACTS);
|
|
125
129
|
const factsHash = sha256(JSON.stringify(facts));
|
|
130
|
+
const progress = state.progress || null;
|
|
126
131
|
|
|
127
132
|
const fm = [
|
|
128
133
|
'---',
|
|
@@ -133,13 +138,27 @@ function write(projectRoot, state) {
|
|
|
133
138
|
`lifecycle: ${state.lifecycle || 'in-arc'}`,
|
|
134
139
|
`current-tier: ${state.currentTier || 'tier-0'}`,
|
|
135
140
|
`current-substep: ${state.currentSubstep || 'orchestration'}`,
|
|
141
|
+
progress ? `progress-pct: ${progress.percent}` : null,
|
|
142
|
+
progress ? `progress-complete: ${progress.completed}` : null,
|
|
143
|
+
progress ? `progress-total: ${progress.total}` : null,
|
|
144
|
+
progress ? `current-step: ${progress.currentStep}` : null,
|
|
136
145
|
`last-action: ${state.lastAction || 'unknown'}`,
|
|
137
146
|
`last-actor: ${state.lastActor || 'unknown'}`,
|
|
138
147
|
`last-update: ${ts}`,
|
|
139
148
|
`facts-hash: sha256:${factsHash}`,
|
|
140
149
|
'---',
|
|
141
150
|
''
|
|
142
|
-
].join('\n');
|
|
151
|
+
].filter(line => line !== null).join('\n');
|
|
152
|
+
|
|
153
|
+
const progressLine = progress
|
|
154
|
+
? `- Progress: **${progress.percent}%** (${progress.completed} of ${progress.total} steps complete; current step ${progress.currentStep} of ${progress.total})`
|
|
155
|
+
: null;
|
|
156
|
+
const recentSummary = actions.length === 0
|
|
157
|
+
? '_(no recent actions recorded yet)_'
|
|
158
|
+
: actions.slice(0, 3).map(a => `- ${a}`).join('\n');
|
|
159
|
+
const nextSummary = state.nextCommand
|
|
160
|
+
? `- ${state.nextCommand}\n- ${state.nextReason || 'No reason recorded.'}`
|
|
161
|
+
: '- Run `/god-next` to compute the next command from disk state.';
|
|
143
162
|
|
|
144
163
|
const body = [
|
|
145
164
|
'# Checkpoint',
|
|
@@ -153,9 +172,18 @@ function write(projectRoot, state) {
|
|
|
153
172
|
`- Project: **${state.project || 'unnamed'}**`,
|
|
154
173
|
`- Mode: **${state.mode || '?'}**${state.modeDSuite ? ' (in multi-repo suite)' : ''}`,
|
|
155
174
|
`- Lifecycle phase: **${state.lifecycle || 'in-arc'}**`,
|
|
175
|
+
progressLine,
|
|
156
176
|
`- Current tier: **${state.currentTier || 'tier-0'}** / **${state.currentSubstep || 'orchestration'}**`,
|
|
157
177
|
`- Last action: \`${state.lastAction || 'unknown'}\` by ${state.lastActor || 'unknown'} at ${ts}`,
|
|
158
178
|
'',
|
|
179
|
+
'## What happened recently',
|
|
180
|
+
'',
|
|
181
|
+
recentSummary,
|
|
182
|
+
'',
|
|
183
|
+
'## What happens next',
|
|
184
|
+
'',
|
|
185
|
+
nextSummary,
|
|
186
|
+
'',
|
|
159
187
|
'## Next suggested command',
|
|
160
188
|
'',
|
|
161
189
|
state.nextCommand
|
|
@@ -191,7 +219,7 @@ function write(projectRoot, state) {
|
|
|
191
219
|
`- Authoritative state: \`.godpowers/state.json\``,
|
|
192
220
|
`- Authoritative history: \`.godpowers/runs/<id>/events.jsonl\` + \`.godpowers/log\``,
|
|
193
221
|
''
|
|
194
|
-
].join('\n');
|
|
222
|
+
].filter(line => line !== null).join('\n');
|
|
195
223
|
|
|
196
224
|
fs.writeFileSync(file, fm + body);
|
|
197
225
|
return file;
|
|
@@ -234,7 +262,7 @@ function recordFact(projectRoot, fact) {
|
|
|
234
262
|
}
|
|
235
263
|
|
|
236
264
|
function frontmatterToState(fm, facts) {
|
|
237
|
-
|
|
265
|
+
const result = {
|
|
238
266
|
project: fm.project,
|
|
239
267
|
mode: fm.mode,
|
|
240
268
|
modeDSuite: fm['mode-d-suite'] === true || fm['mode-d-suite'] === 'true',
|
|
@@ -245,6 +273,15 @@ function frontmatterToState(fm, facts) {
|
|
|
245
273
|
lastActor: fm['last-actor'],
|
|
246
274
|
facts: facts || []
|
|
247
275
|
};
|
|
276
|
+
if (fm['progress-total']) {
|
|
277
|
+
result.progress = {
|
|
278
|
+
percent: Number(fm['progress-pct'] || 0),
|
|
279
|
+
completed: Number(fm['progress-complete'] || 0),
|
|
280
|
+
total: Number(fm['progress-total'] || 0),
|
|
281
|
+
currentStep: Number(fm['current-step'] || 0)
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
return result;
|
|
248
285
|
}
|
|
249
286
|
|
|
250
287
|
/**
|
|
@@ -304,27 +341,26 @@ function syncFromState(projectRoot, opts = {}) {
|
|
|
304
341
|
|
|
305
342
|
const s = state.read(projectRoot);
|
|
306
343
|
if (!s) throw new Error('state.json not initialized');
|
|
344
|
+
const progress = state.progressSummary(s);
|
|
307
345
|
|
|
308
|
-
// Find the current tier + sub-step
|
|
309
|
-
//
|
|
346
|
+
// Find the current tier + sub-step from progressSummary, then keep a
|
|
347
|
+
// separate lastAction pointer to the newest completed step.
|
|
310
348
|
let currentTier = 'tier-0';
|
|
311
349
|
let currentSubstep = 'orchestration';
|
|
312
350
|
let lastAction = 'init';
|
|
313
351
|
let lastUpdate = null;
|
|
314
352
|
let lastActor = 'unknown';
|
|
353
|
+
if (progress.current) {
|
|
354
|
+
currentTier = progress.current.tierKey;
|
|
355
|
+
currentSubstep = progress.current.subStepKey;
|
|
356
|
+
}
|
|
357
|
+
|
|
315
358
|
if (s.tiers) {
|
|
316
|
-
|
|
359
|
+
for (const tierKey of Object.keys(s.tiers).sort()) {
|
|
317
360
|
for (const [substepKey, sub] of Object.entries(s.tiers[tierKey])) {
|
|
318
|
-
if (sub.status === 'in-flight') {
|
|
319
|
-
currentTier = tierKey;
|
|
320
|
-
currentSubstep = substepKey;
|
|
321
|
-
break outer;
|
|
322
|
-
}
|
|
323
361
|
if (sub.status === 'done' && sub.updated) {
|
|
324
362
|
if (!lastUpdate || sub.updated > lastUpdate) {
|
|
325
363
|
lastUpdate = sub.updated;
|
|
326
|
-
currentTier = tierKey;
|
|
327
|
-
currentSubstep = substepKey;
|
|
328
364
|
lastAction = `${tierKey}.${substepKey} done`;
|
|
329
365
|
}
|
|
330
366
|
}
|
|
@@ -372,6 +408,7 @@ function syncFromState(projectRoot, opts = {}) {
|
|
|
372
408
|
lastActor,
|
|
373
409
|
actions,
|
|
374
410
|
facts,
|
|
411
|
+
progress,
|
|
375
412
|
nextCommand: opts.nextCommand,
|
|
376
413
|
nextReason: opts.nextReason
|
|
377
414
|
});
|
package/lib/state.js
CHANGED
|
@@ -10,11 +10,52 @@ const path = require('path');
|
|
|
10
10
|
const crypto = require('crypto');
|
|
11
11
|
|
|
12
12
|
const STATE_VERSION = '1.0.0';
|
|
13
|
+
const COMPLETE_STATUSES = new Set(['done', 'imported', 'skipped', 'not-required']);
|
|
14
|
+
const ACTIVE_STATUSES = new Set(['in-flight', 'failed', 're-invoked']);
|
|
15
|
+
const TIER_LABELS = {
|
|
16
|
+
'tier-0': 'Orchestration',
|
|
17
|
+
'tier-1': 'Planning',
|
|
18
|
+
'tier-2': 'Building',
|
|
19
|
+
'tier-3': 'Shipping'
|
|
20
|
+
};
|
|
21
|
+
const SUBSTEP_LABELS = {
|
|
22
|
+
orchestration: 'Orchestration',
|
|
23
|
+
prd: 'PRD',
|
|
24
|
+
arch: 'Architecture',
|
|
25
|
+
roadmap: 'Roadmap',
|
|
26
|
+
stack: 'Stack',
|
|
27
|
+
design: 'Design',
|
|
28
|
+
product: 'Product',
|
|
29
|
+
repo: 'Repo',
|
|
30
|
+
build: 'Build',
|
|
31
|
+
deploy: 'Deploy',
|
|
32
|
+
observe: 'Observe',
|
|
33
|
+
launch: 'Launch',
|
|
34
|
+
harden: 'Harden'
|
|
35
|
+
};
|
|
13
36
|
|
|
14
37
|
function statePath(projectRoot) {
|
|
15
38
|
return path.join(projectRoot, '.godpowers', 'state.json');
|
|
16
39
|
}
|
|
17
40
|
|
|
41
|
+
function tierNumber(tierKey) {
|
|
42
|
+
const match = String(tierKey).match(/^tier-(\d+)$/);
|
|
43
|
+
return match ? Number(match[1]) : Number.MAX_SAFE_INTEGER;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function labelFromKey(key) {
|
|
47
|
+
return String(key)
|
|
48
|
+
.split(/[-_]/)
|
|
49
|
+
.filter(Boolean)
|
|
50
|
+
.map(part => part.charAt(0).toUpperCase() + part.slice(1))
|
|
51
|
+
.join(' ');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function tierComparator(a, b) {
|
|
55
|
+
const byNumber = tierNumber(a) - tierNumber(b);
|
|
56
|
+
return byNumber === 0 ? String(a).localeCompare(String(b)) : byNumber;
|
|
57
|
+
}
|
|
58
|
+
|
|
18
59
|
/**
|
|
19
60
|
* Read state.json from a project. Returns null if not initialized.
|
|
20
61
|
*/
|
|
@@ -139,4 +180,106 @@ function detectDrift(projectRoot) {
|
|
|
139
180
|
return drift;
|
|
140
181
|
}
|
|
141
182
|
|
|
142
|
-
|
|
183
|
+
function isCompleteStatus(status) {
|
|
184
|
+
return COMPLETE_STATUSES.has(status);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function isActiveStatus(status) {
|
|
188
|
+
return ACTIVE_STATUSES.has(status);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function orderedSubSteps(state) {
|
|
192
|
+
if (!state || !state.tiers) return [];
|
|
193
|
+
const steps = [];
|
|
194
|
+
for (const tierKey of Object.keys(state.tiers).sort(tierComparator)) {
|
|
195
|
+
const tier = state.tiers[tierKey] || {};
|
|
196
|
+
for (const [subStepKey, subStep] of Object.entries(tier)) {
|
|
197
|
+
const status = subStep && subStep.status ? subStep.status : 'pending';
|
|
198
|
+
steps.push({
|
|
199
|
+
tierKey,
|
|
200
|
+
tierNumber: tierNumber(tierKey),
|
|
201
|
+
tierLabel: TIER_LABELS[tierKey] || labelFromKey(tierKey),
|
|
202
|
+
subStepKey,
|
|
203
|
+
subStepLabel: SUBSTEP_LABELS[subStepKey] || labelFromKey(subStepKey),
|
|
204
|
+
status,
|
|
205
|
+
artifact: subStep && subStep.artifact,
|
|
206
|
+
updated: subStep && subStep.updated
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
return steps.map((step, index) => ({ ...step, ordinal: index + 1 }));
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function progressSummary(state) {
|
|
214
|
+
const steps = orderedSubSteps(state);
|
|
215
|
+
const total = steps.length;
|
|
216
|
+
const completed = steps.filter(step => isCompleteStatus(step.status)).length;
|
|
217
|
+
|
|
218
|
+
let currentIndex = steps.findIndex(step => isActiveStatus(step.status));
|
|
219
|
+
if (currentIndex < 0) {
|
|
220
|
+
currentIndex = steps.findIndex(step => !isCompleteStatus(step.status));
|
|
221
|
+
}
|
|
222
|
+
if (currentIndex < 0 && total > 0) currentIndex = total - 1;
|
|
223
|
+
|
|
224
|
+
const current = currentIndex >= 0 ? steps[currentIndex] : null;
|
|
225
|
+
return {
|
|
226
|
+
percent: total === 0 ? 0 : Math.round((completed / total) * 100),
|
|
227
|
+
completed,
|
|
228
|
+
total,
|
|
229
|
+
remaining: Math.max(total - completed, 0),
|
|
230
|
+
currentStep: current ? current.ordinal : 0,
|
|
231
|
+
current,
|
|
232
|
+
tiers: summarizeTiers(steps)
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function summarizeTiers(steps) {
|
|
237
|
+
const byTier = new Map();
|
|
238
|
+
for (const step of steps) {
|
|
239
|
+
if (!byTier.has(step.tierKey)) {
|
|
240
|
+
byTier.set(step.tierKey, {
|
|
241
|
+
tierKey: step.tierKey,
|
|
242
|
+
tierNumber: step.tierNumber,
|
|
243
|
+
tierLabel: step.tierLabel,
|
|
244
|
+
completed: 0,
|
|
245
|
+
total: 0,
|
|
246
|
+
current: false
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
const tier = byTier.get(step.tierKey);
|
|
250
|
+
tier.total += 1;
|
|
251
|
+
if (isCompleteStatus(step.status)) tier.completed += 1;
|
|
252
|
+
if (isActiveStatus(step.status)) tier.current = true;
|
|
253
|
+
}
|
|
254
|
+
return Array.from(byTier.values()).map(tier => ({
|
|
255
|
+
...tier,
|
|
256
|
+
percent: tier.total === 0 ? 0 : Math.round((tier.completed / tier.total) * 100)
|
|
257
|
+
}));
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function renderProgressLine(summary) {
|
|
261
|
+
const progress = summary && typeof summary.total === 'number' ? summary : progressSummary(summary);
|
|
262
|
+
if (!progress || progress.total === 0) {
|
|
263
|
+
return 'Progress: unavailable, no tracked Godpowers steps found';
|
|
264
|
+
}
|
|
265
|
+
const current = progress.current;
|
|
266
|
+
const currentLabel = current
|
|
267
|
+
? `${current.tierLabel} / ${current.subStepLabel}`
|
|
268
|
+
: 'complete';
|
|
269
|
+
return `Progress: ${progress.percent}% (${progress.completed} of ${progress.total} steps complete; current step ${progress.currentStep} of ${progress.total}: ${currentLabel})`;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
module.exports = {
|
|
273
|
+
read,
|
|
274
|
+
write,
|
|
275
|
+
init,
|
|
276
|
+
updateSubStep,
|
|
277
|
+
hashFile,
|
|
278
|
+
detectDrift,
|
|
279
|
+
statePath,
|
|
280
|
+
orderedSubSteps,
|
|
281
|
+
progressSummary,
|
|
282
|
+
renderProgressLine,
|
|
283
|
+
isCompleteStatus,
|
|
284
|
+
isActiveStatus
|
|
285
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "godpowers",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.7",
|
|
4
4
|
"description": "AI-powered development system: 106 slash commands and 39 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"
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"files": [
|
|
67
67
|
"bin/",
|
|
68
68
|
"skills/",
|
|
69
|
-
"agents/",
|
|
69
|
+
"agents/god-*.md",
|
|
70
70
|
"hooks/",
|
|
71
71
|
"templates/",
|
|
72
72
|
"references/",
|
package/skills/god-locate.md
CHANGED
|
@@ -40,6 +40,7 @@ GODPOWERS LOCATE
|
|
|
40
40
|
|
|
41
41
|
Project: <name> Mode: <A/B/C/E> Suite: <yes/no>
|
|
42
42
|
Lifecycle: <phase> Current: <tier>/<substep>
|
|
43
|
+
Progress: <pct>% (<complete> of <total> steps complete; current step <n> of <total>)
|
|
43
44
|
|
|
44
45
|
Last action: <name> by <actor> at <ts>
|
|
45
46
|
Last user instruction: <if available>
|
|
@@ -55,6 +56,14 @@ Recent events (last 5):
|
|
|
55
56
|
- <event>
|
|
56
57
|
- ...
|
|
57
58
|
|
|
59
|
+
What happened recently:
|
|
60
|
+
- <checkpoint action or event summary>
|
|
61
|
+
- <checkpoint action or event summary>
|
|
62
|
+
|
|
63
|
+
What happens next:
|
|
64
|
+
- <next command>
|
|
65
|
+
- <one-line reason>
|
|
66
|
+
|
|
58
67
|
Next suggested: <command>
|
|
59
68
|
Reason: <why>
|
|
60
69
|
|
|
@@ -73,8 +82,12 @@ Drift check:
|
|
|
73
82
|
3. If state.json is missing: project is broken; run `/god-doctor`.
|
|
74
83
|
4. Compute age of CHECKPOINT last-update; flag staleness if > 1 hour
|
|
75
84
|
or > 100 events since last checkpoint write.
|
|
76
|
-
5.
|
|
77
|
-
|
|
85
|
+
5. Compute progress from `lib/state.progressSummary(stateJson)` and show
|
|
86
|
+
percentage, complete count, total count, and current step number.
|
|
87
|
+
6. Summarize "what happened recently" from CHECKPOINT.md actions or recent
|
|
88
|
+
events, then summarize "what happens next" from routing.
|
|
89
|
+
7. Produce single-screen orientation summary.
|
|
90
|
+
8. Append `op:locate` event to events.jsonl.
|
|
78
91
|
|
|
79
92
|
## Difference from /god-status
|
|
80
93
|
|
package/skills/god-mode.md
CHANGED
|
@@ -164,6 +164,8 @@ The God Mode transcript is an operator console, not a prompt debugger.
|
|
|
164
164
|
|
|
165
165
|
Show:
|
|
166
166
|
- detected resume or project mode in plain language
|
|
167
|
+
- a compact "Next step" card before each visible phase or tier sub-step
|
|
168
|
+
- a compact "Step result" card after each visible phase or tier sub-step
|
|
167
169
|
- short progress updates for phases, commands, validations, and file edits
|
|
168
170
|
- concise validation summaries instead of full command noise when possible
|
|
169
171
|
- final changed paths, validation results, and completion or pause status
|
|
@@ -182,6 +184,39 @@ smallest user-facing question. For example, ask for
|
|
|
182
184
|
`STAGING_APP_URL=<deployed staging origin>` instead of exposing the full
|
|
183
185
|
Shipping Closure Protocol.
|
|
184
186
|
|
|
187
|
+
## Step Cards
|
|
188
|
+
|
|
189
|
+
Relay the orchestrator's step cards when present. If the orchestrator output is
|
|
190
|
+
missing them, synthesize them from disk state before continuing.
|
|
191
|
+
|
|
192
|
+
Before work starts:
|
|
193
|
+
|
|
194
|
+
```
|
|
195
|
+
Next step
|
|
196
|
+
Progress: <pct>% (<done> of <total> steps complete; current step <n> of <total>)
|
|
197
|
+
Tier: <tier-number> <tier-label>
|
|
198
|
+
Step: <sub-step-label>
|
|
199
|
+
Why this now: <one sentence>
|
|
200
|
+
What will happen:
|
|
201
|
+
1. <observable action>
|
|
202
|
+
2. <observable action>
|
|
203
|
+
Expected output: <artifact path or verification result>
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
After work completes or pauses:
|
|
207
|
+
|
|
208
|
+
```
|
|
209
|
+
Step result
|
|
210
|
+
Progress: <pct>% (<done> of <total> steps complete; current step <n> of <total>)
|
|
211
|
+
Tier: <tier-number> <tier-label>
|
|
212
|
+
Step: <sub-step-label>
|
|
213
|
+
Result: <done | blocked | failed | skipped | imported>
|
|
214
|
+
What happened:
|
|
215
|
+
1. <observable action completed>
|
|
216
|
+
2. <artifact or verification result>
|
|
217
|
+
Next: <next command or pause question>
|
|
218
|
+
```
|
|
219
|
+
|
|
185
220
|
## Pause Format (relay from orchestrator)
|
|
186
221
|
|
|
187
222
|
```
|
package/skills/god-next.md
CHANGED
|
@@ -147,6 +147,17 @@ Display: "Suggested next: /god-arch
|
|
|
147
147
|
Why: PRD is complete; architecture is the next gate"
|
|
148
148
|
```
|
|
149
149
|
|
|
150
|
+
When the suggestion is based on state.json, also show the immediate route:
|
|
151
|
+
|
|
152
|
+
```
|
|
153
|
+
Path ahead:
|
|
154
|
+
1. Current: <tier>/<substep> - <status>
|
|
155
|
+
2. Next: /god-X - <why>
|
|
156
|
+
3. Then: /god-Y - <next gate, if known>
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Keep the route to 3 lines unless the user asks for the full plan.
|
|
160
|
+
|
|
150
161
|
## Process for Mode 4 (intent-based)
|
|
151
162
|
|
|
152
163
|
```
|
|
@@ -280,10 +291,16 @@ recommending archaeology, reconstruction, arc-ready, pillars, or refactor work.
|
|
|
280
291
|
Godpowers Next
|
|
281
292
|
|
|
282
293
|
Current state: [where we are]
|
|
294
|
+
Progress: [pct]% ([done] of [total] steps complete; current step [n] of [total])
|
|
283
295
|
Suggested next: [/god-X]
|
|
284
296
|
|
|
285
297
|
Why: [one-line reason]
|
|
286
298
|
|
|
299
|
+
Path ahead:
|
|
300
|
+
1. Current: [tier/substep] - [status]
|
|
301
|
+
2. Next: [/god-X] - [why]
|
|
302
|
+
3. Then: [/god-Y or "recompute after gate"]
|
|
303
|
+
|
|
287
304
|
[If prereqs missing]:
|
|
288
305
|
Pre-flight: missing [prereq]
|
|
289
306
|
Auto-complete available: /god-Y
|
package/skills/god-status.md
CHANGED
|
@@ -33,6 +33,9 @@ Re-derive state from disk. Your memory is not authoritative. The file system is.
|
|
|
33
33
|
- If artifact exists but PROGRESS.md says "pending": FLAG as untracked work
|
|
34
34
|
6. Report:
|
|
35
35
|
- Current mode and scale
|
|
36
|
+
- Progress summary: percentage, completed step count, current step number
|
|
37
|
+
- What happened recently, using CHECKPOINT.md actions when available
|
|
38
|
+
- What happens next, using routing and disk state
|
|
36
39
|
- Per-tier status (with disk verification)
|
|
37
40
|
- Any inconsistencies between PROGRESS.md and disk
|
|
38
41
|
- Suggested next action
|
|
@@ -45,6 +48,17 @@ Godpowers Status
|
|
|
45
48
|
|
|
46
49
|
Mode: A (greenfield) Scale: medium
|
|
47
50
|
Started: 2026-05-09
|
|
51
|
+
Progress: 15% (2 of 13 steps complete; current step 3 of 13)
|
|
52
|
+
Current: Tier 1 Planning / Architecture
|
|
53
|
+
|
|
54
|
+
What happened recently:
|
|
55
|
+
1. PRD artifact verified on disk
|
|
56
|
+
2. Tier state refreshed from state.json
|
|
57
|
+
|
|
58
|
+
What happens next:
|
|
59
|
+
1. Run /god-arch
|
|
60
|
+
2. Verify architecture artifact
|
|
61
|
+
3. Recompute next gate with /god-next
|
|
48
62
|
|
|
49
63
|
Tier 1: Planning
|
|
50
64
|
+ PRD done .godpowers/prd/PRD.md (lint clean: 0 errors)
|
package/templates/PROGRESS.md
CHANGED
|
@@ -7,11 +7,33 @@ Mode: [A: greenfield | B: gap-fill | C: audit | D: multi-repo]
|
|
|
7
7
|
Scale: [trivial | small | medium | large | enterprise]
|
|
8
8
|
Started: [ISO 8601 timestamp]
|
|
9
9
|
Last updated: [ISO 8601 timestamp]
|
|
10
|
+
Progress: [0-100]% ([completed] of [total] steps complete; current step [n] of [total])
|
|
11
|
+
Current: [Tier N label] / [sub-step label]
|
|
10
12
|
|
|
11
13
|
## Project Description
|
|
12
14
|
|
|
13
15
|
[One paragraph from /god-init]
|
|
14
16
|
|
|
17
|
+
## Current Step
|
|
18
|
+
|
|
19
|
+
Why this now: [One sentence tied to disk state or the prior gate]
|
|
20
|
+
|
|
21
|
+
What will happen:
|
|
22
|
+
1. [Observable action]
|
|
23
|
+
2. [Observable action]
|
|
24
|
+
3. [Observable action, if needed]
|
|
25
|
+
|
|
26
|
+
Expected output: [Artifact path or verification result]
|
|
27
|
+
|
|
28
|
+
## Recent Step Results
|
|
29
|
+
|
|
30
|
+
What happened:
|
|
31
|
+
1. [Observable action completed]
|
|
32
|
+
2. [Artifact or state update]
|
|
33
|
+
3. [Verification result]
|
|
34
|
+
|
|
35
|
+
Next: [Next command or pause question]
|
|
36
|
+
|
|
15
37
|
## Tier Status
|
|
16
38
|
|
|
17
39
|
| Tier | Sub-step | Status | Artifact | Updated |
|