feat: HTTP evidence source for the observer (closes #18) - #20
Merged
Conversation
Adds a third evidence-source type so the planner can see live HTTP
state (eval endpoints, health dashboards, third-party scoring APIs) in
the same observation bundle that already carries file and shell output.
Design
- `evolution_kernel/config.py`: `EvidenceSource` gains HTTP-only fields
(`url`, `method`, `headers`, `timeout`). `_parse_evidence_sources`
validates the new `type: http` shape with friendly errors.
- `evolution_kernel/observer.py`: new `_collect_http()` uses stdlib
`urllib.request` only (single-dep rule preserved — still only PyYAML).
Captures `status`, `body` (64 KiB cap, `truncated` flag), and a
sorted list of `(name, value)` headers so the ledger is stable for
diffing. Non-2xx responses still record the body so a planner can
react to 4xx/5xx instead of silently retrying. URLError / TimeoutError
/ OSError land in `error` instead of raising.
Tests (16 new, all green)
- `tests/test_pr7b.py`:
- 8 config parsing tests (defaults, headers map, missing/blank URL,
bad timeout, non-positive timeout, bad headers shape, unknown type).
- 6 `_collect_http` tests against a `http.server.ThreadingHTTPServer`
on `127.0.0.1` in a daemon thread: 200 capture, 500-with-body,
custom request headers, body truncation flag, connection-refused
error, blank URL.
- 2 E2E tests: `collect_observation` happy path and
`Governor.run_once` writing the HTTP response into the run's
`observation.json`.
Whole suite: 99 passed (was 83).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds an HTTP evidence source to the observer so the planner can pull live state from HTTP endpoints (status, headers, body) into observation.json alongside the existing file and shell sources. Implementation uses stdlib urllib.request (no new dependency) and follows the kernel's thin-collector model: non-2xx responses still record the body, and network/timeout errors are captured under error rather than raised.
Changes:
- Extends
EvidenceSourcedataclass and config parser withurl/method/headers/timeoutfields plus validation for the newtype: httpshape. - Adds
observer._collect_http()that fetches one endpoint, captures status/headers/byte-capped body with truncation marking, and handlesHTTPError/URLError/TimeoutError/OSError. - Adds 16 tests (config parsing, direct
_collect_httpagainst a localThreadingHTTPServer, plus a Governorrun_onceE2E) and documents the new source type inREADME.md/README.zh.md.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| evolution_kernel/config.py | Adds HTTP fields to EvidenceSource and validates the type: http config shape (url required, method uppercased, headers must be mapping, timeout > 0). |
| evolution_kernel/observer.py | Implements _collect_http and dispatches type: http sources, with byte-capped body, stable sorted headers, and error capture. |
| tests/test_pr7b.py | New test module covering config parsing, _collect_http against an in-process HTTP server, and Governor E2E writing the HTTP record into observation.json. |
| README.md / README.zh.md | Documents the HTTP evidence source and adds an illustrative-scenario disclaimer above the GSM8K narrative. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+272
to
+276
| - type: http # GET a live endpoint; status, headers and body recorded | ||
| url: "https://evals.example.com/run/latest" | ||
| headers: | ||
| Accept: application/json | ||
| timeout: 10 # seconds (default 10) |
Protocol-zero-0
added a commit
that referenced
this pull request
May 14, 2026
Bumps version 0.3.0 → 1.0.0 and updates the status badge to v1.0 following the Phase 4 work (PR #19 firejail sandbox, PR #20 HTTP evidence source). The kernel now has: - A process-level sandbox that stops the executor from writing outside its assigned worktree (firejail backed by OS-level read-only mount, verified end-to-end on CI). - An HTTP evidence source so the observer can pull live state from deployed services into observation.json alongside file and shell sources. Together with the v0.2 multi-round LLM loop, k-branch parallel exploration, goal evaluator, and full ledger audit chain, this crosses the bar for "灵魂插件": a kernel you can point at any git repository and trust to evolve it unattended. 99 tests · CI green on Python 3.10 + 3.12 · single dependency (PyYAML) preserved. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
EvidenceSourcegains HTTP-only fields (url,method,headers,timeout); parser validates the newtype: httpshape.observer._collect_http()uses stdliburllib.request— single-dependency rule preserved (still only PyYAML).bodyso a planner can react to 4xx/5xx instead of silently retrying.URLError/TimeoutError/OSErrorland inerrorinstead of raising.Closes #18.
Test plan
tests/test_pr7b.py(config parsing +_collect_httpagainst aThreadingHTTPServer+ Governor E2E).python3 -m http.serverinstance —observation.jsonrecordstype: http,status: 200, response headers, and body.🤖 Generated with Claude Code