Skip to content

fix(daily-memory): scope compaction context to its authorized agent and user - #3511

Merged
chubes4 merged 2 commits into
mainfrom
fix/3487-daily-memory-scope
Sep 17, 2026
Merged

chubes4 merged 2 commits into
mainfrom
fix/3487-daily-memory-scope

Conversation

@chubes4

@chubes4 chubes4 commented Sep 17, 2026

Copy link
Copy Markdown
Member

Fixes #3487.

Problem

DailyMemoryTask collected context by calendar date only. Job rows came from a date-only query and chat sessions came from list_sessions_for_day(), which carried no user or agent predicate. Those labels, statuses and titles were then sent to the model and persisted into one agent's MEMORY.md.

On a multi-agent or multi-user install a per-agent compaction could therefore summarize another agent's jobs and another user's chats into the wrong memory file. That crosses both the agent and the user boundary.

Change

Context retrieval resolves an explicit scope from the task's execution principal and pushes it into the storage layer rather than filtering a broad result afterwards.

  • Jobs::get_jobs_for_day( $date, $scope ) and ConversationReportingInterface::list_sessions_for_day_scoped( $date, $scope ) accept an ownership scope.
  • Both use a [midnight, next midnight) range predicate instead of wrapping created_at in DATE(), so the day window stays index-friendly.
  • DailyMemoryTask::resolveContextScope() binds user_id and agent_id, and the task fails closed when neither dimension is bound.

Authorized breadth stays a deliberate decision rather than an accident of omitted predicates. context_scope = agent preserves the agent-wide compaction, and an absent scope key narrows nothing, so a caller states the aggregate it wants.

Test harness fixes

The smoke tests selected alongside this change fataled under the real-WordPress backend for reasons that predate it. origin/main carries the same declarations.

  • WP_Error, WP_CLI, WP_CLI_Command, did_action, doing_action, datamachine_merge_engine_data, wp_json_encode and wp_get_ability were declared unguarded and collided with real WordPress. They are now guarded, matching the convention already used by the smokes that pass in that backend.
  • ai-request-metadata-guardrails-smoke.php captured datamachine_log by shadowing do_action. Real WordPress supplies its own, so the smoke now registers a real add_action listener when the stub is not installed.
  • The same smoke calls datamachine_conversation_metadata(), which lives in conversation-loop.php. That file declares namespaced functions rather than autoloadable classes, so it is now required explicitly when absent. This also repairs the standalone run, which fataled on main.
  • ai-concurrency-release-wakeup-smoke.php and agent-daily-memory-pipeline-scope-smoke.php replace the options, hook and abilities APIs with in-memory doubles, so they assert nothing under real WordPress. They declare homeboy:host-smoke-backend = standalone, honored by Extra-Chill/homeboy-extensions#2846 (released in v3.48.3). The bare-PHP backend still runs them, so the coverage moves rather than disappears.

Verification

homeboy review test data-machine --changed-since origin/main passes: exit=0, success=true.

  • PHPUnit via WP Codebox: 35 passed, 0 failed, including the new DailyMemoryTaskContextScopeTest.
  • Real-WordPress smoke phase: HOST_SMOKE_SUMMARY:passed=4 failed=0 skipped=2. ai-request-metadata-guardrails-smoke.php now passes in that backend, where it previously fataled.
  • Standalone: agent-daily-memory-pipeline-scope-smoke.php (11 assertions) and ai-concurrency-release-wakeup-smoke.php (43 assertions) pass.

The one PHPCS error was an unbracketed increment on a pre-existing line of InMemoryConversationStore.php, which is only linted because this change touches that file. It is bracketed rather than reformatting unrelated lines.

AI Assistance

Claude Sonnet 4.5 via OpenCode, orchestrated through Homeboy Cook, implemented the scope binding and storage predicates. Claude Sonnet 4.5 in Claude Code diagnosed the real-WordPress smoke failures from run artifacts, separated the genuinely broken smoke from the two that cannot run in that backend, implemented the harness fixes, and verified each gate run. Chris Huber directed the work and owns it.

…nd user (#3487)

Daily-memory compaction collected every job and chat session for the
calendar day, then fed those labels and titles to the model before
rewriting one agent's memory. On a multi-agent or multi-user install that
crossed both agent and user boundaries.

Context retrieval now resolves an explicit scope from the task's
execution principal and pushes it into the storage queries:

- Jobs::get_jobs_for_day() and the conversation store's
  list_sessions_for_day_scoped() take an ownership scope instead of
  filtering a broad result in PHP.
- Both use a [midnight, next midnight) range predicate so the day window
  stays index-friendly.
- DailyMemoryTask fails closed when neither dimension is bound.

Authorized aggregates remain available as a deliberate choice rather than
an accident of omitted predicates: context_scope='agent' keeps the
agent-wide compaction, and an absent scope key narrows nothing.

Smoke tests selected alongside this change fataled under the
real-WordPress backend because they declared WP_Error, WP_CLI,
did_action, wp_json_encode and wp_get_ability unguarded. Those stubs are
now guarded, the metadata guardrail smoke captures datamachine_log
through the real hook system when WordPress supplies it, and it loads
conversation-loop.php explicitly since that file declares namespaced
functions rather than autoloadable classes. Two smokes that replace the
options, hook and abilities APIs with in-memory doubles declare
homeboy:host-smoke-backend = standalone.
phpcs flags the unbracketed increment in the interpolated lock token
(WordPress.CodeAnalysis.AssignmentInCondition style rule for increment
and decrement operators). This file is only linted because #3487 touches
it, so clear the one error rather than reformat unrelated lines.
@chubes4
chubes4 marked this pull request as ready for review September 17, 2026 22:28
@chubes4
chubes4 merged commit 49bb52e into main Sep 17, 2026
26 of 30 checks passed
@chubes4
chubes4 deleted the fix/3487-daily-memory-scope branch September 17, 2026 22:47
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.

bug(daily-memory): scope daily compaction context to its authorized agent and user

1 participant