ds4-context-engine 0.1.2 → 0.2.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +84 -14
- package/docs/ARCHITECTURE.md +42 -16
- package/docs/CONTEXT_MANIFEST.md +3 -1
- package/docs/CONTEXT_PLANNER.md +9 -1
- package/docs/CONTEXT_QUALITY.md +91 -0
- package/docs/HYBRID_RETRIEVAL.md +117 -0
- package/docs/LEARNED_RANKING.md +90 -0
- package/docs/LOCAL_KV_REUSE.md +131 -0
- package/docs/MEMORY_AND_PINS.md +11 -5
- package/docs/PORTABLE_CORE.md +15 -8
- package/docs/PROJECT_KNOWLEDGE.md +26 -16
- package/docs/RELEASING.md +18 -13
- package/docs/RETRIEVAL.md +1 -1
- package/docs/ROADMAP_0.2.0.md +15 -1
- package/docs/RUNTIME_ADAPTER_KIT.md +145 -0
- package/docs/STORAGE.md +37 -7
- package/package.json +12 -7
- package/quality/corpus-v1.json +208 -0
- package/quality/semantic-corpus-v1.json +84 -0
- package/quality/symbol-corpus-v1.json +38 -0
- package/scripts/compare-context-quality.mjs +23 -0
- package/src/extension/commands.ts +213 -1
- package/src/extension/index.ts +1 -0
- package/src/extension/runtime.ts +622 -16
- package/src/pi-adapter/local-embedding.ts +132 -0
- package/src/pi-adapter/memory-adapter.ts +18 -8
- package/src/pi-adapter/project-memory-sync.ts +499 -0
- package/src/pi-adapter/ranking-adapter.ts +72 -0
- package/src/pi-adapter/runtime-contract.ts +86 -0
- package/src/pi-adapter/version.ts +3 -3
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Hybrid Semantic Retrieval
|
|
2
|
+
|
|
3
|
+
M16 adds opt-in vector candidate generation to historical and trusted-project retrieval. Exact identifiers and FTS5 remain active and authoritative; semantic candidates are fused into the same bounded, deterministic ranking and never replace source provenance or live-hash checks.
|
|
4
|
+
|
|
5
|
+
## Configuration
|
|
6
|
+
|
|
7
|
+
Semantic retrieval remains disabled for upgrades from 0.1:
|
|
8
|
+
|
|
9
|
+
```json
|
|
10
|
+
{
|
|
11
|
+
"retrieval": {
|
|
12
|
+
"semantic": true
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
The supported default is the runtime-owned local feature-hash embedding:
|
|
18
|
+
|
|
19
|
+
```json
|
|
20
|
+
{
|
|
21
|
+
"retrieval": {
|
|
22
|
+
"semantic": true,
|
|
23
|
+
"embedding": {
|
|
24
|
+
"mode": "local",
|
|
25
|
+
"provider": "ds4-local",
|
|
26
|
+
"model": "feature-hash-v1",
|
|
27
|
+
"dimensions": 256,
|
|
28
|
+
"maxSources": 50000,
|
|
29
|
+
"candidatePool": 80,
|
|
30
|
+
"batchSize": 64,
|
|
31
|
+
"queryCacheSize": 64,
|
|
32
|
+
"timeoutMs": 2000
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
It is deterministic, has no native dependency and performs no network access. Core defines `EmbeddingPort`; the Pi adapter supplies the implementation. Other runtimes can inject a compatible local, WASM or remote port without adding model invocation to core.
|
|
39
|
+
|
|
40
|
+
Remote embedding requires all of the following:
|
|
41
|
+
|
|
42
|
+
- `mode: "remote"`;
|
|
43
|
+
- an exact `provider/model` entry in `remoteProfiles` (wildcards are rejected);
|
|
44
|
+
- `privacy.enabled: true`;
|
|
45
|
+
- provider-specific privacy allow rules;
|
|
46
|
+
- a runtime-injected `EmbeddingPort` whose provider, model, dimensions and remote destination exactly match configuration.
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{
|
|
50
|
+
"retrieval": {
|
|
51
|
+
"semantic": true,
|
|
52
|
+
"embedding": {
|
|
53
|
+
"mode": "remote",
|
|
54
|
+
"provider": "embedding.example",
|
|
55
|
+
"model": "semantic-v2",
|
|
56
|
+
"dimensions": 768,
|
|
57
|
+
"remoteProfiles": ["embedding.example/semantic-v2"]
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"privacy": {
|
|
61
|
+
"enabled": true,
|
|
62
|
+
"remoteProviders": {
|
|
63
|
+
"embedding.example": ["normal", "internal"]
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
The packaged Pi adapter intentionally includes no default remote embedding client. Missing or mismatched ports produce lexical-only results.
|
|
70
|
+
|
|
71
|
+
## Privacy
|
|
72
|
+
|
|
73
|
+
Every remote source and query passes through `PrivacyPolicyEngine` before `EmbeddingPort.embed`. A value whose effective classification is `local-only`, or which contains a provider-blocked span, is excluded as a whole and never reaches the remote port. Allowed text is secret-redacted before invocation. Local mode does not cross a provider boundary.
|
|
74
|
+
|
|
75
|
+
Embedding diagnostics contain only counts, model identity, dimensions, destination, freshness, cache status, timings and normalized fallback reasons. They never contain query text, source text, vectors, provider response IDs or remote handles.
|
|
76
|
+
|
|
77
|
+
## Derived storage
|
|
78
|
+
|
|
79
|
+
SQLite schema v13 adds `derived_embeddings`. Each row is keyed by:
|
|
80
|
+
|
|
81
|
+
```text
|
|
82
|
+
source kind + scope + source key + source hash + chunking version
|
|
83
|
+
+ embedding provider + embedding model + dimensions
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Rows contain the source group, numeric vector JSON and indexing time, but no copied query or evidence text. Session entries use `pi-session-entry-v1`; project chunks use their parser version or `text-window-v1`.
|
|
87
|
+
|
|
88
|
+
A source edit prunes only vectors whose key/hash/chunk version is no longer current. Unchanged source rows and unrelated model/dimension profiles remain intact. A model or dimension switch selects a separate profile instead of rewriting compatible rows. Deleting SQLite discards the whole vector projection; canonical Pi JSONL and live project files rebuild it.
|
|
89
|
+
|
|
90
|
+
## Candidate generation and rank fusion
|
|
91
|
+
|
|
92
|
+
Candidate pools are bounded. Generation order is:
|
|
93
|
+
|
|
94
|
+
1. exact project path, qualified symbol, simple symbol, quoted phrase or historical identifier;
|
|
95
|
+
2. escaped FTS5 candidates;
|
|
96
|
+
3. cosine-ranked vector candidates.
|
|
97
|
+
|
|
98
|
+
The lexical and vector ranks are combined with deterministic reciprocal-rank fusion, semantic similarity and stable source-ID tie-breaking. Exact matches retain a score tier that vectors cannot displace. Historical candidates still require active-branch membership and exclusion from the active native context. Project candidates still require project trust, sensitive-file exclusion and a live SHA-256 match before injection.
|
|
99
|
+
|
|
100
|
+
Source vectors are generated during session/project index sync. Query vectors use a bounded volatile hash-keyed cache. Repeating a request with current source vectors performs no embedding call. Query hashes and vectors are not persisted as conversation state.
|
|
101
|
+
|
|
102
|
+
## Failure behavior
|
|
103
|
+
|
|
104
|
+
Missing models, consent failure, privacy exclusion, invalid dimensions, corrupt vectors, synchronous-port timeout, provider exceptions, vector storage errors and vector search errors all return the available exact/FTS result. They cannot fail context planning. Diagnostics expose the fallback reason without source content.
|
|
105
|
+
|
|
106
|
+
## Quality gate
|
|
107
|
+
|
|
108
|
+
[`quality/semantic-corpus-v1.json`](../quality/semantic-corpus-v1.json) is a synthetic extension of the M14 replay methodology. It measures the same evidence-recall and irrelevant-token signals for semantic synonyms and exact-match preservation. The byte-stable golden report records:
|
|
109
|
+
|
|
110
|
+
```text
|
|
111
|
+
lexical evidence recall 0.25
|
|
112
|
+
hybrid evidence recall 1.00
|
|
113
|
+
recall delta +0.75
|
|
114
|
+
irrelevant-token delta 0.00
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Verification covers local query reuse, source-vector caching, profile isolation, changed-source pruning, remote `local-only` exclusion, provider failure, exact priority, historical/project fusion and schema v13 rebuild behavior.
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Learned Ranking
|
|
2
|
+
|
|
3
|
+
M18 adds an optional metadata-only linear ranker while preserving the deterministic static ranker as the universal fallback.
|
|
4
|
+
|
|
5
|
+
## Modes
|
|
6
|
+
|
|
7
|
+
```json
|
|
8
|
+
{
|
|
9
|
+
"ranking": {
|
|
10
|
+
"mode": "shadow",
|
|
11
|
+
"modelPath": "ds4-context/ranking-model.json",
|
|
12
|
+
"minimumTrainingSamples": 20,
|
|
13
|
+
"maxTrainingSamples": 10000,
|
|
14
|
+
"maxLatencyMs": 10
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
- `off` does not load or evaluate a learned model.
|
|
20
|
+
- `shadow` evaluates a valid model, records only aggregate rank disagreement, and keeps static selection unchanged.
|
|
21
|
+
- `active` changes supplemental-candidate ordering only when the checksummed artifact contains a successful promotion report. Missing, incompatible, corrupt, unpromoted, or regressing artifacts fall back to static ranking.
|
|
22
|
+
|
|
23
|
+
`off` is the upgrade default. Privacy filtering, mandatory pins, current-request retention, category budgets, atomic groups, and hard input limits remain authoritative in every mode.
|
|
24
|
+
|
|
25
|
+
## Bounded feature schema
|
|
26
|
+
|
|
27
|
+
`ranking-features-v1` contains only a source-kind enum and ten finite normalized numbers:
|
|
28
|
+
|
|
29
|
+
- static score;
|
|
30
|
+
- exact-match score;
|
|
31
|
+
- FTS score;
|
|
32
|
+
- vector score;
|
|
33
|
+
- recency;
|
|
34
|
+
- active-branch relation;
|
|
35
|
+
- symbol relation;
|
|
36
|
+
- classification eligibility;
|
|
37
|
+
- token cost;
|
|
38
|
+
- prior selection outcome.
|
|
39
|
+
|
|
40
|
+
All numbers are bounded to `[0, 1]`. Candidate text, excerpts, prompts, file paths, symbols, claims, provider payloads, and credentials are not model features. Stable candidate and repository identities are SHA-256 hashes in canonical labels.
|
|
41
|
+
|
|
42
|
+
## Canonical labels and local training
|
|
43
|
+
|
|
44
|
+
Explicit feedback is appended through Pi as a classified `ds4-context-ranking-feedback-v1` custom entry:
|
|
45
|
+
|
|
46
|
+
```text
|
|
47
|
+
/context ranking feedback useful CANDIDATE_ID --classification internal
|
|
48
|
+
/context ranking feedback irrelevant CANDIDATE_ID --classification local-only
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Only candidates from the latest managed context are accepted. A feedback entry contains schema/version, feedback ID, timestamp, classification, label source, label, two hashes, and the bounded feature vector. It contains no candidate text. Sanitized replay labels use the same schema with `labelSource: "replay"`.
|
|
52
|
+
|
|
53
|
+
Train a local shadow artifact from the active canonical Pi branch:
|
|
54
|
+
|
|
55
|
+
```text
|
|
56
|
+
/context ranking train
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Training is deterministic for the same unique labels and timestamp, requires both useful and irrelevant examples, and is bounded by `minimumTrainingSamples` and `maxTrainingSamples`. The artifact is written with mode `0600` where supported. Training never calls a provider and does not make the resulting artifact active.
|
|
60
|
+
|
|
61
|
+
## Artifact integrity and deterministic inference
|
|
62
|
+
|
|
63
|
+
`ranking-model.json` uses schema version `1`, feature version `ranking-features-v1`, algorithm `bounded-linear-centroid-v1`, bounded weights, training counts, a deterministic model ID, and a SHA-256 checksum over its stable JSON payload. Inference uses rounded finite arithmetic and resolves equal scores by static score and then candidate ID.
|
|
64
|
+
|
|
65
|
+
The model artifact is local derived state. Deleting it preserves Pi JSONL labels and restores static ranking. A newly trained artifact can be reconstructed from canonical labels.
|
|
66
|
+
|
|
67
|
+
## Promotion gate
|
|
68
|
+
|
|
69
|
+
`evaluateRankingPromotion()` in `ds4-context-core/ranking/learned-ranker` evaluates sanitized held-out fixtures. `withRankingPromotion()` seals the resulting report into a new checksummed artifact. Promotion succeeds only when all of these conditions hold:
|
|
70
|
+
|
|
71
|
+
- primary quality score improves;
|
|
72
|
+
- exact-identifier recall does not regress;
|
|
73
|
+
- privacy violations do not increase;
|
|
74
|
+
- atomicity failures do not increase;
|
|
75
|
+
- overflow does not increase;
|
|
76
|
+
- measured p95 latency stays within budget;
|
|
77
|
+
- repeated inference yields identical ordering;
|
|
78
|
+
- the configured minimum number of held-out repositories is represented.
|
|
79
|
+
|
|
80
|
+
An artifact without an eligible report can run in shadow mode but cannot alter context in active mode.
|
|
81
|
+
|
|
82
|
+
## Diagnostics
|
|
83
|
+
|
|
84
|
+
```text
|
|
85
|
+
/context ranking
|
|
86
|
+
/context health
|
|
87
|
+
/context manifest
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Ranking diagnostics include mode/status, versions, model identity, promotion state, label counts, malformed/duplicate counts, candidate count, top-rank disagreement, pairwise disagreements, mean rank shift, inference duration, and fallback reason. Shadow diagnostics and Context Manifests contain aggregate comparison only—never candidate IDs, labels, features, or text.
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# Local KV Reuse
|
|
2
|
+
|
|
3
|
+
M20 adds an opt-in, runtime-neutral prefix/KV capability for local inference runtimes. KV state is only an inference optimization: it is not canonical history, memory, retrieval evidence, a Context Manifest source, or a SQLite projection.
|
|
4
|
+
|
|
5
|
+
Pi does not expose native KV handles and continues to report `local-kv-reuse` as unsupported. The callback/JSONL reference adapter can exercise the capability when its host injects a `LocalKvRuntimePort`; no provider SDK is added to core or the reference package.
|
|
6
|
+
|
|
7
|
+
## Boundary
|
|
8
|
+
|
|
9
|
+
```text
|
|
10
|
+
runtime/provider payload
|
|
11
|
+
↓
|
|
12
|
+
adapter privacy enforcement
|
|
13
|
+
↓
|
|
14
|
+
runtime-specific prefix/options extraction from sanitized payload
|
|
15
|
+
↓
|
|
16
|
+
core exact-byte eligibility hashes
|
|
17
|
+
↓
|
|
18
|
+
volatile LocalKvRuntimePort lookup + transport
|
|
19
|
+
├─ exact hit ───────────────> cached completion
|
|
20
|
+
└─ miss/rejected/unavailable -> full prompt replay
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Core receives the provider-ready prefix only long enough to hash it. It returns metadata-only component hashes and an aggregate fingerprint. A runtime port maps that fingerprint to its own volatile handle. Handles never cross the port, and core has no API for serializing them.
|
|
24
|
+
|
|
25
|
+
## Configuration and negotiation
|
|
26
|
+
|
|
27
|
+
Configuration is disabled by default:
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"localKvReuse": {
|
|
32
|
+
"enabled": false
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Enabling configuration is not sufficient. The active adapter must independently declare a versioned `local-kv-reuse` capability and provide a `LocalKvRuntimePort`. Unsupported or malformed declarations disable KV reuse without affecting history, privacy, completion fallback, or any other capability.
|
|
38
|
+
|
|
39
|
+
A reference-adapter host opts in explicitly:
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
const adapter = new JsonlReferenceRuntimeAdapter({
|
|
43
|
+
// canonical history, model, privacy, and ordinary transport options...
|
|
44
|
+
localKv: {
|
|
45
|
+
enabled: true,
|
|
46
|
+
port: myVolatileKvPort,
|
|
47
|
+
runtimeRevision: "llama-runtime-build-42",
|
|
48
|
+
modelRevision: "model-checksum-abc",
|
|
49
|
+
prepare(sanitizedPayload) {
|
|
50
|
+
return {
|
|
51
|
+
promptPrefix: exactProviderPrefixBytes(sanitizedPayload),
|
|
52
|
+
systemOptions: providerSystemOptions(sanitizedPayload),
|
|
53
|
+
toolOptions: providerToolOptions(sanitizedPayload),
|
|
54
|
+
prefixTokenCount: 32_000,
|
|
55
|
+
contextTokenCount: 40_000,
|
|
56
|
+
};
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`prepare()` receives only the payload returned by adapter privacy enforcement. Remote destinations never enter the local KV path.
|
|
63
|
+
|
|
64
|
+
## Exact eligibility
|
|
65
|
+
|
|
66
|
+
`deriveLocalKvEligibility()` uses `local-kv-eligibility-v1`. An eligible fingerprint includes independent SHA-256 components for:
|
|
67
|
+
|
|
68
|
+
- exact provider, model, and model revision;
|
|
69
|
+
- exact UTF-8/string or byte prefix;
|
|
70
|
+
- deterministic JSON-compatible system and tool options;
|
|
71
|
+
- privacy policy version and local destination;
|
|
72
|
+
- runtime identity, runtime revision, and capability implementation version.
|
|
73
|
+
|
|
74
|
+
Identifiers are not case-folded or wildcard-matched. Prefix bytes are not normalized. Option object keys are ordered only for deterministic serialization; values, array order, missing/undefined values, and system/tool separation remain significant. Functions, symbols, binary option values, accessors, custom prototypes, circular values, and non-finite numbers are ineligible instead of being hashed ambiguously.
|
|
75
|
+
|
|
76
|
+
Any changed prefix byte, provider/model identity, model revision, system/tool option, privacy version, runtime revision, or capability version produces a different fingerprint. Disabled configuration, unsupported capability, remote destination, invalid identifiers, an empty prefix, or invalid token counts bypass reuse.
|
|
77
|
+
|
|
78
|
+
## Runtime port and replay
|
|
79
|
+
|
|
80
|
+
`LocalKvRuntimePort` deliberately exposes no handle:
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
interface LocalKvRuntimePort {
|
|
84
|
+
tryReuse(request): Promise<
|
|
85
|
+
| { status: "hit"; output: unknown; savedPrefillTokens: number; prefillLatencyMs: number }
|
|
86
|
+
| { status: "miss" | "rejected" | "unavailable" }
|
|
87
|
+
>;
|
|
88
|
+
fullReplay(request): Promise<{
|
|
89
|
+
output: unknown;
|
|
90
|
+
prefillTokens: number;
|
|
91
|
+
prefillLatencyMs: number;
|
|
92
|
+
}>;
|
|
93
|
+
shutdown?(): Promise<void>;
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
The runtime owns fingerprint-to-handle lookup, eviction, provider transport, and restart cleanup. `LocalKvReuseController` treats thrown lookup errors and malformed lookup results as unavailable state. Every miss, stale rejection, unavailable state, or runtime restart invokes `fullReplay()` with the complete sanitized payload. If the injected KV full replay itself fails, the reference adapter retries the complete sanitized payload through its ordinary native transport.
|
|
98
|
+
|
|
99
|
+
Adapter shutdown calls optional port shutdown once. Cache deletion, eviction, process loss, or runtime restart therefore changes performance only; it cannot change canonical state or prevent a full replay.
|
|
100
|
+
|
|
101
|
+
## Aggregate diagnostics
|
|
102
|
+
|
|
103
|
+
`local-kv-diagnostics-v1` contains numbers only:
|
|
104
|
+
|
|
105
|
+
- requests, eligible requests, and bypasses;
|
|
106
|
+
- hits, misses, rejected states, unavailable states, full replays, and transport failures;
|
|
107
|
+
- reusable prefix tokens and total context-occupancy tokens;
|
|
108
|
+
- saved prefill tokens;
|
|
109
|
+
- full-replay prefill tokens and runtime-reported prefill latency.
|
|
110
|
+
|
|
111
|
+
Diagnostics never include provider/model text, prefix or payload content, component fingerprints, runtime handles, credentials, provider response IDs, or output. Per-request completion metadata keeps `contextTokens`, `savedPrefillTokens`, `replayPrefillTokens`, and `prefillLatencyMs` as separate fields; context occupancy is never reported as cache savings.
|
|
112
|
+
|
|
113
|
+
## Privacy and persistence
|
|
114
|
+
|
|
115
|
+
Privacy enforcement precedes runtime-specific prefix extraction and hash verification. A remote payload is sanitized and sent through ordinary transport without consulting local KV state. An enabled local policy is still applied before extraction. A prior cached state cannot authorize material excluded by the current privacy policy because the policy version and sanitized exact prefix are both part of eligibility.
|
|
116
|
+
|
|
117
|
+
No KV handle or prefix copy is written to:
|
|
118
|
+
|
|
119
|
+
- Pi JSONL or reference canonical JSONL;
|
|
120
|
+
- Context Manifests;
|
|
121
|
+
- DS4 SQLite;
|
|
122
|
+
- learned-ranking artifacts;
|
|
123
|
+
- adapter/core diagnostics.
|
|
124
|
+
|
|
125
|
+
There is no M20 database migration. Deleting all volatile runtime KV state requires no DS4 rebuild and no canonical-history migration.
|
|
126
|
+
|
|
127
|
+
## Verification and benchmark
|
|
128
|
+
|
|
129
|
+
Unit and reference-adapter integration tests cover exact hits, changed bytes/options, provider/model/privacy/runtime invalidation, cache loss, stale rejection, unavailable state, full replay, privacy-before-verification, aggregate-only diagnostics, idempotent shutdown, and unchanged canonical JSONL.
|
|
130
|
+
|
|
131
|
+
`tests/benchmarks/local-kv.bench.ts` hashes a synthetic 32,000-token reusable prefix inside a 40,000-token context and separately benchmarks a warm completion whose simulated runtime metadata reports 32,000 saved prefill tokens and `0.5 ms` prefill latency. On the development host, exact eligibility averaged about `0.259 ms` and the warm controller path about `0.248 ms`. These are observational, not portable provider-latency guarantees; the benchmark intentionally reports runtime prefill latency/token savings separately from context occupancy.
|
package/docs/MEMORY_AND_PINS.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Memory and Persistent Pins
|
|
2
2
|
|
|
3
|
-
M9 separates durable, user-curated state from conversation history while keeping Pi JSONL canonical.
|
|
3
|
+
M9 separates durable, user-curated state from conversation history while keeping Pi JSONL canonical. M17 optionally reconstructs explicit project-scoped mutations from sibling Pi sessions for the same trusted canonical project.
|
|
4
4
|
|
|
5
5
|
## Authority and scope
|
|
6
6
|
|
|
@@ -30,9 +30,12 @@ Pins remain subordinate to system/developer instructions. Memory tells the model
|
|
|
30
30
|
/context memory supersede MEMORY_ID [--classification LEVEL] [--source ID,ID] <new claim>
|
|
31
31
|
/context memory invalidate MEMORY_ID [reason]
|
|
32
32
|
/context memory expire MEMORY_ID [reason]
|
|
33
|
+
/context memory sources
|
|
34
|
+
/context memory exclude SESSION_ID [reason]
|
|
35
|
+
/context memory include SESSION_ID
|
|
33
36
|
```
|
|
34
37
|
|
|
35
|
-
Arguments support single/double quotes and backslash escaping. `--` ends option parsing. Source entry IDs must be on Pi's active branch. Project scope requires Pi project trust.
|
|
38
|
+
Arguments support single/double quotes and backslash escaping. `--` ends option parsing. Source entry IDs must be on Pi's active branch. Project scope requires Pi project trust. Source exclusion affects only project-scoped contributions and persists until `include`; the active session cannot be newly excluded but can restore a prior exclusion.
|
|
36
39
|
|
|
37
40
|
Mutations are manual-first. Repeating the same normalized pin/claim returns its existing ID without appending another entry.
|
|
38
41
|
|
|
@@ -60,7 +63,7 @@ No row is silently overwritten. SQLite mutation and materialized tables are disp
|
|
|
60
63
|
3. replays all known mutations in timestamp + canonical entry order;
|
|
61
64
|
4. rebuilds memory, pin, source, lifecycle, and FTS rows transactionally.
|
|
62
65
|
|
|
63
|
-
Deleting `context.db` and reopening the canonical source session reconstructs its state.
|
|
66
|
+
Deleting `context.db` and reopening the canonical source session reconstructs its state. With `memory.crossSession: true`, DS4 discovers bounded sibling `.jsonl` files, accepts only headers whose `cwd` resolves to the exact trusted canonical project identity, incrementally indexes each source, and reconstructs project items without opening every session manually. No claim is extracted from ordinary conversation text.
|
|
64
67
|
|
|
65
68
|
## Supersession and contradiction handling
|
|
66
69
|
|
|
@@ -80,7 +83,7 @@ A conflicting `add` is rejected with the IDs involved. The user must issue expli
|
|
|
80
83
|
"Package export mode defaults to SingleFile."
|
|
81
84
|
```
|
|
82
85
|
|
|
83
|
-
The old item remains stored as `superseded` and points to the new active item. During replay,
|
|
86
|
+
The old item remains stored as `superseded` and points to the new active item. During replay, records are ordered by timestamp, source session ID, source entry order, mutation ID and mutation entry key. Concurrent active records with the same key are both preserved; the deterministic later record is marked `invalid` with a conflict reason rather than replacing the earlier one. Selected items retain source-session file/ID, mutation entry, creation branch leaf, evidence entries, classification, supersession and contradiction IDs.
|
|
84
87
|
|
|
85
88
|
Pins use the same immutable replacement pattern through `--supersedes`. `/context unpin` records a soft `deleted` lifecycle mutation.
|
|
86
89
|
|
|
@@ -126,7 +129,7 @@ User text is JSON-quoted. Context Manifests contain IDs, scope, classification,
|
|
|
126
129
|
|
|
127
130
|
M10 stores an optional classification in the canonical mutation. Before a remote call, a prohibited pin/memory is omitted as a whole and recorded only by ID/classification/reason. Explicit classification cannot be downgraded by markers inside its content. See [`PRIVACY.md`](PRIVACY.md).
|
|
128
131
|
|
|
129
|
-
## SQLite schema v9
|
|
132
|
+
## SQLite schema v9 and v15
|
|
130
133
|
|
|
131
134
|
Schema v9 extends materialized `memory_items` and `pins` with:
|
|
132
135
|
|
|
@@ -136,6 +139,8 @@ Schema v9 extends materialized `memory_items` and `pins` with:
|
|
|
136
139
|
|
|
137
140
|
`memory_mutations` and `pin_mutations` reference canonical indexed Pi custom entries. `memory_sources` retains exact scoped entry provenance. `memory_fts` is rebuilt transactionally.
|
|
138
141
|
|
|
142
|
+
Schema v15 adds source-branch provenance, per-session project-memory checkpoints, source status and explicit source exclusions. These rows are derived and disposable. Missing, truncated, moved, identity-mismatched or corrupt sibling files are marked unavailable and their unverifiable project-scoped mutations stop contributing; session-scoped state remains isolated and the active session keeps its last transactional projection on refresh failure. Restoration or database deletion causes deterministic replay from JSONL.
|
|
143
|
+
|
|
139
144
|
Migration preserves legacy materialized rows for inspection. Because they have no canonical mutation entry, a later full replay may discard them; new operations are always event-sourced.
|
|
140
145
|
|
|
141
146
|
## Diagnostics
|
|
@@ -148,6 +153,7 @@ Migration preserves legacy materialized rows for inspection. Because they have n
|
|
|
148
153
|
/context excluded
|
|
149
154
|
/context pins
|
|
150
155
|
/context memory
|
|
156
|
+
/context memory sources
|
|
151
157
|
/context health
|
|
152
158
|
/context rebuild-index
|
|
153
159
|
```
|
package/docs/PORTABLE_CORE.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Portable Core
|
|
2
2
|
|
|
3
|
-
M13 extracts the runtime-neutral implementation into the independently buildable `ds4-context-core` workspace package. The root `ds4-context-engine` package remains the Pi integration.
|
|
3
|
+
M13 extracts the runtime-neutral implementation into the independently buildable `ds4-context-core` workspace package. The root `ds4-context-engine` package remains the Pi integration. M19 adds the versioned adapter contract/conformance kit in core and a separately compiled non-Pi callback/JSONL reference adapter. M20 adds exact local-KV eligibility and replay orchestration while leaving every provider SDK and native cache handle in the runtime adapter.
|
|
4
4
|
|
|
5
5
|
## Dependency rule
|
|
6
6
|
|
|
@@ -14,7 +14,7 @@ ds4-context-core
|
|
|
14
14
|
|
|
15
15
|
Core never imports an adapter or runtime SDK. The Pi adapter imports core through its public ESM exports.
|
|
16
16
|
|
|
17
|
-
The core may use Node.js standard-library facilities such as `node:sqlite`, filesystem APIs and cryptographic hashing. Portable means independent of
|
|
17
|
+
The core may use Node.js standard-library facilities such as `node:sqlite`, filesystem APIs and cryptographic hashing. Portable means independent of every agent runtime SDK and reusable by another Node-based agent runtime; it does not mean browser-compatible.
|
|
18
18
|
|
|
19
19
|
## Package contents
|
|
20
20
|
|
|
@@ -30,6 +30,7 @@ The core may use Node.js standard-library facilities such as `node:sqlite`, file
|
|
|
30
30
|
- memory/pin materialization;
|
|
31
31
|
- privacy classification and provider policy;
|
|
32
32
|
- native-continuation eligibility and hash state;
|
|
33
|
+
- exact local-KV eligibility, handle-free runtime port types, replay policy and aggregate diagnostics;
|
|
33
34
|
- rebuildable SQLite repositories;
|
|
34
35
|
- stable serialization, hashing and logging.
|
|
35
36
|
|
|
@@ -44,7 +45,7 @@ The root adapter owns all Pi-specific behavior:
|
|
|
44
45
|
|
|
45
46
|
## Adapter responsibilities
|
|
46
47
|
|
|
47
|
-
|
|
48
|
+
Every `runtime-adapter-v1` implementation must:
|
|
48
49
|
|
|
49
50
|
1. preserve its runtime's canonical history and expose stable source identifiers;
|
|
50
51
|
2. convert native messages to DS4 canonical messages without losing tool-call/result atomicity;
|
|
@@ -54,17 +55,22 @@ A future runtime adapter must:
|
|
|
54
55
|
6. append memory/pin mutations to canonical runtime history before materializing derived state;
|
|
55
56
|
7. invoke model completion at the adapter boundary for generated summaries;
|
|
56
57
|
8. enforce privacy immediately before provider transport;
|
|
57
|
-
9.
|
|
58
|
-
10.
|
|
58
|
+
9. retain optional local-KV handles inside its volatile runtime port and replay the full sanitized payload after every non-hit;
|
|
59
|
+
10. discard or rebuild SQLite and artifact projections safely;
|
|
60
|
+
11. fall back to native runtime behavior when operational integration fails.
|
|
61
|
+
|
|
62
|
+
The executable contract, independent capability negotiation and framework-neutral seven-case conformance runner are exported from `ds4-context-core/adapter/runtime-adapter` and `ds4-context-core/adapter/conformance`. M20's handle-free port and controller are exported from `ds4-context-core/adapter/local-kv`. See [Runtime Adapter Kit](RUNTIME_ADAPTER_KIT.md) and [Local KV Reuse](LOCAL_KV_REUSE.md).
|
|
59
63
|
|
|
60
64
|
## Build and exports
|
|
61
65
|
|
|
62
66
|
```bash
|
|
63
67
|
npm run build:core
|
|
68
|
+
npm run build:adapters
|
|
64
69
|
npm run typecheck
|
|
65
70
|
npm test
|
|
66
71
|
npm run pack:check
|
|
67
72
|
npm pack --dry-run --workspace ds4-context-core
|
|
73
|
+
npm pack --dry-run --workspace ds4-context-reference-adapter
|
|
68
74
|
```
|
|
69
75
|
|
|
70
76
|
TypeScript sources compile to `packages/core/dist` as ESM JavaScript, source maps and declaration files. The npm package exports a top-level API and fine-grained subpaths such as:
|
|
@@ -74,11 +80,11 @@ import { calculateContextBudget } from "ds4-context-core";
|
|
|
74
80
|
import { planManagedContext } from "ds4-context-core/planner/context-planner";
|
|
75
81
|
```
|
|
76
82
|
|
|
77
|
-
The Pi
|
|
83
|
+
The Pi and reference packages declare exact same-release dependencies on `ds4-context-core`. Release order is core, reference adapter, then Pi adapter. `npm run pack:check` verifies all three tarball inventories, installs them together in a clean temporary consumer, probes core ESM exports, runs compiled reference conformance and starts the packaged Pi adapter with isolated RPC state. See [Releasing DS4](RELEASING.md) for the publication checklist.
|
|
78
84
|
|
|
79
85
|
## Enforcement
|
|
80
86
|
|
|
81
|
-
`tests/unit/portable-core-boundary.test.ts` recursively rejects Pi SDK and adapter imports from core source, then imports the compiled package and exercises portable model/budget policy. Existing integration tests consume core through package exports, so the Pi adapter is tested across the actual package boundary.
|
|
87
|
+
`tests/unit/portable-core-boundary.test.ts` recursively rejects Pi SDK and adapter imports from core source, then imports the compiled package and exercises portable model/budget policy. Runtime-adapter unit tests validate capability isolation and canonical tool groups; the reference package passes the shared conformance runner. Existing integration tests consume core through package exports, so the Pi adapter is tested across the actual package boundary.
|
|
82
88
|
|
|
83
89
|
## State guarantees
|
|
84
90
|
|
|
@@ -87,6 +93,7 @@ Extraction does not change DS4 state semantics:
|
|
|
87
93
|
- Pi JSONL remains canonical for Pi sessions;
|
|
88
94
|
- SQLite remains disposable and rebuildable;
|
|
89
95
|
- compaction remains non-destructive and strictly validated;
|
|
90
|
-
- provider continuation handles remain volatile;
|
|
96
|
+
- provider continuation and local-KV handles remain volatile and adapter-owned;
|
|
97
|
+
- local-KV cache loss changes only prefill performance and transparently replays the full sanitized payload;
|
|
91
98
|
- planner, retrieval, compaction and persistence failures still fail open at the adapter boundary;
|
|
92
99
|
- enabled privacy enforcement still fails closed before remote transport.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Project Knowledge
|
|
2
2
|
|
|
3
|
-
M7 indexes trusted project files as a disposable SQLite projection and injects only task-relevant, hash-current snippets. Live files remain canonical.
|
|
3
|
+
M7 indexes trusted project files as a disposable SQLite projection and injects only task-relevant, hash-current snippets. M15 adds runtime-neutral structural symbol parsing and exact symbol lookup. M16 optionally adds vectors over those structural/text chunks while preserving exact and FTS retrieval. Live files remain canonical.
|
|
4
4
|
|
|
5
5
|
## Trust boundary
|
|
6
6
|
|
|
@@ -36,29 +36,37 @@ DS4 excludes VCS metadata, `.pi`, dependencies, build outputs, caches, virtual e
|
|
|
36
36
|
|
|
37
37
|
## File and snippet index
|
|
38
38
|
|
|
39
|
-
SQLite schema v7
|
|
39
|
+
SQLite schema v7 introduced:
|
|
40
40
|
|
|
41
41
|
- `project_states`: canonical project path, Git root/branch/HEAD, dirty flag, changed paths, index time;
|
|
42
42
|
- `project_files`: path, SHA-256, bytes, mtime, language, indexed Git HEAD, tracked/modified state, lifecycle;
|
|
43
|
-
- `project_snippets`: immutable file hash, line range, source,
|
|
43
|
+
- `project_snippets`: immutable file hash, line range, source, token estimate and stale flag;
|
|
44
44
|
- `project_snippets_fts`: FTS5 content/path/symbol index.
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
Schema v12 adds derived structural metadata to each snippet: chunk kind, parser version, symbol ID/name/kind, qualified name, signature, parent symbol, imports and references. Exact-name indexes remain disposable and rebuild from live project files. Schema v13 stores separately keyed derived vectors; a file-hash change prunes only vectors for no-longer-current chunks, while unrelated source and embedding-profile rows remain intact.
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
`ds4-context-core` exposes a `SymbolParser` interface. The built-in `regex-structural-v1` parser has deterministic coverage for TypeScript, JavaScript, Python and Go without native dependencies. Optional parser adapters run first through `SymbolParserChain`; an unavailable or throwing adapter falls through to the built-in parser. Unsupported languages, malformed delimiter structure, supported files with no declarations and files carrying explicit DS4 classification spans retain the M7 overlapping text-window fallback. Keeping marked spans intact ensures M10 privacy enforcement sees the same boundaries as the 0.1 index.
|
|
49
|
+
|
|
50
|
+
Structural chunks follow declaration boundaries and retain signatures, parent relationships, imports/references and exact line ranges. Large declarations are split into bounded overlapping subchunks while sharing one symbol identity. Symbol IDs are SHA-256 values derived from canonical project identity, relative path, file hash, structural range, symbol kind and qualified name. Text fallback IDs retain their deterministic project/path/hash/range derivation.
|
|
51
|
+
|
|
52
|
+
A full or incremental sync compares size, mtime, Git revision and modified state. Source is re-read and SHA-256 hashed whenever metadata changes. Replacing one file marks only that path's prior snippets stale, then transactionally inserts the new file-hash rows and FTS entries; unrelated file rows keep their IDs. Stale rows remain inspectable, but every exact and FTS query requires `stale = 0` and a current file row.
|
|
49
53
|
|
|
50
54
|
## Retrieval and ranking
|
|
51
55
|
|
|
52
|
-
The same current-request `TaskDescriptor` used for historical retrieval supplies file paths, symbols, identifiers, errors, quoted phrases, technologies
|
|
56
|
+
The same current-request `TaskDescriptor` used for historical retrieval supplies file paths, symbols, identifiers, errors, quoted phrases, technologies and keywords. Candidate generation queries literal exact path/basename and exact qualified/simple symbol indexes before generic literal content and escaped FTS5 candidates. Exact lookup does not treat comment, string or reference text as a declaration.
|
|
57
|
+
|
|
58
|
+
When `retrieval.semantic` is enabled, the current embedding profile also contributes a bounded cosine-ranked pool. Deterministic reciprocal-rank fusion combines lexical and vector ranks; exact paths and symbols retain higher score tiers. Source vectors are populated during index sync and query vectors use a bounded volatile cache. Vector/model/privacy failures return the exact/FTS candidates unchanged. See [`HYBRID_RETRIEVAL.md`](HYBRID_RETRIEVAL.md).
|
|
53
59
|
|
|
54
60
|
Deterministic ranking prioritizes:
|
|
55
61
|
|
|
56
62
|
```text
|
|
57
|
-
exact
|
|
58
|
-
exact
|
|
59
|
-
|
|
63
|
+
exact qualified symbol 190
|
|
64
|
+
exact project-relative path 180
|
|
65
|
+
exact simple symbol 170
|
|
66
|
+
exact basename 150
|
|
67
|
+
declared fallback symbol 115
|
|
60
68
|
exact phrase 90
|
|
61
|
-
symbol text
|
|
69
|
+
symbol text 65
|
|
62
70
|
FTS match 60..20
|
|
63
71
|
working-tree change 10
|
|
64
72
|
tracked source 3
|
|
@@ -123,17 +131,19 @@ Source text is not copied into the Context Manifest or structured logs. It remai
|
|
|
123
131
|
|
|
124
132
|
## Fail-open behavior
|
|
125
133
|
|
|
126
|
-
Project discovery, Git, indexing, FTS, validation
|
|
134
|
+
Project discovery, Git, optional parser adapters, indexing, FTS, validation and retrieval errors are isolated from session indexing and context planning. Parser adapter failure uses deterministic regex fallback; unsupported or invalid source uses bounded text chunks. A project subsystem failure records local diagnostics and contributes no snippets; Pi and historical retrieval continue. SQLite startup failure retains the existing runtime-wide Pi fallback.
|
|
135
|
+
|
|
136
|
+
## Verification and benchmark
|
|
127
137
|
|
|
128
|
-
|
|
138
|
+
`quality/symbol-corpus-v1.json` is a synthetic, versioned TypeScript/JavaScript/Python/Go corpus with expected and forbidden declarations. Unit coverage verifies that structural parsing produces fewer false symbol matches than the preserved 0.1 regex extractor. Integration coverage verifies exact qualified/path lookup, metadata fields, stable IDs, unsupported/invalid fallback, changed-file invalidation, unrelated-file stability, trust/exclusion behavior and live-hash validation.
|
|
129
139
|
|
|
130
140
|
`tests/benchmarks/project-knowledge.bench.ts` creates and indexes 5,000 source files, then executes exact path/symbol plus FTS retrieval with live hash validation:
|
|
131
141
|
|
|
132
142
|
```text
|
|
133
|
-
mean
|
|
134
|
-
p75
|
|
135
|
-
p99 21
|
|
136
|
-
max 21
|
|
143
|
+
mean 29.99 ms
|
|
144
|
+
p75 31.71 ms
|
|
145
|
+
p99 37.21 ms
|
|
146
|
+
max 37.21 ms
|
|
137
147
|
```
|
|
138
148
|
|
|
139
149
|
Command:
|