Skip to content

feat: add optional ACP semantic edges - #2449

Merged
hallerite merged 22 commits into
mainfrom
codex/rlm-lineage
Aug 31, 2026
Merged

feat: add optional ACP semantic edges#2449
hallerite merged 22 commits into
mainfrom
codex/rlm-lineage

Conversation

@hallerite

@hallerite hallerite commented Aug 26, 2026

Copy link
Copy Markdown
Member

Summary

Adds an optional, versioned ACP extension for typed semantic relationships between model requests while leaving Verifiers' physical training branches unchanged.

  • accept cumulative SemanticEdgeSet payloads under ai.prime.acp/semantic-edges-v1
  • record harness-owned correlation IDs as ModelCall.acp.request_id
  • resolve request-ID edges incrementally into typed MessageNode.semantic_parents
  • preserve arbitrary validated edge labels so new harness relationships do not require a Verifiers schema change
  • pin nano-RLM's merged semantic-edge implementation from #153 at 4a63696

This remains one message-node DAG with physical and semantic parent links, not a second lineage graph. The unrelated concurrent physical-graph race is handled separately in #2477.

Data model

Concept Meaning
MessageNode.parent Exact physical-prefix parent used for training branches.
MessageNode.semantic_parents Ordered typed links to other committed message nodes. Multiple semantic parents are valid.
ParentLink {node, type}, where node is an index into Trace.nodes.
Branch A root-to-leaf physical-parent path, not an agent/session identity.
ACPInfo.request_id Harness-owned request identifier used to resolve ACP edges to committed Verifiers nodes.

For example, a parent request consuming two child results is represented directly on its message node:

MessageNode(
    parent=physical_parent,
    semantic_parents=[
        ParentLink(node=5, type="subagent_return"),
        ParentLink(node=8, type="subagent_return"),
    ],
    ...,
)

nano-RLM initially uses continuation, subagent_call, subagent_return, and compaction. These are conventions rather than a closed enum; other validated labels and namespaced relationships are preserved.

Transport

  1. The harness assigns a request ID and includes X-ACP-Model-Request-ID on the corresponding model request.
  2. Interception stores the ID as ModelCall.acp.request_id and removes both the private correlation header and its locally owned Idempotency-Key before provider forwarding.
  3. The harness publishes its cumulative request-ID edge set in ACP response metadata.
  4. Trace.add_semantic_edges resolves committed source and target requests, validates the additions atomically, and appends ParentLinks to the target nodes.
  5. Replayed cumulative payloads are idempotent, and WireTrace persists the resolved links with the rollout.

Harnesses that omit the header and extension metadata behave exactly as before: ModelCall.acp=None and semantic_parents=[].

Validation

  • full deterministic Verifiers suite passes locally; credential-gated cases skip when credentials are absent
  • focused trace/interception and cumulative-replay coverage: 11 passed
  • Ruff, formatting, Ty, commit hooks, and push hooks pass
  • CI is green on Python 3.11, 3.12, and 3.13, including the live V1 E2E

Note

Medium Risk
Touches interception (headers, idempotency/streaming), trace serialization, and ACP shutdown; behavior is backward-compatible when harnesses omit the extension, but edge resolution errors or mis-correlated request IDs could fail rollouts.

Overview
Adds an optional ACP extension so harnesses can declare typed relationships between logical model requests without changing how physical training branches are built from MessageNode.parent.

Harnesses can send X-ACP-Model-Request-ID on intercepted calls; the server stores it on ModelCall.acp and strips private ACP headers before the provider. Cumulative edge payloads under ai.prime.acp/semantic-edges-v1 are applied on ACP turns and on session/close via Trace.add_semantic_edges, which maps request IDs to sampled nodes and appends MessageNode.semantic_parents (ParentLink with extensible edge types). Validation rejects duplicates, self-edges, and cycles; SDK retries sharing one request ID resolve to the last committed node.

RLM is bumped to a nano-rlm commit that emits these edges, with version-scoped install caches and session metrics also consumable from close metadata. E2E checks for RLM now assert every call has ACP info and semantic parent links point at sampled nodes. aiohttp is pinned to >=3.14.1.

Reviewed by Cursor Bugbot for commit a0dc9c8. Bugbot is set up for automated code reviews on this repo. Configure here.

@hallerite hallerite changed the title feat: record recursive RLM lineage feat: add optional ACP lineage provenance Aug 27, 2026
@hallerite
hallerite marked this pull request as ready for review August 27, 2026 01:59
Comment thread verifiers/v1/interception/server.py Outdated
@macroscopeapp

macroscopeapp Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR introduces a substantial ACP semantic-edge capability across interception, trace serialization, ACP session lifecycle, and the RLM runtime, including a new default dependency pin. The extension is optional and additive for ordinary requests, but its cross-cutting changes to shared production paths warrant human review.

No code changes detected at a0dc9c8. Prior analysis still applies.

You can add or adjust custom eligibility rules. Learn more.

Comment thread verifiers/v1/interception/server.py
Comment thread verifiers/v1/harnesses/rlm/harness.py Outdated
Comment thread verifiers/v1/trace.py Outdated
Comment thread verifiers/v1/trace.py Outdated
Comment thread verifiers/v1/semantic.py Outdated
Comment thread verifiers/v1/trace.py Outdated
Comment thread verifiers/v1/trace.py Outdated
@hallerite hallerite changed the title feat: add optional ACP lineage provenance feat: add optional ACP semantic edges Aug 27, 2026
Comment thread verifiers/v1/harnesses/rlm/harness.py Outdated

@mikasenghaas mikasenghaas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nice this looks quite clean indeed. i think one thing we need to make super clear in the api itself is that the difference between

  • vf-owned message node linking (rn we have a list of nodes and use indices to point ot parents and link model calls to nodes)
  • harness-owned (via acp) linking, rn via request_id
    it shoud be ultra clear which ids/indices come from vf and which are advertised by the harness

Comment thread verifiers/v1/trace.py Outdated
Comment thread verifiers/v1/trace.py Outdated
Comment thread verifiers/v1/trace.py Outdated
Comment thread verifiers/v1/trace.py Outdated
Comment thread verifiers/v1/semantic.py Outdated
Comment thread verifiers/v1/semantic.py Outdated
Comment thread verifiers/v1/graph.py
Comment thread verifiers/v1/graph.py Outdated
Comment thread verifiers/v1/graph.py

@cursor cursor 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.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit ce54823. Configure here.

Comment thread verifiers/v1/interception/server.py

@mikasenghaas mikasenghaas left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nice!

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.

2 participants