Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
0ddca5e
feat(images): add opt-in image sources and Codex capture
knqiufan Oct 12, 2026
dcd6114
fix(images): prepare Atomic Memory draft and collector recovery
knqiufan Oct 12, 2026
7c6ec3e
docs(images): record draft PR submission and validation
knqiufan Oct 12, 2026
ad8deec
chore(images): track CI repair and upstream sync
knqiufan Oct 13, 2026
6adc11e
fix(images): resolve CI failures after upstream rebase
knqiufan Oct 13, 2026
b3e2269
fix(ci): update isolated plugin fixture and ZCode skill pin
knqiufan Oct 13, 2026
bd5129e
fix(runtime): prevent memory audit locks and isolate MiniCPM
knqiufan Oct 13, 2026
e539371
chore(images): record recall contract integration
knqiufan Oct 13, 2026
073e5ce
docs(images): refresh contract integration status
knqiufan Oct 13, 2026
a2b9f2c
fix(images): stabilize recovery under parallel testing
knqiufan Oct 13, 2026
d5adc8f
fix(images): recover collector queues and await capture fault results
knqiufan Oct 13, 2026
fe20e0a
fix(images): integrate current master contracts and host startup
knqiufan Oct 20, 2026
957d0ca
fix(images): adapt capture setup to current installer contracts
knqiufan Oct 21, 2026
7733da0
chore(images): sync generated contracts and dependency locks
knqiufan Oct 21, 2026
bada505
fix(images): repair isolated installs and capture recovery
knqiufan Oct 22, 2026
40e5b7e
fix(images): recover outbox capacity and preserve thumbnail alpha
knqiufan Oct 23, 2026
dfe5953
merge: integrate master into image source experiment
knqiufan Oct 23, 2026
1e0d292
fix(desktop): qualify the integrated image source contract
knqiufan Oct 23, 2026
9abb362
docs(images): record rebased review verification
knqiufan Oct 25, 2026
3151384
feat(media): align image evidence with RFC 1972
knqiufan Oct 25, 2026
4894785
merge: sync master for media integration
knqiufan Oct 25, 2026
74dada2
perf(media): index active work and record qualification
knqiufan Oct 25, 2026
6b86fcd
fix(ci): sync image capability contracts and expectations
knqiufan Oct 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,18 @@ POWERCONTEXT_LANGGRAPH_BASE_URL=http://127.0.0.1:8000

# Prompt capture is enabled by default; these explicit values make the template self-documenting.
POWERCONTEXT_CODEX_CAPTURE_PROMPTS=true
# Optional PNG/JPEG evidence (durable file SQLite). Install [server,images].
# Existing databases need the registered media migration; bytes stay in SQLite.
# Setup records workspace consent.
POWERCONTEXT_SERVER_IMAGES_ENABLED=false
POWERCONTEXT_CODEX_CAPTURE_IMAGES=false
# Reuse an image-capable OpenAI Chat generation connection explicitly:
POWERCONTEXT_SERVER_INFERENCE_VISION_USE_GENERATION=false
# Or configure a dedicated Vision connection. Credentials stay local.
# POWERCONTEXT_SERVER_INFERENCE_VISION_MODEL=your-vision-model
# POWERCONTEXT_SERVER_INFERENCE_VISION_BASE_URL=https://your-provider.example/v1
# POWERCONTEXT_SERVER_INFERENCE_VISION_DEPLOYMENT_ID=your-deployment-v1
# POWERCONTEXT_SERVER_INFERENCE_VISION_HEADERS='{"Authorization":"Bearer YOUR_API_KEY"}'
POWERCONTEXT_CLAUDE_CAPTURE_PROMPTS=true
POWERCONTEXT_DSH_CAPTURE_PROMPTS=true
POWERCONTEXT_OPENCODE_CAPTURE_PROMPTS=true
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/master.yml
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ jobs:
fail-fast: false
matrix:
python-version: ["3.11", "3.14"]
extras: ["builtin", "cli", "builtin,cli", "server,cli"]
extras: ["builtin", "images", "cli", "builtin,cli", "server,cli"]
steps:
- name: Check out
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
Expand Down
12 changes: 12 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,15 @@ Pull requests should link the relevant issue or RFC, explain the rationale, summ
## Security & Configuration Tips

Do not commit secrets, local virtual environments, caches, `.powercontext/`, `dist/`, or generated website output. Keep dependency changes reflected in `uv.lock`, and use `make check` to catch lock drift before review.

## Image Source Experiment

This worktree contains a local, opt-in Image Source experiment. Before changing this feature, read
[the implementation guide](docs/experiments/image-source/README.md) and
[the implementation log](docs/experiments/image-source/implementation-log.md).

- Follow the guide's capture, durable original, background vision parsing, immutable analysis Source, and text-evidence flow. Keep the feature disabled by default and respect the documented scope and phase acceptance criteria.
- For every AI coding session, record the target phase before work and update the implementation log before completion or interruption with actual changes, commands, results, limitations, and the next concrete step. Mark a phase complete only when its acceptance criteria are met.
- Distinguish offline tests, direct hook calls, real model execution, and real host uploads. Never claim a real integration works from simulated inputs alone.
- Run all feature commands in this worktree with a separate database, asset directory, environment file, and port. Do not reuse the primary checkout's live services or private data.
- Keep credentials and private image evidence in ignored local storage. Do not push this experiment, create an upstream PR, or publish it unless the user explicitly requests that action.
60 changes: 58 additions & 2 deletions desktop/VALIDATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,74 @@ cargo test --locked --manifest-path desktop/src-tauri/Cargo.toml

## Compatibility scope

[compatibility.json](src-tauri/src/connections/compatibility.json) preserves the recorded Server sources, normalized OpenAPI contract digests and qualification-wheel digests for the historical profiles below. The current contract is qualified by `sqlite-atomic-1da99747-v1` below; ordinary builds require explicitly selecting it and checking the connection before business operations become available. The `sqlite-atomic-d9a78567-v1`, `sqlite-atomic-caf2a35a-v1`, `sqlite-atomic-683e2db0-v1` and `sqlite-atomic-cab054db-v1` records qualify their corresponding Server source deployments and do not match this bundled contract. Historical records are disabled in the selector, and saved unavailable selections remain visible until explicitly replaced. CI builds have their own artifact identities and do not change product qualification.
[compatibility.json](src-tauri/src/connections/compatibility.json) preserves the recorded Server sources, normalized OpenAPI contract digests and qualification-wheel digests for the profiles below. The current contract is qualified by `sqlite-atomic-4894785a-v1`; ordinary builds require explicitly selecting it and checking the connection before business operations become available. Earlier records qualify their corresponding Server source deployments and do not match this bundled contract. Historical records are disabled in the selector, and saved unavailable selections remain visible until explicitly replaced. CI builds have their own artifact identities and do not change product qualification.

The real Server harness covers SQLite with anonymous loopback, static Bearer, HTTPS with explicit CA/base path, and injected-provider/enforced access. It exercises save/search/exact reads, identity changes, binding revocation, ambiguous writes without replay and Scope pagination. Installed UI checks cover repeated launches preserving the existing editor, late committed-save responses preserving a new Scope draft, explicit connection/Scope selection, clipboard copies, connection isolation, draft cancellation, byte limits and independent Server survival after Desktop exit.

Selecting a compatibility profile does not attest the remote binary identity. Existing `sqlite-1.1.1-v1` / `sqlite-63f918b7-v1` / `sqlite-ab43e3a7-v1` / `sqlite-f1089f4e-v1` / `sqlite-6e237568-v1` / `sqlite-legacy-58f7f4f6-v1` selections require explicitly choosing an available matching profile and rechecking the connection. Desktop reads memories only through Atomic Memory references, so Servers that answer only with Memory entry citations are not qualified. CLI diagnostics separately verify the registered executable path and digest, then validate the diagnostic response schema. The observed version is optional report information; a registration does not require a version.

### Current Server protocol qualification

#### Server 4894785a protocol qualification

`sqlite-atomic-4894785a-v1` identifies Server sources at
`4894785a6efd65d1f0ce89e4f2af3250ab2a7ae7` and normalized OpenAPI digest
`6551eda05dbcafdafd2810fe20c8a5a33d377eb041bf6d8e47eb756bf7038dd4`.
The qualification wheel is `powercontext-1.4.1.dev194+g4894785a6-py3-none-any.whl`,
SHA-256 `90e72fcb9a9672dc0d3663a735ba471ef858a9561baa0547063e47b5ea714387`.
All 578 packaged runtime files match that commit after CRLF/LF normalization;
the contract, project configuration and lock were also compared with the recorded commit.
The sorted wheel runtime source-manifest digest is
`7a1922be7317e98cd1bd15f98e30bea5f6616ccd56487bd90d5879c0e6ab002f`
(one `wheel/path sha256` entry per line with a final newline, hashing actual wheel bytes).

On Windows 11 AMD64, Python 3.14.5 and Rust 1.95.0, the unmodified native `server_probe`
and real-Server harness passed against the isolated wheel and SQLite in all four modes:
anonymous loopback, static Bearer, HTTPS with explicit CA/base path, and injected-provider/enforced access.
The ten recorded operations cover Scope pagination, Atomic Memory save/search/exact revision reads,
identity changes, same-identity revocation, committed writes with lost responses without replay,
and independent Server survival after client exit. The product's locked native dependencies were used.

Reproduce by building the wheel at the recorded commit, running
`fixture_qualification.py --server-commit 4894785a6efd65d1f0ce89e4f2af3250ab2a7ae7`,
building the native `server_probe`, and running `desktop/tests/real_server.py`.
This qualifies the ordinary Desktop protocol with the shared-media contract additions;
it does not qualify image UI, a production binary, installed packages, native macOS behavior,
credential-store workflows, signing or release readiness. Earlier qualification identities remain unchanged.

#### Server ec32d953 protocol qualification

`sqlite-atomic-ec32d953-v1` identifies Server sources at
`ec32d953be18b52ace1099ceb7107f6a89ba66c9` and normalized OpenAPI digest
`f86ca993b9e39e75948a83a4a038c0eaa2aadf6e0d14c60b37fcc9be83e2dfcb`.
The qualification wheel is `powercontext-1.4.1.dev154+gec32d953b.d20261023-py3-none-any.whl`,
SHA-256 `a00e8b88cb6aedabb4632ba52143c4e4c22ab639f187eae5755fadc7216a248d`.
All 556 packaged runtime files match the recorded commit after CRLF/LF normalization;
the OpenAPI contract, project configuration and lock are unchanged from that commit.
The sorted wheel runtime source-manifest digest is
`1d80147341b3d0f04261d3d1274946e37fdd78b3d6e58c78198684a4559cfad1`
(one `wheel/path sha256` entry per line, with a final newline; hashes cover the actual wheel bytes).

The unmodified native `server_probe` and real-Server harness passed against this isolated wheel
and SQLite in all four modes: anonymous loopback, static Bearer, HTTPS with an explicit CA and
base path, and an injected provider with enforced access. The ten recorded Desktop operations
cover Scope selection and pagination, Atomic Memory save/search/exact revision reads, identity
changes, same-identity revocation, committed writes with lost responses without replay, and
independent Server survival after the client exits.

Qualification ran on Windows 11 AMD64, Python 3.14.5 and Rust 1.95.0 using the locked product
dependencies and the native debug client. Reproduce by building the wheel at the recorded commit,
running `fixture_qualification.py --server-commit ec32d953be18b52ace1099ceb7107f6a89ba66c9`,
building `server_probe`, and running `uv run python desktop/tests/real_server.py`.
The harness uses explicit disposable qualification evidence; the resulting protocol evidence
supports this separate product record. This does not qualify image operations in the native
Desktop UI, external production deployments, installed packages, native macOS behavior, signing,
credential-store workflows or release readiness. Historical records retain their original identities.

#### Server 1da99747 protocol qualification

`sqlite-atomic-1da99747-v1` qualifies Server sources at
`1da997476651c2850ff7141e2b7cd512d0152a90` for the bundled OpenAPI digest
`1da997476651c2850ff7141e2b7cd512d0152a90` for the recorded OpenAPI digest
`5878999ce9e239d6642e4da858074b281ed465629432c578b3584eec47cbce6c`. The qualification wheel is
`powercontext-0.1.dev1120+g2066de01d-py3-none-any.whl`, SHA-256
`f87da56c813fe0e994ba60c29e8ba99eb48567dc561ac9f19ac2979e0599c1a6`. It was built from clean Desktop commit
Expand Down
38 changes: 38 additions & 0 deletions desktop/src-tauri/src/connections/compatibility.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,42 @@
[
{
"id": "sqlite-atomic-4894785a-v1",
"serverCommit": "4894785a6efd65d1f0ce89e4f2af3250ab2a7ae7",
"contractSha256": "6551eda05dbcafdafd2810fe20c8a5a33d377eb041bf6d8e47eb756bf7038dd4",
"artifactSha256": "90e72fcb9a9672dc0d3663a735ba471ef858a9561baa0547063e47b5ea714387",
"operations": [
"get_access_principal",
"get_artifact_revision",
"get_capabilities",
"get_default_scope",
"get_liveness",
"get_readiness",
"get_scope",
"list_scopes",
"remember_memory",
"search_memory"
],
"evidence": "desktop/VALIDATION.md#server-4894785a-protocol-qualification"
},
{
"id": "sqlite-atomic-ec32d953-v1",
"serverCommit": "ec32d953be18b52ace1099ceb7107f6a89ba66c9",
"contractSha256": "f86ca993b9e39e75948a83a4a038c0eaa2aadf6e0d14c60b37fcc9be83e2dfcb",
"artifactSha256": "a00e8b88cb6aedabb4632ba52143c4e4c22ab639f187eae5755fadc7216a248d",
"operations": [
"get_access_principal",
"get_artifact_revision",
"get_capabilities",
"get_default_scope",
"get_liveness",
"get_readiness",
"get_scope",
"list_scopes",
"remember_memory",
"search_memory"
],
"evidence": "desktop/VALIDATION.md#server-ec32d953-protocol-qualification"
},
{
"id": "sqlite-6e237568-v1",
"serverCommit": "6e2375688bc38a667840c6b2dc8269d8848027bc",
Expand Down
2 changes: 1 addition & 1 deletion desktop/src-tauri/src/transport/operations.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"contractSha256": "5878999ce9e239d6642e4da858074b281ed465629432c578b3584eec47cbce6c",
"contractSha256": "6551eda05dbcafdafd2810fe20c8a5a33d377eb041bf6d8e47eb756bf7038dd4",
"operations": {
"get_liveness": {
"method": "GET",
Expand Down
55 changes: 55 additions & 0 deletions desktop/src-tauri/src/transport/wire.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,8 @@ pub enum ArtifactReadFamily {
Prompt,
#[serde(rename = "topic-memory")]
TopicMemory,
#[serde(rename = "image-analysis")]
ImageAnalysis,
}

impl std::fmt::Display for ArtifactReadFamily {
Expand All @@ -403,6 +405,7 @@ impl std::fmt::Display for ArtifactReadFamily {
Self::Profile => write!(f, "profile"),
Self::Prompt => write!(f, "prompt"),
Self::TopicMemory => write!(f, "topic-memory"),
Self::ImageAnalysis => write!(f, "image-analysis"),
}
}
}
Expand Down Expand Up @@ -648,6 +651,16 @@ impl std::fmt::Display for AtomicMemoryState {
#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, TS)]
#[serde(deny_unknown_fields)]
pub struct Capabilities {
/// Image binding configuration and storage admission readiness; this does not call Vision.
#[ts(optional)]
#[ts(type = "ImageProcessingCapability | null")]
#[serde(
rename = "media",
default,
with = "::serde_with::rust::double_option",
skip_serializing_if = "Option::is_none"
)]
pub media: Option<Option<ImageProcessingCapability>>,
#[ts(optional)]
#[serde(rename = "prompts", skip_serializing_if = "Option::is_none")]
pub prompts: Option<std::collections::HashMap<String, PromptCapability>>,
Expand Down Expand Up @@ -713,6 +726,7 @@ impl Capabilities {
context_versions: Vec<PreparedContextSchema>,
) -> Capabilities {
Capabilities {
media: None,
prompts: None,
artifact_dreaming: None,
artifact_dreaming_operations: None,
Expand Down Expand Up @@ -994,6 +1008,46 @@ impl HealthResponse {
}
}

#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, TS)]
#[serde(deny_unknown_fields)]
pub struct ImageProcessingCapability {
#[serde(rename = "enabled")]
pub enabled: bool,
#[serde(rename = "available")]
pub available: bool,
#[serde(rename = "processing_enabled")]
pub processing_enabled: bool,
#[serde(rename = "vision_configured")]
pub vision_configured: bool,
#[ts(type = "string | null")]
#[serde(rename = "profile_digest", deserialize_with = "Option::deserialize")]
pub profile_digest: Option<String>,
#[ts(type = "string | null")]
#[serde(rename = "error_code", deserialize_with = "Option::deserialize")]
pub error_code: Option<String>,
}

impl ImageProcessingCapability {
#[allow(clippy::too_many_arguments)]
pub fn new(
enabled: bool,
available: bool,
processing_enabled: bool,
vision_configured: bool,
profile_digest: Option<String>,
error_code: Option<String>,
) -> ImageProcessingCapability {
ImageProcessingCapability {
enabled,
available,
processing_enabled,
vision_configured,
profile_digest,
error_code,
}
}
}

#[derive(Clone, Default, Debug, PartialEq, Serialize, Deserialize, TS)]
#[serde(deny_unknown_fields)]
pub struct MemoryMutationResponse {
Expand Down Expand Up @@ -1470,6 +1524,7 @@ pub fn declarations(config: &ts_rs::Config) -> Vec<String> {
<ExtractionObservationStatus as ts_rs::TS>::decl(config),
<ExtractionStatus as ts_rs::TS>::decl(config),
<HealthResponse as ts_rs::TS>::decl(config),
<ImageProcessingCapability as ts_rs::TS>::decl(config),
<Location as ts_rs::TS>::decl(config),
<MatchedBy as ts_rs::TS>::decl(config),
<MemoryMutationResponse as ts_rs::TS>::decl(config),
Expand Down
Loading
Loading