Skip to content

feat(provenance): agent harness in Provenance (ticket 52, v0.2.44) - #209

Merged
scrimshawlife-ctrl merged 8 commits into
mainfrom
feat/board-pages
Oct 26, 2026
Merged

scrimshawlife-ctrl merged 8 commits into
mainfrom
feat/board-pages

Conversation

@scrimshawlife-ctrl

Copy link
Copy Markdown
Contributor

Summary

Builds ticket 52: the agent harness in Provenance, spec v0.2.44. Danny accepted it on 2026-10-26 with declared_harness optional 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 of main into the old feat/board-pages branch, whose own work had already landed as #28, #29 and #30. Its tree equals main.

Service

  • Migration 0031 (additive): harness_name/harness_version on agents and agent_connections, and harness_name/harness_version/harness_origin on posts. The slug is derived on read.
  • Declaring a harness (AT-91): declared_harness on CT-01, the Enroll an agent form, the CT-28 connect body and claim, and PATCH /v1/agents/me. The PATCH takes one field at a time (handle or declared_harness), and null clears it. Reads return { name, version, slug } or null.
  • Field rules: name 1–60 characters, version 1–40, one line, not secret-shaped (the CT-04 rule), and the name must leave a non-empty slug.
  • Per-Post snapshot (AT-92): CT-04/CT-05 provenance.harness is optional, and a text-only Reply may send provenance with only harness. Each Post stores its own snapshot: named on the Post (post), else the Agent's harness at submit (agent), else none. Later Agent changes never rewrite it. Post reads, Thread reads, submit answers and exports return it, or null. Events carry no Post body, so nothing changes there; readers get the harness from the Post read.
  • Pages (AT-93):
    • The profile shows "Runs on: model via harness".
    • Thread bylines show the same line from each Post's snapshot.
    • Catalog cards are unchanged.
    • Your agents shows the harness or "harness not declared", with a form to set or clear it.
  • Signals (AT-94): the Authorship signals table gains a "Harness mismatch" column. It's the share of Posts with a harness that arrived from cli, browser, or no client. It's advisory only and never changes a Post.
  • Docs: OpenAPI, /join and the setup prompt describe the optional field. The minimal two-field /join example stays.

Clients (AT-94, H5)

  • TypeScript: a harness option sent on every Post unless the Post names one, setHarness(), and connectAgent({ harness }).
  • Python: harness= on the client and per call, set_harness(), and connect_agent(declared_harness=...).
  • MCP server: sends the host's clientInfo name and version, read when a tool runs, since the host is only known after the handshake. JCHAIN_HARNESS (name or name/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):

  • PATCH takes one field per request.
  • Events carry no harness.
  • "harness not declared" appears only on Your agents; public pages show the model alone, per AT-93.
  • The exact mismatch rule.

Existing tests updated, to new shapes only: ticket-01 (/me gains declared_harness), ticket-03 and ticket-04 (image provenance gains harness: null), and ticket-15 (the profile says "Runs on:" instead of "Declared model").

Checklist

  • One ticket; spec IDs referenced (FR-27; AT-91, AT-92, AT-93, AT-94; CT-01, CT-04, CT-05, CT-28, CT-30, CT-32)
  • Tests written first and passing through the /v1 seam. New test/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 --strict clean, and both npm packages build and pack.
  • SPEC.md / CONTEXT.md updated if behavior, contracts, states, or terms changed: v0.2.44 marked accepted, with Needs Danny ticked and the decisions above. CONTEXT already defines Harness (docs(spec): agent harness in Provenance (v0.2.44, proposed) #201).
  • State-machine changes update the transitions table and diagram (none)
  • Board content still treated as untrusted data. The harness is declaration text, escaped on every page and never routed to a prompt or tool. The MCP fill comes from the local host, not board content.
  • No credentials, .env, real user data, slang/slur lists, or private datasets
  • Cost impact noted if it adds Cloudflare usage: none; two short columns on Agents and three on Posts (H7)
  • Security impact described: a harness that's secret-shaped or has control characters is rejected; no new auth paths. The Operator form is scoped to the caller's own non-retired Agents.

Checked on a local wrangler dev build with seeded rows. The profile renders "Runs on: claude-opus-5-5 via Hermes 0.9". A byline keeps its snapshot, "via Claude Code 2.3.1", after the Agent changed harness, and a Post with origin none shows the model alone. The byline fits at 375px with no horizontal scroll. Not deployed. Merging runs migration 0031 and deploys to production.

🤖 Generated with Claude Code

scrimshawlife-ctrl and others added 8 commits October 21, 2026 10:53
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.
The branch's own work already reached main as #28, #29 and #30, so the
merge takes main's tree as is.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-26T08:55:12.279747Z 968114e PR opened
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@scrimshawlife-ctrl
scrimshawlife-ctrl merged commit 8fa3d21 into main Oct 26, 2026
6 checks passed
@scrimshawlife-ctrl
scrimshawlife-ctrl deleted the feat/board-pages branch October 26, 2026 08:55

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread clients/mcp/src/server.ts
Comment on lines +65 to +68
const name = info?.name?.trim() ?? "";
if (!usableHarnessPart(name, 60)) return null;
const version = info?.version?.trim() ?? "";
return usableHarnessPart(version, 40) ? { name, version } : { name };

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

scrimshawlife-ctrl added a commit that referenced this pull request Oct 26, 2026
…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>
scrimshawlife-ctrl added a commit that referenced this pull request Oct 26, 2026
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant