Skip to content

feat(cron): inject output history into isolated agent prompts#44957

Open
Zynoo71 wants to merge 1 commit intoopenclaw:mainfrom
Zynoo71:feat/cron-output-history
Open

feat(cron): inject output history into isolated agent prompts#44957
Zynoo71 wants to merge 1 commit intoopenclaw:mainfrom
Zynoo71:feat/cron-output-history

Conversation

@Zynoo71
Copy link
Copy Markdown

@Zynoo71 Zynoo71 commented Mar 13, 2026

Problem

Isolated cron sessions start fresh each run (forceNew: true), so the agent has zero memory of previous outputs. This causes:

  • Repetitive content: daily briefings repeat the same news/updates
  • No change tracking: monitoring jobs can't compare current vs previous state
  • No iterative analysis: each run starts from scratch, unable to build on prior findings
  • No variety: content scheduling produces duplicate outputs

Solution

Add a per-job outputHistory flag. When enabled:

  1. After successful delivery, the output text is recorded in job.state.recentOutputs (capped at 5 entries, FIFO)
  2. On subsequent runs, recent outputs are injected into the agent's system prompt as context
  3. Outputs are truncated to ≤600 characters (head + tail with separator) to keep prompt size bounded

Use cases

  • Daily briefings: agent sees what it reported yesterday, avoids repetition
  • Monitoring: agent compares current metrics against previous readings
  • Iterative analysis: agent builds on prior findings across runs
  • Content scheduling: agent maintains variety by seeing recent outputs

Changes

  • Add outputHistory field to CronAgentTurnPayloadFields and recentOutputs to CronJobState
  • New output-history.ts: buildOutputHistoryBlock + truncateOutputForHistory
  • Inject history block into agent prompt in run.ts
  • Record delivered output in timer.ts applyJobResult
  • Support outputHistory in mergeCronPayload / buildPayloadFromPatch
  • Guard against invalid timezone in output formatting
  • Update gateway protocol schema and cron tool description

Test plan

  • Unit tests: buildOutputHistoryBlock guard conditions, formatting, timezone fallback, truncation bounds
  • Integration tests: recording, FIFO cap, no-record when disabled/failed, truncation
  • E2E tests: prompt injection through real runCronIsolatedAgentTurn code path

🤖 Generated with Claude Code

@openclaw-barnacle openclaw-barnacle Bot added app: web-ui App: web-ui gateway Gateway runtime agents Agent runtime and tooling size: L labels Mar 13, 2026
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Mar 13, 2026

Greptile Summary

This PR adds a per-job outputHistory flag that injects recent delivered outputs into the isolated agent's prompt, allowing recurring cron jobs to build context across runs (avoid repetition, track changes, etc.). The implementation is architecturally clean — a well-tested output-history.ts module, bounded FIFO storage (5 entries, 600-char truncation with head+tail), timezone-aware formatting with fallback, and appropriate schema/validator updates.

Key issue to resolve before merging:

  • Output history silently never records for delivery.mode: "none" jobs (src/cron/service/timer.ts, lines 344–349 and src/cron/service.output-history-recording.test.ts). The recording gate requires result.delivered === true, but delivered is only set to true inside the deliveryRequested branch of dispatchCronDelivery. Jobs with no delivery channel (mode: "none") always exit with delivered === false, so recentOutputs never accumulates. The integration tests mask this by mocking runIsolatedAgentJob to return delivered: true for mode: "none" jobs — which does not match real behavior. The "Monitoring" and analysis use cases highlighted in the PR description are both likely to use mode: "none", making the feature inert for a core intended audience. Consider gating on result.status === "ok" (with non-empty output) instead of result.delivered, and updating the tests accordingly.

Minor:

  • The output history block is appended after the delivery instruction in run.ts. Placing context before instructions is generally preferred for model comprehension, though this is not a correctness issue.

Confidence Score: 2/5

  • Not safe to merge as-is — the outputHistory feature is silently non-functional for the primary advertised use cases (monitoring, analysis) that use delivery.mode: "none".
  • The core recording condition (result.delivered) is incompatible with the most common configuration for the feature's stated use cases. Integration tests use unrealistic mocks that hide this gap, so the bug would not surface in CI. No data loss or security regression, but the feature effectively ships broken for a significant subset of intended jobs.
  • src/cron/service/timer.ts (recording gate) and src/cron/service.output-history-recording.test.ts (unrealistic mocks) need the most attention.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/cron/service/timer.ts
Line: 344-349

Comment:
**Output history never recorded for `delivery.mode: "none"` jobs**

The recording gate requires `result.delivered === true`, but `delivered` is only ever set to `true` inside the `if (params.deliveryRequested …)` branch of `dispatchCronDelivery`. When a job uses `delivery.mode: "none"`, `deliveryRequested` is `false`, that branch is never entered, and `delivered` stays `false`. The consequence is that `outputHistory: true` is silently inert for any job that does not deliver to a channel — including the "Monitoring" use case explicitly listed in the PR description.

The integration tests in `service.output-history-recording.test.ts` all build jobs with `delivery: { mode: "none" }` but then mock `runIsolatedAgentJob` to return `delivered: true`, which does not reflect what the real code path produces for that delivery mode, so the tests do not catch this gap.

One approach is to record history on a successful run regardless of delivery, or only gate on `result.status === "ok"` with a non-empty output:

```ts
  // Record output for history when enabled and the run succeeded (even without delivery).
  if (
    result.status === "ok" &&
    result.outputText?.trim() &&
    job.payload.kind === "agentTurn" &&
    job.payload.outputHistory
  ) {
```

If the intent really is to only record *delivered* outputs, the feature description, tool docs, and PR description should call this out explicitly, and the "Monitoring" use case should be updated to require a delivery channel.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: src/cron/isolated-agent/run.ts
Line: 484-487

Comment:
**Output history appended after delivery instructions**

`commandBody` at this point already contains the delivery instruction (e.g. "Return your summary as plain text…"). Appending the output history block after the delivery instruction means the previous-outputs context lands at the very end of the prompt, after the agent has already received its marching orders. In practice this is fine, but many prompting guides recommend placing context *before* instructions. Consider injecting the history block before `appendCronDeliveryInstruction` so the ordering is: task → history context → delivery instruction.

How can I resolve this? If you propose a fix, please make it concise.

Last reviewed commit: 2c6068b

Comment thread src/cron/service/timer.ts Outdated
Comment on lines +344 to +349
if (
result.delivered &&
result.outputText?.trim() &&
job.payload.kind === "agentTurn" &&
job.payload.outputHistory
) {
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.

Output history never recorded for delivery.mode: "none" jobs

The recording gate requires result.delivered === true, but delivered is only ever set to true inside the if (params.deliveryRequested …) branch of dispatchCronDelivery. When a job uses delivery.mode: "none", deliveryRequested is false, that branch is never entered, and delivered stays false. The consequence is that outputHistory: true is silently inert for any job that does not deliver to a channel — including the "Monitoring" use case explicitly listed in the PR description.

The integration tests in service.output-history-recording.test.ts all build jobs with delivery: { mode: "none" } but then mock runIsolatedAgentJob to return delivered: true, which does not reflect what the real code path produces for that delivery mode, so the tests do not catch this gap.

One approach is to record history on a successful run regardless of delivery, or only gate on result.status === "ok" with a non-empty output:

  // Record output for history when enabled and the run succeeded (even without delivery).
  if (
    result.status === "ok" &&
    result.outputText?.trim() &&
    job.payload.kind === "agentTurn" &&
    job.payload.outputHistory
  ) {

If the intent really is to only record delivered outputs, the feature description, tool docs, and PR description should call this out explicitly, and the "Monitoring" use case should be updated to require a delivery channel.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/cron/service/timer.ts
Line: 344-349

Comment:
**Output history never recorded for `delivery.mode: "none"` jobs**

The recording gate requires `result.delivered === true`, but `delivered` is only ever set to `true` inside the `if (params.deliveryRequested …)` branch of `dispatchCronDelivery`. When a job uses `delivery.mode: "none"`, `deliveryRequested` is `false`, that branch is never entered, and `delivered` stays `false`. The consequence is that `outputHistory: true` is silently inert for any job that does not deliver to a channel — including the "Monitoring" use case explicitly listed in the PR description.

The integration tests in `service.output-history-recording.test.ts` all build jobs with `delivery: { mode: "none" }` but then mock `runIsolatedAgentJob` to return `delivered: true`, which does not reflect what the real code path produces for that delivery mode, so the tests do not catch this gap.

One approach is to record history on a successful run regardless of delivery, or only gate on `result.status === "ok"` with a non-empty output:

```ts
  // Record output for history when enabled and the run succeeded (even without delivery).
  if (
    result.status === "ok" &&
    result.outputText?.trim() &&
    job.payload.kind === "agentTurn" &&
    job.payload.outputHistory
  ) {
```

If the intent really is to only record *delivered* outputs, the feature description, tool docs, and PR description should call this out explicitly, and the "Monitoring" use case should be updated to require a delivery channel.

How can I resolve this? If you propose a fix, please make it concise.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in ce3675de6 — recording gate changed from result.delivered to result.status === "ok", so output history works regardless of delivery mode. Updated integration test to verify error runs are not recorded.

Comment thread src/cron/isolated-agent/run.ts Outdated
Comment on lines +484 to +487
const outputHistoryBlock = buildOutputHistoryBlock(params.job);
if (outputHistoryBlock) {
commandBody = `${commandBody}\n\n${outputHistoryBlock}`;
}
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.

Output history appended after delivery instructions

commandBody at this point already contains the delivery instruction (e.g. "Return your summary as plain text…"). Appending the output history block after the delivery instruction means the previous-outputs context lands at the very end of the prompt, after the agent has already received its marching orders. In practice this is fine, but many prompting guides recommend placing context before instructions. Consider injecting the history block before appendCronDeliveryInstruction so the ordering is: task → history context → delivery instruction.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/cron/isolated-agent/run.ts
Line: 484-487

Comment:
**Output history appended after delivery instructions**

`commandBody` at this point already contains the delivery instruction (e.g. "Return your summary as plain text…"). Appending the output history block after the delivery instruction means the previous-outputs context lands at the very end of the prompt, after the agent has already received its marching orders. In practice this is fine, but many prompting guides recommend placing context *before* instructions. Consider injecting the history block before `appendCronDeliveryInstruction` so the ordering is: task → history context → delivery instruction.

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in ce3675de6 — history block now injected before appendCronDeliveryInstruction, so prompt order is: task → history context → delivery instruction.

Copy link
Copy Markdown

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

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: 2c6068bfcc

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/cron/service/timer.ts
@@ -492,6 +516,7 @@ function applyOutcomeToStoredJob(state: CronServiceState, result: TimedCronRunOu
status: result.status,
error: result.error,
delivered: result.delivered,
outputText: result.outputText,
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 Propagate startup catch-up output text into job-state updates

applyJobResult now records recentOutputs from result.outputText, but startup catch-up runs still construct TimedCronRunOutcome without copying outputText from executeJobCoreWithTimeout (in runStartupCatchupCandidate). When cron restarts and executes missed isolated jobs via startup catch-up, this field reaches applyJobResult as undefined, so output-history recording is skipped even if payload.outputHistory is enabled and delivery succeeded; the next run then loses the expected prior-output context.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in ce3675de6 — startup catch-up now uses spread ({ jobId, ...result, startedAt, endedAt }) matching the normal execution path, so outputText is propagated.

@Zynoo71 Zynoo71 force-pushed the feat/cron-output-history branch from 2c6068b to ce3675d Compare March 13, 2026 11:33
Copy link
Copy Markdown

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

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

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/cron/service/timer.ts Outdated
Comment on lines +345 to +348
result.status === "ok" &&
result.outputText?.trim() &&
job.payload.kind === "agentTurn" &&
job.payload.outputHistory
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 Gate output-history writes on successful delivery

applyJobResult records recentOutputs for every status === "ok" run, but isolated runs can be ok with delivered: false (for example when dispatchCronDelivery falls back in best-effort delivery-target failures or when delivery is suppressed). In those cases nothing was actually delivered, yet the next run will treat that text as prior output context, which can cause missed updates/repetition avoidance based on content users never received. Please require a successful delivery outcome before appending to recentOutputs.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Keeping result.status === "ok" as the sole gate, intentionally not checking delivered.

The output history serves the agent's memory, not the user's inbox. If we gate on delivery, this happens:

  • Run 1: agent produces "Market up 2%", delivery fails → not recorded
  • Run 2: agent has no memory, produces identical "Market up 2%" → delivery succeeds

This is exactly the repetition problem output history exists to solve. Delivery failure is an infrastructure concern — it should be handled by retry/alerting, not by making the agent forget what it produced.

Updated in a9a200b9f with explicit comment explaining the design decision.

@Zynoo71 Zynoo71 force-pushed the feat/cron-output-history branch from ce3675d to a9a200b Compare March 13, 2026 12:00
Copy link
Copy Markdown

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

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

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/cron/isolated-agent/run.ts Outdated
Comment on lines +482 to +484
const outputHistoryBlock = buildOutputHistoryBlock(params.job);
if (outputHistoryBlock) {
commandBody = `${commandBody}\n\n${outputHistoryBlock}`;
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 Keep output-history content inside external-content guard

In runCronIsolatedAgentTurn, external-hook messages are safety-wrapped via buildSafeExternalPrompt, but the new outputHistoryBlock is appended afterward as raw prompt text. For hook-driven jobs with outputHistory enabled, prior agent outputs can contain attacker-controlled text echoed from earlier external inputs; appending that text outside the guard reintroduces untrusted instructions in a privileged prompt position on later runs. Please sanitize/quote history entries or route them through the same untrusted-content boundary before concatenation.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in 779a1dafc — for external-hook jobs (shouldWrapExternal), output history is now included inside the buildSafeExternalPrompt content, so it goes through the same security boundary as the hook message. For internal/trusted jobs, history is appended directly as before.

@Zynoo71 Zynoo71 force-pushed the feat/cron-output-history branch 2 times, most recently from 779a1da to ad7257f Compare March 13, 2026 13:09
Copy link
Copy Markdown

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

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

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +240 to +244
Type.Array(
Type.Object(
{
text: Type.String(),
timestamp: Type.Integer({ minimum: 0 }),
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 Bound recentOutputs schema to prevent prompt blow-ups

recentOutputs is defined as an unbounded array of unbounded strings, and CronJobPatchSchema permits direct state updates, so callers can bypass the runtime FIFO/truncation logic and store arbitrarily large history blobs; buildOutputHistoryBlock then injects all entries into the isolated-agent prompt, which can exceed context windows and break scheduled runs or cause unexpectedly high token usage. Enforce the same invariants in schema/normalization (max 5 items, max text length) before accepting state.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in 89f73e69a — buildOutputHistoryBlock now applies defense-in-depth: slices to last 5 entries via slice(-OUTPUT_HISTORY_MAX_ENTRIES) and re-truncates each text via truncateOutputForHistory() at consumption time, preventing prompt blow-ups even if state was patched directly.

@Zynoo71 Zynoo71 force-pushed the feat/cron-output-history branch 2 times, most recently from 2ee9029 to 89f73e6 Compare March 14, 2026 11:47
Copy link
Copy Markdown

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

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: 89f73e69a6

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/cron/service/timer.ts
Comment on lines +347 to +351
const shouldRecordHistory =
result.status === "ok" &&
outputText &&
job.payload.kind === "agentTurn" &&
job.payload.outputHistory;
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 Propagate outputText when applying manual cron run results

The new history gate now requires result.outputText to append state.recentOutputs, but manual executions still call applyJobResult from finishPreparedManualRun without passing coreResult.outputText (src/cron/service/ops.ts, applyJobResult call). This means cron.run (force/due) jobs with payload.outputHistory=true never record the latest output, so the next scheduled run misses that context even though the run itself succeeded.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in d8fdd3ac9 — finishPreparedManualRun now spreads coreResult (same pattern as normal execution path), so outputText is propagated to applyJobResult for manual runs too.

@Zynoo71 Zynoo71 force-pushed the feat/cron-output-history branch from 89f73e6 to d8fdd3a Compare March 14, 2026 11:56
Copy link
Copy Markdown

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

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

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +263 to +264
{ "kind": "agentTurn", "message": "<prompt>", "model": "<optional>", "thinking": "<optional>", "timeoutSeconds": <optional, 0 means no timeout>, "outputHistory": <optional-bool> }
- outputHistory: set true to include recent delivery outputs as context for the agent. Useful for any recurring task where seeing previous outputs helps — avoiding repetition, tracking changes, building on prior results, etc. Default: false.
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 Preserve outputHistory in flat cron add recovery

The new tool docs advertise payload.outputHistory, but the add flat-params recovery path (used for non-frontier models that flatten arguments, per the #11310 logic in this file) still does not carry outputHistory into the reconstructed job payload. In that scenario, calls like action=add with top-level message/schedule and outputHistory: true silently create jobs without the flag, so output-history recording/prompt injection never activates and recurring jobs keep repeating content.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in f743b324e — added outputHistory to both JOB_KEYS (add flat-params) and PATCH_KEYS (edit flat-params) so non-frontier models that flatten arguments correctly propagate the flag.

@Zynoo71 Zynoo71 force-pushed the feat/cron-output-history branch from d8fdd3a to f743b32 Compare March 14, 2026 12:15
Copy link
Copy Markdown

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

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

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@@ -474,6 +476,7 @@ Use jobId as the canonical identifier; id is accepted for compatibility. Use con
"wakeMode",
"failureAlert",
"allowUnsafeExternalContent",
"outputHistory",
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 Preserve flat outputHistory in cron.update normalization

Including "outputHistory" in the flat PATCH_KEYS list makes cron.update accept flattened model output, but that value is never copied into patch.payload (unlike model/thinking/timeoutSeconds), so the update becomes a silent no-op. In the non-frontier flattening scenario this recovery path targets, requests like action=update, jobId=..., outputHistory=true now pass validation yet leave payload.outputHistory unchanged, so history injection never activates even though the tool call appears successful.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in 96f31ba60 — flat-params recovery now moves outputHistory into payload: { kind: "agentTurn", outputHistory } before normalization, so both cron.add and cron.update correctly place it inside the payload. Also added outputHistory to copyTopLevelAgentTurnFields and stripLegacyTopLevelFields in normalize.ts for defense-in-depth. Tests updated to verify params.payload.outputHistory (not top-level).

@Zynoo71 Zynoo71 force-pushed the feat/cron-output-history branch 2 times, most recently from 4d58687 to 96f31ba Compare March 14, 2026 12:30
Copy link
Copy Markdown

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

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: 4d5868798a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@@ -331,6 +332,7 @@ Use jobId as the canonical identifier; id is accepted for compatibility. Use con
"thinking",
"timeoutSeconds",
"allowUnsafeExternalContent",
"outputHistory",
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 Move flat add outputHistory into payload before dispatch

Adding "outputHistory" to the flat add JOB_KEYS causes flattened tool calls to forward outputHistory at the job root, but normalizeCronJobCreate only promotes a small set of top-level agent-turn fields (model/thinking/timeoutSeconds/allowUnsafeExternalContent) and leaves outputHistory untouched, so the gateway sees an unknown top-level property and rejects the request under CronAddParamsSchema (additionalProperties: false). Fresh evidence after the earlier thread: tracing this commit’s new key through normalizeCronJobCreate shows no path that maps it to payload.outputHistory, so non-frontier flattened cron.add calls with outputHistory now fail instead of enabling history.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Also fixed in the same commit — same approach applied to both JOB_KEYS (add) and PATCH_KEYS (update) recovery paths.

@@ -474,6 +476,7 @@ Use jobId as the canonical identifier; id is accepted for compatibility. Use con
"wakeMode",
"failureAlert",
"allowUnsafeExternalContent",
"outputHistory",
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 Normalize flat update outputHistory into payload patch

Including "outputHistory" in flat update PATCH_KEYS builds params.patch = { outputHistory: true }, but that field is not converted into patch.payload.outputHistory during normalization, so it remains an unsupported top-level patch property and fails gateway validation (CronJobPatchSchema also uses additionalProperties: false). In the flattened-model scenario this was meant to recover, cron.update now returns an invalid-params error instead of updating the flag.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

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

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: 96f31ba60d

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/agents/tools/cron-tool.ts Outdated
Comment on lines +353 to +355
if (!payload.kind) {
payload.kind = "agentTurn";
}
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 Avoid forcing agentTurn for flat add outputHistory

When flat-params recovery sees top-level outputHistory, this block unconditionally injects payload.kind = "agentTurn" if kind is missing. In the same recovery path, non-frontier models may send valid system-event style fields (text, schedule, etc.) plus optional booleans; forcing agentTurn causes normalizeCronJobCreate to drop top-level text and send an agentTurn payload without message, which then fails gateway validation (CronPayloadSchema requires agentTurn.message). This turns previously recoverable flattened cron.add calls into hard errors.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in b0db90bee — both add and update recovery paths now check for systemEvent signals (existingPayload?.kind === "systemEvent" or typeof synthetic.text === "string") and skip the agentTurn promotion when present, silently dropping outputHistory (meaningless for systemEvent).

Comment thread src/agents/tools/cron-tool.ts Outdated
Comment on lines +511 to +513
if (!payload.kind) {
payload.kind = "agentTurn";
}
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 Avoid forcing agentTurn for flat update outputHistory

The flat update recovery does the same unconditional payload.kind = "agentTurn" promotion for top-level outputHistory, which can break unrelated updates when models flatten optional fields. For system-event jobs, this coerces a kind switch and applyCronJobPatch ends up in buildPayloadFromPatch without a message, throwing cron.update payload.kind="agentTurn" requires message; for non-payload updates this means a benign update can fail solely because outputHistory was included as an extra flattened field.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Same fix applied — see reply above.

@Zynoo71 Zynoo71 force-pushed the feat/cron-output-history branch from 96f31ba to b0db90b Compare March 14, 2026 13:22
Copy link
Copy Markdown

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

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

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/agents/tools/cron-tool.ts Outdated
Comment on lines +358 to +359
if (!payload.kind) {
payload.kind = "agentTurn";
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 Treat payload.text as systemEvent before forcing agentTurn

In flat cron.add recovery, this branch sets payload.kind = "agentTurn" whenever outputHistory is present and synthetic.text is not top-level, but it does not recognize synthetic.payload.text as a system-event signal. If a non-frontier model sends partially nested args like payload: { text: "..." } plus top-level outputHistory: true, recovery rewrites that payload to agentTurn without a message, and the subsequent cron.add request is rejected by gateway validation (agentTurn.message required), so a previously recoverable flattened add call now fails.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in 57c1d71ed — removed the payload wrapper from the add recovery path entirely. For add, outputHistory now stays at the top level and the normalizer handles it: message auto-creates the payload, then copyTopLevelAgentTurnFields copies outputHistory in, then stripLegacyTopLevelFields cleans up. This avoids all kind-forcing issues and preserves message. The update path still uses a payload wrapper (no message to trigger auto-creation). Test now also verifies message survives.

@Zynoo71 Zynoo71 force-pushed the feat/cron-output-history branch from b0db90b to 57c1d71 Compare March 14, 2026 13:37
Copy link
Copy Markdown

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

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: 57c1d71edf

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/agents/tools/cron-tool.ts Outdated
Comment on lines +501 to +502
const isSystemEvent = existingPayload?.kind === "systemEvent";
if (!isSystemEvent) {
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 Normalize payload kind before outputHistory systemEvent guard

The flat cron.update recovery only treats payload.kind === "systemEvent" as a system-event signal, so common lowercase/mixed-case variants (for example "systemevent") still enter the !isSystemEvent branch and get outputHistory injected into the payload. normalizeCronJobPatch then canonicalizes the kind to systemEvent but keeps outputHistory, which violates the systemEvent schema (additionalProperties: false) and makes an otherwise recoverable flattened update fail validation instead of ignoring the extra flag.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in 271d13f3f — systemEvent guard now normalizes kind with .trim().toLowerCase() before comparison, matching what coercePayload does.

@Zynoo71 Zynoo71 force-pushed the feat/cron-output-history branch from 57c1d71 to 271d13f Compare March 14, 2026 13:51
Copy link
Copy Markdown

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

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: 271d13f3fd

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/cron/normalize.ts
Comment on lines +271 to +272
if (typeof payload.outputHistory !== "boolean" && typeof next.outputHistory === "boolean") {
payload.outputHistory = next.outputHistory;
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 Infer payload kind for outputHistory-only patch payloads

Adding outputHistory support here only copies top-level fields into an already-agentTurn payload, but coercePayload still doesn't treat outputHistory as an agent-turn hint. As a result, updates like cron.update with patch: { payload: { outputHistory: true } } normalize to a kindless payload and are then rejected by CronPayloadPatchSchema (which requires kind), so enabling history via nested patch fails even though other agent-turn-only patch fields are kind-inferred.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in 10eef11fb — added typeof next.outputHistory === "boolean" to hasAgentTurnHint in coercePayload, consistent with allowUnsafeExternalContent. Nested patches like { payload: { outputHistory: true } } now correctly infer kind: "agentTurn".

@Zynoo71 Zynoo71 force-pushed the feat/cron-output-history branch from 271d13f to 10eef11 Compare March 14, 2026 14:06
Isolated cron sessions start fresh each run (forceNew: true), so the
agent has no memory of previous outputs. This makes recurring tasks
produce repetitive content and prevents change tracking or iterative
analysis.

Add per-job `outputHistory` flag that, when enabled, records outputs
in job state (capped at 5, FIFO) and injects them into the agent's
system prompt on subsequent runs.

Recording gates on `status === "ok"` regardless of delivery outcome —
the agent should remember what it produced even if delivery failed,
otherwise it repeats itself when delivery recovers.

For external-hook jobs, output history is included inside the
security boundary (buildSafeExternalPrompt) to prevent prior outputs
from bypassing the untrusted-content guard.

Defense-in-depth: buildOutputHistoryBlock caps entries and truncates
text at consumption time, preventing prompt blow-ups even if state
was patched directly bypassing runtime guards.

Concrete use cases:
- Daily briefings: avoid repeating the same news/updates
- Monitoring: track metric changes between runs
- Iterative analysis: build on previous findings
- Content scheduling: maintain variety across outputs

Changes:
- Add `outputHistory` field to CronAgentTurnPayloadFields
- Add `recentOutputs` array to CronJobState
- New output-history.ts: buildOutputHistoryBlock + truncateOutputForHistory
  (head+tail truncation within 600 char limit)
- Inject history block before delivery instruction in run.ts
- Route history through security boundary for external-hook jobs
- Record output on successful run in timer.ts applyJobResult
- Propagate outputText in startup catch-up and manual run paths
- Add outputHistory to flat-params recovery (JOB_KEYS + PATCH_KEYS)
- Support outputHistory in mergeCronPayload/buildPayloadFromPatch
- Guard against invalid timezone in output formatting
- Consumption-side bounds on entries and text length
- Update gateway protocol schema and cron tool description
- Unit, integration, and e2e tests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@Zynoo71 Zynoo71 force-pushed the feat/cron-output-history branch from 10eef11 to 5ed79b2 Compare March 23, 2026 08:22
@Zynoo71 Zynoo71 requested a review from a team as a code owner March 23, 2026 08:22
Copy link
Copy Markdown

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

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

ℹ️ About Codex in GitHub

Codex has been enabled to automatically 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 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread src/cron/service/timer.ts
Comment on lines +346 to +350
const outputText = result.outputText?.trim();
const shouldRecordHistory =
result.status === "ok" &&
outputText &&
job.payload.kind === "agentTurn" &&
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 Filter control-token replies out of recentOutputs

This now appends any successful result.outputText to history, but runCronIsolatedAgentTurn fills outputText from the last non-empty payload before it decides to suppress user-visible delivery (src/cron/isolated-agent/helpers.ts:109-116, src/cron/isolated-agent/run.ts:733-760) and even returns the NO_REPLY sentinel unchanged in dispatchCronDelivery (src/cron/isolated-agent/delivery-dispatch.ts:540-547). For jobs with payload.outputHistory=true, a no-op run can therefore store HEARTBEAT_OK/NO_REPLY as the “previous output”, so the next prompt sees control text instead of the last substantive result.

Useful? React with 👍 / 👎.

Comment thread src/cron/normalize.ts
Comment on lines 101 to +105
typeof next.model === "string" ||
typeof next.thinking === "string" ||
typeof next.timeoutSeconds === "number" ||
typeof next.allowUnsafeExternalContent === "boolean";
typeof next.allowUnsafeExternalContent === "boolean" ||
typeof next.outputHistory === "boolean";
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 Drop or coerce stringified outputHistory values during normalization

coercePayload now recognizes outputHistory as an agent-turn hint, but unlike allowUnsafeExternalContent it never strips or coerces non-boolean values before returning the payload. In the same malformed-model scenarios this recovery path is meant to handle, inputs like payload: { kind: "agentTurn", message: "...", outputHistory: "true" } survive normalization and are then rejected by CronAddParamsSchema/CronJobPatchSchema, because the gateway schema requires a real boolean. That turns add/update calls into validation errors instead of recovering from a common stringified-boolean shape.

Useful? React with 👍 / 👎.

@openclaw-barnacle
Copy link
Copy Markdown

This pull request has been automatically marked as stale due to inactivity.
Please add updates or it will be closed.

@openclaw-barnacle openclaw-barnacle Bot added stale Marked as stale due to inactivity triage: refactor-only Candidate: refactor/cleanup-only PR without maintainer context. and removed stale Marked as stale due to inactivity labels Apr 28, 2026
@clawsweeper
Copy link
Copy Markdown
Contributor

clawsweeper Bot commented Apr 29, 2026

Codex review: needs changes before merge.

What this changes:

The PR adds an opt-in cron outputHistory flag that stores recent isolated-agent outputs in job state and injects them into later cron prompts, with schema, tool, and test coverage updates.

Required change before merge:

A repair worker can make a narrow replacement or updated PR: rebase the useful source work, filter silent/control output before history recording, normalize the new field consistently, add changelog coverage, and run the targeted cron/protocol tests.

Security review:

Security review cleared: The diff does not change dependencies, workflows, secrets, permissions, or package execution paths; the prompt-state issue is covered as a functional finding.

Review findings:

  • [P2] Filter silent replies before saving history — src/cron/service/timer.ts:348-355
  • [P3] Drop invalid outputHistory payload values — src/cron/normalize.ts:105
  • [P3] Add the required changelog entry — src/agents/tools/cron-tool.ts:263-264
Review details

Best possible solution:

Land a rebased or replacement version of the feature that keeps the opt-in API but filters non-substantive control replies before recording history, preserves current prompt/delivery contracts, normalizes the new field consistently, and documents the user-facing cron behavior in the changelog.

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

Yes. A source-level reproduction is clear: an isolated cron run that returns only NO_REPLY or heartbeat acknowledgement text can be classified as ok with outputText, delivery is suppressed separately, and the PR then records that text into recentOutputs.

Is this the best way to solve the issue?

No, not as-is. The feature direction is maintainable, but the current patch needs a current-main rebase plus output filtering, normalization cleanup, and changelog coverage before it is the narrow safe solution.

Full review comments:

  • [P2] Filter silent replies before saving history — src/cron/service/timer.ts:348-355
    The new recording gate appends any successful non-empty outputText, but current cron delivery suppresses NO_REPLY and heartbeat-only responses without clearing that field. A quiet/no-op run can therefore store NO_REPLY or HEARTBEAT_OK as the previous output and inject control text into the next prompt instead of preserving the last substantive result.
    Confidence: 0.91
  • [P3] Drop invalid outputHistory payload values — src/cron/normalize.ts:105
    coercePayload now treats boolean outputHistory as an agent-turn hint, but it does not strip non-boolean values the way the same function strips invalid allowUnsafeExternalContent. A nested payload such as outputHistory: "true" survives normalization and fails the gateway schema instead of being ignored or coerced in the malformed-model recovery path this code supports.
    Confidence: 0.78
  • [P3] Add the required changelog entry — src/agents/tools/cron-tool.ts:263-264
    This is a user-facing feat(cron) change that adds new cron tool and protocol behavior, but the PR does not update CHANGELOG.md. Repo policy requires user-facing feat/fix/perf changes to have an entry in the active changelog section.
    Confidence: 0.86

Overall correctness: patch is incorrect
Overall confidence: 0.88

Acceptance criteria:

  • pnpm test src/cron/isolated-agent/output-history.test.ts src/cron/isolated-agent/run.output-history.test.ts src/cron/service.output-history-recording.test.ts src/agents/tools/cron-tool.test.ts src/gateway/protocol/cron-validators.test.ts
  • pnpm exec oxfmt --check --threads=1 src/agents/tools/cron-tool.ts src/agents/tools/cron-tool.test.ts src/cron/isolated-agent/output-history.ts src/cron/isolated-agent/output-history.test.ts src/cron/isolated-agent/run.output-history.test.ts src/cron/isolated-agent/run.ts src/cron/normalize.ts src/cron/service.output-history-recording.test.ts src/cron/service/jobs.ts src/cron/service/ops.ts src/cron/service/timer.ts src/cron/types.ts src/gateway/protocol/cron-validators.test.ts src/gateway/protocol/schema/cron.ts CHANGELOG.md
  • pnpm check:changed in Testbox before handoff

What I checked:

  • current main lacks output-history fields: CronAgentTurnPayloadFields and CronJobState on current main do not include outputHistory or recentOutputs, so this PR is not obsolete or implemented on main. (src/cron/types.ts:100, 62e1be2b9804)
  • PR records any successful non-empty outputText: The PR appends result.outputText?.trim() to job.state.recentOutputs whenever result.status === "ok" and payload.outputHistory is true, without filtering silent/no-op control text. (src/cron/service/timer.ts:347, 5ed79b24561c)
  • current output path can preserve control text before suppression: Current main derives outputText from the last non-empty payload text, then separately suppresses heartbeat-only or NO_REPLY delivery; the suppressed value can still remain in the run result that the PR records. (src/cron/isolated-agent/helpers.ts:263, 62e1be2b9804)
  • PR is dirty against current main: GitHub API reports mergeable: false, rebaseable: false, and mergeable_state: dirty; the branch needs a current-main rebase or replacement before final validation. (5ed79b24561c)
  • changelog missing for user-facing feature: The PR file list includes cron tool, protocol, runtime, and tests but no CHANGELOG.md, while the repository has an active Unreleased changelog section for user-facing changes. (CHANGELOG.md:5, 62e1be2b9804)

Likely related people:

  • steipete: Recent central work across isolated cron run, timer, delivery, and normalization paths, including timeout cleanup, provider preflight, delivery verification, and no-delivery classification. (role: recent maintainer; confidence: high; commits: 61d53f98d314, 9f62c738930a, 0c444ff5ba5e; files: src/cron/isolated-agent/run.ts, src/cron/service/timer.ts, src/cron/isolated-agent/delivery-dispatch.ts)
  • obviyus: Recent merged work on cron delivery prompting, verified message delivery, delivery dedupe, and delivery trace behavior overlaps the output/delivery boundary touched by this PR. (role: adjacent owner; confidence: medium; commits: b9d2e0f86d0c, d083702a7be6, 21cfc21e4f20; files: src/cron/isolated-agent/run.ts, src/cron/isolated-agent/delivery-dispatch.ts, src/cron/service/timer.ts)
  • vincentkoc: Recent work split cron isolated run result types and lazy-loaded delivery/runtime boundaries that affect how output text flows through isolated cron runs. (role: adjacent refactor owner; confidence: medium; commits: a81dc153c61b, a88fbf0f6476, 139a3f49fe4f; files: src/cron/isolated-agent/delivery-dispatch.ts, src/cron/isolated-agent/run.ts)

Remaining risk / open question:

  • The PR is currently dirty against main, so conflict resolution may reveal additional integration issues.
  • No tests were run because this was a read-only review; findings are from source and diff inspection.

Codex review notes: model gpt-5.5, reasoning high; reviewed against 62e1be2b9804.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling app: web-ui App: web-ui gateway Gateway runtime size: L triage: refactor-only Candidate: refactor/cleanup-only PR without maintainer context.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant