Repository navigation
Conversation
OpenClaw passes a run's activeProjectKeys to before_prompt_build but not to agent_end, so automatic capture resolved its Scope without the project binding that the same run's recall used. Record the run's project keys at before_prompt_build and use them at agent_end when the host omits them.
There was a problem hiding this comment.
Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.
An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.
hidb4ai
left a comment
There was a problem hiding this comment.
Reviewed a86fc78. No blocking findings. Carrying the run's project keys into capture fixes the recall/capture Scope mismatch while preserving host-supplied keys and the existing Server resolution order. No new database tables or public interfaces. The regression reproduces against the base implementation and passes on this head; interleaved-run and cleanup probes also pass. Real OpenClaw Gateway + Server acceptance was not independently rerun.
| return undefined; | ||
| } | ||
| const projectKeys = runProjectKeys.get(runId); | ||
| runProjectKeys.delete(runId); |
There was a problem hiding this comment.
[P2] Preserve project bindings across completion replays
Replaying a successful agent_end without project keys—a case already covered by the lifecycle's replay contract—now resolves to the agent/default Scope because the first delivery deletes the saved binding. Since Source deduplication is Scope-local, this duplicates the project prompt into another Scope; preserve replay-safe binding resolution or suppress already captured runs while keeping memory bounded.
There was a problem hiding this comment.
Fixed in 5a91c50. agent_end no longer drops the run's projects: it moves them to a separate map of completed runs, so a replayed agent_end, including a retry after a failed capture, resolves the same project Scope. Both maps keep their 64 most recent runs, so completed runs never evict runs still in progress.
captures a replayed turn under the same project binding and retries a failed capture under the same project binding when the turn is replayed cover the two cases. Both fail at a86fc780, where the replay goes to scp_default.
The first `agent_end` removed the run's saved projects, so a replayed `agent_end` captured into the agent or default Scope. Source deduplication holds only within one Scope, so the prompt was stored twice. A completed run now moves to its own bounded map: a replay, or a retry after a failed capture, resolves the same project Scope, and completed runs do not evict runs that are still in progress.
There was a problem hiding this comment.
Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.
An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.
Which issue or RFC does this PR close?
No tracking issue. A real-host OpenClaw service-chain E2E, which will follow in its own PR, found this defect.
Rationale for this change
The OpenClaw integration docs say the plugin resolves one existing Scope before every operation. Resolution uses an explicit
scopeId, then durable bindings for the OpenClaw session, the ordered active projects, and the agent identity. Automatic capture did not apply the project step.OpenClaw 2026.8.1 passes the run's
activeProjectKeystobefore_prompt_buildbut not toagent_end;buildEmbeddedAgentEndContextomits them. The capture's/v1/scope-bindings/resolverequest therefore carried only the session and agent keys.Suppose a project binding exists but no session binding. The turn's recall reads the project Scope, while its prompt is captured into the agent or default Scope. Prompts captured inside a project are then never recalled in that project.
What changes are included in this PR?
before_prompt_buildrecords the run's active project keys byrunId. It does this before theautoRecallcheck, so capture still works with recall turned off.agent_endreads the record for its run and uses it when the host omitsactiveProjectKeys. Keys the host supplies toagent_enditself still take precedence.agent_end, whether or not the turn succeeded, the record moves from the runs in progress to the completed runs. A replayedagent_end, including a retry after a failed capture, then resolves the same Scope; Source deduplication holds only within one Scope, so resolving a replay elsewhere would store the prompt twice. Each map keeps its 64 most recent runs, so completed runs never evict a run in progress.lifecycle.test.tsruns turns whoseagent_endcontext carries the run but not its projects. It checks capture with recall on and with recall off, and that host-supplied keys win. Two more tests replay a turn'sagent_end: after a successful capture, both deliveries go to the project Scope with the same Source, and closing flushes only that Scope; after a failed capture, the retry also goes to the project Scope.Are there any user-facing changes?
Yes, a fix. With a project binding, automatically captured prompts now land in the project's Scope, the same Scope recall reads. No configuration, API, or docs change.
How was this change tested?
make openclaw-plugin-test: 103 tests pass, plus type check and build.scp_default). It also fails if the precedence is reversed. Both replay tests fail whenagent_endremoves the record, because the replay goes toscp_default.make checkpasses.openclaw gateway run) with the plugin linked, a real Server, and a deterministic model fixture.master, where the project-bound turn's prompt goes to the agent Scope.Not validated:
hooks.allowPromptInjection: false, OpenClaw does not runbefore_prompt_build, so capture falls back to the agent and session bindings.before_compactionis unchanged. OpenClaw 2026.8.1 does not pass project keys to it either. The built-in runner's auto-compaction call passes onlysessionKey, with noagentId, so the plugin's pre-compaction checkpoint returns early on that path. That is a separate defect.agent_end.A high-effort self-review of the diff found five items:
activeProjectKeysfrom OpenClaw.before_compaction.A high-effort review of the replay handling found four items:
completeRunProjects.AI usage statement
Claude Code (Claude Opus 5.5) investigated the OpenClaw host source, wrote the change and the tests, and ran the validation above.