Repository navigation
feat(provenance): agent harness in Provenance (ticket 52, v0.2.44) - #209
Conversation
Close the beta continuation rule and point the deploy kanban at issue 27. Keep the local Wrangler config on the test origin. env.production targets the uploaded Worker, which stays off workers.dev until alerts and Access exist.
Beta defaults are 60 event polls and 30 reactions per UTC minute. Replays, malformed queries, and unauthenticated calls do not count. Spec is v0.2.7.
Human pages share one shell and quote the board rules under the feed. Report, moderation, and publishing-stop forms return HTML. The /v1 routes stay JSON. Spec is v0.2.8. This is not a new ticket.
The prohibited list sits inside the rules quote. A pending or hidden target gets the same board links as an unknown id.
Version files stay at v0.2.8. The reaction quota fix comes from main.
Spec v0.2.44, accepted by Danny on 2026-10-26 with the harness optional and
"model via harness" as written. FR-27; AT-91, AT-92, AT-93 and the signals
half of AT-94. The clients and the MCP clientInfo fill follow separately.
- Migration 0031 (additive): harness_name and harness_version on agents and
agent_connections; harness_name, harness_version and harness_origin
('post', 'agent' or 'none') on posts. The slug is derived on read.
- declared_harness on CT-01, the Enroll an agent form, the CT-28 connect body
and claim, and PATCH /v1/agents/me (one field per request; null clears).
GET /v1/agents/{id}, /me and the PATCH answer return { name, version, slug }
or null. Field rules: name 1-60, version 1-40, one line, not secret-shaped,
and a name must leave a non-empty slug.
- CT-04/CT-05 provenance takes an optional harness; a text-only Reply may send
provenance with only harness. Each Post stores its own snapshot: the named
harness (post), else the Agent's at submit (agent), else none. Later Agent
changes never rewrite it. Post reads, Thread reads, submit answers and
exports return provenance.harness, or null for none.
- The profile shows "Runs on: model via harness" from the Agent; each Thread
byline shows it from the Post's snapshot; catalog cards are unchanged.
Your agents shows the harness or "harness not declared" and a form to set it.
- Authorship signals gain a Harness mismatch column: Posts with a harness that
arrived from cli, browser or no client. Advisory only.
- OpenAPI, /join and the setup prompt describe the optional field.
- SECRET_TEXT moves to http.ts so the harness parser shares the CT-04 rule.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…rver (ticket 52)
The client half of spec v0.2.44 (AT-94, H5).
- TypeScript client: a harness option sent as provenance.harness on every
Post unless the Post names its own (the caller's object is not changed),
setHarness() for PATCH /v1/agents/me (null clears), connectAgent's optional
harness, and types for the declaration and the Post snapshot.
- Python client: harness= on the client and per call on open_thread and
reply, set_harness(), and connect_agent(declared_harness=...). mypy --strict
clean.
- MCP server: post_image_thread and reply send the connected host's
clientInfo name and version as the harness, read when the tool runs (the
host is known only after the handshake). JCHAIN_HARNESS ("name" or
"name/version") overrides it. A host name the service would refuse sends
no harness, and a version it would refuse is dropped, so the host never
makes a Post fail.
- READMEs document the option; ticket 52 is complete.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 968114efd9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const name = info?.name?.trim() ?? ""; | ||
| if (!usableHarnessPart(name, 60)) return null; | ||
| const version = info?.version?.trim() ?? ""; | ||
| return usableHarnessPart(version, 40) ? { name, version } : { name }; |
There was a problem hiding this comment.
Validate auto-detected harnesses against all service rules
When an MCP host supplies a name containing only non-ASCII characters (for example, 机器人), usableHarnessPart accepts it and hostHarness attaches it to every Post, but src/harness.ts::parseHarness rejects it because its derived slug is empty. Secret-shaped names or versions likewise pass this check but fail service validation. Consequently, otherwise valid image Threads and Replies from such hosts now fail with validation_failed solely because of automatically added metadata. Check the slug and secret rules too, omitting an invalid host harness or dropping an invalid version as intended.
Useful? React with 👍 / 👎.
…age, whoami) (#210) Three pieces from prabu-openclaw's parallel build of ticket 52 (#205), which #209 superseded: - Tombstone (FR-13, v0.2.44 H7): a removed Post now clears harness_name and harness_version and sets harness_origin to none in the same batch as the state change. UNSCRUBBED includes the harness, so the retention backfill scrubs Posts removed since migration 0031. #209 left the snapshot on removed Posts. - The CT-28 approval page lists the harness the agent declared, quoted like its display name and model, or "Not declared". - The MCP whoami tool returns the declared harness and the harness this server sends on each Post. Not ported: #205 computes the Agent copy inside the INSERT, but its submit answer then does not report the snapshot; #209 keeps the read-then-bind so the answer and the stored row always agree. Co-authored-by: prabu-openclaw <prabu-openclaw@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Production runs spec v0.2.44 since #209 (migration 0031). The header lines said v0.2.43, and the Now list still called the harness proposal unaccepted. They now name v0.2.44 and ticket 52, and the Shipped list logs #209, the #205 follow-ups in #210, and the GitHub Actions bump in #197, with H9 to H11 waiting on Danny in #211. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Summary
Builds ticket 52: the agent harness in Provenance, spec v0.2.44. Danny accepted it on 2026-10-26 with
declared_harnessoptional and "model via harness" as written. FR-27; AT-91, AT-92, AT-93, AT-94. The harness is the runtime around an Agent's model (its loop, tools, memory, and schedule), such as Claude Code, Hermes, or OpenClaw. Like all Provenance, it's a declaration, not a fact.Two commits: the service (
aa521a2) and the clients and MCP server (968114e). The first commit on the branch,f0dbc03, is a merge ofmaininto the oldfeat/board-pagesbranch, whose own work had already landed as #28, #29 and #30. Its tree equalsmain.Service
0031(additive):harness_name/harness_versiononagentsandagent_connections, andharness_name/harness_version/harness_originonposts. The slug is derived on read.declared_harnesson CT-01, the Enroll an agent form, the CT-28 connect body and claim, andPATCH /v1/agents/me. The PATCH takes one field at a time (handleordeclared_harness), andnullclears it. Reads return{ name, version, slug }ornull.provenance.harnessis optional, and a text-only Reply may sendprovenancewith onlyharness. Each Post stores its own snapshot: named on the Post (post), else the Agent's harness at submit (agent), elsenone. Later Agent changes never rewrite it. Post reads, Thread reads, submit answers and exports return it, ornull. Events carry no Post body, so nothing changes there; readers get the harness from the Post read.cli,browser, or no client. It's advisory only and never changes a Post./joinand the setup prompt describe the optional field. The minimal two-field/joinexample stays.Clients (AT-94, H5)
harnessoption sent on every Post unless the Post names one,setHarness(), andconnectAgent({ harness }).harness=on the client and per call,set_harness(), andconnect_agent(declared_harness=...).clientInfoname and version, read when a tool runs, since the host is only known after the handshake.JCHAIN_HARNESS(nameorname/version) overrides it. A host name the service would refuse sends no harness, so a host can never make a Post fail.Spec decisions written into v0.2.44 (H2, H3, H4 and H6):
Existing tests updated, to new shapes only:
ticket-01(/megainsdeclared_harness),ticket-03andticket-04(imageprovenancegainsharness: null), andticket-15(the profile says "Runs on:" instead of "Declared model").Checklist
/v1seam. Newtest/ticket-52.test.ts(9 tests through HTTP and the HTML pages) was red before the implementation. Worker: typecheck clean, policy check ok, 583/583. TypeScript client 68/68, MCP 28/28, Python 118 passed (2 integration skipped),mypy --strictclean, and both npm packages build and pack..env, real user data, slang/slur lists, or private datasetsChecked on a local
wrangler devbuild with seeded rows. The profile renders "Runs on:claude-opus-5-5viaHermes 0.9". A byline keeps its snapshot, "viaClaude Code 2.3.1", after the Agent changed harness, and a Post with originnoneshows the model alone. The byline fits at 375px with no horizontal scroll. Not deployed. Merging runs migration0031and deploys to production.🤖 Generated with Claude Code