waker-ai 1.1.2__tar.gz
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.
- waker_ai-1.1.2/LICENSE +21 -0
- waker_ai-1.1.2/PKG-INFO +301 -0
- waker_ai-1.1.2/README.md +265 -0
- waker_ai-1.1.2/pyproject.toml +68 -0
- waker_ai-1.1.2/setup.cfg +4 -0
- waker_ai-1.1.2/src/waker/__init__.py +4 -0
- waker_ai-1.1.2/src/waker/__main__.py +3 -0
- waker_ai-1.1.2/src/waker/adapters/__init__.py +13 -0
- waker_ai-1.1.2/src/waker/adapters/base.py +33 -0
- waker_ai-1.1.2/src/waker/adapters/claude.py +88 -0
- waker_ai-1.1.2/src/waker/adapters/generic.py +70 -0
- waker_ai-1.1.2/src/waker/adapters/opencode.py +102 -0
- waker_ai-1.1.2/src/waker/adapters/pty.py +205 -0
- waker_ai-1.1.2/src/waker/blind_runner.py +142 -0
- waker_ai-1.1.2/src/waker/claude_events.py +82 -0
- waker_ai-1.1.2/src/waker/cli.py +698 -0
- waker_ai-1.1.2/src/waker/daemon.py +262 -0
- waker_ai-1.1.2/src/waker/dashboard.py +234 -0
- waker_ai-1.1.2/src/waker/detect.py +74 -0
- waker_ai-1.1.2/src/waker/detector.py +81 -0
- waker_ai-1.1.2/src/waker/doctor.py +200 -0
- waker_ai-1.1.2/src/waker/engine.py +886 -0
- waker_ai-1.1.2/src/waker/evidence.py +345 -0
- waker_ai-1.1.2/src/waker/globs.py +100 -0
- waker_ai-1.1.2/src/waker/injector.py +120 -0
- waker_ai-1.1.2/src/waker/llm_plan.py +149 -0
- waker_ai-1.1.2/src/waker/models.py +271 -0
- waker_ai-1.1.2/src/waker/opencode_events.py +149 -0
- waker_ai-1.1.2/src/waker/planner.py +538 -0
- waker_ai-1.1.2/src/waker/process.py +200 -0
- waker_ai-1.1.2/src/waker/scheduler.py +52 -0
- waker_ai-1.1.2/src/waker/skill_install.py +50 -0
- waker_ai-1.1.2/src/waker/skill_templates/claude/SKILL.md +58 -0
- waker_ai-1.1.2/src/waker/skill_templates/gemini/SKILL.md +58 -0
- waker_ai-1.1.2/src/waker/skill_templates/generic/AGENTS.md +12 -0
- waker_ai-1.1.2/src/waker/skill_templates/opencode/SKILL.md +84 -0
- waker_ai-1.1.2/src/waker/state.py +333 -0
- waker_ai-1.1.2/src/waker/ui.py +185 -0
- waker_ai-1.1.2/src/waker/vault.py +216 -0
- waker_ai-1.1.2/src/waker/vault_runner.py +189 -0
- waker_ai-1.1.2/src/waker/vault_validate.py +162 -0
- waker_ai-1.1.2/src/waker/winjob.py +136 -0
- waker_ai-1.1.2/src/waker/winproc.py +55 -0
- waker_ai-1.1.2/src/waker_ai.egg-info/PKG-INFO +301 -0
- waker_ai-1.1.2/src/waker_ai.egg-info/SOURCES.txt +77 -0
- waker_ai-1.1.2/src/waker_ai.egg-info/dependency_links.txt +1 -0
- waker_ai-1.1.2/src/waker_ai.egg-info/entry_points.txt +2 -0
- waker_ai-1.1.2/src/waker_ai.egg-info/requires.txt +13 -0
- waker_ai-1.1.2/src/waker_ai.egg-info/top_level.txt +1 -0
- waker_ai-1.1.2/tests/test_blind_acceptance.py +178 -0
- waker_ai-1.1.2/tests/test_blind_runner.py +146 -0
- waker_ai-1.1.2/tests/test_claude_adapter.py +58 -0
- waker_ai-1.1.2/tests/test_cli.py +285 -0
- waker_ai-1.1.2/tests/test_cost_guard.py +80 -0
- waker_ai-1.1.2/tests/test_daemon.py +117 -0
- waker_ai-1.1.2/tests/test_dashboard.py +107 -0
- waker_ai-1.1.2/tests/test_detect.py +48 -0
- waker_ai-1.1.2/tests/test_detector.py +129 -0
- waker_ai-1.1.2/tests/test_doctor.py +44 -0
- waker_ai-1.1.2/tests/test_engine.py +188 -0
- waker_ai-1.1.2/tests/test_engine_blind.py +167 -0
- waker_ai-1.1.2/tests/test_evidence.py +103 -0
- waker_ai-1.1.2/tests/test_globs.py +33 -0
- waker_ai-1.1.2/tests/test_live_opencode.py +50 -0
- waker_ai-1.1.2/tests/test_llm_plan.py +60 -0
- waker_ai-1.1.2/tests/test_opencode_events.py +75 -0
- waker_ai-1.1.2/tests/test_planner.py +166 -0
- waker_ai-1.1.2/tests/test_process.py +59 -0
- waker_ai-1.1.2/tests/test_pty_adapter.py +46 -0
- waker_ai-1.1.2/tests/test_resume.py +59 -0
- waker_ai-1.1.2/tests/test_run_lock.py +63 -0
- waker_ai-1.1.2/tests/test_scheduler.py +42 -0
- waker_ai-1.1.2/tests/test_skill_install.py +45 -0
- waker_ai-1.1.2/tests/test_state.py +86 -0
- waker_ai-1.1.2/tests/test_ui.py +86 -0
- waker_ai-1.1.2/tests/test_vault.py +187 -0
- waker_ai-1.1.2/tests/test_vault_validate.py +141 -0
- waker_ai-1.1.2/tests/test_winjob.py +43 -0
- waker_ai-1.1.2/tests/test_winproc.py +101 -0
waker_ai-1.1.2/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 waker-ai contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
waker_ai-1.1.2/PKG-INFO
ADDED
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: waker-ai
|
|
3
|
+
Version: 1.1.2
|
|
4
|
+
Summary: Watchdog & supervisor for AI coding agents: never let an agent sleep on the job.
|
|
5
|
+
Author: waker-ai contributors
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/khoacat12345/waker-ai
|
|
8
|
+
Project-URL: Repository, https://github.com/khoacat12345/waker-ai
|
|
9
|
+
Project-URL: Issues, https://github.com/khoacat12345/waker-ai/issues
|
|
10
|
+
Keywords: ai,agent,supervisor,watchdog,opencode,claude,aider,ci
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
16
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
17
|
+
Classifier: Operating System :: MacOS
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
22
|
+
Classifier: Topic :: Software Development :: Testing
|
|
23
|
+
Requires-Python: >=3.11
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: pyyaml>=6.0
|
|
27
|
+
Requires-Dist: rich>=13.0
|
|
28
|
+
Provides-Extra: pty
|
|
29
|
+
Requires-Dist: pywinpty>=3.0; sys_platform == "win32" and extra == "pty"
|
|
30
|
+
Requires-Dist: pyte>=0.8; extra == "pty"
|
|
31
|
+
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
33
|
+
Requires-Dist: build>=1.2; extra == "dev"
|
|
34
|
+
Requires-Dist: wheel>=0.43; extra == "dev"
|
|
35
|
+
Dynamic: license-file
|
|
36
|
+
|
|
37
|
+
# waker-ai
|
|
38
|
+
|
|
39
|
+
[](https://github.com/khoacat12345/waker-ai/actions/workflows/ci.yml)
|
|
40
|
+
|
|
41
|
+

|
|
42
|
+
|
|
43
|
+
**Never let your AI coding agent sleep on the job again.**
|
|
44
|
+
|
|
45
|
+
`waker` is an independent supervisor for AI coding agents. It watches the disk
|
|
46
|
+
(not the agent's words), verifies a frozen contract, and wakes the agent up until
|
|
47
|
+
every task has on-disk evidence and every gate is green.
|
|
48
|
+
|
|
49
|
+
> Agent claims. Waker verifies. The disk decides.
|
|
50
|
+
|
|
51
|
+
```text
|
|
52
|
+
$ waker run --tasks .waker/tasks.yaml --adapter opencode --test "pytest -q"
|
|
53
|
+
|
|
54
|
+
**waker · run cff9c232 · 1/1 — 100%**
|
|
55
|
+
`████████████████` ⏱ 00:45 🔁 0/5 🧪 PASS 💰 $0.0016
|
|
56
|
+
|
|
57
|
+
| | Task | Work | Evidence | Gate |
|
|
58
|
+
|---|------|-------------------|---------------|------|
|
|
59
|
+
| ✅ | T1 | create live.txt | src/live.txt | pass |
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Why
|
|
63
|
+
|
|
64
|
+
AI agents do four things that ruin unattended runs:
|
|
65
|
+
|
|
66
|
+
1. **Stop early** — finish 1 of 5 tasks, exit 0, go quiet.
|
|
67
|
+
2. **Lie** — print "all tasks completed" while the test suite is red.
|
|
68
|
+
3. **Cheat** — edit the tests until they pass.
|
|
69
|
+
4. **Spin** — rewrite the same two lines five times with no progress.
|
|
70
|
+
|
|
71
|
+
Waker handles all four because it never trusts the agent's output. It only
|
|
72
|
+
trusts `git diff` and exit codes.
|
|
73
|
+
|
|
74
|
+
## Feature comparison
|
|
75
|
+
|
|
76
|
+
| Capability | Manual babysitting | `until` loop in bash | Agent built-in "auto" | **waker-ai** |
|
|
77
|
+
|---|:---:|:---:|:---:|:---:|
|
|
78
|
+
| Verifies work on disk (not claims) | ❌ | partial | ❌ | ✅ |
|
|
79
|
+
| Session resume across wakes | ❌ | ❌ | partial | ✅ T1 |
|
|
80
|
+
| Detects test tampering | ❌ | ❌ | ❌ | ✅ |
|
|
81
|
+
| Detects "claimed done, tests red" | ❌ | ❌ | ❌ | ✅ |
|
|
82
|
+
| Detects frozen / thrashing agents | ❌ | ❌ | ❌ | ✅ |
|
|
83
|
+
| Per-task checklist with evidence | ❌ | ❌ | partial | ✅ |
|
|
84
|
+
| Cost guard (USD) | ❌ | ❌ | ❌ | ✅ |
|
|
85
|
+
| Works with many CLIs | ❌ | ✅ | ❌ | ✅ T1/T2/T3 |
|
|
86
|
+
| Survives chatbox close (`--detach`) | ❌ | ✅ | ❌ | ✅ |
|
|
87
|
+
| Live TUI + web dashboard | ❌ | ❌ | ❌ | ✅ |
|
|
88
|
+
| Runs 100% offline for parsing/lint | ❌ | ✅ | ❌ | ✅ 0 token |
|
|
89
|
+
|
|
90
|
+
## Install
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
# PyPI upload workflow is ready; until the first release is published:
|
|
94
|
+
pip install "waker-ai @ git+https://github.com/khoacat12345/waker-ai.git"
|
|
95
|
+
|
|
96
|
+
# one command: detect installed CLIs and install the waker skill
|
|
97
|
+
waker setup
|
|
98
|
+
|
|
99
|
+
# Windows PTY tier-3 (optional)
|
|
100
|
+
pip install "pywinpty>=3.0" "pyte>=0.8"
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
From source:
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
git clone https://github.com/khoacat12345/waker-ai
|
|
107
|
+
cd waker-ai
|
|
108
|
+
python -m venv .venv
|
|
109
|
+
.venv\Scripts\activate # Windows
|
|
110
|
+
pip install -e ".[dev]"
|
|
111
|
+
pytest
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Quickstart (60 seconds)
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
# 0) detect the test runner already used by the repo
|
|
118
|
+
waker detect
|
|
119
|
+
|
|
120
|
+
# 1a) prompt with scope/verify -> contract (0 token, deterministic)
|
|
121
|
+
waker plan --prompt "Phase 1: auth, scope: src/auth/**, verify: pytest tests/auth -q"
|
|
122
|
+
|
|
123
|
+
# 1b) vague prompt -> one OpenCode planning turn writes the contract
|
|
124
|
+
waker plan --via opencode --model <provider/model> \
|
|
125
|
+
--prompt "làm app quản lý chi tiêu, có login, xuất excel"
|
|
126
|
+
|
|
127
|
+
# 2) validate the contract - fail closed on missing scope/verify
|
|
128
|
+
waker lint --tasks .waker/tasks.yaml
|
|
129
|
+
|
|
130
|
+
# 3) supervise the agent
|
|
131
|
+
waker run --tasks .waker/tasks.yaml \
|
|
132
|
+
--adapter opencode --model opencode-go/deepseek-v4.1-flash \
|
|
133
|
+
--test "pytest tests/ -q" \
|
|
134
|
+
--max-kicks 5 --max-cost 0.50
|
|
135
|
+
|
|
136
|
+
# 4) after a crash/reboot, continue the same run
|
|
137
|
+
waker run --resume <run_id> --repo .
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Background mode, then watch from anywhere:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
waker start --detach --tasks .waker/tasks.yaml \
|
|
144
|
+
--adapter opencode --model <provider/model> --test "pytest tests/ -q"
|
|
145
|
+
|
|
146
|
+
waker status --repo .
|
|
147
|
+
waker watch --repo .
|
|
148
|
+
waker dashboard --repo . --open
|
|
149
|
+
waker stop --repo .
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Install the chatbox skill:
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
waker setup # detects OpenCode/Claude/Gemini, installs globally
|
|
156
|
+
# or explicit:
|
|
157
|
+
waker install-skill --for opencode --global # ~/.opencode/skills/waker/SKILL.md
|
|
158
|
+
waker install-skill --for claude --global # ~/.claude/skills/waker/SKILL.md
|
|
159
|
+
waker install-skill --for gemini --global # ~/.gemini/config/skills/waker/SKILL.md
|
|
160
|
+
waker install-skill --for generic # AGENTS.md block (idempotent)
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Skills are loaded when the chat session starts — restart your CLI after
|
|
164
|
+
installing. A `pip install` cannot write into your agent's config by itself
|
|
165
|
+
(that is a security boundary); `waker setup` is the one-time post-install step.
|
|
166
|
+
|
|
167
|
+
## Blind evaluation (v1.1)
|
|
168
|
+
|
|
169
|
+
The Architect (chatbox) can write **hidden tests** that the worker never sees:
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
waker vault init --repo .
|
|
173
|
+
# → vault_id: 9f3a2c7d1e4b (the vault lives outside the repo)
|
|
174
|
+
|
|
175
|
+
waker vault add --vault 9f3a2c7d1e4b --suite auth --task T1 tests/test_auth_hidden.py
|
|
176
|
+
waker vault validate --vault 9f3a2c7d1e4b --repo .
|
|
177
|
+
# → fails on baseline? good. import error / skip / flaky? reject.
|
|
178
|
+
|
|
179
|
+
waker run --tasks .waker/tasks.yaml --vault 9f3a2c7d1e4b --adapter opencode ...
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
```yaml
|
|
183
|
+
- id: T1
|
|
184
|
+
verify: "pytest tests/test_auth_smoke.py -q" # public smoke, worker sees
|
|
185
|
+
public_api: ["login(name, password) -> token | None"]
|
|
186
|
+
blind:
|
|
187
|
+
suite: auth
|
|
188
|
+
baseline: red # hidden must fail before work
|
|
189
|
+
leak: message # minimal | message
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
- `DONE` requires **100% hidden pass** plus public smoke and constraints.
|
|
193
|
+
- Failures are sanitized: `hidden://auth/test_3: AssertionError: ...`; no source,
|
|
194
|
+
no paths, no locals.
|
|
195
|
+
- `VAULT_TAMPER` stops the run if the vault hash changes.
|
|
196
|
+
- **Honest scope:** v1.1 is blind by construction, not an adversarial sandbox.
|
|
197
|
+
The worker runs as the same OS user; real isolation (Docker/Windows Sandbox)
|
|
198
|
+
is v1.2. See [`docs/BLIND_EVALUATION_SPEC.md`](docs/BLIND_EVALUATION_SPEC.md).
|
|
199
|
+
|
|
200
|
+
## How done is decided
|
|
201
|
+
|
|
202
|
+
For every task:
|
|
203
|
+
|
|
204
|
+
```python
|
|
205
|
+
done(T) = (git diff ∩ T.scope ≠ ∅) and (T.verify exits 0)
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
| Gate | Stops |
|
|
209
|
+
|---|---|
|
|
210
|
+
| `scope ∩ diff` | touching an unrelated file to look busy |
|
|
211
|
+
| `verify` exit 0 | claiming success while tests are red |
|
|
212
|
+
| test hash | editing the exam (`TAMPER` → restore + kick) |
|
|
213
|
+
| contract hash | moving the goalposts mid-run |
|
|
214
|
+
| cost / kicks / wall clock | burning the budget in a retry loop |
|
|
215
|
+
|
|
216
|
+
## Adapters
|
|
217
|
+
|
|
218
|
+
| Tier | Mechanism | CLIs | Status |
|
|
219
|
+
|---|---|---|---|
|
|
220
|
+
| **T1** | native session resume | OpenCode (`run --session --format json`) | ✅ live E2E |
|
|
221
|
+
| **T1** | native session resume | Claude Code (`-p --resume --output-format stream-json`) | 🧪 beta (unit-tested, no live CI) |
|
|
222
|
+
| **T2** | fresh process + context digest | any CLI with a non-interactive flag (`aider --message`, `gemini -p`, custom commands) | ✅ |
|
|
223
|
+
| **T3** | PTY keystroke injection (ConPTY + pyte) | any text-mode TUI, even without a headless mode | ✅ Windows only |
|
|
224
|
+
|
|
225
|
+
`waker doctor` detects what is installed and prints the tier:
|
|
226
|
+
|
|
227
|
+
```text
|
|
228
|
+
$ waker doctor --inject-test
|
|
229
|
+
OK opencode tier T1 (opencode 2.0.32)
|
|
230
|
+
OK claude tier T1 (claude 1.x)
|
|
231
|
+
-- aider tier -
|
|
232
|
+
OK any-text-cli tier T3 (pywinpty)
|
|
233
|
+
injector self-test: PASS - marker seen
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
The injector self-test drives a harmless shell, never an AI session.
|
|
237
|
+
|
|
238
|
+
Importantly: **cost guard is exact only for OpenCode.** It reads
|
|
239
|
+
`opencode session export` before/after each turn. For Claude it uses the
|
|
240
|
+
`total_cost_usd` delta from the stream; for generic/PTY it is 0 (no measurement).
|
|
241
|
+
|
|
242
|
+
## Safety on Windows
|
|
243
|
+
|
|
244
|
+
- Every run is assigned to a **Win32 Job Object**
|
|
245
|
+
(`JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE`); `taskkill /T /F` is always issued as a
|
|
246
|
+
fallback, so grandchildren die too.
|
|
247
|
+
- **Live freeze probe**: no stdout **and** no file activity for `--freeze-after`
|
|
248
|
+
seconds → kill the tree and mark the turn `FROZEN`; no waiting for a
|
|
249
|
+
15-minute timeout.
|
|
250
|
+
- Prompts are passed as argv, never through a shell (shell quoting corrupts
|
|
251
|
+
prompts that contain quotes or backslashes).
|
|
252
|
+
|
|
253
|
+
## CLI
|
|
254
|
+
|
|
255
|
+
```text
|
|
256
|
+
waker plan prompt -> contract (0 token, or --via opencode for vague prompts)
|
|
257
|
+
waker lint contract validation (0 token)
|
|
258
|
+
waker detect detect pytest / npm / cargo / go / make test
|
|
259
|
+
waker run supervise in the foreground (--resume <id> to continue)
|
|
260
|
+
waker start supervise in the background (detached)
|
|
261
|
+
waker stop stop a run (tree kill)
|
|
262
|
+
waker serve loopback HTTP control plane
|
|
263
|
+
waker status markdown/JSON snapshot
|
|
264
|
+
waker watch live Rich TUI
|
|
265
|
+
waker dashboard static HTML or live web dashboard
|
|
266
|
+
waker report print the acceptance report
|
|
267
|
+
waker doctor environment + adapter tier + injector test
|
|
268
|
+
waker setup detect CLIs and install the skill (one command)
|
|
269
|
+
waker install-skill opencode / claude / gemini / generic
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## Demo
|
|
273
|
+
|
|
274
|
+
The animated demo at the top is generated by
|
|
275
|
+
[`scripts/make_demo_gif.py`](scripts/make_demo_gif.py). The 45-second recording
|
|
276
|
+
script lives in [`docs/demo-45s.md`](docs/demo-45s.md).
|
|
277
|
+
|
|
278
|
+
## Design
|
|
279
|
+
|
|
280
|
+
Full design and decision log: [`plan.md`](plan.md).
|
|
281
|
+
Phase reports: `.waker/runs/phase1_report.md`, `phase2_report.md`, `phase3_report.md`.
|
|
282
|
+
|
|
283
|
+
## Status
|
|
284
|
+
|
|
285
|
+
**v1.1.0** — blind evaluation (hidden vault + sanitized grading), engine,
|
|
286
|
+
3 adapter tiers, daemon/skills, CI matrix, dashboard and release automation.
|
|
287
|
+
|
|
288
|
+
Maturity:
|
|
289
|
+
|
|
290
|
+
- **OpenCode T1** — live E2E verified.
|
|
291
|
+
- **Claude T1** — beta: command/stream/permission handling unit-tested, no live
|
|
292
|
+
CI run yet (the CLI is not installed on the build runner).
|
|
293
|
+
- **PTY T3** — Windows only; POSIX support is planned for v1.1.
|
|
294
|
+
- **Cost guard** — exact for OpenCode, best-effort for Claude, 0 for generic/PTY.
|
|
295
|
+
|
|
296
|
+
PyPI: the `publish.yml` workflow is ready (trusted publishing or
|
|
297
|
+
`PYPI_API_TOKEN`); publish the v1.0.0 release to trigger the first upload.
|
|
298
|
+
|
|
299
|
+
## License
|
|
300
|
+
|
|
301
|
+
MIT
|
waker_ai-1.1.2/README.md
ADDED
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
# waker-ai
|
|
2
|
+
|
|
3
|
+
[](https://github.com/khoacat12345/waker-ai/actions/workflows/ci.yml)
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
**Never let your AI coding agent sleep on the job again.**
|
|
8
|
+
|
|
9
|
+
`waker` is an independent supervisor for AI coding agents. It watches the disk
|
|
10
|
+
(not the agent's words), verifies a frozen contract, and wakes the agent up until
|
|
11
|
+
every task has on-disk evidence and every gate is green.
|
|
12
|
+
|
|
13
|
+
> Agent claims. Waker verifies. The disk decides.
|
|
14
|
+
|
|
15
|
+
```text
|
|
16
|
+
$ waker run --tasks .waker/tasks.yaml --adapter opencode --test "pytest -q"
|
|
17
|
+
|
|
18
|
+
**waker · run cff9c232 · 1/1 — 100%**
|
|
19
|
+
`████████████████` ⏱ 00:45 🔁 0/5 🧪 PASS 💰 $0.0016
|
|
20
|
+
|
|
21
|
+
| | Task | Work | Evidence | Gate |
|
|
22
|
+
|---|------|-------------------|---------------|------|
|
|
23
|
+
| ✅ | T1 | create live.txt | src/live.txt | pass |
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Why
|
|
27
|
+
|
|
28
|
+
AI agents do four things that ruin unattended runs:
|
|
29
|
+
|
|
30
|
+
1. **Stop early** — finish 1 of 5 tasks, exit 0, go quiet.
|
|
31
|
+
2. **Lie** — print "all tasks completed" while the test suite is red.
|
|
32
|
+
3. **Cheat** — edit the tests until they pass.
|
|
33
|
+
4. **Spin** — rewrite the same two lines five times with no progress.
|
|
34
|
+
|
|
35
|
+
Waker handles all four because it never trusts the agent's output. It only
|
|
36
|
+
trusts `git diff` and exit codes.
|
|
37
|
+
|
|
38
|
+
## Feature comparison
|
|
39
|
+
|
|
40
|
+
| Capability | Manual babysitting | `until` loop in bash | Agent built-in "auto" | **waker-ai** |
|
|
41
|
+
|---|:---:|:---:|:---:|:---:|
|
|
42
|
+
| Verifies work on disk (not claims) | ❌ | partial | ❌ | ✅ |
|
|
43
|
+
| Session resume across wakes | ❌ | ❌ | partial | ✅ T1 |
|
|
44
|
+
| Detects test tampering | ❌ | ❌ | ❌ | ✅ |
|
|
45
|
+
| Detects "claimed done, tests red" | ❌ | ❌ | ❌ | ✅ |
|
|
46
|
+
| Detects frozen / thrashing agents | ❌ | ❌ | ❌ | ✅ |
|
|
47
|
+
| Per-task checklist with evidence | ❌ | ❌ | partial | ✅ |
|
|
48
|
+
| Cost guard (USD) | ❌ | ❌ | ❌ | ✅ |
|
|
49
|
+
| Works with many CLIs | ❌ | ✅ | ❌ | ✅ T1/T2/T3 |
|
|
50
|
+
| Survives chatbox close (`--detach`) | ❌ | ✅ | ❌ | ✅ |
|
|
51
|
+
| Live TUI + web dashboard | ❌ | ❌ | ❌ | ✅ |
|
|
52
|
+
| Runs 100% offline for parsing/lint | ❌ | ✅ | ❌ | ✅ 0 token |
|
|
53
|
+
|
|
54
|
+
## Install
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# PyPI upload workflow is ready; until the first release is published:
|
|
58
|
+
pip install "waker-ai @ git+https://github.com/khoacat12345/waker-ai.git"
|
|
59
|
+
|
|
60
|
+
# one command: detect installed CLIs and install the waker skill
|
|
61
|
+
waker setup
|
|
62
|
+
|
|
63
|
+
# Windows PTY tier-3 (optional)
|
|
64
|
+
pip install "pywinpty>=3.0" "pyte>=0.8"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
From source:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
git clone https://github.com/khoacat12345/waker-ai
|
|
71
|
+
cd waker-ai
|
|
72
|
+
python -m venv .venv
|
|
73
|
+
.venv\Scripts\activate # Windows
|
|
74
|
+
pip install -e ".[dev]"
|
|
75
|
+
pytest
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Quickstart (60 seconds)
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# 0) detect the test runner already used by the repo
|
|
82
|
+
waker detect
|
|
83
|
+
|
|
84
|
+
# 1a) prompt with scope/verify -> contract (0 token, deterministic)
|
|
85
|
+
waker plan --prompt "Phase 1: auth, scope: src/auth/**, verify: pytest tests/auth -q"
|
|
86
|
+
|
|
87
|
+
# 1b) vague prompt -> one OpenCode planning turn writes the contract
|
|
88
|
+
waker plan --via opencode --model <provider/model> \
|
|
89
|
+
--prompt "làm app quản lý chi tiêu, có login, xuất excel"
|
|
90
|
+
|
|
91
|
+
# 2) validate the contract - fail closed on missing scope/verify
|
|
92
|
+
waker lint --tasks .waker/tasks.yaml
|
|
93
|
+
|
|
94
|
+
# 3) supervise the agent
|
|
95
|
+
waker run --tasks .waker/tasks.yaml \
|
|
96
|
+
--adapter opencode --model opencode-go/deepseek-v4.1-flash \
|
|
97
|
+
--test "pytest tests/ -q" \
|
|
98
|
+
--max-kicks 5 --max-cost 0.50
|
|
99
|
+
|
|
100
|
+
# 4) after a crash/reboot, continue the same run
|
|
101
|
+
waker run --resume <run_id> --repo .
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Background mode, then watch from anywhere:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
waker start --detach --tasks .waker/tasks.yaml \
|
|
108
|
+
--adapter opencode --model <provider/model> --test "pytest tests/ -q"
|
|
109
|
+
|
|
110
|
+
waker status --repo .
|
|
111
|
+
waker watch --repo .
|
|
112
|
+
waker dashboard --repo . --open
|
|
113
|
+
waker stop --repo .
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Install the chatbox skill:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
waker setup # detects OpenCode/Claude/Gemini, installs globally
|
|
120
|
+
# or explicit:
|
|
121
|
+
waker install-skill --for opencode --global # ~/.opencode/skills/waker/SKILL.md
|
|
122
|
+
waker install-skill --for claude --global # ~/.claude/skills/waker/SKILL.md
|
|
123
|
+
waker install-skill --for gemini --global # ~/.gemini/config/skills/waker/SKILL.md
|
|
124
|
+
waker install-skill --for generic # AGENTS.md block (idempotent)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Skills are loaded when the chat session starts — restart your CLI after
|
|
128
|
+
installing. A `pip install` cannot write into your agent's config by itself
|
|
129
|
+
(that is a security boundary); `waker setup` is the one-time post-install step.
|
|
130
|
+
|
|
131
|
+
## Blind evaluation (v1.1)
|
|
132
|
+
|
|
133
|
+
The Architect (chatbox) can write **hidden tests** that the worker never sees:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
waker vault init --repo .
|
|
137
|
+
# → vault_id: 9f3a2c7d1e4b (the vault lives outside the repo)
|
|
138
|
+
|
|
139
|
+
waker vault add --vault 9f3a2c7d1e4b --suite auth --task T1 tests/test_auth_hidden.py
|
|
140
|
+
waker vault validate --vault 9f3a2c7d1e4b --repo .
|
|
141
|
+
# → fails on baseline? good. import error / skip / flaky? reject.
|
|
142
|
+
|
|
143
|
+
waker run --tasks .waker/tasks.yaml --vault 9f3a2c7d1e4b --adapter opencode ...
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
```yaml
|
|
147
|
+
- id: T1
|
|
148
|
+
verify: "pytest tests/test_auth_smoke.py -q" # public smoke, worker sees
|
|
149
|
+
public_api: ["login(name, password) -> token | None"]
|
|
150
|
+
blind:
|
|
151
|
+
suite: auth
|
|
152
|
+
baseline: red # hidden must fail before work
|
|
153
|
+
leak: message # minimal | message
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
- `DONE` requires **100% hidden pass** plus public smoke and constraints.
|
|
157
|
+
- Failures are sanitized: `hidden://auth/test_3: AssertionError: ...`; no source,
|
|
158
|
+
no paths, no locals.
|
|
159
|
+
- `VAULT_TAMPER` stops the run if the vault hash changes.
|
|
160
|
+
- **Honest scope:** v1.1 is blind by construction, not an adversarial sandbox.
|
|
161
|
+
The worker runs as the same OS user; real isolation (Docker/Windows Sandbox)
|
|
162
|
+
is v1.2. See [`docs/BLIND_EVALUATION_SPEC.md`](docs/BLIND_EVALUATION_SPEC.md).
|
|
163
|
+
|
|
164
|
+
## How done is decided
|
|
165
|
+
|
|
166
|
+
For every task:
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
done(T) = (git diff ∩ T.scope ≠ ∅) and (T.verify exits 0)
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
| Gate | Stops |
|
|
173
|
+
|---|---|
|
|
174
|
+
| `scope ∩ diff` | touching an unrelated file to look busy |
|
|
175
|
+
| `verify` exit 0 | claiming success while tests are red |
|
|
176
|
+
| test hash | editing the exam (`TAMPER` → restore + kick) |
|
|
177
|
+
| contract hash | moving the goalposts mid-run |
|
|
178
|
+
| cost / kicks / wall clock | burning the budget in a retry loop |
|
|
179
|
+
|
|
180
|
+
## Adapters
|
|
181
|
+
|
|
182
|
+
| Tier | Mechanism | CLIs | Status |
|
|
183
|
+
|---|---|---|---|
|
|
184
|
+
| **T1** | native session resume | OpenCode (`run --session --format json`) | ✅ live E2E |
|
|
185
|
+
| **T1** | native session resume | Claude Code (`-p --resume --output-format stream-json`) | 🧪 beta (unit-tested, no live CI) |
|
|
186
|
+
| **T2** | fresh process + context digest | any CLI with a non-interactive flag (`aider --message`, `gemini -p`, custom commands) | ✅ |
|
|
187
|
+
| **T3** | PTY keystroke injection (ConPTY + pyte) | any text-mode TUI, even without a headless mode | ✅ Windows only |
|
|
188
|
+
|
|
189
|
+
`waker doctor` detects what is installed and prints the tier:
|
|
190
|
+
|
|
191
|
+
```text
|
|
192
|
+
$ waker doctor --inject-test
|
|
193
|
+
OK opencode tier T1 (opencode 2.0.32)
|
|
194
|
+
OK claude tier T1 (claude 1.x)
|
|
195
|
+
-- aider tier -
|
|
196
|
+
OK any-text-cli tier T3 (pywinpty)
|
|
197
|
+
injector self-test: PASS - marker seen
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
The injector self-test drives a harmless shell, never an AI session.
|
|
201
|
+
|
|
202
|
+
Importantly: **cost guard is exact only for OpenCode.** It reads
|
|
203
|
+
`opencode session export` before/after each turn. For Claude it uses the
|
|
204
|
+
`total_cost_usd` delta from the stream; for generic/PTY it is 0 (no measurement).
|
|
205
|
+
|
|
206
|
+
## Safety on Windows
|
|
207
|
+
|
|
208
|
+
- Every run is assigned to a **Win32 Job Object**
|
|
209
|
+
(`JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE`); `taskkill /T /F` is always issued as a
|
|
210
|
+
fallback, so grandchildren die too.
|
|
211
|
+
- **Live freeze probe**: no stdout **and** no file activity for `--freeze-after`
|
|
212
|
+
seconds → kill the tree and mark the turn `FROZEN`; no waiting for a
|
|
213
|
+
15-minute timeout.
|
|
214
|
+
- Prompts are passed as argv, never through a shell (shell quoting corrupts
|
|
215
|
+
prompts that contain quotes or backslashes).
|
|
216
|
+
|
|
217
|
+
## CLI
|
|
218
|
+
|
|
219
|
+
```text
|
|
220
|
+
waker plan prompt -> contract (0 token, or --via opencode for vague prompts)
|
|
221
|
+
waker lint contract validation (0 token)
|
|
222
|
+
waker detect detect pytest / npm / cargo / go / make test
|
|
223
|
+
waker run supervise in the foreground (--resume <id> to continue)
|
|
224
|
+
waker start supervise in the background (detached)
|
|
225
|
+
waker stop stop a run (tree kill)
|
|
226
|
+
waker serve loopback HTTP control plane
|
|
227
|
+
waker status markdown/JSON snapshot
|
|
228
|
+
waker watch live Rich TUI
|
|
229
|
+
waker dashboard static HTML or live web dashboard
|
|
230
|
+
waker report print the acceptance report
|
|
231
|
+
waker doctor environment + adapter tier + injector test
|
|
232
|
+
waker setup detect CLIs and install the skill (one command)
|
|
233
|
+
waker install-skill opencode / claude / gemini / generic
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
## Demo
|
|
237
|
+
|
|
238
|
+
The animated demo at the top is generated by
|
|
239
|
+
[`scripts/make_demo_gif.py`](scripts/make_demo_gif.py). The 45-second recording
|
|
240
|
+
script lives in [`docs/demo-45s.md`](docs/demo-45s.md).
|
|
241
|
+
|
|
242
|
+
## Design
|
|
243
|
+
|
|
244
|
+
Full design and decision log: [`plan.md`](plan.md).
|
|
245
|
+
Phase reports: `.waker/runs/phase1_report.md`, `phase2_report.md`, `phase3_report.md`.
|
|
246
|
+
|
|
247
|
+
## Status
|
|
248
|
+
|
|
249
|
+
**v1.1.0** — blind evaluation (hidden vault + sanitized grading), engine,
|
|
250
|
+
3 adapter tiers, daemon/skills, CI matrix, dashboard and release automation.
|
|
251
|
+
|
|
252
|
+
Maturity:
|
|
253
|
+
|
|
254
|
+
- **OpenCode T1** — live E2E verified.
|
|
255
|
+
- **Claude T1** — beta: command/stream/permission handling unit-tested, no live
|
|
256
|
+
CI run yet (the CLI is not installed on the build runner).
|
|
257
|
+
- **PTY T3** — Windows only; POSIX support is planned for v1.1.
|
|
258
|
+
- **Cost guard** — exact for OpenCode, best-effort for Claude, 0 for generic/PTY.
|
|
259
|
+
|
|
260
|
+
PyPI: the `publish.yml` workflow is ready (trusted publishing or
|
|
261
|
+
`PYPI_API_TOKEN`); publish the v1.0.0 release to trigger the first upload.
|
|
262
|
+
|
|
263
|
+
## License
|
|
264
|
+
|
|
265
|
+
MIT
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "waker-ai"
|
|
7
|
+
version = "1.1.2"
|
|
8
|
+
description = "Watchdog & supervisor for AI coding agents: never let an agent sleep on the job."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
license-files = ["LICENSE"]
|
|
13
|
+
authors = [{ name = "waker-ai contributors" }]
|
|
14
|
+
keywords = ["ai", "agent", "supervisor", "watchdog", "opencode", "claude", "aider", "ci"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 4 - Beta",
|
|
17
|
+
"Environment :: Console",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"Operating System :: OS Independent",
|
|
20
|
+
"Operating System :: Microsoft :: Windows",
|
|
21
|
+
"Operating System :: POSIX :: Linux",
|
|
22
|
+
"Operating System :: MacOS",
|
|
23
|
+
"Programming Language :: Python :: 3",
|
|
24
|
+
"Programming Language :: Python :: 3.11",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
26
|
+
"Topic :: Software Development :: Quality Assurance",
|
|
27
|
+
"Topic :: Software Development :: Testing",
|
|
28
|
+
]
|
|
29
|
+
dependencies = [
|
|
30
|
+
"pyyaml>=6.0",
|
|
31
|
+
"rich>=13.0",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[project.optional-dependencies]
|
|
35
|
+
pty = [
|
|
36
|
+
"pywinpty>=3.0; sys_platform == 'win32'",
|
|
37
|
+
"pyte>=0.8",
|
|
38
|
+
]
|
|
39
|
+
dev = [
|
|
40
|
+
"pytest>=8.0",
|
|
41
|
+
"build>=1.2",
|
|
42
|
+
"wheel>=0.43",
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
[project.urls]
|
|
46
|
+
Homepage = "https://github.com/khoacat12345/waker-ai"
|
|
47
|
+
Repository = "https://github.com/khoacat12345/waker-ai"
|
|
48
|
+
Issues = "https://github.com/khoacat12345/waker-ai/issues"
|
|
49
|
+
|
|
50
|
+
[project.scripts]
|
|
51
|
+
waker = "waker.cli:main"
|
|
52
|
+
|
|
53
|
+
[tool.setuptools]
|
|
54
|
+
include-package-data = true
|
|
55
|
+
|
|
56
|
+
[tool.setuptools.packages.find]
|
|
57
|
+
where = ["src"]
|
|
58
|
+
|
|
59
|
+
[tool.setuptools.package-data]
|
|
60
|
+
waker = ["skill_templates/*/*"]
|
|
61
|
+
|
|
62
|
+
[tool.pytest.ini_options]
|
|
63
|
+
testpaths = ["tests"]
|
|
64
|
+
addopts = "-q"
|
|
65
|
+
pythonpath = ["src"]
|
|
66
|
+
filterwarnings = ["ignore::DeprecationWarning"]
|
|
67
|
+
markers = ["live: real CLI E2E, disabled unless WAKER_LIVE_TEST=1"]
|
|
68
|
+
|
waker_ai-1.1.2/setup.cfg
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from .base import Adapter, TurnContext
|
|
2
|
+
from .claude import ClaudeAdapter
|
|
3
|
+
from .generic import GenericProcessAdapter, quote_arg
|
|
4
|
+
from .opencode import OpenCodeAdapter
|
|
5
|
+
|
|
6
|
+
__all__ = [
|
|
7
|
+
"Adapter",
|
|
8
|
+
"TurnContext",
|
|
9
|
+
"GenericProcessAdapter",
|
|
10
|
+
"OpenCodeAdapter",
|
|
11
|
+
"ClaudeAdapter",
|
|
12
|
+
"quote_arg",
|
|
13
|
+
]
|