- Proposal Name:
artifact_candidate_review_inbox - Start Date: 2026-07-29
- RFC PR: oceanbase/powercontext#50
- Related RFCs: RFC 0001, RFC 0014, RFC 0019, RFC 0028
Summary¶
This RFC defines Artifact Candidate and Review Inbox for Artifact Families that require explicit Review confirmation.
Whether content enters Review is not chosen by the user and does not depend on whether an LLM is involved. It is fixed by the Artifact Family: Memory continues to write directly to an Artifact, while Experience and Skill must first become a pending Candidate and can form an Artifact Revision only after approval. Task Outcome is not yet defined, so this RFC does not assign it a Review policy. Handoff is a downstream result composed from these sources and is not treated as a peer Family in this RFC's Review policy.
A Candidate is a persisted, untrusted proposal, not an Artifact. It does not enter search or PreparedContext. Review Inbox is a query view of pending Candidates in the current scope. The first implementation ships with the Experience Artifact Family, and Skill reuses it later. This RFC does not introduce a generic workflow framework without a real consumer.
This review must confirm four decisions:
- Review policy is fixed on the Artifact Family; the user does not provide a mode.
- Memory writes directly, while Experience and Skill require Review.
- Pending and rejected Candidates are fully isolated from Artifact retrieval and PreparedContext.
- Review operations are exposed consistently through HTTP, the Python Client, the CLI, and MCP; MCP is not a separate approval-policy boundary.
Motivation¶
Different Artifacts carry different risks.
Memory stores facts, conventions, and preferences. It is written frequently and can retain exact evidence. Requiring separate Review confirmation for every Memory write would turn Review Inbox into a routine operational burden.
Experience and Skill are higher-order Artifacts. Experience derives a situation, action, outcome, and lesson from multiple results. Skill distills Experience into reusable steps. Incorrect generalization, semantic merging, or operating steps can affect many later tasks, so these Artifacts require explicit Review.
PowerMem has demonstrated the value of Experience and Skill distillation, deduplication, and merging. It also shows the
governance risk of a direct distill -> merge -> store path. PowerContext preserves automatic generation while separating
the generation and confirmation of higher-order Artifacts:
Memory -> Artifact Revision
task result evidence -> Experience Candidate -> Review Inbox -> Experience Revision
Experience -> Skill Candidate -> Review Inbox -> Skill Revision
Memory + optional Task Outcome + approved Experience/Skill -> handoff context
The existing Source-to-Memory path remains unchanged:
Source window -> CandidatePipeline.extract() -> Memory Revision
Guide-level explanation¶
Which Artifacts require Review¶
The initial version uses a fixed policy. It does not provide user configuration or a generic rules engine:
| Artifact Family | Review policy | Result |
|---|---|---|
| Memory | direct |
Create a Revision through the existing Memory write path |
| Experience | review |
Enter Review Inbox first and create a Revision after approval |
| Skill | review |
Enter Review Inbox first and create a Revision after approval |
direct does not mean creating an automatically approved Candidate. It means no Candidate is created. review means
that creation and modification for the Family must enter Review Inbox before an Artifact Revision can be committed. Each
new Artifact Family must declare its policy in its own RFC. The Runtime does not guess a default for an unknown Family.
Example 1: write ordinary Memory directly¶
A user asks Codex to remember a project convention:
"Run contract tests after changing OpenAPI."
Codex calls remember_memory, and the Runtime creates a Memory Revision through the existing path. The user does not
provide a mode and does not need to approve the write again in Review Inbox. POST /v1/memory/flush also retains its
existing behavior of writing Memory directly from a Source window.
Example 2: Experience requires Review¶
A task system provides bounded result evidence, including the goal, changes, and test results. The Runtime derives this proposal:
Candidate: cand_exp_123@1
Family: experience
Proposal: "After changing OpenAPI, regenerate the Client and run contract tests."
Evidence: source:task-result/run_42
Status: pending
This is cross-task Experience. While pending, it does not enter Artifact search or PreparedContext. The Runtime commits an Experience Revision only after a reviewer approves it.
Example 3: revise Experience before approval¶
The model proposes an overgeneralized Experience:
cand_exp_124@1: "Run contract tests after changing any YAML file."
The reviewer calls revise with a complete replacement proposal:
cand_exp_124@2: "Run contract tests after changing openapi/powercontext.yaml."
Version 1 remains immutable, and version 2 remains pending. The reviewer approves version 2 after confirming it, ensuring that the committed content exactly matches the reviewed content.
Example 4: reject a Skill¶
The Runtime distills a Skill from approved Experience, but the proposal has no failure handling:
Candidate: cand_skill_7@1
Family: skill
Steps: modify spec -> generate client -> run tests
Failure handling: missing
Status: pending
The reviewer rejects the Candidate. It does not form a Skill Artifact and cannot be published, mounted, or included in Context Pack. Even after a Skill is approved, execution and mounting remain subject to later Skill governance. Artifact approval is not execution authorization.
Reference-level explanation¶
Family review policy¶
Review policy is a built-in Runtime Family contract, not a parameter on each request:
direct families: memory
review families: experience, skill
- A
directFamily retains its own validation, identity, Revision, and CAS semantics. - Public create and modify operations for a
reviewFamily produce a Candidate instead of committing an Artifact. - Only Review approval can call the internal Artifact commit of a
reviewFamily. - Policy does not vary by caller, MCP, HTTP, CLI, LLM, or rule.
- The initial version adds no policy DSL, dynamic registry, tenant-level switch, or per-request override.
The first implementation ships with the Experience Family. Skill reuses the same Candidate envelope and lifecycle when it is introduced. Experience and Skill content schemas are defined by their respective RFCs; this RFC does not predefine an arbitrary JSON payload. Task Outcome's schema, lifecycle, and Review policy, as well as Handoff composition and persistence semantics, are left to later RFCs.
Candidate model¶
A Candidate consists of a family-neutral envelope and a family-owned typed proposal:
| Field | Meaning |
|---|---|
scope_id + candidate_id + version |
Exact optimistic-concurrency reference for the Candidate |
family |
experience or skill |
status |
pending, approved, or rejected |
proposal |
Complete, strongly typed proposal defined by the corresponding Family |
sources/artifacts |
Exact evidence supporting the proposal; at least one reference is required |
target |
Exact active ArtifactRef when modifying an existing Artifact |
reason |
Untrusted explanation that does not affect authorization or ranking |
result_artifact |
Exact Artifact Revision produced after approval |
decision_reason |
Reviewer-supplied rejection reason; absent for other states |
A Candidate reference is not an ArtifactRef. A Candidate has no Artifact identity and cannot be read by the Artifact
catalog, a Family search index, or the Context builder.
Lifecycle and concurrency¶
create version 1 -> pending
pending --revise--> pending version N+1
pending --approve-> approved
pending --reject--> rejected
approve confirms only the current Candidate version and cannot modify the proposal at the same time. To change content,
the reviewer first calls revise, creates a complete new version, and then approves that version. approved and
rejected are terminal states; the initial version does not support reopening them.
A Candidate that modifies an existing Artifact must also include its exact target in artifacts evidence. This keeps
the direct predecessor in the approved Revision's lineage instead of relying only on a temporary target field in the
Candidate envelope.
Every Review write requires expected_version. The Runtime performs two concurrency checks:
- Candidate version CAS prevents a reviewer from acting on a stale proposal.
- Family target CAS prevents a proposal from being committed against an Artifact head that has changed.
A stale Candidate returns candidate_conflict, and a stale target returns artifact_conflict. The Runtime does not
perform an automatic three-way merge.
Persistence and transactions¶
Builtin Runtime uses two logical tables:
artifact_candidate_headsstores the current version, status, and approval result.artifact_candidate_versionsstores each immutable proposal version.
Review Inbox queries pending heads and their current versions. It adds no queue, assignment, or search-index table. Model generation runs outside the database transaction, and a Candidate appears in the Inbox only after its write completes.
During approval, the Family Artifact commit and the Candidate's approved status must be committed in the same database
transaction. Any failure rolls back the entire operation and leaves the Candidate pending. SQLite and OceanBase must pass
the same lifecycle, CAS, rollback, and isolation contract tests.
API and compatibility¶
OpenAPI remains the source of truth for the HTTP contract. Review Inbox adds:
| operationId | Purpose |
|---|---|
list_artifact_candidates |
Page by scope, status, and optional family; list only pending items by default |
get_artifact_candidate |
Read the current Candidate head |
approve_artifact_candidate |
Approve by expected version without accepting content changes |
reject_artifact_candidate |
Reject by expected version and reason |
revise_artifact_candidate |
Submit a complete replacement proposal by expected version |
The initial Experience vertical slice also exposes propose_experience and get_experience. The former creates only a
pending Candidate; the latter reads an approved Experience Revision only by exact ArtifactRef. Their HTTP paths are
/v1/experience/propose and /v1/experience/get. The five Review paths are under /v1/artifact-candidates/.
The generated Python Client exposes the same operations, the CLI provides
candidate list/show/approve/reject/revise, and MCP projects all five Review operations as tools. Transport does not
change Candidate validation, expected_version checks, or the atomic approval transaction. PowerContext does not treat
MCP visibility as an authorization boundary; deployments that require reviewer separation must control access to the
MCP endpoint.
This RFC does not modify the existing Memory contract:
POST /v1/memory/flushcontinues to process a Source window into Memory.remember_memory,revise_memory_entry, andretire_memory_entryremain unchanged.MemoryRememberModeand its existing behavior remain unchanged. It controls only how Memory content is generated and is unrelated to Review.- The Codex Hook, existing Memory MCP tools, and
prepare_contextcontract remain unchanged; Review adds five MCP tools.
Candidate and Review code ships with the first Experience vertical slice. The project does not first deliver infrastructure consisting only of tables and unused APIs.
Retrieval and trust boundary¶
The following invariants must hold:
- Pending or rejected Experience and Skill Candidates do not enter Artifact or Family search.
- Pending or rejected Candidates do not enter
prepare_context. - Only Experience or Skill Artifacts produced by successful approval may become future Context contributors.
- Candidate status is not a retrieval-ranking signal.
- Candidate content is always displayed as untrusted data; body, reason, and evidence previews are not logged.
scope_idremains a business partition, not authentication or ACL.
PreparedContext v1 now reads active Memory and relevant approved current Experience heads. Approval makes an Experience eligible for the scope-local rebuildable FTS projection; it does not guarantee selection under the query and shared byte budget. Skill approval still does not expand Context Pack.
Acceptance¶
| Scenario | Passing condition |
|---|---|
| Family routing | Memory writes directly to an Artifact; Experience and Skill produce only Candidates |
| Inspect | Client and CLI can show family, proposal, version, and exact evidence |
| Gate | Pending and rejected Candidates do not enter Artifact search or PreparedContext |
| Revise | Create an immutable next Candidate version that remains pending |
| Approve | An expected version succeeds only once; Artifact commit and approved status are atomic |
| Conflict | A stale Candidate or Artifact target returns a typed conflict without automatic merge |
| Reject | Write no Artifact; a terminal Candidate cannot be approved or revised again |
| Compatibility | Existing Memory flush, HTTP, MCP, Hook, and the PreparedContext v1 public envelope remain unchanged |
| MCP parity | MCP can list, read, revise, approve, and reject Candidates with the same lifecycle and CAS rules |
Drawbacks¶
- Memory does not go through Review, so incorrect content must be corrected through its existing revision semantics.
- Experience and Skill are not available immediately after generation; they must wait for explicit Review.
- Candidates may accumulate without assignment, notifications, or bulk operations.
- A fixed policy is simple, but every new Family must explicitly choose
directorreview. - Candidate heads and versions add storage and migration costs.
Rationale and alternatives¶
| Option | Decision |
|---|---|
| Review every Artifact | Rejected; it would create too much review work for high-volume Memory and task records |
| Let the user select a mode for each request | Rejected; it is easy to choose incorrectly and lets callers bypass Family governance |
| Decide based on whether an LLM is involved | Rejected; the Runtime cannot reliably determine whether a model exists behind the call chain |
| Fix policy by Artifact Family | Adopted; the rule is stable and explainable and adds no user parameter |
| Build a generic policy engine now | Rejected; only two review Families exist and there is no need for dynamic rules |
| Make Candidate an Artifact Family | Rejected; unreviewed content would receive Artifact identity too early |
Prior art¶
- RFC 0014 treats Memory pipeline output as an untrusted candidate but still commits it directly after Memory validation; this RFC does not change that path.
- RFC 0019 defines the Source window, cursor, and Memory flush; this RFC preserves their public behavior.
- RFC 0028 owns PreparedContext selection and the final byte budget; pending Candidates remain isolated from it.
- PowerMem's Experience and Skill distillation, deduplication, and merging provide a reference for generation, but automatic content review is not Artifact approval.
Limits and deferred work¶
The initial implementation uses these fixed limits:
- A Candidate may contain at most 32 exact evidence references across
sourcesandartifacts. reasonand the rejection-onlydecision_reasonare limited to 2,000 characters each.- Inbox pages contain 50 items by default. Callers may choose a
limitfrom 1 through 100 and continue withnext_cursor. - Each Family's typed schema limits its proposal payload. Each of the four initial Experience fields is limited to 8,000 characters.
Experience and Skill generation rules and Family write semantics are defined by their own RFCs. Candidate retention, reviewer identity, RBAC, notifications, bulk review, and multi-IDE UI remain future work.
Future possibilities¶
The later dependency chain is:
task result evidence -> Experience Candidate -> approved Experience
approved Experience -> Skill Candidate -> approved Skill
Memory + optional Task Outcome + approved Experience/Skill
-> multi-Artifact Context Profile
-> PreparedContext (ephemeral) / Handoff Artifact (persisted when replay or audit is required)
-> retrieval quality evaluation
- Semantic Experience merging can produce only a new Candidate; it cannot overwrite an approved Artifact directly.
- Skill approval does not automatically grant execution, publication, or mounting permission.
- Context Pack expands its contributor, budget, and provenance contract only after Experience or Skill becomes a real source.
- Retrieval quality is measured against the existing FTS/vector/RRF baseline for freshness, conflict, and diversity. Graph, sparse retrieval, and reranking are implemented only after they demonstrate an improvement.