ds4-context-engine 0.2.0 → 0.3.0-alpha.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 +31 -3
- package/docs/ADR/README.md +5 -0
- package/docs/ARCHITECTURE.md +9 -1
- package/docs/CONTEXT_PERSISTENCE_TOOL.md +131 -0
- package/docs/DOGFOODING_0.3.0_ALPHA.md +304 -0
- package/docs/MEMORY_AND_PINS.md +3 -3
- package/docs/PRIVACY.md +9 -1
- package/docs/RELEASING.md +15 -5
- package/docs/STORAGE.md +2 -2
- package/docs/releases/0.3.0-alpha.1.md +89 -0
- package/docs/releases/0.3.0-alpha.2.md +61 -0
- package/package.json +3 -2
- package/src/extension/context-persistence-contract.ts +159 -0
- package/src/extension/context-persistence-egress.ts +224 -0
- package/src/extension/context-persistence-result.ts +451 -0
- package/src/extension/context-persistence-tool.ts +1948 -0
- package/src/extension/index.ts +2 -0
- package/src/extension/runtime.ts +355 -22
- package/src/pi-adapter/version.ts +1 -1
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ bounded active context with provenance
|
|
|
16
16
|
Pi provider
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
> **Project status:** Stable `0.2.0` includes M0–M20 and
|
|
19
|
+
> **Project status:** Stable `0.2.0` includes M0–M20 and frozen 0.2 contracts. Prerelease `0.3.0-alpha.2` hardens the confirmation-gated `context_persistence` tool by rejecting its output-only historical egress sentinel on input, without changing canonical Pin/Memory records, SQLite schema 15, or the reference history contract. npm `latest` remains `0.2.0`; the maintenance line targets Pi `0.84.3`.
|
|
20
20
|
|
|
21
21
|
## Why DS4
|
|
22
22
|
|
|
@@ -31,6 +31,7 @@ It provides:
|
|
|
31
31
|
- trust-gated structural project indexing, Git-aware invalidation and bounded source snippets;
|
|
32
32
|
- hierarchical, validated, non-destructive compaction summaries;
|
|
33
33
|
- persistent pins and append-only durable memory stored canonically in Pi JSONL;
|
|
34
|
+
- a bounded, metadata-only `context_persistence` tool with local confirmation for every model-callable write;
|
|
34
35
|
- opt-in checkpointed project-memory replay across exact trusted Pi project sessions;
|
|
35
36
|
- content-addressed storage and bounded references for large tool results;
|
|
36
37
|
- privacy classifications, secret redaction and provider-specific allow rules;
|
|
@@ -88,6 +89,14 @@ pi install npm:ds4-context-engine
|
|
|
88
89
|
|
|
89
90
|
The stable `0.2.0` packages (`ds4-context-engine`, `ds4-context-core`, and `ds4-context-reference-adapter`) use the same exact version. Both adapters require the matching core version.
|
|
90
91
|
|
|
92
|
+
To dogfood the published alpha without replacing a global stable installation, pin it in a disposable project:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
pi install -l npm:ds4-context-engine@0.3.0-alpha.2
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Follow the [0.3 alpha dogfooding runbook](docs/DOGFOODING_0.3.0_ALPHA.md); use synthetic data and a dedicated session directory.
|
|
99
|
+
|
|
91
100
|
### Local checkout
|
|
92
101
|
|
|
93
102
|
```bash
|
|
@@ -198,6 +207,19 @@ Project configuration and project source indexing are disabled when Pi reports t
|
|
|
198
207
|
|
|
199
208
|
Valid privacy classifications are `normal`, `internal`, `sensitive` and `local-only`.
|
|
200
209
|
|
|
210
|
+
### LLM-callable tools
|
|
211
|
+
|
|
212
|
+
DS4 registers two model-callable tools:
|
|
213
|
+
|
|
214
|
+
| Tool | Purpose |
|
|
215
|
+
| --- | --- |
|
|
216
|
+
| `context_artifact_search` | Search a known DS4 artifact reference with bounded quoted excerpts |
|
|
217
|
+
| `context_persistence` | Inspect Pins, Memory, and project-memory sources; perform explicitly requested persistence mutations |
|
|
218
|
+
|
|
219
|
+
`context_persistence` read actions return bounded metadata and sanitized find previews. Every write requires a fresh local `ctx.ui.confirm()` decision. In print/JSON or any other no-UI mode, reads remain available and writes fail closed with `confirmation-required`. Sessions without a persistent Pi JSONL destination (for example `--no-session`) fail closed with `runtime-unavailable` before confirmation. Destructive writes require an exact ID or volatile source reference plus the `targetRevision` returned by a prior read; fuzzy writes are not supported.
|
|
220
|
+
|
|
221
|
+
Canonical Pin and Memory changes append Pi custom entries and reconcile disposable SQLite projections. Project-memory source include/exclude is derived local SQLite policy and never appends a fake canonical entry. See [`docs/CONTEXT_PERSISTENCE_TOOL.md`](docs/CONTEXT_PERSISTENCE_TOOL.md).
|
|
222
|
+
|
|
201
223
|
Learned-ranking feedback and local training are explicit:
|
|
202
224
|
|
|
203
225
|
```text
|
|
@@ -390,9 +412,11 @@ npm run typecheck
|
|
|
390
412
|
npm test
|
|
391
413
|
npm run check
|
|
392
414
|
npm run quality:compare
|
|
415
|
+
npm run schema:context-persistence
|
|
416
|
+
npm run latency:check -- /path/to/exact/ds4-context-core@0.1.2
|
|
393
417
|
npm run pack:check
|
|
394
418
|
# Post-publication, with an exact version rather than a dist-tag:
|
|
395
|
-
npm run registry:check -- 0.
|
|
419
|
+
npm run registry:check -- 0.3.0-alpha.2
|
|
396
420
|
npm pack --dry-run
|
|
397
421
|
npm pack --dry-run --workspace ds4-context-core
|
|
398
422
|
npm pack --dry-run --workspace ds4-context-reference-adapter
|
|
@@ -430,6 +454,8 @@ scripts package and release-readiness checks
|
|
|
430
454
|
- [Project knowledge](docs/PROJECT_KNOWLEDGE.md)
|
|
431
455
|
- [Artifacts](docs/ARTIFACTS.md)
|
|
432
456
|
- [Memory and pins](docs/MEMORY_AND_PINS.md)
|
|
457
|
+
- [Context persistence tool](docs/CONTEXT_PERSISTENCE_TOOL.md)
|
|
458
|
+
- [0.3 alpha dogfooding runbook](docs/DOGFOODING_0.3.0_ALPHA.md)
|
|
433
459
|
- [Privacy](docs/PRIVACY.md)
|
|
434
460
|
- [Model awareness](docs/MODEL_AWARENESS.md)
|
|
435
461
|
- [Native continuation](docs/NATIVE_CONTINUATION.md)
|
|
@@ -442,6 +468,8 @@ scripts package and release-readiness checks
|
|
|
442
468
|
- [0.2.0 release readiness](docs/RELEASE_READINESS_0.2.0.md)
|
|
443
469
|
- [0.2.0 release notes](docs/releases/0.2.0.md)
|
|
444
470
|
- [0.2.0-rc.1 release notes](docs/releases/0.2.0-rc.1.md)
|
|
471
|
+
- [0.3.0-alpha.2 prerelease notes](docs/releases/0.3.0-alpha.2.md)
|
|
472
|
+
- [0.3.0-alpha.1 prerelease notes](docs/releases/0.3.0-alpha.1.md)
|
|
445
473
|
- [Architecture decisions](docs/ADR/README.md)
|
|
446
474
|
- [Original development plan](DS4_Context_Engine_Extension_Piano_Sviluppo.md)
|
|
447
475
|
|
|
@@ -449,7 +477,7 @@ scripts package and release-readiness checks
|
|
|
449
477
|
|
|
450
478
|
The original M0–M13 roadmap is complete. `ds4-context-core` contains the compiled runtime-neutral implementation. M14 context-quality metrics, M15 rich symbol indexing, M16 hybrid semantic retrieval, M17 cross-session project memory, M18 learned-ranking shadow evaluation, M19's runtime adapter/conformance kit, and M20 opt-in local KV eligibility/replay are implemented on `main`. Learned active ranking remains promotion-gated, Pi reports local KV as unsupported, and static ranking/native completion stay authoritative on every failure.
|
|
451
479
|
|
|
452
|
-
The [0.2.0 roadmap](docs/ROADMAP_0.2.0.md) is complete. The [readiness record](docs/RELEASE_READINESS_0.2.0.md)
|
|
480
|
+
The [0.2.0 roadmap](docs/ROADMAP_0.2.0.md) is complete. Prerelease `0.3.0-alpha.2` hardens the [context persistence tool](docs/CONTEXT_PERSISTENCE_TOOL.md) delivered in alpha.1 while retaining the stable canonical/configuration/SQLite/runtime contracts. The [0.2 readiness record](docs/RELEASE_READINESS_0.2.0.md) remains the compatibility baseline. Sensitive or transport-specific behavior remains opt-in, and the 0.1 lexical planner stays available as the deterministic fallback.
|
|
453
481
|
|
|
454
482
|
## Contributing
|
|
455
483
|
|
package/docs/ADR/README.md
CHANGED
|
@@ -56,5 +56,10 @@ The initial decisions from the development plan are accepted:
|
|
|
56
56
|
| 050 | Retry rejected stale continuation state once with the complete managed replay before exposing output | Accepted |
|
|
57
57
|
| 051 | Keep continuation handles volatile and exclude them from manifests, logs, and DS4 persistence | Accepted |
|
|
58
58
|
| 052 | Compile `ds4-context-core` as ESM and keep the Pi adapter dependency one-way | Accepted |
|
|
59
|
+
| 053 | Dispatch `context_persistence` directly through `Ds4ContextRuntime`, never through slash-command parsing | Accepted |
|
|
60
|
+
| 054 | Use fresh local Pi UI confirmation as the V1 authorization boundary for every model-callable write | Accepted |
|
|
61
|
+
| 055 | Enforce a dedicated metadata-only tool egress guard independently of `privacy.enabled` | Accepted |
|
|
62
|
+
| 056 | Keep project-memory source exclusion as disposable derived SQLite policy | Accepted |
|
|
63
|
+
| 057 | Derive mutation provenance from the active branch and exclude model-supplied source IDs from V1 | Accepted |
|
|
59
64
|
|
|
60
65
|
Each decision will receive a dedicated record when implementation pressure introduces alternatives or consequences not already covered by the development plan.
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -156,6 +156,14 @@ session_tree / shutdown
|
|
|
156
156
|
-> transactional reconciliation from canonical JSONL, memory/pin replay, artifact regeneration and forced project rescan
|
|
157
157
|
```
|
|
158
158
|
|
|
159
|
+
## Context persistence tool boundary
|
|
160
|
+
|
|
161
|
+
`context_persistence` is a Pi-adapter capability, not a portable-core or reference-adapter API. Its controller calls `Ds4ContextRuntime` directly rather than relaying slash commands. Read actions use bounded keyset/visible-item APIs and emit only allowlisted metadata plus policy-sanitized find previews. Every LLM-callable write fails closed without Pi UI and requires a fresh local confirmation; model-provided consent fields are not accepted.
|
|
162
|
+
|
|
163
|
+
Pin and Memory mutations resolve provenance from the active Pi branch, revalidate it after confirmation, append the existing `ds4-context-pin-v1` or `ds4-context-memory-v1` record through `pi.appendEntry()`, and then reconcile the disposable projection. Exact revisions bind target state to active session/project/branch context. Project-source include/exclude resolves a volatile `sourceRef` to an internal session identity and updates only coordinated SQLite policy—never Pi JSONL.
|
|
164
|
+
|
|
165
|
+
Historical tool arguments and results are a provider-egress surface even when general privacy is disabled. A dedicated guard removes content, query, key, reason, paths and raw errors while preserving only action linkage and safe IDs/revisions. Provenance IDs and source paths are runtime-derived; the model cannot supply them in the V1 schema. Post-append failures distinguish an indeterminate append from a known canonical commit with pending projection, so callers are never encouraged to retry blindly.
|
|
166
|
+
|
|
159
167
|
## Boundaries
|
|
160
168
|
|
|
161
169
|
Dependency direction is one-way:
|
|
@@ -198,7 +206,7 @@ Adapters may import core exports. Core source must never import `@earendil-works
|
|
|
198
206
|
|
|
199
207
|
## Canonical and derived state
|
|
200
208
|
|
|
201
|
-
The Pi session JSONL remains canonical for conversation/tool state, inline classification markers, append-only classified memory/pin mutations and metadata-only learned-ranking feedback/replay labels; live files remain canonical for project knowledge. Native continuation keeps only volatile request/response-item hashes plus the minimum response handle and creates no continuation table or custom entry. SQLite and content-addressed object files store only rebuildable indexes, source-hash/model-keyed vectors, summary nodes/edges, metadata-only manifests, project file/snippet projections, artifact copies/references, materialized memory/pins, calibration data, and bounded metadata-only quality samples. The checksummed learned-ranking model is a separate disposable local artifact reconstructed from canonical labels; it contains bounded weights and aggregate gate metadata, never raw text. Each aggregate's active text is the Pi compaction summary; non-active nodes created by the same operation are embedded in its details, while older ancestors remain in earlier entries. Deleting the database must never damage or alter a Pi session or project. Reopening a source session replays its memory/pin mutations. Ephemeral sessions keep manifests and graph nodes in memory, disable durable memory/pins/artifacts, and may share the project index because files—not session JSONL—are its durable source.
|
|
209
|
+
The Pi session JSONL remains canonical for conversation/tool state, inline classification markers, append-only classified memory/pin mutations and metadata-only learned-ranking feedback/replay labels; live files remain canonical for project knowledge. Volatile `context_persistence` source-reference/revision maps and derived project-source exclusion policy are local process/SQLite state and are never canonical. Native continuation keeps only volatile request/response-item hashes plus the minimum response handle and creates no continuation table or custom entry. SQLite and content-addressed object files store only rebuildable indexes, source-hash/model-keyed vectors, summary nodes/edges, metadata-only manifests, project file/snippet projections, artifact copies/references, materialized memory/pins, calibration data, and bounded metadata-only quality samples. The checksummed learned-ranking model is a separate disposable local artifact reconstructed from canonical labels; it contains bounded weights and aggregate gate metadata, never raw text. Each aggregate's active text is the Pi compaction summary; non-active nodes created by the same operation are embedded in its details, while older ancestors remain in earlier entries. Deleting the database must never damage or alter a Pi session or project. Reopening a source session replays its memory/pin mutations. Ephemeral sessions keep manifests and graph nodes in memory, disable durable memory/pins/artifacts, and may share the project index because files—not session JSONL—are its durable source.
|
|
202
210
|
|
|
203
211
|
## Lifecycle
|
|
204
212
|
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# Context Persistence Tool
|
|
2
|
+
|
|
3
|
+
`context_persistence` is DS4's bounded model-callable interface for inspecting and explicitly updating Persistent Pins, Durable Memory, and cross-session project-memory source policy. It is available in the Pi adapter only; the portable core and reference adapter do not expose this Pi-specific tool.
|
|
4
|
+
|
|
5
|
+
Contract identifiers:
|
|
6
|
+
|
|
7
|
+
```text
|
|
8
|
+
tool: ds4-context-persistence-tool-v1
|
|
9
|
+
result: ds4-context-persistence-result-v1
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
The tool declares `executionMode: "sequential"`. This orders sibling calls from one model response; SQLite writes still use the shared coordinator and every targeted mutation still checks its revision.
|
|
13
|
+
|
|
14
|
+
## Pins and Memory
|
|
15
|
+
|
|
16
|
+
Pins are confirmed constraints or instructions that should remain prominent. They may use `session`, `branch`, or trusted `project` scope. Branch Pins can remain lifecycle-active while not applying to the active branch.
|
|
17
|
+
|
|
18
|
+
Memory is quoted durable factual, decision, or historical data. It supports `session` and trusted `project` scope, never `branch` scope. DS4 does not automatically extract either concept from ordinary conversation.
|
|
19
|
+
|
|
20
|
+
## Actions
|
|
21
|
+
|
|
22
|
+
| Action | Class | Purpose |
|
|
23
|
+
| --- | --- | --- |
|
|
24
|
+
| `pins_list` | read | List visible Pins with metadata and revisions |
|
|
25
|
+
| `pins_find` | read | Bounded Pin search with sanitized previews |
|
|
26
|
+
| `pin_add` | canonical write | Append a new Pin |
|
|
27
|
+
| `pin_supersede` | canonical write | Replace one exact active Pin immutably |
|
|
28
|
+
| `pin_unpin` | canonical write | Append a deleted lifecycle status |
|
|
29
|
+
| `memory_list` | read | List visible Memory with metadata and revisions |
|
|
30
|
+
| `memory_find` | read | Bounded Memory search with sanitized previews |
|
|
31
|
+
| `memory_add` | canonical write | Append session/project Memory |
|
|
32
|
+
| `memory_supersede` | canonical write | Replace one exact active Memory item immutably |
|
|
33
|
+
| `memory_invalidate` | canonical write | Append an invalid lifecycle status |
|
|
34
|
+
| `memory_expire` | canonical write | Append an expired lifecycle status |
|
|
35
|
+
| `memory_sources` | read | List cross-session sources through volatile references |
|
|
36
|
+
| `memory_source_exclude` | derived write | Exclude one source in local SQLite policy |
|
|
37
|
+
| `memory_source_include` | derived write | Restore one source in local SQLite policy |
|
|
38
|
+
|
|
39
|
+
Read results are keyset-bounded and metadata-only. List results never include Pin content, Memory claims, keys, paths, source session IDs, reasons, complete errors, or totals requiring an unbounded count. Find results may include a short provider-safe preview in text; `details.items` remains metadata-only.
|
|
40
|
+
|
|
41
|
+
## Read before a targeted write
|
|
42
|
+
|
|
43
|
+
Supersede, lifecycle, include, and exclude operations require:
|
|
44
|
+
|
|
45
|
+
```text
|
|
46
|
+
exact id or sourceRef
|
|
47
|
+
targetRevision from a prior read
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
A revision is a process-local HMAC token bound to the item fingerprint and active session/project/branch context. It expires and is invalid after restart. A changed target, switched context, expired token, unknown reference, or non-active target is rejected. The tool never converts a fuzzy query or a high-scoring match into a write target.
|
|
51
|
+
|
|
52
|
+
`memory_sources` returns `sourceRef`, not a session ID or file path. The mapping is process-local, TTL/cap-bounded, and never persisted. The opaque reference itself may remain in Pi's normal tool-result history so a subsequent exact call can use it.
|
|
53
|
+
|
|
54
|
+
## Confirmation and no-UI behavior
|
|
55
|
+
|
|
56
|
+
Every model-callable write requires a fresh local Pi UI decision:
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
await ctx.ui.confirm("DS4 Context Persistence", message)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The dialog identifies the action and persistence class. Canonical add/supersede dialogs show bounded full content and effective classification; lifecycle dialogs show a bounded local target preview and optional reason. Source-policy dialogs show only the volatile reference and safe status/counters. Confirmation text is never copied into the tool result or logs.
|
|
63
|
+
|
|
64
|
+
A model cannot provide `confirmed=true`; it is not in the schema. If `ctx.hasUI` is false, all writes return:
|
|
65
|
+
|
|
66
|
+
```text
|
|
67
|
+
outcome=unavailable
|
|
68
|
+
errorCode=confirmation-required
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Reads remain available. Refusal, dialog closure, or abort before dispatch causes no write. Pi `0.84.3` RPC can advertise UI capability even when no client is currently answering UI requests. In that case the confirmation request remains pending in Pi's RPC transport; DS4 does not infer consent or refusal, and no append occurs before a positive response. RPC clients that expose UI capability must answer the request explicitly. If the active Pi session has no persistent JSONL destination (for example `--no-session`), reads and writes both fail closed with `runtime-unavailable`; no confirmation is shown and no canonical commit is claimed.
|
|
72
|
+
|
|
73
|
+
## Canonical and derived persistence
|
|
74
|
+
|
|
75
|
+
Pin and Memory mutations call `Ds4ContextRuntime`, append the existing versioned custom entry through `pi.appendEntry()`, and reconcile SQLite:
|
|
76
|
+
|
|
77
|
+
```text
|
|
78
|
+
ds4-context-pin-v1
|
|
79
|
+
ds4-context-memory-v1
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The tool never inserts canonical Pin or Memory state directly into SQLite and never rewrites Pi JSONL. Provenance is derived from the latest preceding user message on the active branch, not from model-supplied source IDs, and is revalidated after confirmation.
|
|
83
|
+
|
|
84
|
+
Project-memory source exclusion is intentionally different. It updates `project_memory_source_exclusions` through the coordinated runtime repository and reports `persistenceClass=derived-local-policy`. It does not append a fake Pi entry. Deleting `context.db` resets this policy; replay restores source contributions from unchanged sibling JSONL.
|
|
85
|
+
|
|
86
|
+
## Privacy and provider policy
|
|
87
|
+
|
|
88
|
+
The tool enforces its own egress policy even when general privacy is disabled:
|
|
89
|
+
|
|
90
|
+
- current and historical content, query, key, reason, preview, path, source identity, and raw errors are removed unless explicitly allowed;
|
|
91
|
+
- the fixed historical omission sentinel is output-only; any incoming string argument containing it is rejected as `egress-placeholder` before runtime access, confirmation, or persistence, so retries must use fresh user-provided text;
|
|
92
|
+
- results use deterministic metadata-only templates;
|
|
93
|
+
- marker/credential detection may raise a mutation classification;
|
|
94
|
+
- an explicit supersede classification cannot lower the target's effective protection;
|
|
95
|
+
- remote-disallowed or `local-only` writes are rejected before append;
|
|
96
|
+
- provider/trust/provenance/target state is checked again after confirmation.
|
|
97
|
+
|
|
98
|
+
Selecting `local-only` does not prove that a remote model never saw the original message or tool arguments. Use the direct `/context` command surface or a verified local provider when data must never be disclosed remotely.
|
|
99
|
+
|
|
100
|
+
## Outcomes and recovery
|
|
101
|
+
|
|
102
|
+
| Outcome | Meaning |
|
|
103
|
+
| --- | --- |
|
|
104
|
+
| `ok` | Read succeeded, add was duplicate, or source policy already matched |
|
|
105
|
+
| `committed` | Canonical append/materialization or derived policy update succeeded |
|
|
106
|
+
| `rejected` | Validation, policy, trust, provenance, conflict, target, or revision check failed |
|
|
107
|
+
| `cancelled` | User refusal/dialog closure or abort before dispatch |
|
|
108
|
+
| `unavailable` | Runtime/capability/UI unavailable; no commit is claimed |
|
|
109
|
+
| `committed_projection_pending` | Canonical append succeeded but projection/result materialization did not complete safely |
|
|
110
|
+
| `indeterminate` | The append call did not return, so completion cannot be established |
|
|
111
|
+
|
|
112
|
+
Never automatically retry `committed_projection_pending` or `indeterminate`. Inspect with a read, `/context health`, or `/context rebuild-index` first. SQLite is disposable; canonical Pin/Memory state reappears after replay. Source exclusions intentionally do not.
|
|
113
|
+
|
|
114
|
+
## `/context` relationship
|
|
115
|
+
|
|
116
|
+
`/context` remains the direct local administrative and inspection surface. It can show local detail that must not enter a provider-visible tool result. `context_persistence` calls the same runtime mutation primitives but has a narrower schema, automatic branch provenance, exact-revision requirements, confirmation on every write, and a dedicated historical egress guard.
|
|
117
|
+
|
|
118
|
+
Useful diagnostics:
|
|
119
|
+
|
|
120
|
+
```text
|
|
121
|
+
/context pins
|
|
122
|
+
/context memory
|
|
123
|
+
/context memory sources
|
|
124
|
+
/context privacy
|
|
125
|
+
/context health
|
|
126
|
+
/context rebuild-index
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Alpha dogfooding
|
|
130
|
+
|
|
131
|
+
Use the published package with synthetic data and exercise TUI, RPC, print, and JSON behavior through the dedicated [`0.3 alpha dogfooding runbook`](DOGFOODING_0.3.0_ALPHA.md). The runbook distinguishes RPC's UI request/response bridge from genuinely no-UI print/JSON modes and includes a metadata-only canonical append audit.
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
# Dogfooding DS4 0.3.0 Alpha
|
|
2
|
+
|
|
3
|
+
This runbook validates the published `ds4-context-engine@0.3.0-alpha.2` package through sustained real Pi use. It complements automated tests and release smoke checks; it does not replace them.
|
|
4
|
+
|
|
5
|
+
The primary target is the model-callable `context_persistence` surface. Pi JSONL must remain canonical and append-only, SQLite must remain rebuildable, and no model-callable write may occur without a fresh positive local UI decision.
|
|
6
|
+
|
|
7
|
+
## Safety and scope
|
|
8
|
+
|
|
9
|
+
- Use the exact prerelease version, not the mutable `alpha` dist-tag.
|
|
10
|
+
- Use a disposable trusted project and a dedicated session directory.
|
|
11
|
+
- Use synthetic, non-secret Pin/Memory content. Local TUI dialogs and JSON event streams may display current tool arguments.
|
|
12
|
+
- Published alpha.1 had a retry limitation: copying `[omitted-by-ds4-egress-policy]` from sanitized history could present a confirmation for the literal marker. Alpha.2 reserves that output-only marker and must reject it as `egress-placeholder` before runtime access, confirmation, canonical append, or derived-policy update.
|
|
13
|
+
- Do not use `--no-session` except for the explicit fail-closed test. Without a persistent Pi JSONL destination, both reads and writes return `runtime-unavailable`.
|
|
14
|
+
- Do not retry `committed_projection_pending` or `indeterminate`. Inspect state with a read, `/context health`, or `/context rebuild-index` first.
|
|
15
|
+
- Use `/context` only for local inspection and recovery. Mutations under test must go through `context_persistence` so the confirmation and provider-egress boundaries are exercised.
|
|
16
|
+
- Never edit a Pi session JSONL file during the run.
|
|
17
|
+
|
|
18
|
+
Recommended minimum before promoting the alpha: three normal work sessions, two process restarts, one branch change, one projection rebuild, the TUI/RPC/print/JSON matrix, one configured remote provider, and—when available—one verified local provider.
|
|
19
|
+
|
|
20
|
+
## Isolated setup
|
|
21
|
+
|
|
22
|
+
Pi packages execute with the user's full permissions. Review the package before installation.
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
mkdir -p /tmp/ds4-alpha-dogfood
|
|
26
|
+
cd /tmp/ds4-alpha-dogfood
|
|
27
|
+
git init
|
|
28
|
+
mkdir -p sessions evidence
|
|
29
|
+
pi install -l npm:ds4-context-engine@0.3.0-alpha.2
|
|
30
|
+
pi list
|
|
31
|
+
pi --version
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
The `-l` installation is project-local and the exact npm version is pinned. Run Pi from this directory. Use `--approve` only after trusting this disposable project; non-interactive modes cannot show the project-trust dialog.
|
|
35
|
+
|
|
36
|
+
Use the same dedicated session directory throughout:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
export DS4_DOGFOOD_SESSIONS="$PWD/sessions"
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Record the Pi version, DS4 version, provider/model, mode, session name, expected result, observed result, and pass/fail status for every scenario.
|
|
43
|
+
|
|
44
|
+
## Synthetic test data
|
|
45
|
+
|
|
46
|
+
Use unique non-sensitive values so duplicates from earlier runs cannot hide a failure. Example run label:
|
|
47
|
+
|
|
48
|
+
```text
|
|
49
|
+
alpha2-run-01
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Example Pin:
|
|
53
|
+
|
|
54
|
+
```text
|
|
55
|
+
For alpha2-run-01 verification, use Node.js 22 in this disposable project.
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Example Memory:
|
|
59
|
+
|
|
60
|
+
```text
|
|
61
|
+
For alpha2-run-01, the synthetic release channel is amber.
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Never use real credentials, customer data, private paths, or production policy in dogfooding prompts.
|
|
65
|
+
|
|
66
|
+
## TUI procedure
|
|
67
|
+
|
|
68
|
+
Start a persistent interactive session:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
pi --approve --session-dir "$DS4_DOGFOOD_SESSIONS" \
|
|
72
|
+
--name "ds4-alpha-tui"
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Run these scenarios in order:
|
|
76
|
+
|
|
77
|
+
1. Inspect `/context health`, `/context pins`, `/context memory`, and `/context privacy`.
|
|
78
|
+
2. Send an ordinary suggestion without asking to persist it, for example: `The synthetic release channel amber seems useful.` No `context_persistence` call or confirmation dialog should appear.
|
|
79
|
+
3. Explicitly request the synthetic Memory: `Remember for this session that the synthetic release channel for alpha2-run-01 is amber.` Verify that the dialog identifies the action and canonical persistence class. Accept it. Expect one committed Memory mutation.
|
|
80
|
+
4. Ask the model to use `context_persistence` to list active Memory. Verify bounded metadata and no complete claim, key, reason, path, or raw error in the result.
|
|
81
|
+
5. Explicitly request the synthetic Pin, but reject or close the confirmation dialog. Verify with `/context pins` that it was not created.
|
|
82
|
+
6. Ask the model to retry using the sanitized value remaining in history. If it copies `[omitted-by-ds4-egress-policy]`, expect `rejected / egress-placeholder` before any new confirmation, runtime mutation, or append. If it asks for fresh text instead, record that safe routing result and run the exact-marker case from the JSON procedure.
|
|
83
|
+
7. Request the Pin again with fresh synthetic text and accept it. Ask the model to list Pins, then use the exact returned Pin ID and `targetRevision` to unpin it in the same process. Accept the destructive confirmation. Fuzzy targeting must not be used.
|
|
84
|
+
8. With a remote provider, request a `local-only` Pin. Expect provider-policy denial before confirmation and no append.
|
|
85
|
+
9. Restart Pi and continue the session:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
pi --approve --session-dir "$DS4_DOGFOOD_SESSIONS" -c
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Verify the accepted Memory remains visible. Revision handles from the previous process are intentionally invalid; perform a fresh read before any targeted write.
|
|
92
|
+
10. Run `/context rebuild-index`, then verify the same canonical Memory/Pin lifecycle state is reconstructed.
|
|
93
|
+
|
|
94
|
+
TUI passes when accepted writes append once, refusal/closure appends nothing, destructive writes require an exact fresh revision, ordinary conversation does not persist, and rebuild preserves canonical state.
|
|
95
|
+
|
|
96
|
+
## RPC procedure
|
|
97
|
+
|
|
98
|
+
RPC mode exposes extension dialogs through a JSON request/response protocol. It reports `ctx.hasUI=true` because a client can answer those requests; the client is the UI bridge.
|
|
99
|
+
|
|
100
|
+
Start a persistent RPC process from the disposable project:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
pi --mode rpc --approve \
|
|
104
|
+
--session-dir "$DS4_DOGFOOD_SESSIONS" \
|
|
105
|
+
--name "ds4-alpha-rpc" \
|
|
106
|
+
2>evidence/rpc.stderr.log
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Enter one JSON object per line on stdin. First request a read:
|
|
110
|
+
|
|
111
|
+
```json
|
|
112
|
+
{"id":"read-1","type":"prompt","message":"Use context_persistence with action pins_list to inspect active Pins. Do not perform a write."}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Wait for the turn to end before sending the next prompt. For a write:
|
|
116
|
+
|
|
117
|
+
```json
|
|
118
|
+
{"id":"write-1","type":"prompt","message":"Persist a session Pin for alpha2-run-01 stating that this disposable project uses Node.js 22 for verification."}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Pi should emit a request shaped like:
|
|
122
|
+
|
|
123
|
+
```json
|
|
124
|
+
{"type":"extension_ui_request","id":"<dynamic-id>","method":"confirm","title":"DS4 Context Persistence","message":"..."}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
After inspecting the request, approve it with the exact dynamic ID:
|
|
128
|
+
|
|
129
|
+
```json
|
|
130
|
+
{"type":"extension_ui_response","id":"<dynamic-id>","confirmed":true}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Expect the `context_persistence` tool result to report a committed outcome without echoing complete Pin content. Repeat with a different synthetic value and reject it:
|
|
134
|
+
|
|
135
|
+
```json
|
|
136
|
+
{"type":"extension_ui_response","id":"<dynamic-id>","confirmed":false}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
The rejected call must report cancellation and append nothing. `{"cancelled":true}` is also a valid dialog dismissal response.
|
|
140
|
+
|
|
141
|
+
### RPC without a responding UI client
|
|
142
|
+
|
|
143
|
+
Start a separate disposable RPC process, request a write, and do not send an `extension_ui_response`. In Pi `0.84.3`, the confirmation remains pending because RPC still advertises UI capability. This is not converted to `confirmation-required`; no append may occur before a positive response. Terminate the disposable process after recording the pending request, then inspect the session from TUI.
|
|
144
|
+
|
|
145
|
+
### RPC without a persistent session
|
|
146
|
+
|
|
147
|
+
Start a separate process:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
pi --mode rpc --approve --no-session
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Send a read and a write prompt. Both must return `runtime-unavailable`; no `extension_ui_request` should be emitted and no canonical commit should be claimed.
|
|
154
|
+
|
|
155
|
+
RPC passes when positive confirmation commits once, negative/cancelled confirmation appends nothing, an unanswered dialog remains pending without append, `--no-session` fails before confirmation, and result content/details remain bounded and metadata-only.
|
|
156
|
+
|
|
157
|
+
## Print-mode procedure
|
|
158
|
+
|
|
159
|
+
Print mode has no extension UI. Keep session persistence enabled:
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
pi -p --approve --session-dir "$DS4_DOGFOOD_SESSIONS" \
|
|
163
|
+
"Use context_persistence with action memory_list to inspect active Memory. Do not write."
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
The read should complete. Then request a write:
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
pi -p --approve --session-dir "$DS4_DOGFOOD_SESSIONS" \
|
|
170
|
+
"Use context_persistence to add a session Memory saying that alpha2-run-01 uses the synthetic channel amber."
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Expected behavior:
|
|
174
|
+
|
|
175
|
+
```text
|
|
176
|
+
outcome=unavailable
|
|
177
|
+
errorCode=confirmation-required
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
No dialog can appear and no canonical custom entry may be appended. The assistant's final wording can vary; use JSON mode or the canonical audit below when the exact tool envelope is needed. If the model does not call the tool, record that separately as a routing observation and repeat with the explicit action name to isolate runtime behavior.
|
|
181
|
+
|
|
182
|
+
Adding `--no-session` changes the expected error to `runtime-unavailable` for both reads and writes.
|
|
183
|
+
|
|
184
|
+
## JSON event-stream procedure
|
|
185
|
+
|
|
186
|
+
JSON mode is also non-interactive, but it exposes authoritative tool lifecycle events. Capture the complete local stream; it may include current non-secret tool arguments.
|
|
187
|
+
|
|
188
|
+
Read case:
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
pi --mode json --approve --session-dir "$DS4_DOGFOOD_SESSIONS" \
|
|
192
|
+
"Use context_persistence with action pins_list to inspect active Pins. Do not write." \
|
|
193
|
+
2>evidence/json-read.stderr.log | tee evidence/json-read.jsonl
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Write case:
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
pi --mode json --approve --session-dir "$DS4_DOGFOOD_SESSIONS" \
|
|
200
|
+
"Use context_persistence to add a session Pin for alpha2-run-01 stating that this disposable project uses Node.js 22." \
|
|
201
|
+
2>evidence/json-write.stderr.log | tee evidence/json-write.jsonl
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Reserved historical-placeholder regression:
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
pi --mode json --approve --session-dir "$DS4_DOGFOOD_SESSIONS" \
|
|
208
|
+
"Call context_persistence exactly once with action pin_add, scope session, classification normal, and content exactly [omitted-by-ds4-egress-policy]." \
|
|
209
|
+
2>evidence/json-placeholder.stderr.log | tee evidence/json-placeholder.jsonl
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Extract tool completions:
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
jq -c '
|
|
216
|
+
select(.type == "tool_execution_end" and .toolName == "context_persistence")
|
|
217
|
+
| {isError, result}
|
|
218
|
+
' evidence/json-*.jsonl
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
The read should succeed. The ordinary write must return `confirmation-required` and append nothing. The placeholder case must return `rejected / egress-placeholder`, not request confirmation, and append nothing. Inspect `result.content` and `result.details` for bounded allowlisted metadata; they must not echo complete content, claims, keys, reasons, paths, source-session identity, confirmation text, or raw errors.
|
|
222
|
+
|
|
223
|
+
The local `tool_execution_start.args` event can contain the current synthetic arguments supplied to the tool. That local event is not the provider-facing result contract, which is why dogfooding must use non-sensitive data and evidence files must not be published blindly.
|
|
224
|
+
|
|
225
|
+
## Canonical append audit
|
|
226
|
+
|
|
227
|
+
List only metadata for canonical Pin/Memory entries in the dedicated sessions:
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
find "$DS4_DOGFOOD_SESSIONS" -name '*.jsonl' -print0 \
|
|
231
|
+
| xargs -0 -r jq -r '
|
|
232
|
+
select(
|
|
233
|
+
.type == "custom"
|
|
234
|
+
and (
|
|
235
|
+
.customType == "ds4-context-pin-v1"
|
|
236
|
+
or .customType == "ds4-context-memory-v1"
|
|
237
|
+
)
|
|
238
|
+
)
|
|
239
|
+
| [.customType, .id, .timestamp, (.data.operation // "unknown")]
|
|
240
|
+
| @tsv
|
|
241
|
+
'
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
Expected invariants:
|
|
245
|
+
|
|
246
|
+
- each accepted canonical add/supersede/status operation contributes exactly one append-only custom entry;
|
|
247
|
+
- cancelled, rejected, unavailable, and unanswered-confirmation operations contribute none;
|
|
248
|
+
- print/JSON writes contribute none;
|
|
249
|
+
- `--no-session` contributes none;
|
|
250
|
+
- source include/exclude policy contributes no Pin/Memory custom entry because it is derived local SQLite policy;
|
|
251
|
+
- rebuild changes projections, not the JSONL mutation sequence.
|
|
252
|
+
|
|
253
|
+
Do not publish the session files: they are canonical local history and may contain prompt/tool argument text even when tool results are metadata-only.
|
|
254
|
+
|
|
255
|
+
## Extended provider and lifecycle matrix
|
|
256
|
+
|
|
257
|
+
After the basic mode matrix passes, repeat the relevant TUI/RPC cases with:
|
|
258
|
+
|
|
259
|
+
- a configured remote provider;
|
|
260
|
+
- a verified local provider whose exact provider ID is listed in `privacy.localProviders`;
|
|
261
|
+
- privacy enabled and disabled;
|
|
262
|
+
- a provider switch between read and targeted write;
|
|
263
|
+
- a branch switch between read and targeted write;
|
|
264
|
+
- trusted and untrusted project state;
|
|
265
|
+
- two simultaneous Pi sessions using the shared SQLite database;
|
|
266
|
+
- cross-session project Memory when `memory.crossSession` is explicitly enabled.
|
|
267
|
+
|
|
268
|
+
Provider, trust, branch, provenance, capability, target state, and classification changes after confirmation must fail safely. A model-supplied `local-only` classification is never evidence that earlier input stayed local.
|
|
269
|
+
|
|
270
|
+
## Result record
|
|
271
|
+
|
|
272
|
+
Use one record per scenario:
|
|
273
|
+
|
|
274
|
+
```text
|
|
275
|
+
Run ID:
|
|
276
|
+
Date:
|
|
277
|
+
Pi version:
|
|
278
|
+
DS4 exact version:
|
|
279
|
+
Provider/model:
|
|
280
|
+
Mode and session persistence:
|
|
281
|
+
Scenario:
|
|
282
|
+
Expected outcome:
|
|
283
|
+
Observed outcome:
|
|
284
|
+
Confirmation shown/answered:
|
|
285
|
+
Canonical entries before/after:
|
|
286
|
+
Projection/rebuild observation:
|
|
287
|
+
Result leak check:
|
|
288
|
+
Pass/fail:
|
|
289
|
+
Issue/reference:
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
## Promotion criteria
|
|
293
|
+
|
|
294
|
+
Do not promote the alpha if any run shows:
|
|
295
|
+
|
|
296
|
+
- a write without a fresh positive local UI decision;
|
|
297
|
+
- canonical JSONL rewrite, loss, duplication, or a false commit claim;
|
|
298
|
+
- complete persistent content or prohibited metadata in provider-facing results/history;
|
|
299
|
+
- fuzzy destructive targeting or acceptance of a stale revision;
|
|
300
|
+
- failure to reconstruct canonical state from JSONL;
|
|
301
|
+
- an actionable warning hidden as routine debug output;
|
|
302
|
+
- a reproducible regression above the release latency/quality/schema gates.
|
|
303
|
+
|
|
304
|
+
A missing live local-provider run should remain explicitly recorded rather than inferred from remote-provider or automated-test results.
|
package/docs/MEMORY_AND_PINS.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Memory and Persistent Pins
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
DS4 separates durable, user-curated state from conversation history while keeping Pi JSONL canonical. Cross-session replay 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
|
|
|
@@ -37,7 +37,7 @@ Pins remain subordinate to system/developer instructions. Memory tells the model
|
|
|
37
37
|
|
|
38
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.
|
|
39
39
|
|
|
40
|
-
Mutations are manual-first. Repeating the same normalized pin/claim returns its existing ID without appending another entry.
|
|
40
|
+
Mutations are manual-first: persistence requires an explicit user request, and every LLM-tool write additionally requires local UI confirmation. DS4 never harvests ordinary conversation into Pins or Memory automatically. `/context` remains the direct local command surface; `context_persistence` is the bounded model-callable surface and requires a prior exact read plus revision for destructive operations. Repeating the same normalized pin/claim returns its existing ID without appending another entry.
|
|
41
41
|
|
|
42
42
|
## Canonical append-only mutations
|
|
43
43
|
|
|
@@ -63,7 +63,7 @@ No row is silently overwritten. SQLite mutation and materialized tables are disp
|
|
|
63
63
|
3. replays all known mutations in timestamp + canonical entry order;
|
|
64
64
|
4. rebuilds memory, pin, source, lifecycle, and FTS rows transactionally.
|
|
65
65
|
|
|
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.
|
|
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. Source exclusions are deliberately derived local policy: deleting the database removes them, replay restores the source from unchanged canonical JSONL, and no source-policy operation rewrites a session file.
|
|
67
67
|
|
|
68
68
|
## Supersession and contradiction handling
|
|
69
69
|
|
package/docs/PRIVACY.md
CHANGED
|
@@ -34,7 +34,7 @@ Persistent pin and memory commands also accept an explicit classification:
|
|
|
34
34
|
|
|
35
35
|
The classification is part of the canonical Pi custom-entry mutation and survives SQLite deletion, session resume, branch changes, and compaction. Existing unclassified mutations use `privacy.defaultClassification` at selection time.
|
|
36
36
|
|
|
37
|
-
Automatic
|
|
37
|
+
Automatic harvesting/classification of ordinary conversation remains disabled. Persistent commands use explicit markers, explicit Pin/Memory metadata, and the configured default. For a confirmed `context_persistence` content-bearing mutation, marker and credential-like detection may only raise the stored classification floor; it can never lower an existing target classification.
|
|
38
38
|
|
|
39
39
|
## Provider destination and allow rules
|
|
40
40
|
|
|
@@ -91,6 +91,14 @@ Pi's fallback compactor is still covered by the final provider-payload hook.
|
|
|
91
91
|
|
|
92
92
|
The local content-addressed object may retain exact restricted bytes because Pi JSONL is canonical and object hashes require exact recovery. Artifact references persist the derived classification in `metadata_json`. Context selection hides prohibited tool results before offload/reference injection. `context_artifact_search` applies the stored artifact classification to every returned excerpt; a remote request receives no matches/content for a prohibited artifact.
|
|
93
93
|
|
|
94
|
+
### Context persistence tool egress
|
|
95
|
+
|
|
96
|
+
`context_persistence` treats both its current result and historical Pi tool-call/result records as provider-egress surfaces independently of `privacy.enabled`. List/source results contain only bounded IDs or volatile references, scope/lifecycle/classification/timestamps, revisions and safe counters. Find previews are sanitized across the complete bounded source before Unicode-scalar truncation; prohibited previews become metadata-only omissions. Mutation results never echo content, claim, key or reason.
|
|
97
|
+
|
|
98
|
+
A dedicated historical guard preserves provider-specific tool-call/result linkage while replacing `content`, `query`, `key`, `reason`, unknown fields, raw previews and malformed payloads with the fixed omission sentinel `[omitted-by-ds4-egress-policy]`. That sentinel is output-only and reserved: any incoming `context_persistence` string argument containing it is rejected with `egress-placeholder` before runtime lookup, UI confirmation, canonical append, or derived-policy update. A follow-up call must use fresh user-provided text rather than copying the historical placeholder. IDs and revisions must match their opaque grammars; paths, source session identity, complete errors and UI confirmation text are never copied. Local `sourceRef` mappings, revision HMAC secrets and target fingerprints are volatile and contain no content.
|
|
99
|
+
|
|
100
|
+
Every write is policy-checked before local confirmation and checked again immediately before dispatch, covering provider or trust changes while the dialog is open. `local-only` supplied by a model is not proof that earlier input stayed local; remote-denied writes return only `provider-policy-denied` and do not append.
|
|
101
|
+
|
|
94
102
|
### Final provider payload
|
|
95
103
|
|
|
96
104
|
`before_provider_request` runs after provider-specific serialization. DS4 recursively checks known provider content containers (`system`, `messages`, `input`, `contents`, `context`, tool descriptions/arguments, and related text fields), strips classification markers, removes prohibited blocks, and redacts credential-like values. Structural provider fields remain unchanged.
|