Skip to content

feat(goals): keep active session goals in per-turn context + continuance QA scenarios#100468

Merged
steipete merged 3 commits into
mainfrom
feat/goal-continuance-65fd03
Jul 6, 2026
Merged

feat(goals): keep active session goals in per-turn context + continuance QA scenarios#100468
steipete merged 3 commits into
mainfrom
feat/goal-continuance-65fd03

Conversation

@steipete

@steipete steipete commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

A session goal (docs/tools/goal.md) persists as session state, but nothing surfaces it to the model on later turns: after a few turns or a compaction, the agent only rediscovers the objective if it happens to call get_goal. Persistence of the goal record is not persistence of pursuit — long-form work silently stalls and operators end up re-prompting "continue". There was also zero QA coverage proving multi-turn goal followthrough, so continuance regressions were invisible.

Closes #100409.

Why This Change Was Made

Per-turn goal context (active goals only). buildInboundUserContextPrefix (src/auto-reply/reply/inbound-meta.ts) now appends one bounded line when the session goal is active:

Active goal: <objective> — advance it or update its status (get_goal/update_goal).
  • User-role, current-turn context only — system prompt and prior transcript bytes untouched, so prompt caching is preserved.
  • paused/blocked/budget_limited/usage_limited/complete inject nothing: an operator stop stays stopped. Heartbeat turns are excluded.
  • Objectives are whitespace-normalized and truncated at 200 chars.
  • No goal-state writes from this path, no new config surface.

Staleness across queueing/interrupts. Queued turns build their context early; a goal can complete/pause/start while they wait. Admission (reply-turn-admission.ts) already loads the latest session entry under the lifecycle fence, so it now exposes that entry, and queued/interrupt-delayed turns refresh only the previously injected goal line at admission (refreshActiveGoalContext, provenance-tracked via injectedGoalContexts so only generated lines are ever touched — never user text). Interrupt-race path in get-reply-run.ts re-resolves after an actual admission wait.

QA continuance scenarios (qa/scenarios/goals/, new theme + goals.context-injection/goals.continuance coverage IDs in taxonomy.yaml):

  1. goal-context-next-turn/goal start, then an unrelated turn; asserts the exact goal line in the captured mock-provider request payload.
  2. goal-context-survives-compaction — goal line still present on the post-compaction turn.
  3. goal-followthrough-live (live-only tier) — with an active multi-step goal, a bare "continue" turn must advance the next concrete step instead of re-planning, mirroring the instruction-followthrough contract.

User Impact

Sessions with an active /goal keep pursuing it: the objective is visible to the model on every turn and survives compaction, queueing, and interruptions. Operator semantics unchanged — pausing/completing a goal immediately stops injection. Documented in the new "Goal context on every turn" section of goal docs.

Evidence

  • Focused Testbox run: 399 tests passed (366 reply-path + 33 QA catalog/schema); repository guards + full typecheck passed; targeted lint clean; import-cycle check and git diff --check clean.
  • Local focused rerun of inbound-meta.test.ts, followup-runner.test.ts, get-reply-run.media-only.test.ts (active/inactive/no-goal/truncation, queued-refresh staleness, heartbeat exclusion, interrupt-race regression).
  • Prompt snapshots unchanged (no system-prompt/tool-catalog changes).
  • Structured second-model review (Codex, gpt-5.5): no actionable findings.
  • Live-only QA scenario is catalog-validated; not executed against a paid live model in this PR.
  • Release-note context: user-facing feat — active session goals now stay in per-turn context and are covered by continuance QA scenarios.

@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation agents Agent runtime and tooling extensions: qa-lab size: L maintainer Maintainer-authored PR labels Jul 5, 2026
@clawsweeper

clawsweeper Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 5, 2026, 10:49 PM ET / 02:49 UTC.

Summary
The branch injects active session-goal context into per-turn reply prompts, refreshes queued goal context at admission, documents the behavior, and adds goal continuance QA scenarios and taxonomy entries.

PR surface: Source +151, Tests +310, Docs +13, Other +435. Total +909 across 17 files.

Reproducibility: yes. for the review blockers by source inspection. The active-goal line is generated into currentInboundContext, the default steer path sends only prompt text, and room-event wrapping places the same line into ambient room context.

Review metrics: 2 noteworthy metrics.

  • Generated Context Delivery Paths: 1 new marker, 1 default steer path bypasses it. The new active-goal marker is carried through currentInboundContext, but the default active-run steering API accepts only text and options.
  • Maturity Projections: 1 taxonomy feature added, 0 docs/maturity projections updated. The scoped docs guide marks docs/maturity as generated from taxonomy.yaml, so the committed projections should stay in sync.

Stored data model
Persistent data-model change detected: database schema: src/auto-reply/reply/followup-runner.test.ts, database schema: src/auto-reply/reply/inbound-meta.test.ts, serialized state: src/auto-reply/reply/followup-runner.test.ts, vector/embedding metadata: src/auto-reply/reply/followup-runner.test.ts. Confirm migration or upgrade compatibility proof before merge.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #100409
Summary: This PR is the candidate implementation for the linked goal-continuance feature issue, but the implementation still has merge-blocking delivery and docs consistency gaps.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🧂 unranked krab
Proof: 🌊 off-meta tidepool
Patch quality: 🧂 unranked krab
Result: blocked by patch quality or review findings.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P2] Fix active-run steer delivery so active-goal context reaches the model on default queued turns.
  • Suppress active-goal context for ambient room events or gate it to user-request turns.
  • Regenerate the maturity docs from the updated taxonomy.

Risk before merge

  • [P1] Merging as-is would leave active-goal context out of default active-run steer turns, so concurrent messages can still lose the goal state the PR claims to preserve.
  • [P1] Merging as-is can turn ambient room events into goal-advancement nudges, creating unsolicited or wrongly triggered replies in channels that default to silence.
  • [P1] The PR changes model-visible prompt context for every active-goal session, so maintainers still need to confirm the every-turn prompt contract.
  • [P1] The taxonomy addition without regenerated maturity docs would publish stale scorecard projections and can fail maturity consistency checks.

Maintainer options:

  1. Fix Context Delivery Before Merge (recommended)
    Update the steer path to include refreshed active-goal context, suppress goal nudges for ambient room events, and regenerate maturity docs before merge.
  2. Accept A Narrower First Contract
    Maintain the current implementation only if maintainers explicitly accept that active-run steering and ambient room events are outside this release's goal-continuance contract.
  3. Pause For Prompt Contract Review
    Pause the PR if maintainers want to revisit whether active goals should be injected automatically on every turn.

Next step before merge

  • [P1] Protected maintainer/product-direction PR needs author or maintainer follow-up on the prompt contract plus the three merge blockers before it can land.

Maintainer decision needed

  • Question: Should OpenClaw adopt bounded active-goal context as the permanent every-turn prompt contract for all active /goal sessions once the runtime blockers are fixed?
  • Rationale: This changes model-visible behavior across all active-goal sessions and the linked issue already carries product-decision signaling, so the exact contract should be confirmed by an owner rather than treated as a pure bug fix.
  • Likely owner: steipete — He owns the current goal feature proposal and has the strongest recent history across session goals and adjacent reply-run behavior.
  • Options:
    • Adopt Every-Turn Active-Goal Context (recommended): Proceed with this PR direction after fixing steer delivery, suppressing ambient room-event nudges, refreshing generated docs, and keeping inactive goals out of context.
    • Limit Scope To QA First: Keep or land only scenarios/source proof while deferring automatic active-goal injection until a later product decision.
    • Pause The Direction: Hold or close this PR if goals should remain explicit command/tool state rather than automatic per-turn prompt context.

Security
Cleared: No dependency, workflow, lockfile, permission, secret-handling, or downloaded-code changes were found; the blockers are session-context and generated-doc correctness.

Review findings

  • [P2] Include active-goal context in steered turns — src/auto-reply/reply/prompt-prelude.ts:247
  • [P2] Suppress goal nudges for ambient room events — src/auto-reply/reply/inbound-meta.ts:811
  • [P2] Regenerate maturity docs for the taxonomy feature — taxonomy.yaml:1615-1617
Review details

Best possible solution:

Land bounded active-goal context only after steering delivery, room-event gating, and generated maturity docs are fixed, then have maintainers confirm the every-turn goal prompt contract.

Do we have a high-confidence way to reproduce the issue?

Yes for the review blockers by source inspection. The active-goal line is generated into currentInboundContext, the default steer path sends only prompt text, and room-event wrapping places the same line into ambient room context.

Is this the best way to solve the issue?

No as written. The per-turn active-goal design is plausible, but it must cover steering, avoid ambient room-event nudges, refresh generated maturity docs, and receive product confirmation before merge.

Full review comments:

  • [P2] Include active-goal context in steered turns — src/auto-reply/reply/prompt-prelude.ts:247
    The previous steering blocker is still present: the new Active goal: line is carried through currentInboundContext, but default active-run steering calls queueEmbeddedAgentMessageWithOutcomeAsync with only followupRun.prompt. A turn that arrives while a run is active therefore misses the documented every-turn goal context; fold the refreshed context into the steer text or route this path through a context-aware delivery API.
    Confidence: 0.9
  • [P2] Suppress goal nudges for ambient room events — src/auto-reply/reply/inbound-meta.ts:811
    For room_event turns, buildReplyPromptEnvelopeBase wraps inboundUserContext into Room context, while the room-event directive says the default is no reply. Because this PR appends Active goal: ... advance it to that same context, unrelated ambient Slack or Discord activity in a goal session can trigger goal work without a user request. Late note: this was unchanged since the earlier reviewed head, but it is still a concrete blocker.
    Confidence: 0.86
    Late finding: first raised on code an earlier review cycle already covered.
  • [P2] Regenerate maturity docs for the taxonomy feature — taxonomy.yaml:1615-1617
    Adding Goal continuance to taxonomy.yaml changes the source taxonomy, but docs/maturity/taxonomy.md at this head still reports Context Engine as 2 capabilities and omits docs/tools/goal.md. The docs guide says docs/maturity/** is generated from taxonomy.yaml, so refresh the generated maturity docs with the taxonomy change. Late note: this mismatch was visible before the latest QA-only commit.
    Confidence: 0.88
    Late finding: first raised on code an earlier review cycle already covered.

Overall correctness: patch is incorrect
Overall confidence: 0.91

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 75c8753a2cb5.

Label changes

Label changes:

  • add merge-risk: 🚨 message-delivery: The PR can inject a goal-advancement instruction into ambient room-event context where the current contract defaults to no reply.

Label justifications:

  • P2: This is a normal-priority feature PR with bounded but merge-blocking session-context and docs-consistency defects.
  • merge-risk: 🚨 session-state: The PR changes active session goal context and currently leaves the default concurrent-turn path without the intended goal state.
  • merge-risk: 🚨 message-delivery: The PR can inject a goal-advancement instruction into ambient room-event context where the current contract defaults to no reply.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🌊 off-meta tidepool and patch quality is 🧂 unranked krab.
  • status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Not applicable: The external contributor proof gate is not applied because this PR carries the protected maintainer label; the PR body reports Testbox/local evidence, while the live-only QA scenario remains unrun.
Evidence reviewed

PR surface:

Source +151, Tests +310, Docs +13, Other +435. Total +909 across 17 files.

View PR surface stats
Area Files Added Removed Net
Source 7 163 12 +151
Tests 3 311 1 +310
Docs 2 13 0 +13
Config 0 0 0 0
Generated 0 0 0 0
Other 5 435 0 +435
Total 17 922 13 +909

What I checked:

Likely related people:

  • steipete: GitHub history ties him to the core session goals feature and recent agent-runner work, and he opened the linked goal-continuance issue and this PR. (role: feature owner and recent adjacent contributor; confidence: high; commits: a509c48f0ea2, 2c31af136429, f0093b7020e7; files: src/config/sessions/goals.ts, src/auto-reply/reply/agent-runner.ts, docs/tools/goal.md)
  • obviyus: Recent GitHub path history shows several inbound-meta and room-event prompt changes that share the invariant this PR touches. (role: recent inbound-context and room-event contributor; confidence: medium; commits: 3706ebed331f, 568be74e159e, 59a6240dae13; files: src/auto-reply/reply/inbound-meta.ts, src/auto-reply/reply/prompt-prelude.ts)
  • RomneyDa: GitHub history shows repeated recent ownership of taxonomy and generated maturity scorecard infrastructure. (role: maturity scorecard and taxonomy contributor; confidence: medium; commits: 27711b500c39, 4460fa78c320, 9666db607eb5; files: taxonomy.yaml, docs/maturity/taxonomy.md, qa/maturity-scores.yaml)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (3 earlier review cycles)
  • reviewed 2026-07-05T21:50:08.888Z sha 5fc6155 :: needs real behavior proof before merge. :: [P1] Keep active-goal context out of transcript history
  • reviewed 2026-07-05T22:00:11.312Z sha 5fc6155 :: needs real behavior proof before merge. :: [P1] Keep active-goal context out of transcript history | [P2] Include goal context in steered turns
  • reviewed 2026-07-06T01:56:03.439Z sha ae10620 :: needs real behavior proof before merge. :: [P2] Include active-goal context in steered turns

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

Copy link
Copy Markdown
Contributor

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: 5fc6155837

ℹ️ 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".

baseBody: baseBodyFinal,
hasUserBody,
inboundUserContext,
activeGoalContext,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Badge Include goal context in steered turns

When a session is already active and queue mode stays at its default steer (resolveQueueSettings defaults to "steer"), runReplyAgent injects only followupRun.prompt through queueEmbeddedAgentMessageWithOutcomeAsync (src/auto-reply/reply/agent-runner.ts:1288-1294) and does not apply followupRun.currentInboundContext. Since the new active-goal line is carried only via activeGoalContext/currentInboundContext here, any turn sent while a run is streaming is steered without the active goal context, contradicting the new docs/QA claim that every user/chat turn with an active goal includes it. Please fold the current inbound context into the steer prompt or extend the steering path to accept it.

Useful? React with 👍 / 👎.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. P2 Normal backlog priority with limited blast radius. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. labels Jul 5, 2026
steipete added 2 commits July 5, 2026 18:44
Active goals now inject one bounded user-role context line on every
non-heartbeat turn, refreshed at queued/interrupt admission via
provenance-tracked generated lines so operator stops take effect
immediately. Adds qa/scenarios/goals continuance scenarios and
goals.* coverage IDs.
@steipete
steipete force-pushed the feat/goal-continuance-65fd03 branch from c0731c3 to ae10620 Compare July 6, 2026 01:47

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

Copy link
Copy Markdown
Contributor

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: ae10620c40

ℹ️ 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 on lines +809 to +811
const activeGoalContext = formatActiveGoalContext(sessionEntry);
if (activeGoalContext) {
blocks.push(activeGoalContext);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Badge Skip goal nudges for ambient room events

When ctx.InboundEventKind === "room_event", this block still lands in the Room context because buildReplyPromptEnvelopeBase wraps inboundUserContext with buildRoomEventContext. Room events include ambient/unmentioned Slack and Discord messages and the room-event directive says the default is no reply, but this new line tells the model to advance the active goal, so an unrelated channel message in a session with an active goal can start goal work without a user request. Gate this injection to actual user-request turns or explicitly suppress it for room_event.

Useful? React with 👍 / 👎.

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

Copy link
Copy Markdown
Contributor

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: 818dd18ded

ℹ️ 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 taxonomy.yaml
Comment on lines +1615 to +1617
- name: Goal continuance
coverageIds: [goals.context-injection, goals.continuance]
description: Active session goals remain visible in current-turn context and drive concrete followthrough across later turns and compaction.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Badge Regenerate maturity docs for the taxonomy addition

Adding this third Context Engine feature changes the taxonomy inputs, but the generated docs/maturity/** projections were not refreshed: docs/maturity/taxonomy.md still reports Context Engine as 2 capabilities and omits docs/tools/goal.md, and repo-wide search only finds goals.context-injection / goals.continuance in taxonomy.yaml plus the new scenarios. The scoped docs guide says docs/maturity/** is generated from taxonomy.yaml via pnpm maturity:render, so leaving it stale will make the maturity check fail once dependencies are present and will publish an outdated scorecard.

Useful? React with 👍 / 👎.

@clawsweeper clawsweeper Bot added the merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. label Jul 6, 2026
@steipete
steipete merged commit bf04d04 into main Jul 6, 2026
108 checks passed
@steipete
steipete deleted the feat/goal-continuance-65fd03 branch July 6, 2026 03:55
github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 6, 2026
…nce QA scenarios (openclaw#100468)

* feat(goals): keep active session goals in per-turn context (openclaw#100409)

Active goals now inject one bounded user-role context line on every
non-heartbeat turn, refreshed at queued/interrupt admission via
provenance-tracked generated lines so operator stops take effect
immediately. Adds qa/scenarios/goals continuance scenarios and
goals.* coverage IDs.

* docs: regenerate docs map for goal context section

* fix(qa): use requiredChannelDriver instead of execution.channel pin in goal scenarios
giodl73-repo pushed a commit to giodl73-repo/openclaw that referenced this pull request Jul 8, 2026
…nce QA scenarios (openclaw#100468)

* feat(goals): keep active session goals in per-turn context (openclaw#100409)

Active goals now inject one bounded user-role context line on every
non-heartbeat turn, refreshed at queued/interrupt admission via
provenance-tracked generated lines so operator stops take effect
immediately. Adds qa/scenarios/goals continuance scenarios and
goals.* coverage IDs.

* docs: regenerate docs map for goal context section

* fix(qa): use requiredChannelDriver instead of execution.channel pin in goal scenarios
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling docs Improvements or additions to documentation extensions: qa-lab maintainer Maintainer-authored PR merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. P2 Normal backlog priority with limited blast radius. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: L status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Goal continuance — per-turn goal context + QA continuance scenarios

1 participant