Manage context

Review Dream revisions

Use a coordinated Client supporting Dream contract 2. The Python Client and CLI send X-PowerContext-Dream-Contract: 2 automatically. External integrations must send the header after updating their closed operation enums and proposal types. A legacy Client receives HTTP 426 client_upgrade_required when it encounters a new type. GET /v1/capabilities advertises the enabled operations; unconfigured operations reject admission.

Dream selects exact evidence and creates a pending Candidate. Generation does not approve, install, execute, or publish anything. Existing automatic generation retains its own policy. Approval is an explicit human decision against the exact current Candidate version.

Profile and Handoff boundaries

Profile Dream freezes generation-affecting policy settings at admission. Ordinary Source processing, pending-candidate changes, and Source-only activation settings do not invalidate the proposal. Changing generation settings requires a new Dream run; changing the Profile head independently causes a target conflict. Approval does not consume the Source cursor or clear the ordinary pending candidate.

Handoff approval publishes the new revision immediately. A subsequent explicit Continue can select it under the existing latest-read rules; approval itself does not call Continue, execute work, or record receiver acceptance. Receiver checks of live state, capability, and authorization remain separate. ActivateHandoff generates a draft and is not required to activate an approved revision.

Coordinated upgrade

The unified Candidate routes and physical table rename ship together, including for A0/A1-only deployments with Tag disabled. Existing databases require explicit maintenance through the unified migration framework (RFC #1771): stop writers, apply the selected backup policy, migrate and verify, then start the matching Server and upgrade Client/SDK/CLI/MCP/integrations before resuming traffic. Dream startup checks its required storage without renaming tables, adding columns, or creating its deduplication index. The removed /v1/artifact-candidates/* routes have no aliases or compatibility filtering; direct removal is an explicit release exception to the usual deprecation period. Database migration does not preserve old clients. Tag enablement does not require another Candidate table rename.

Before stopping all writers, stop new Dream admissions and let the old runtime finish every queued/running Dream run. Migration rejects unfinished runs with dream_tasks_require_drain; it does not change frozen prompts, model configuration, retry budgets or deadlines. Completed runs and pending Candidates remain readable and reviewable after upgrade. The migration also updates Handoff/Prompt processing bindings explicitly; ordinary startup does not repair the processing manifest. An unsupported manifest blocks migration with unknown_processing_manifest.

Production upgrade is not enabled by the Dream contribution alone. PR #1772 must register the complete Server baseline, revision chain, legacy-task checks and backend acceptance. Its four-table SQLite prototype does not establish Server readiness. This branch rejects legacy Dream storage with migration_required and versioned databases with migration_framework_not_ready until full framework readiness is integrated; do not bypass these errors by stamping a revision or creating empty replacement tables. Registered retained tables and recovery objects remain under the framework's retention policy.

Prompt configuration

Read the current Prompt Artifact revision for a registered custom-capable key, such as atomic_memory.extract, and choose an exact Source describing an observed error and its expected output. The same /v1/scopes/{scope_id}/dream route handles the request:

from powercontext.client import PowerContextClient
from powercontext.http import (
    ArtifactReference, CreateDreamRunRequest, DreamSourceReference,
    GetCandidateRequest, ApproveCandidateRequest,
)

async def propose_prompt(client: PowerContextClient, scope_id: str,
                         current: ArtifactReference, evidence_source_id: str):
    # current names the existing Prompt key and its exact current revision.
    request = CreateDreamRunRequest(
        operation="revise_prompt", target=current, artifacts=[current],
        sources=[DreamSourceReference(source_type="content", source_id=evidence_source_id)],
        idempotency_key="prompt-correction-2026-09-22",
    )
    return await client.create_dream_run(scope_id, request)

async def inspect_prompt(client: PowerContextClient, scope_id: str, run_id: str):
    run = await client.get_dream_run(scope_id, run_id)
    if run.status.value == "succeeded" and run.candidate is not None:
        return await client.get_candidate(GetCandidateRequest(
            scope_id=scope_id, candidate_id=run.candidate.candidate_id))

Read the proposal, reason, exact evidence, and diff in /dashboard/review. Only after a human approves the inspected version, call approve_candidate(ApproveCandidateRequest(scope_id=scope_id, candidate_id=candidate.candidate_id, expected_version=candidate.version)). Approval requires review authority and Prompt write authority. It publishes the configuration for future inferences; in-flight inference retains its frozen revision. Rollback uses the existing Artifact replacement API to write the selected earlier configuration as a higher revision.

The CLI accepts the same JSON request:

powercontext dream run --scope-id "$SCOPE_ID" --request-file prompt-dream.json
powercontext dream show --scope-id "$SCOPE_ID" "$RUN_ID"
powercontext candidate show --scope-id "$SCOPE_ID" "$CANDIDATE_ID"
powercontext candidate revise json --request-file candidate-revision.json
powercontext candidate approve --scope-id "$SCOPE_ID" "$CANDIDATE_ID" --expected-version 2

candidate-revision.json is a complete ReviseCandidateRequest, including scope, identity, expected version, proposal, exact evidence, and target. Saving a revision creates a new pending version requiring review.

Tag metadata

Read the current target Tag set and its ETag with get_artifact_tags, and read the exact Artifact revision that provides the content baseline. Submit revise_tags on the same Dream route. Its tag_target is separate from the Artifact target:

from powercontext.http import TagDreamTarget, ArtifactTagTarget

async def propose_tags(client, scope_id, current, tags_etag, evidence_source_id):
    return await client.create_dream_run(scope_id, CreateDreamRunRequest(
        operation="revise_tags",
        tag_target=TagDreamTarget(
            target=ArtifactTagTarget(type="artifact", family=current.family,
                                     artifact_id=current.artifact_id),
            expected_etag=tags_etag, basis_ref=current),
        artifacts=[current],
        sources=[DreamSourceReference(source_type="content", source_id=evidence_source_id)],
        idempotency_key="tag-correction-2026-09-22",
    ))

Atomic Memory uses ArtifactTagTarget(family="atomic-memory", ...) and the exact basis_ref, just like other Artifacts. Its target is comparison context and cannot support its own Tag change; supply independent evidence. The resulting run has candidate.kind="tag". Inspect it using get_candidate(GetCandidateRequest(...)); approval uses approve_candidate(ApproveCandidateRequest(...)). The unified /v1/candidates/list|get|history|revise|approve|reject interfaces preserve Tag's distinct lifecycle. Approval checks both the Tag ETag and content baseline atomically. The result contains the complete tags and new ETag, with no Artifact revision.

powercontext candidate list --candidate-kind tag --scope-id "$SCOPE_ID"
powercontext candidate show --scope-id "$SCOPE_ID" "$CANDIDATE_ID"
powercontext candidate history --scope-id "$SCOPE_ID" "$CANDIDATE_ID"
powercontext candidate revise json --request-file tag-revision.json
powercontext candidate approve --scope-id "$SCOPE_ID" "$CANDIDATE_ID" --expected-version 2

Tag candidates preserve the selected supporting Artifact references and recheck their access at approval. A revision submits the complete proposal; only after_tags may change. The target, ETag, content baseline, and before_tags remain immutable. Omitting sources or artifacts retains the existing evidence; explicitly supplying either replaces that evidence list.

The unified Dashboard lists Artifact and Tag candidates through one cursor and supports filtering by candidate_kind. A stale version, changed target, revoked evidence, or changed Tag ETag leaves the candidate pending with a conflict. Inspect current state before submitting another decision. no_change and needs_evidence create no candidate. Neither a model proposal nor approval proves improvement on later tasks.

Revise one Atomic Memory

Submit revise_memory with the same exact ArtifactRef(family="atomic-memory", ...) in target and artifacts, plus independently selected Sources or Artifacts. The proposal contains kind and text. Generation only creates a pending Candidate. Approval rechecks the target revision, active state, evidence and current permissions, then publishes the new revision, updates the index and records the decision in one transaction. A changed or forgotten target leaves the Candidate pending. Other Memories and automatic extraction remain independent.

On this page