77 branches : [main]
88
99jobs :
10- # ── Detect changes ──────────────────────────────────────────
11- changes :
12- runs-on : ubuntu-latest
13- outputs :
14- openclaw : ${{ steps.filter.outputs.openclaw }}
15- hermes : ${{ steps.filter.outputs.hermes }}
16- steps :
17- - uses : actions/checkout@v4
18- - uses : dorny/paths-filter@v3
19- id : filter
20- with :
21- filters : |
22- openclaw:
23- - 'openclaw-plugin/**'
24- hermes:
25- - 'hermes-plugin/**'
26-
27- # ── TypeScript (openclaw-plugin) ──────────────────────────────
28- typecheck :
29- runs-on : ubuntu-latest
30- needs : changes
31- if : needs.changes.outputs.openclaw == 'true' || github.event_name == 'push'
32- steps :
33- - uses : actions/checkout@v4
34-
35- - uses : actions/setup-node@v4
36- with :
37- node-version : " 22"
38- cache : " npm"
39- cache-dependency-path : openclaw-plugin/package-lock.json
40-
41- - name : Install dependencies
42- working-directory : openclaw-plugin
43- run : npm ci
44-
45- - name : Type check
46- working-directory : openclaw-plugin
47- run : npx tsc --noEmit
48-
49- build :
50- runs-on : ubuntu-latest
51- needs : typecheck
52- if : needs.typecheck.result == 'success'
53- steps :
54- - uses : actions/checkout@v4
55-
56- - uses : actions/setup-node@v4
57- with :
58- node-version : " 22"
59- cache : " npm"
60- cache-dependency-path : openclaw-plugin/package-lock.json
61-
62- - name : Install dependencies
63- working-directory : openclaw-plugin
64- run : npm ci
65-
66- - name : Build (TypeScript)
67- working-directory : openclaw-plugin
68- run : npm run build
69-
70- - name : Build bundle (esbuild)
71- working-directory : openclaw-plugin
72- run : npm run build:bundle
73-
74- lint :
75- runs-on : ubuntu-latest
76- needs : typecheck
77- if : needs.typecheck.result == 'success'
78- steps :
79- - uses : actions/checkout@v4
80-
81- - uses : actions/setup-node@v4
82- with :
83- node-version : " 22"
84- cache : " npm"
85- cache-dependency-path : openclaw-plugin/package-lock.json
86-
87- - name : Install dependencies
88- working-directory : openclaw-plugin
89- run : npm ci
90-
91- - name : Lint
92- working-directory : openclaw-plugin
93- run : npx tsc --noEmit --pretty 2>&1 | grep "error TS" && exit 1 || echo "No errors"
94-
95- # ── Python (hermes-plugin) ────────────────────────────────────
10+ # ── Python (hermes-plugin + evolution) ─────────────────────
9611 python-test :
9712 runs-on : ubuntu-latest
98- needs : changes
99- if : needs.changes.outputs.hermes == 'true' || github.event_name == 'push'
100- defaults :
101- run :
102- working-directory : hermes-plugin
10313 steps :
10414 - uses : actions/checkout@v4
10515
10818 with :
10919 python-version : " 3.11"
11020
111- - name : Syntax check
21+ - name : Syntax check — hermes-plugin
11222 run : |
23+ cd hermes-plugin
11324 python -m py_compile services/workflow_service.py
11425 python -m py_compile services/scheduler.py
11526 python -m py_compile store/sqlite_store.py
@@ -122,8 +33,16 @@ jobs:
12233 python -m py_compile models.py
12334 python -m py_compile config.py
12435
36+ - name : Syntax check — evolution
37+ run : |
38+ python -m py_compile evolution/__init__.py
39+ python -m py_compile evolution/pattern_detector.py
40+ python -m py_compile evolution/skill_packager.py
41+ python -m py_compile evolution/quality_scorer.py
42+
12543 - name : Import check
12644 run : |
45+ cd hermes-plugin
12746 python -c "
12847 from store.sqlite_store import SQLiteStore
12948 from services.workflow_service import WorkflowService
@@ -137,63 +56,17 @@ jobs:
13756 print('All imports OK')
13857 "
13958
140- - name : Run integration tests
59+ - name : Import check — evolution
14160 run : |
142- cat > /tmp/test_soloflow.py << 'TESTEOF'
143- import sys, asyncio, tempfile
144- sys.path.insert(0, ".")
145- from pathlib import Path
146- from store.sqlite_store import SQLiteStore
147- from services.workflow_service import WorkflowService
148- from services.scheduler import Scheduler
149-
150- passed = failed = 0
151- def check(name, cond, detail=""):
152- global passed, failed
153- if cond: passed += 1; print(f" ✅ {name}")
154- else: failed += 1; print(f" ❌ {name} {detail}")
155-
156- async def main():
157- tmpdir = tempfile.mkdtemp()
158- store = SQLiteStore(Path(tmpdir) / "test.db")
159- store.initialize()
160- ws = WorkflowService(store)
161- ws.set_scheduler(Scheduler(store, ws))
162-
163- steps = [
164- {"id": "a", "name": "A", "description": "", "discipline": "quick", "prompt": "Do A"},
165- {"id": "b", "name": "B", "description": "", "discipline": "quick", "prompt": "Do B"},
166- {"id": "c", "name": "C", "description": "", "discipline": "quick", "prompt": "Do C"},
167- ]
168- wf = await ws.create_workflow("test", "Test", steps, [("a","b"),("b","c")])
169- check("created", wf["state"] == "draft")
170- check("3 steps", len(wf["steps"]) == 3)
171-
172- await ws.start_workflow(wf["id"])
173- ready = await ws.get_ready_steps(wf["id"])
174- check("a ready", "a" in ready)
175-
176- await ws.advance_step(wf["id"], "a", result="A done")
177- await ws.advance_step(wf["id"], "b", result="B done")
178- await ws.advance_step(wf["id"], "c", result="C done")
179- status = await ws.get_workflow_status(wf["id"])
180- check("completed", status["state"] == "completed")
181- check("progress 3/3", status["progress"]["completed"] == 3)
182-
183- wf2 = await ws.create_workflow("test2", "Test2",
184- [{"id": "x", "name": "X", "description": "", "discipline": "quick", "prompt": "X"}], [])
185- await ws.start_workflow(wf2["id"])
186- await ws.cancel_workflow(wf2["id"])
187- status2 = await ws.get_workflow_status(wf2["id"])
188- check("cancelled", status2["state"] == "cancelled")
189-
190- all_wfs = await ws.list_workflows()
191- check("2 workflows", len(all_wfs) == 2)
192- store.close()
61+ python -c "
62+ from evolution.pattern_detector import PatternDetector
63+ from evolution.skill_packager import SkillPackager
64+ from evolution.quality_scorer import QualityScorer
65+ print('Evolution imports OK')
66+ "
19367
194- print(f"\nResults: {passed} passed, {failed} failed")
195- return failed
68+ - name : Install pytest
69+ run : pip install pytest pytest-asyncio
19670
197- sys.exit(asyncio.run(main()))
198- TESTEOF
199- python /tmp/test_soloflow.py
71+ - name : Run tests
72+ run : python -m pytest tests/ -v --tb=short
0 commit comments