> ## Documentation Index
> Fetch the complete documentation index at: https://powercontext.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Source

> A successful capture is not durable knowledge. A Source only proves that something happened.

Capture may succeed while Memory (Selected project knowledge that should matter later.) search stays empty. That is usually not a failed write.

A Source (Records what happened. Capture does not write durable knowledge.) records what happened. A user prompt, a task result, or a host-captured turn may all become a Source. It does not decide whether the content deserves long-term retention. Memory, Experience, Skill, and Handoff handle those later decisions.

Treat those as two separate stages. The Source is already stored safely. Reusable knowledge appears only after an extraction window finishes.

> [!NOTE]
>
> For install options, interface details, and deployment, use the latest published [official docs](https://oceanbase.github.io/powercontext/). This page helps you separate evidence, journal position, and processing progress.

## Get a stable identity first

PowerContext refers to a Source with `source_type` and `source_id`.

```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
SourceRef
├── source_type
└── source_id
```

The full identity also includes `scope_id`. The same `source_type` and `source_id` may exist independently in different Scopes.

For the built-in content Source, a successful capture returns a SourceRef and a scope-local journal position.

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "status": "accepted",
  "source": {
    "source_type": "content",
    "source_id": "openapi-task-1"
  },
  "position": 1
}
```

A `source_id` should be stable and reproducible. Hosts often derive it from the Scope, session, turn, or content so a retry stays idempotent.

## Captured and referenced Sources differ

Once the identity is stable, decide whether this Source stores a snapshot or only an external reference. A Source adapter stores content in one of two ways.

| Mode | What PowerContext stores | How it is read |
| - | - | - |
| `captured` | A content snapshot and metadata | Directly from persistence |
| `referenced` | A reference to material managed elsewhere | Resolved by the adapter when read |

Captured Sources suit prompts, task results, and event text. Referenced Sources suit material owned by another system.

The distinction is practical. Captured content is a snapshot from that moment. Material behind a referenced Source may have changed by the next resolution.

## One journal per Scope

After a Source is persisted in the current Scope, it also receives a position that only has meaning there. The position starts at 1 and increases monotonically. Distinct Source adapters share one sequence, and an idempotent retry does not consume a new position.

Suppose two content Sources arrive in order.

```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
content/openapi-task-1 → position 1
content/openapi-task-2 → position 2
```

The Source journal only establishes order. It does not say which Source has been processed, and it does not say whether Memory exists.

## The trigger only selects a window

Processing progress is not the position itself. It is the window the trigger selects. `SourceWindowTrigger` only selects a window. It compares the current high position with the cursor and returns the next bounded window.

```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
state.sequence = 0
high_watermark = 2
limit = 1

ProcessSourceWindow(after=0, through=1)
```

The next activation returns the following window.

```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
ProcessSourceWindow(after=1, through=2)
```

Once the cursor reaches 2, there is no action.

The window is written as `(after, through]`. It excludes `after` and includes `through`. `source_window_limit` limits one processing batch, not the total journal length.

The trigger does not call a model or perform extraction. It returns new state and the actions still to run.

## The cursor tracks consumption

After a window is selected, the cursor is what remembers how far processing has gone. Two numbers are easy to mix up. Cursor `sequence` is the Source position the application has processed. Stored cursor `generation` is the concurrency-control version of that cursor row.

A cursor may say that processing reached position 12 while the row generation is 4. The numbers are unrelated.

PowerContext applies extraction and Memory changes before saving the next cursor. If Memory apply fails, advancing the cursor first would skip the failed window.

## Capture does not create Memory

This operation creates a Source only.

```http theme={"theme":{"light":"github-light","dark":"github-dark"}}
POST /v1/sources/content
```

Memory follows one of two paths. If you already know what to retain, write Memory explicitly. Or configure a generation pipeline and let the scheduler or `flush_memory` process pending Source windows.

Even when extraction runs successfully, the model may find nothing worth adding or revising. Processing a Source does not guarantee a new Memory Revision.

> [!NOTE]
>
> `flush_memory` processes pending Sources. It is not another spelling of `remember_memory`.

## Idempotency and conflict

Capturing the same Source identity again in one Scope has two outcomes. If the serialized payload bytes are identical, PowerContext returns the original position. If the payload bytes differ, it reports a conflict and leaves the old Source intact.

The comparison looks at serialized bytes, not whether the meaning is the same. Even metadata with the same keys and values may conflict when key order changes the serialized bytes. A retry should reuse the same serialized input.

Do not keep reusing one fixed `source_id` for changing content.

Concurrency has explicit guarantees too. Distinct concurrent Sources receive a contiguous sequence of positions. Concurrent retries of the same Source and payload resolve to one position. When two workers update a cursor, only the write with the expected generation succeeds.

## Sources beyond chat capture

Sources do not come only from chat hosts. Work continuity also records exact Sources, including Work Contracts, Handoff boundaries, Handoff acknowledgement receipts, and Task Outcomes.

That lets Handoff Report project work history from the journal without rewriting Handoff Artifacts.

## Walk through the OpenAPI example

Capture the first piece of evidence.

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "scope_id": "project:powercontext-101",
  "source_id": "openapi-task-1",
  "content": "The OpenAPI contract changed. Regenerate the checked-in client and run contract tests.",
  "metadata": {
    "origin": "tutorial"
  }
}
```

Then check these four facts. The response SourceRef should be `content/openapi-task-1`. The position should be greater than zero. Retrying the same request should return the same position. Reusing the ID with changed content should return a conflict.

Then decide whether the content should remain evidence or become explicit Memory. Most Sources do not need to become long-term knowledge.

## If you get stuck, match these first

### Capture succeeded, but Memory did not change

Check the generation capability, then verify that the cursor reached the captured position. Even when both are correct, extraction may return no-op.

### Flush returned idle

The scheduler may have processed the window first. Compare `current_cursor` with the capture position instead of treating `idle` as failure.

### A retry became a conflict

The `source_id` was probably reused with different canonical content or metadata.

### Different hosts produce positions in one sequence

That is expected when they use the same Scope and Server. All adapters share the scope-local journal.

## How you know the layers are separate

1. Source identity includes Scope, type, and ID.
2. Journal position and cursor sequence are different numbers.
3. Cursor sequence and cursor generation are also different numbers.
4. The window is understood as `(after, through]`.
5. A successful capture is not a Memory write.
6. An idempotent retry keeps the original position.

If any of those fail, start with [Troubleshooting](https://powercontext.mintlify.site/en/start/troubleshooting.md). To walk capture and extraction yourself, use [Source and Memory in practice](https://powercontext.mintlify.site/en/basic-usage/source-and-memory.md).

## Next

> [card] [See how durable knowledge stays](https://powercontext.mintlify.site/en/mental-model/memory.md)
>
> Memory answers what the project should remember later. An explicit write does not need a Source first.

> [card] [Walk a capture yourself](https://powercontext.mintlify.site/en/basic-usage/source-and-memory.md)
>
> When the objects are clear, capture a Source and check whether it becomes Memory.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.