Skip to content

feat(work): add source-backed working notes - #1949

Open
Qiao-yq wants to merge 14 commits into
oceanbase:masterfrom
Qiao-yq:feat/1790-working-notes
Open

Qiao-yq wants to merge 14 commits into
oceanbase:masterfrom
Qiao-yq:feat/1790-working-notes

Conversation

@Qiao-yq

@Qiao-yq Qiao-yq commented Oct 12, 2026

Copy link
Copy Markdown

Which issue or RFC does this PR close?

Closes #1790

Rationale for this change

Long-running host sessions need short-lived, source-backed work state that can be carried into a later Handoff without polluting durable Memory. This implements the smallest compatible design: Working Notes are a server-owned Source kind, not a new Artifact family.

What changes are included in this PR?

  • Define retention, access-control, citation, and promotion boundaries in the English and Chinese RFCs.
  • Add explicit runtime capture with session and note-kind metadata, logical expiry, server-owned classification, and idempotent replay behavior.
  • Exclude Working Notes from automatic Memory, Topic Memory, Experience, and other Artifact generation.
  • Allow exact Working Note Source citations as Handoff evidence while rejecting expired notes and non-exact references.
  • Expose capture through OpenAPI, generated HTTP bindings, the Python client, Server, MCP, capability manifests, and Codex, DSH, OpenCode, and Pi host integrations.
  • Reject caller-supplied reserved Working Note metadata, including kind, session_id, note_kind, and expires_at.
  • Add runtime, HTTP, SDK, MCP, host-contract, and regression coverage.

Are there any user-facing changes?

Yes. Hosts and clients can explicitly capture short-lived Working Notes through the new capture_working_note operation. Working Notes remain access-controlled Source records, are retained after logical expiry, are not promoted automatically into Memory, and can only be used in Handoff through exact Source citations. No new Artifact family or persisted Notes format is introduced.

How was this change tested?

  • 225 passed, 3 skipped for the focused runtime, Handoff, HTTP, SDK, MCP, CLI, and API contract suite.
  • make check passed, including Ruff, formatting, type checks, workflow checks, and integration manifests.
  • make contract-test: 51 passed.
  • git diff --check passed.
  • make docs-test was not run because pnpm is not installed in the validation environment.

AI usage statement

OpenAI Codex assisted with implementation, conflict resolution after rebasing onto the latest origin/master, test updates, validation, and this PR description.

@CLAassistant

CLAassistant commented Oct 12, 2026 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@Qiao-yq
Qiao-yq requested a review from frf12 as a code owner October 12, 2026 08:26

@knqiufan knqiufan left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed commit 0d84457061c0900ee03148da25858792d9eead49. Requesting changes because a Handoff citing an active Working Note can be prepared and finalized but cannot be committed; its Source lineage is rejected by the persistence path.

Possible capability gap (non-blocking): the DSH, OpenCode, and Pi changes only update operation tables. Their tool registries (integrations/dsh/plugins/powercontext/src/tools.ts, integrations/opencode/plugins/powercontext/src/index.ts, and integrations/pi/plugins/powercontext/src/tools.ts) do not expose capture_working_note. Please add the host tools, or narrow the support claim and track those entries in a follow-up issue.

AI-assisted review using Open Code Review and Codex; the blocking failure was independently reproduced with the public runtime API and SQLite.

Comment on lines +71 to +72
if source.is_working_note:
raise SourceNotEligibleError(source_ref)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P1] Allow explicit Working Note lineage when committing a Handoff

This guard also runs from ArtifactRepository._validate_lineage_sources during Artifact create/revise. In a SQLite runtime, capturing an unexpired Working Note and then calling prepare(...) and finalize(...) with its exact Source citation succeeds, but commit(prepared) raises SourceNotEligibleError: HandoffService.commit includes the cited note in draft.sources, so persistence rejects it here. The documented Working Note/Handoff workflow therefore cannot produce a durable milestone. Permit valid exact Working Note citations in the Handoff persistence path while retaining the exclusion from automatic generation, and cover the complete prepare/finalize/commit workflow.

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 1dbacfd. Handoff persistence now has an explicit allow_working_notes capability enabled only by RelationalHandoffBackend; active notes are accepted, unavailable notes still fail at write time, and ordinary Artifact/generation paths remain denied by default. The regression now covers capture -> prepare -> finalize -> commit -> latest readback and exact Source lineage. I also added the requested DSH/OpenCode/Pi model-facing capture tools in 761b6a7, including mutation confirmation, secret screening, schemas, routing tests, and rebuilt bundles; 298ce3e synchronizes the integration manifest. Validation: make check, make contract-test (51 passed), full Handoff e2e (14 passed), DSH unit/e2e (320/9 passed), OpenCode (73 passed + typecheck), Pi (106 passed + typecheck).

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

Reviewed commit 0d84457061c0900ee03148da25858792d9eead49. I independently reproduced the existing unresolved P1 through the public runtime API with SQLite: capturing an active Working Note, prepare, and finalize succeed, but commit raises SourceNotEligibleError.

HandoffService.commit adds the cited Source to lineage, and ArtifactRepository._validate_lineage_sources calls the new guard that rejects Working Notes unconditionally. Please allow valid exact Working Note citations in the Handoff persistence path while preserving their exclusion from automatic generation, and add a regression covering prepare/finalize/commit and readback. The current Working Note Handoff test stops at prepare. This remains a merge blocker; I am referencing the existing thread rather than opening a duplicate.

Possible capability gap (non-blocking): DSH, OpenCode, and Pi add operation-table entries but do not expose capture_working_note in their tool registries. Please add the host tools or narrow the support claim and track the missing entries separately.

Validation was limited to SQLite and a controlled Handoff pipeline; real model, OceanBase, and native host workflows were not verified. AI-assisted review with Codex.

@hidb4ai

hidb4ai commented Oct 13, 2026

Copy link
Copy Markdown
Contributor

please update & resolve conflcts

@AlexStocks AlexStocks added the 1.4.0 v1.4.0 release tracking label Oct 13, 2026
@AlexStocks

Copy link
Copy Markdown
Contributor

@Qiao-yq please fix the file confliction.

@knqiufan knqiufan left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Reviewed commit 606bdb01d40871656d16c62d393b7908aed849b6. Requesting changes for two new regressions: the DSH tool schema aborts registration with the pinned runtime, and explicit Handoff activation rejects an active Working Note used as its boundary Source.

The previous Handoff persistence P1 is fixed: prepare/finalize/commit/readback and exact Source lineage succeeded. The DSH/OpenCode/Pi capture tools have also been added; the DSH registration failure is a separate issue in the new tool schema.

AI-assisted review using Open Code Review and Codex. Failures were verified through the public runtime/HTTP API with SQLite and controlled generation, and the actual pinned DSH schema compiler with a fixture registration context. Full native-host acceptance was not executed.

content: { type: 'string', required: true, description: 'Temporary work state to persist.' },
session_id: { type: 'string', required: true, description: 'Host/session correlation id.' },
note_kind: { type: 'string', required: true, enum: [...WORKING_NOTE_KINDS] },
expires_at: { type: 'string', format: 'date-time', description: 'Optional future logical expiry.' },

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P1] Use a DSH-supported schema for expires_at

The pinned runtime's @deepseek-ai/dsh-tools@0.1.2-rc.1 rejects format in its value-schema DSL. Calling registerTools with its real defineTool throws UNSUPPORTED_SCHEMA: parameters.expires_at.format is not supported by the value schema DSL. Because the tool array is constructed before the registration loop, zero PowerContext tools are registered, and apply stops before installing recall and commands. This happens even when callers omit expires_at. Use a schema supported by the host while retaining expiry validation, and check registration with the actual compiler.

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 9677862.

Removed the unsupported date-time format from the DSH expires_at schema. RFC 3339 validation remains enforced by the PowerContext server. Added coverage for the Working Note capture tool.

Comment on lines +72 to +77
if source.is_working_note:
if allow_working_notes:
if source.is_working_note_active():
return
raise WorkingNoteUnavailableError(source_ref)
raise SourceNotEligibleError(source_ref)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P2] Accept active Working Note boundaries in Handoff activation

_RelationalTriggers.activate_handoff still calls both GenerationSourceAccess.require_for_generation and this guard without allow_working_notes=True. In the public HTTP API with SQLite, capturing an active note returns 202 and preparing a Handoff with its exact citation succeeds, but passing the same reference as boundary_source to /v1/handoff/activate returns 422 source_not_eligible. ActivateHandoff.action_evidence() includes that boundary as an exact Handoff citation, so this explicit consumer is inconsistently rejected. Allow active notes on the activation path while continuing to reject expired notes and exclude notes from automatic generation.

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 9677862.

activate_handoff now accepts active Working Notes as boundary sources while still rejecting expired ones. Added regression coverage for both cases.

@hidb4ai

hidb4ai commented Oct 14, 2026

Copy link
Copy Markdown
Contributor

please update & resolve conflicts

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

LGTM

@knqiufan knqiufan left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Targeted follow-up on commit e09a7ff0a43d8915e12956a5d4438415848a40fa. Requesting changes for one P1 and two P2 issues: Working Note capture fails through HTTP/SDK/MCP, the public enum import prevents HTTP/SDK test collection, and DSH independently denies the new MCP tool because its catalog and bundle are stale. Details and required outcomes are in the inline comments.

Validation used local SQLite, ASGI-backed HTTP/SDK/MCP, pytest collection, the JS generation check, and direct invocation of the DSH policy hook. OceanBase and the complete native DSH host workflow were not executed. This follow-up covers these three findings, not a new full-PR review.

AI-assisted review using Codex and Open Code Review delegation mode.

application: Annotated[ServerApplication, Depends(_require_application)],
) -> CaptureContentSourceResponse:
result = await application.sources.for_scope(request.scope_id).capture_working_note(
mapping.working_note_capture_request(request)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P1] Add the missing Working Note request conversion

mapping.working_note_capture_request is not defined in server/mapping.py, so this call raises AttributeError before the note reaches the runtime. After creating a Scope in a SQLite-backed app, a valid POST /v1/sources/working-notes request returns 500 internal_error; the SDK does the same, and the MCP tool reports the missing attribute. This blocks capture through all three public entry points, leaving no new note to cite in a Handoff. Implement the HTTP-to-runtime conversion, preserving the request's session, note kind, and expiry, and verify successful public capture.

CaptureContentSourceRequest,
CaptureContentSourceResponse,
CaptureStatus,
CaptureWorkingNoteRequest,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P2] Export WorkingNoteKind through the public HTTP module

The generated WorkingNoteKind enum is used by CaptureWorkingNoteRequest, but it is not re-exported here. from powercontext.http import WorkingNoteKind raises ImportError, including at module import in the updated tests/e2e/test_runtime_server.py; pytest cannot collect that file, so its HTTP/SDK scenarios cannot run. SDK consumers using the same public import also fail before making a request. Re-export the enum and include it in __all__.

set_scope_binding: { method: 'PUT', path: '/v1/scope-bindings', location: "body", scopeMode: 'none', pathParameters: [], queryParams: [], headerParams: [], successStatuses: [200], emptyStatuses: [] },
clear_scope_binding: { method: 'POST', path: '/v1/scope-bindings/clear', location: "body", scopeMode: 'none', pathParameters: [], queryParams: [], headerParams: [], successStatuses: [200], emptyStatuses: [] },
capture_content_source: { method: 'POST', path: '/v1/sources/content', location: "body", scopeMode: 'current', pathParameters: [], queryParams: [], headerParams: [], successStatuses: [202], emptyStatuses: [] },
capture_working_note: { method: 'POST', path: '/v1/sources/working-notes', location: "body", scopeMode: 'current', pathParameters: [], queryParams: [], headerParams: [], successStatuses: [202], emptyStatuses: [] },

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P2] Synchronize the DSH MCP catalog and shipped bundle

This updates the HTTP operation table, but src/mcp-operations.generated.ts still omits capture_working_note, and the shipped lib/index.js also lacks it. rawOperation in src/mcp.ts only accepts names in MCP_OPERATIONS: directly invoking the registered policy hook for mcp__powercontext__capture_working_note with valid arguments returns deny with "unavailable in the plugin catalog" before any MCP request is sent. This independently blocks DSH even after the server mapper is fixed. scripts/generate_js_operations.py --check also fails on the stale catalog. Regenerate the MCP metadata and rebuild the checked-in DSH bundle so the tool reaches the normal mutation approval path. This was verified by invoking the policy hook, not by running the complete native host.

This branch has not been deployed

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

Labels

1.4.0 v1.4.0 release tracking

Projects

None yet

Development

Successfully merging this pull request may close these issues.

research(work): evaluate Source-backed working notes separate from Memory

5 participants