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.
Files changed (79) hide show
  1. waker_ai-1.1.2/LICENSE +21 -0
  2. waker_ai-1.1.2/PKG-INFO +301 -0
  3. waker_ai-1.1.2/README.md +265 -0
  4. waker_ai-1.1.2/pyproject.toml +68 -0
  5. waker_ai-1.1.2/setup.cfg +4 -0
  6. waker_ai-1.1.2/src/waker/__init__.py +4 -0
  7. waker_ai-1.1.2/src/waker/__main__.py +3 -0
  8. waker_ai-1.1.2/src/waker/adapters/__init__.py +13 -0
  9. waker_ai-1.1.2/src/waker/adapters/base.py +33 -0
  10. waker_ai-1.1.2/src/waker/adapters/claude.py +88 -0
  11. waker_ai-1.1.2/src/waker/adapters/generic.py +70 -0
  12. waker_ai-1.1.2/src/waker/adapters/opencode.py +102 -0
  13. waker_ai-1.1.2/src/waker/adapters/pty.py +205 -0
  14. waker_ai-1.1.2/src/waker/blind_runner.py +142 -0
  15. waker_ai-1.1.2/src/waker/claude_events.py +82 -0
  16. waker_ai-1.1.2/src/waker/cli.py +698 -0
  17. waker_ai-1.1.2/src/waker/daemon.py +262 -0
  18. waker_ai-1.1.2/src/waker/dashboard.py +234 -0
  19. waker_ai-1.1.2/src/waker/detect.py +74 -0
  20. waker_ai-1.1.2/src/waker/detector.py +81 -0
  21. waker_ai-1.1.2/src/waker/doctor.py +200 -0
  22. waker_ai-1.1.2/src/waker/engine.py +886 -0
  23. waker_ai-1.1.2/src/waker/evidence.py +345 -0
  24. waker_ai-1.1.2/src/waker/globs.py +100 -0
  25. waker_ai-1.1.2/src/waker/injector.py +120 -0
  26. waker_ai-1.1.2/src/waker/llm_plan.py +149 -0
  27. waker_ai-1.1.2/src/waker/models.py +271 -0
  28. waker_ai-1.1.2/src/waker/opencode_events.py +149 -0
  29. waker_ai-1.1.2/src/waker/planner.py +538 -0
  30. waker_ai-1.1.2/src/waker/process.py +200 -0
  31. waker_ai-1.1.2/src/waker/scheduler.py +52 -0
  32. waker_ai-1.1.2/src/waker/skill_install.py +50 -0
  33. waker_ai-1.1.2/src/waker/skill_templates/claude/SKILL.md +58 -0
  34. waker_ai-1.1.2/src/waker/skill_templates/gemini/SKILL.md +58 -0
  35. waker_ai-1.1.2/src/waker/skill_templates/generic/AGENTS.md +12 -0
  36. waker_ai-1.1.2/src/waker/skill_templates/opencode/SKILL.md +84 -0
  37. waker_ai-1.1.2/src/waker/state.py +333 -0
  38. waker_ai-1.1.2/src/waker/ui.py +185 -0
  39. waker_ai-1.1.2/src/waker/vault.py +216 -0
  40. waker_ai-1.1.2/src/waker/vault_runner.py +189 -0
  41. waker_ai-1.1.2/src/waker/vault_validate.py +162 -0
  42. waker_ai-1.1.2/src/waker/winjob.py +136 -0
  43. waker_ai-1.1.2/src/waker/winproc.py +55 -0
  44. waker_ai-1.1.2/src/waker_ai.egg-info/PKG-INFO +301 -0
  45. waker_ai-1.1.2/src/waker_ai.egg-info/SOURCES.txt +77 -0
  46. waker_ai-1.1.2/src/waker_ai.egg-info/dependency_links.txt +1 -0
  47. waker_ai-1.1.2/src/waker_ai.egg-info/entry_points.txt +2 -0
  48. waker_ai-1.1.2/src/waker_ai.egg-info/requires.txt +13 -0
  49. waker_ai-1.1.2/src/waker_ai.egg-info/top_level.txt +1 -0
  50. waker_ai-1.1.2/tests/test_blind_acceptance.py +178 -0
  51. waker_ai-1.1.2/tests/test_blind_runner.py +146 -0
  52. waker_ai-1.1.2/tests/test_claude_adapter.py +58 -0
  53. waker_ai-1.1.2/tests/test_cli.py +285 -0
  54. waker_ai-1.1.2/tests/test_cost_guard.py +80 -0
  55. waker_ai-1.1.2/tests/test_daemon.py +117 -0
  56. waker_ai-1.1.2/tests/test_dashboard.py +107 -0
  57. waker_ai-1.1.2/tests/test_detect.py +48 -0
  58. waker_ai-1.1.2/tests/test_detector.py +129 -0
  59. waker_ai-1.1.2/tests/test_doctor.py +44 -0
  60. waker_ai-1.1.2/tests/test_engine.py +188 -0
  61. waker_ai-1.1.2/tests/test_engine_blind.py +167 -0
  62. waker_ai-1.1.2/tests/test_evidence.py +103 -0
  63. waker_ai-1.1.2/tests/test_globs.py +33 -0
  64. waker_ai-1.1.2/tests/test_live_opencode.py +50 -0
  65. waker_ai-1.1.2/tests/test_llm_plan.py +60 -0
  66. waker_ai-1.1.2/tests/test_opencode_events.py +75 -0
  67. waker_ai-1.1.2/tests/test_planner.py +166 -0
  68. waker_ai-1.1.2/tests/test_process.py +59 -0
  69. waker_ai-1.1.2/tests/test_pty_adapter.py +46 -0
  70. waker_ai-1.1.2/tests/test_resume.py +59 -0
  71. waker_ai-1.1.2/tests/test_run_lock.py +63 -0
  72. waker_ai-1.1.2/tests/test_scheduler.py +42 -0
  73. waker_ai-1.1.2/tests/test_skill_install.py +45 -0
  74. waker_ai-1.1.2/tests/test_state.py +86 -0
  75. waker_ai-1.1.2/tests/test_ui.py +86 -0
  76. waker_ai-1.1.2/tests/test_vault.py +187 -0
  77. waker_ai-1.1.2/tests/test_vault_validate.py +141 -0
  78. waker_ai-1.1.2/tests/test_winjob.py +43 -0
  79. 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.
@@ -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
+ [![tests](https://github.com/khoacat12345/waker-ai/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/khoacat12345/waker-ai/actions/workflows/ci.yml)
40
+
41
+ ![waker demo](docs/demo.gif)
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
@@ -0,0 +1,265 @@
1
+ # waker-ai
2
+
3
+ [![tests](https://github.com/khoacat12345/waker-ai/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/khoacat12345/waker-ai/actions/workflows/ci.yml)
4
+
5
+ ![waker demo](docs/demo.gif)
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
+
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,4 @@
1
+ """waker-ai — watchdog & supervisor for AI coding agents."""
2
+
3
+ __version__ = "1.1.2"
4
+
@@ -0,0 +1,3 @@
1
+ from .cli import main
2
+
3
+ raise SystemExit(main())
@@ -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
+ ]