wao 0.40.0 → 0.40.1
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/cjs/create.js +32 -27
- package/cjs/workspace/.claude/agents/builder.md +4 -2
- package/cjs/workspace/.claude/skills/build/SKILL.md +34 -12
- package/cjs/workspace/.claude/skills/build-aos/SKILL.md +10 -1
- package/cjs/workspace/.claude/skills/build-device/SKILL.md +37 -23
- package/cjs/workspace/.claude/skills/build-frontend/SKILL.md +17 -14
- package/cjs/workspace/.claude/skills/build-module/SKILL.md +10 -1
- package/cjs/workspace/.claude/skills/plan/SKILL.md +12 -4
- package/cjs/workspace/.claude/skills/readme/SKILL.md +151 -45
- package/cjs/workspace/.claude/skills/report/SKILL.md +2 -1
- package/cjs/workspace/dashboard/index.html +154 -3
- package/cjs/workspace/dashboard/public/favicon.ico +0 -0
- package/cjs/workspace/dashboard/public/favicon.png +0 -0
- package/cjs/workspace/dashboard/server.js +93 -12
- package/cjs/workspace/dashboard/src/App.jsx +2297 -372
- package/cjs/workspace/package.json +1 -1
- package/esm/create.js +3 -0
- package/esm/workspace/.claude/agents/builder.md +4 -2
- package/esm/workspace/.claude/skills/build/SKILL.md +34 -12
- package/esm/workspace/.claude/skills/build-aos/SKILL.md +10 -1
- package/esm/workspace/.claude/skills/build-device/SKILL.md +37 -23
- package/esm/workspace/.claude/skills/build-frontend/SKILL.md +17 -14
- package/esm/workspace/.claude/skills/build-module/SKILL.md +10 -1
- package/esm/workspace/.claude/skills/plan/SKILL.md +12 -4
- package/esm/workspace/.claude/skills/readme/SKILL.md +151 -45
- package/esm/workspace/.claude/skills/report/SKILL.md +2 -1
- package/esm/workspace/dashboard/index.html +154 -3
- package/esm/workspace/dashboard/public/favicon.ico +0 -0
- package/esm/workspace/dashboard/public/favicon.png +0 -0
- package/esm/workspace/dashboard/server.js +93 -12
- package/esm/workspace/dashboard/src/App.jsx +2297 -372
- package/esm/workspace/package.json +1 -1
- package/package.json +1 -1
package/cjs/create.js
CHANGED
|
@@ -478,16 +478,21 @@ var main = /*#__PURE__*/function () {
|
|
|
478
478
|
t.fail("Failed to install dependencies");
|
|
479
479
|
return _context5.a(2);
|
|
480
480
|
case 15:
|
|
481
|
+
t.sub("root dependencies installed");
|
|
482
|
+
_context5.n = 16;
|
|
483
|
+
return exec("cd \"".concat(appdir, "/dashboard\" && npm install"));
|
|
484
|
+
case 16:
|
|
485
|
+
t.sub("dashboard dependencies installed");
|
|
481
486
|
t.done();
|
|
482
487
|
hbWarnings = [];
|
|
483
488
|
if (!(hbMode !== "skip")) {
|
|
484
|
-
_context5.n =
|
|
489
|
+
_context5.n = 27;
|
|
485
490
|
break;
|
|
486
491
|
}
|
|
487
492
|
t.step("Detecting HyperBEAM environment");
|
|
488
|
-
_context5.n =
|
|
493
|
+
_context5.n = 17;
|
|
489
494
|
return detectHBEnv();
|
|
490
|
-
case
|
|
495
|
+
case 17:
|
|
491
496
|
_yield$detectHBEnv = _context5.v;
|
|
492
497
|
deps = _yield$detectHBEnv.deps;
|
|
493
498
|
missing = _yield$detectHBEnv.missing;
|
|
@@ -522,24 +527,24 @@ var main = /*#__PURE__*/function () {
|
|
|
522
527
|
t.sub(".env.hyperbeam \u2192 CWD=".concat(hbCwd));
|
|
523
528
|
t.done();
|
|
524
529
|
if (!(hbMode === "clone")) {
|
|
525
|
-
_context5.n =
|
|
530
|
+
_context5.n = 24;
|
|
526
531
|
break;
|
|
527
532
|
}
|
|
528
533
|
t.step("Cloning HyperBEAM");
|
|
529
534
|
t.sub("tag: ".concat(HB_TAG));
|
|
530
|
-
_context5.n =
|
|
535
|
+
_context5.n = 18;
|
|
531
536
|
return exec("cd \"".concat(appdir, "\" && git clone --depth 1 --branch ").concat(HB_TAG, " ").concat(HB_REPO, " HyperBEAM"), {
|
|
532
537
|
maxBuffer: 50 * 1024 * 1024,
|
|
533
538
|
timeout: 600000
|
|
534
539
|
});
|
|
535
|
-
case
|
|
540
|
+
case 18:
|
|
536
541
|
t.done();
|
|
537
542
|
if (!(deps.erl && deps.rebar3 && missing.length === 0)) {
|
|
538
|
-
_context5.n =
|
|
543
|
+
_context5.n = 23;
|
|
539
544
|
break;
|
|
540
545
|
}
|
|
541
546
|
t.step("Compiling HyperBEAM (with genesis-wasm)");
|
|
542
|
-
_context5.p =
|
|
547
|
+
_context5.p = 19;
|
|
543
548
|
envParts = [];
|
|
544
549
|
if (deps.gcc) {
|
|
545
550
|
envParts.push("CC=gcc-".concat(deps.gcc), "CXX=g++-".concat(deps.gcc));
|
|
@@ -548,46 +553,46 @@ var main = /*#__PURE__*/function () {
|
|
|
548
553
|
envParts.push("CMAKE_POLICY_VERSION_MINIMUM=3.5");
|
|
549
554
|
}
|
|
550
555
|
envPrefix = envParts.join(" ");
|
|
551
|
-
_context5.n =
|
|
556
|
+
_context5.n = 20;
|
|
552
557
|
return exec("cd \"".concat(appdir, "/HyperBEAM\" && ").concat(envPrefix, " rebar3 as genesis_wasm compile"), {
|
|
553
558
|
maxBuffer: 50 * 1024 * 1024,
|
|
554
559
|
timeout: 600000
|
|
555
560
|
});
|
|
556
|
-
case
|
|
561
|
+
case 20:
|
|
557
562
|
t.sub("genesis-wasm device compiled");
|
|
558
563
|
t.done();
|
|
559
|
-
_context5.n =
|
|
564
|
+
_context5.n = 22;
|
|
560
565
|
break;
|
|
561
|
-
case
|
|
562
|
-
_context5.p =
|
|
566
|
+
case 21:
|
|
567
|
+
_context5.p = 21;
|
|
563
568
|
_t4 = _context5.v;
|
|
564
569
|
t.fail("Compile failed — check .env.hyperbeam and run manually");
|
|
565
|
-
case 21:
|
|
566
|
-
_context5.n = 23;
|
|
567
|
-
break;
|
|
568
570
|
case 22:
|
|
571
|
+
_context5.n = 24;
|
|
572
|
+
break;
|
|
573
|
+
case 23:
|
|
569
574
|
if (missing.length > 0) {
|
|
570
575
|
t.step("Skipping compilation (missing dependencies)");
|
|
571
576
|
t.sub("Run 'cd HyperBEAM && rebar3 compile' after installing dependencies");
|
|
572
577
|
t.done();
|
|
573
578
|
}
|
|
574
|
-
case
|
|
579
|
+
case 24:
|
|
575
580
|
// Generate wallet in HyperBEAM directory
|
|
576
581
|
hbWalletDir = (0, _path.resolve)(appdir, hbCwd);
|
|
577
582
|
t.step("Generating HyperBEAM wallet");
|
|
578
583
|
hbArweave = _arweave["default"].init();
|
|
579
|
-
_context5.n =
|
|
584
|
+
_context5.n = 25;
|
|
580
585
|
return hbArweave.wallets.generate();
|
|
581
|
-
case
|
|
586
|
+
case 25:
|
|
582
587
|
hbJwk = _context5.v;
|
|
583
|
-
_context5.n =
|
|
588
|
+
_context5.n = 26;
|
|
584
589
|
return hbArweave.wallets.jwkToAddress(hbJwk);
|
|
585
|
-
case
|
|
590
|
+
case 26:
|
|
586
591
|
hbAddr = _context5.v;
|
|
587
592
|
(0, _fs.writeFileSync)((0, _path.resolve)(hbWalletDir, ".wallet.json"), JSON.stringify(hbJwk));
|
|
588
593
|
t.sub("address: ".concat(hbAddr));
|
|
589
594
|
t.done();
|
|
590
|
-
case
|
|
595
|
+
case 27:
|
|
591
596
|
if (withFrontend) {
|
|
592
597
|
t.step("Setting up frontend");
|
|
593
598
|
t.sub("Vite + React + wao/web");
|
|
@@ -634,16 +639,16 @@ var main = /*#__PURE__*/function () {
|
|
|
634
639
|
console.log(" ".concat(dim("$"), " yarn deploy src/counter.lua --wallet .wallet.json"));
|
|
635
640
|
console.log();
|
|
636
641
|
});
|
|
637
|
-
_context5.n =
|
|
642
|
+
_context5.n = 29;
|
|
638
643
|
break;
|
|
639
|
-
case
|
|
640
|
-
_context5.p =
|
|
644
|
+
case 28:
|
|
645
|
+
_context5.p = 28;
|
|
641
646
|
_t5 = _context5.v;
|
|
642
647
|
t.fail(_t5.message);
|
|
643
|
-
case
|
|
648
|
+
case 29:
|
|
644
649
|
return _context5.a(2);
|
|
645
650
|
}
|
|
646
|
-
}, _callee5, null, [[
|
|
651
|
+
}, _callee5, null, [[19, 21], [7, 28]]);
|
|
647
652
|
}));
|
|
648
653
|
return function main() {
|
|
649
654
|
return _ref5.apply(this, arguments);
|
|
@@ -35,8 +35,10 @@ Read these before building:
|
|
|
35
35
|
- **aos**: Write AOS scripts in `src/` with input validation
|
|
36
36
|
- **aos-test**: Write in-memory tests in `test/`, iterate until `yarn test` passes
|
|
37
37
|
- **aos-integration**: Write HyperBEAM tests, iterate until they pass
|
|
38
|
-
- **
|
|
39
|
-
- **
|
|
38
|
+
- **module-lua**: Write standalone Lua module in `custom-lua/`, no AOS framework
|
|
39
|
+
- **module-wasm**: Write Rust WASM64 module in `custom-wasm/`, `#![no_std]`
|
|
40
|
+
- **module-test**: Write HyperBEAM integration tests for custom modules
|
|
41
|
+
- **device**: Write Erlang device + inline eunit tests in same `.erl` file, compile with `rebar3 as genesis_wasm compile`, iterate until `rebar3 eunit` passes
|
|
40
42
|
- **device-integration**: Write WAO SDK integration tests against running HyperBEAM
|
|
41
43
|
- **frontend**: Write React components with `wao/web`
|
|
42
44
|
- **frontend-test**: Write vitest tests, iterate until they pass
|
|
@@ -31,7 +31,20 @@ Full build orchestrator. Sequences through plan → build → test → validate
|
|
|
31
31
|
|
|
32
32
|
### 1. Check for existing plan (resume support)
|
|
33
33
|
|
|
34
|
-
Read `plan.md` and `tasks.json` at the project root. If both exist and tasks.json has `"current_step"`, resume
|
|
34
|
+
Read `plan.md` and `tasks.json` at the project root. If both exist and tasks.json has `"current_step"`, resume:
|
|
35
|
+
|
|
36
|
+
1. Find the first task with `"status": "in_progress"` — resume debugging that task immediately.
|
|
37
|
+
2. If no `in_progress` task, find the first task with `"status": "pending"` — start it.
|
|
38
|
+
3. If ALL tasks are `"done"`, **re-verify every test task** by running its tests:
|
|
39
|
+
- `aos-test` → `yarn test <files>`
|
|
40
|
+
- `aos-integration` → `yarn test <files>`
|
|
41
|
+
- `device` → `cd $HB_DIR && rebar3 eunit --module=<module>`
|
|
42
|
+
- `device-integration` → `yarn test <files>`
|
|
43
|
+
- `frontend-test` → `cd frontend && npm run test:unit`
|
|
44
|
+
- `frontend-integration` → `cd frontend && npm run test:e2e`
|
|
45
|
+
- `validate` → run all validation gates
|
|
46
|
+
|
|
47
|
+
If any test task fails, set that task back to `"in_progress"` in tasks.json and resume debugging it. Do NOT skip over failing tests just because the task was previously marked done.
|
|
35
48
|
|
|
36
49
|
If no plan exists, proceed to step 2.
|
|
37
50
|
|
|
@@ -75,7 +88,7 @@ Before starting the build loop, check which tracks are selected and verify their
|
|
|
75
88
|
grep '^CWD=' .env.hyperbeam 2>/dev/null | cut -d= -f2-
|
|
76
89
|
```
|
|
77
90
|
|
|
78
|
-
If the plan includes `device`, `device-
|
|
91
|
+
If the plan includes `device`, `device-integration`, `aos-integration`, `module-lua`, `module-wasm`, or `module-test` tasks, verify:
|
|
79
92
|
|
|
80
93
|
1. `.env.hyperbeam` exists and has a `CWD` value
|
|
81
94
|
2. The `CWD` path points to a valid HyperBEAM directory (`$CWD/src` exists)
|
|
@@ -108,8 +121,7 @@ b. Read the skill file for this task's type and follow its instructions. The map
|
|
|
108
121
|
| `module-lua` | `.claude/skills/build-module/SKILL.md` |
|
|
109
122
|
| `module-wasm` | `.claude/skills/build-module/SKILL.md` |
|
|
110
123
|
| `module-test` | `.claude/skills/build-module/SKILL.md` |
|
|
111
|
-
| `device` | `.claude/skills/build-device/SKILL.md` |
|
|
112
|
-
| `device-test` | `.claude/skills/build-device/SKILL.md` |
|
|
124
|
+
| `device` | `.claude/skills/build-device/SKILL.md` (eunit tests are inline — same file) |
|
|
113
125
|
| `device-integration` | `.claude/skills/test-device/SKILL.md` |
|
|
114
126
|
| `frontend` | `.claude/skills/build-frontend/SKILL.md` |
|
|
115
127
|
| `frontend-test` | `.claude/skills/build-frontend/SKILL.md` |
|
|
@@ -125,12 +137,21 @@ d. After completing, verify the task's `done_when` criteria are met:
|
|
|
125
137
|
|
|
126
138
|
e. If the criteria are met, update the task status to `"done"` in `tasks.json`.
|
|
127
139
|
|
|
128
|
-
f. If
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
140
|
+
f. **If tests fail, keep debugging.** Do not stop. On each iteration:
|
|
141
|
+
1. Read the full error output — stack traces, assertion messages, log lines
|
|
142
|
+
2. Identify the root cause (wrong logic, missing handler, bad import, timing issue, etc.)
|
|
143
|
+
3. Fix the code — not the test, unless the test itself has a bug
|
|
144
|
+
4. Re-run the failing test file specifically (faster feedback than full suite)
|
|
145
|
+
5. If the same error persists after 3 different fix attempts, step back:
|
|
146
|
+
- Re-read the relevant docs (AOS patterns, HyperBEAM device protocol, etc.)
|
|
147
|
+
- Check if the plan itself has a wrong assumption
|
|
148
|
+
- Try a completely different approach
|
|
149
|
+
6. Continue iterating until all tests pass — there is no retry limit
|
|
150
|
+
|
|
151
|
+
g. Only escalate to the user if:
|
|
152
|
+
- The failure is environmental (port conflict, missing binary, permissions)
|
|
153
|
+
- The test requires user input (wallet, external service URL)
|
|
154
|
+
- You've tried 10+ iterations with no progress on the same error
|
|
134
155
|
|
|
135
156
|
h. Move to the next task.
|
|
136
157
|
|
|
@@ -161,7 +182,8 @@ Overall: PASS / FAIL
|
|
|
161
182
|
|
|
162
183
|
## Failure handling
|
|
163
184
|
|
|
164
|
-
-
|
|
185
|
+
- **Test failures are expected.** The build loop is: write code → run tests → read failures → fix → re-run. This is the core loop — never skip it, never give up early.
|
|
186
|
+
- If a skill exits with test failures, read the full output, diagnose the root cause, fix the code (not the test), and re-run. Keep iterating until 100% pass.
|
|
165
187
|
- If a skill cannot be dispatched (unknown type), skip and warn.
|
|
166
188
|
- If the user interrupts, save current state to tasks.json so the next session can resume.
|
|
167
189
|
|
|
@@ -180,7 +202,7 @@ Never force a task to `done` status with failing tests. The TaskCompleted hook w
|
|
|
180
202
|
|
|
181
203
|
### Build stalls on a single task
|
|
182
204
|
- Check if it's a test failure loop — read the last test output
|
|
183
|
-
- If the same error
|
|
205
|
+
- If the same error persists after 3 different fix attempts, step back and reconsider — the plan may have a wrong assumption
|
|
184
206
|
- Run `/debug` to diagnose port/process/WASM issues
|
|
185
207
|
|
|
186
208
|
### Resume doesn't pick up the right task
|
|
@@ -117,4 +117,13 @@ For each test-fix cycle:
|
|
|
117
117
|
3. Classify: is the bug in source code or test code?
|
|
118
118
|
4. Fix ONE issue per iteration (don't change multiple things at once)
|
|
119
119
|
5. Re-run only the failing test first, then full suite
|
|
120
|
-
6. If the same
|
|
120
|
+
6. If the same error persists after 3 different fix attempts, step back:
|
|
121
|
+
- Re-read the relevant docs (AOS patterns, Lua conventions, etc.)
|
|
122
|
+
- Check if the plan itself has a wrong assumption
|
|
123
|
+
- Try a completely different approach
|
|
124
|
+
7. Continue iterating until all tests pass — there is no retry limit
|
|
125
|
+
|
|
126
|
+
Only escalate to the user if:
|
|
127
|
+
- The failure is environmental (missing binary, permissions, port conflict)
|
|
128
|
+
- The test requires user input (wallet, external service URL)
|
|
129
|
+
- You've tried 10+ iterations with no progress on the same error
|
|
@@ -59,7 +59,7 @@ Do NOT mark the task as done if any prerequisite fails. Set the task status to `
|
|
|
59
59
|
|
|
60
60
|
3. Read `docs/hyperbeam-dev.md` for the device protocol (arity/3 functions, state management, auth patterns).
|
|
61
61
|
|
|
62
|
-
4.
|
|
62
|
+
4. Write the Erlang device with **inline eunit tests** (HyperBEAM convention — device and tests live in the same file):
|
|
63
63
|
|
|
64
64
|
Write `$HB_DIR/src/dev_{name}.erl`:
|
|
65
65
|
|
|
@@ -67,6 +67,9 @@ Do NOT mark the task as done if any prerequisite fails. Set the task status to `
|
|
|
67
67
|
-module(dev_{name}).
|
|
68
68
|
-export([info/3, init/3, compute/3]).
|
|
69
69
|
-include("include/hb.hrl").
|
|
70
|
+
-ifdef(TEST).
|
|
71
|
+
-include_lib("eunit/include/eunit.hrl").
|
|
72
|
+
-endif.
|
|
70
73
|
|
|
71
74
|
%% Exports: list available keys
|
|
72
75
|
info(_Msg1, _Msg2, Opts) ->
|
|
@@ -88,35 +91,37 @@ Do NOT mark the task as done if any prerequisite fails. Set the task status to `
|
|
|
88
91
|
{ok, Msg1};
|
|
89
92
|
handle_action(_, Msg1, _Msg2, _Opts) ->
|
|
90
93
|
{ok, hb_maps:put(<<"Error">>, <<"Unknown action">>, Msg1)}.
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
Key patterns:
|
|
94
|
-
- Use `hb_maps` for state (not plain maps)
|
|
95
|
-
- Use `hb_private` for secrets
|
|
96
|
-
- Use `ar_wallet` for auth/signing
|
|
97
|
-
- Route actions via `hb_ao:get(<<"Action">>, Msg2, Opts)`
|
|
98
|
-
- Return `{ok, UpdatedMsg}` or `{error, Reason}`
|
|
99
|
-
|
|
100
|
-
5. **If the task type is `device-test`** — write eunit tests:
|
|
101
|
-
|
|
102
|
-
Write `$HB_DIR/test/dev_{name}_tests.erl`:
|
|
103
94
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
95
|
+
%%%===================================================================
|
|
96
|
+
%%% EUnit Tests (inline — HyperBEAM convention)
|
|
97
|
+
%%%===================================================================
|
|
98
|
+
-ifdef(TEST).
|
|
107
99
|
|
|
108
100
|
info_test() ->
|
|
109
|
-
{ok, Info} =
|
|
101
|
+
{ok, Info} = info(#{}, #{}, #{}),
|
|
110
102
|
?assertMatch(#{<<"exports">> := _}, Info).
|
|
111
103
|
|
|
112
104
|
compute_test() ->
|
|
113
|
-
{ok, State} =
|
|
105
|
+
{ok, State} = init(#{}, #{}, #{}),
|
|
114
106
|
Msg = #{<<"Action">> => <<"MyAction">>},
|
|
115
|
-
{ok, Result} =
|
|
107
|
+
{ok, Result} = compute(State, Msg, #{}),
|
|
116
108
|
?assertMatch(#{}, Result).
|
|
109
|
+
|
|
110
|
+
-endif.
|
|
117
111
|
```
|
|
118
112
|
|
|
119
|
-
|
|
113
|
+
Key patterns:
|
|
114
|
+
- **Device + tests in same file** — use `-ifdef(TEST).` / `-endif.` guards
|
|
115
|
+
- Tests call local functions directly (no `module:function` prefix needed)
|
|
116
|
+
- Use `hb_maps` for state (not plain maps)
|
|
117
|
+
- Use `hb_private` for secrets
|
|
118
|
+
- Use `ar_wallet` for auth/signing
|
|
119
|
+
- Route actions via `hb_ao:get(<<"Action">>, Msg2, Opts)`
|
|
120
|
+
- Return `{ok, UpdatedMsg}` or `{error, Reason}`
|
|
121
|
+
|
|
122
|
+
**Do NOT create separate test files** in `$HB_DIR/test/`. All eunit tests go inline in the device source file.
|
|
123
|
+
|
|
124
|
+
5. Compile (use the `$HB_DIR` path):
|
|
120
125
|
|
|
121
126
|
```bash
|
|
122
127
|
cd $HB_DIR && rebar3 as genesis_wasm compile
|
|
@@ -130,10 +135,10 @@ Do NOT mark the task as done if any prerequisite fails. Set the task status to `
|
|
|
130
135
|
|
|
131
136
|
If the beam file is missing, compilation failed silently. Read the full output and fix.
|
|
132
137
|
|
|
133
|
-
|
|
138
|
+
6. Run eunit tests (note: test the device module directly, not a separate test module):
|
|
134
139
|
|
|
135
140
|
```bash
|
|
136
|
-
cd $HB_DIR && rebar3 eunit --module=dev_{name}
|
|
141
|
+
cd $HB_DIR && rebar3 eunit --module=dev_{name}
|
|
137
142
|
```
|
|
138
143
|
|
|
139
144
|
8. If compilation errors or test failures:
|
|
@@ -175,4 +180,13 @@ For each test-fix cycle:
|
|
|
175
180
|
3. Classify: is the bug in source code or test code?
|
|
176
181
|
4. Fix ONE issue per iteration (don't change multiple things at once)
|
|
177
182
|
5. Re-run only the failing test first, then full suite
|
|
178
|
-
6. If the same
|
|
183
|
+
6. If the same error persists after 3 different fix attempts, step back:
|
|
184
|
+
- Re-read the relevant docs (HyperBEAM device protocol, Erlang patterns, etc.)
|
|
185
|
+
- Check if the plan itself has a wrong assumption
|
|
186
|
+
- Try a completely different approach
|
|
187
|
+
7. Continue iterating until all tests pass — there is no retry limit
|
|
188
|
+
|
|
189
|
+
Only escalate to the user if:
|
|
190
|
+
- The failure is environmental (rebar3 missing, Erlang version, port conflict)
|
|
191
|
+
- The test requires user input (wallet, external service URL)
|
|
192
|
+
- You've tried 10+ iterations with no progress on the same error
|
|
@@ -112,20 +112,23 @@ cd frontend && npx playwright --version 2>/dev/null || echo "Playwright not inst
|
|
|
112
112
|
cd frontend && npm run test:unit
|
|
113
113
|
```
|
|
114
114
|
|
|
115
|
-
7. If
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
115
|
+
7. **If tests fail, keep debugging.** Do not stop. On each iteration:
|
|
116
|
+
1. Read the full error output — stack traces, assertion messages, log lines
|
|
117
|
+
2. Identify the FIRST failing test (fix failures in order)
|
|
118
|
+
3. Classify: is the bug in component code or test code?
|
|
119
|
+
4. Fix ONE issue per iteration (don't change multiple things at once)
|
|
120
|
+
5. Re-run the failing test file specifically (faster feedback than full suite)
|
|
121
|
+
6. If the same error persists after 3 different fix attempts, step back:
|
|
122
|
+
- Re-read the relevant docs (`wao/web` patterns, React testing library, vitest mocking)
|
|
123
|
+
- Check if the plan itself has a wrong assumption
|
|
124
|
+
- Try a completely different approach
|
|
125
|
+
7. Continue iterating until all tests pass — there is no retry limit
|
|
126
|
+
|
|
127
|
+
Only escalate to the user if:
|
|
128
|
+
- The failure is environmental (missing dependency, port conflict, permissions)
|
|
129
|
+
- The test requires user input (wallet, external service URL)
|
|
130
|
+
- You've tried 10+ iterations with no progress on the same error
|
|
120
131
|
|
|
121
132
|
8. Update the task status to `"done"` in `tasks.json`.
|
|
122
133
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
For each test-fix cycle:
|
|
126
|
-
1. Run tests and capture FULL output
|
|
127
|
-
2. Identify the FIRST failing test (fix failures in order)
|
|
128
|
-
3. Classify: is the bug in source code or test code?
|
|
129
|
-
4. Fix ONE issue per iteration (don't change multiple things at once)
|
|
130
|
-
5. Re-run only the failing test first, then full suite
|
|
131
|
-
6. If the same test fails 3 times with the same error, stop and reconsider the approach — the plan may need updating
|
|
134
|
+
**IMPORTANT**: Only mark done if all tests pass 100%.
|
|
@@ -244,7 +244,16 @@ For each test-fix cycle:
|
|
|
244
244
|
3. Classify: is the bug in module code or test code?
|
|
245
245
|
4. Fix ONE issue per iteration (don't change multiple things at once)
|
|
246
246
|
5. Re-run only the failing test first, then full suite
|
|
247
|
-
6. If the same
|
|
247
|
+
6. If the same error persists after 3 different fix attempts, step back:
|
|
248
|
+
- Re-read the relevant docs (custom module patterns, WASM64/Lua conventions, etc.)
|
|
249
|
+
- Check if the plan itself has a wrong assumption
|
|
250
|
+
- Try a completely different approach
|
|
251
|
+
7. Continue iterating until all tests pass — there is no retry limit
|
|
252
|
+
|
|
253
|
+
Only escalate to the user if:
|
|
254
|
+
- The failure is environmental (cargo missing, WASM build tools, port conflict)
|
|
255
|
+
- The test requires user input (wallet, external service URL)
|
|
256
|
+
- You've tried 10+ iterations with no progress on the same error
|
|
248
257
|
|
|
249
258
|
## Troubleshooting
|
|
250
259
|
|
|
@@ -119,8 +119,7 @@ Plan a feature before building it. The plan and tasks are written to files so an
|
|
|
119
119
|
| `module-lua` | `/build-module` |
|
|
120
120
|
| `module-wasm` | `/build-module` |
|
|
121
121
|
| `module-test` | `/build-module` |
|
|
122
|
-
| `device` | `/build-device` |
|
|
123
|
-
| `device-test` | `/build-device` |
|
|
122
|
+
| `device` | `/build-device` (eunit tests inline — same file) |
|
|
124
123
|
| `device-integration` | `/test-device` |
|
|
125
124
|
| `frontend` | `/build-frontend` |
|
|
126
125
|
| `frontend-test` | `/build-frontend` |
|
|
@@ -134,8 +133,8 @@ Plan a feature before building it. The plan and tasks are written to files so an
|
|
|
134
133
|
- Tests: `{ "type": "module-test", "skill": "/build-module", "files": ["test/{name}-module.test.js"], "done_when": "yarn test test/{name}-module.test.js — all pass" }`
|
|
135
134
|
|
|
136
135
|
**Device tasks** (if building Erlang devices) — add `"device"` to `tracks` array and add these to `tasks`:
|
|
137
|
-
- `{ "type": "device", "skill": "/build-device", "files": ["HyperBEAM/src/dev_{name}.erl"], "done_when": "rebar3
|
|
138
|
-
-
|
|
136
|
+
- `{ "type": "device", "skill": "/build-device", "files": ["HyperBEAM/src/dev_{name}.erl"], "done_when": "rebar3 compile + eunit — all pass" }`
|
|
137
|
+
- **HyperBEAM convention**: device source and eunit tests live in the same `.erl` file using `-ifdef(TEST).` guards. Do NOT create separate test files in `HyperBEAM/test/`.
|
|
139
138
|
- `{ "type": "device-integration", "skill": "/test-device", "files": ["test/{name}-device.test.js"], "done_when": "yarn test test/{name}-device.test.js — all pass" }`
|
|
140
139
|
|
|
141
140
|
**Frontend tasks** (if building frontend) — add `"frontend"` to `tracks` array and add these to `tasks`:
|
|
@@ -149,6 +148,15 @@ Plan a feature before building it. The plan and tasks are written to files so an
|
|
|
149
148
|
**Final validation** — always the last task:
|
|
150
149
|
- `{ "type": "validate", "skill": "/validate", "done_when": "overall PASS" }`
|
|
151
150
|
|
|
151
|
+
### IMPORTANT: Replace all placeholders with actual names
|
|
152
|
+
|
|
153
|
+
The templates above use `{name}` as a placeholder. When writing `tasks.json`, replace ALL placeholders with the actual file names from the plan. For example:
|
|
154
|
+
- `"files": ["src/{name}.lua"]` → `"files": ["src/token.lua", "src/registry.lua"]`
|
|
155
|
+
- `"files": ["test/{name}.test.js"]` → `"files": ["test/token.test.js", "test/registry.test.js"]`
|
|
156
|
+
- `"done_when": "yarn test test/{name}.test.js — all pass"` → `"done_when": "yarn test test/token.test.js test/registry.test.js — all pass"`
|
|
157
|
+
|
|
158
|
+
The `files` array must list every actual file the task will create. The `done_when` must reference the actual test commands. Never leave `{name}` as a literal string in the output.
|
|
159
|
+
|
|
152
160
|
### Task ordering rules
|
|
153
161
|
|
|
154
162
|
The build order matters. Within each component:
|