ds4-context-engine 0.3.0-alpha.3 → 0.3.0-alpha.5

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 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 frozen 0.2 contracts. Published 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 `alpha` points to `0.3.0-alpha.2`, `latest` remains `0.2.0`, and the maintenance line targets Pi `0.84.3`.
19
+ > **Project status:** Stable `0.2.0` includes M0–M20 and frozen 0.2 contracts. Published prerelease `0.3.0-alpha.4` improves `context_persistence` action guidance and privacy-safe validation categories, and moves routine successful compaction lifecycle events to `debug`. Confirmation, canonical records, strict compaction validation, Pi fallback, SQLite schema 15, and runtime contracts remain unchanged. npm `alpha` points to `0.3.0-alpha.4`, `latest` remains `0.2.0`, and the maintenance line targets Pi `0.84.3`.
20
20
 
21
21
  ## Why DS4
22
22
 
@@ -29,7 +29,7 @@ It provides:
29
29
  - exact and FTS5 historical retrieval with source provenance;
30
30
  - opt-in hybrid semantic retrieval with a deterministic local embedding and lexical fallback;
31
31
  - trust-gated structural project indexing, Git-aware invalidation and bounded source snippets;
32
- - hierarchical, validated, non-destructive compaction summaries;
32
+ - hierarchical, validated, non-destructive compaction summaries with overflow-safe multi-request fan-out/fan-in;
33
33
  - persistent pins and append-only durable memory stored canonically in Pi JSONL;
34
34
  - a bounded, metadata-only `context_persistence` tool with local confirmation for every model-callable write;
35
35
  - opt-in checkpointed project-memory replay across exact trusted Pi project sessions;
@@ -92,7 +92,7 @@ The stable `0.2.0` packages (`ds4-context-engine`, `ds4-context-core`, and `ds4-
92
92
  To dogfood the published alpha without replacing a global stable installation, pin it in a disposable project:
93
93
 
94
94
  ```bash
95
- pi install -l npm:ds4-context-engine@0.3.0-alpha.2
95
+ pi install -l npm:ds4-context-engine@0.3.0-alpha.4
96
96
  ```
97
97
 
98
98
  Follow the [0.3 alpha dogfooding runbook](docs/DOGFOODING_0.3.0_ALPHA.md); use synthetic data and a dedicated session directory.
@@ -416,7 +416,7 @@ npm run schema:context-persistence
416
416
  npm run latency:check -- /path/to/exact/ds4-context-core@0.1.2
417
417
  npm run pack:check
418
418
  # Post-publication, with an exact version rather than a dist-tag:
419
- npm run registry:check -- 0.3.0-alpha.2
419
+ npm run registry:check -- 0.3.0-alpha.4
420
420
  npm pack --dry-run
421
421
  npm pack --dry-run --workspace ds4-context-core
422
422
  npm pack --dry-run --workspace ds4-context-reference-adapter
@@ -468,6 +468,8 @@ scripts package and release-readiness checks
468
468
  - [0.2.0 release readiness](docs/RELEASE_READINESS_0.2.0.md)
469
469
  - [0.2.0 release notes](docs/releases/0.2.0.md)
470
470
  - [0.2.0-rc.1 release notes](docs/releases/0.2.0-rc.1.md)
471
+ - [0.3.0-alpha.4 prerelease notes](docs/releases/0.3.0-alpha.4.md)
472
+ - [0.3.0-alpha.3 prerelease notes](docs/releases/0.3.0-alpha.3.md)
471
473
  - [0.3.0-alpha.2 prerelease notes](docs/releases/0.3.0-alpha.2.md)
472
474
  - [0.3.0-alpha.1 prerelease notes](docs/releases/0.3.0-alpha.1.md)
473
475
  - [Architecture decisions](docs/ADR/README.md)
@@ -477,7 +479,7 @@ scripts package and release-readiness checks
477
479
 
478
480
  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.
479
481
 
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.
482
+ The [0.2.0 roadmap](docs/ROADMAP_0.2.0.md) is complete. Prerelease `0.3.0-alpha.4` builds on the prior [context persistence tool](docs/CONTEXT_PERSISTENCE_TOOL.md) and privacy-safe [compaction](docs/COMPACTION.md) hardening with clearer action-specific failures and quieter routine lifecycle logs. Confirmation, exact targeting, strict summary grounding, Pi fallback, and stable canonical/configuration/SQLite/runtime contracts remain unchanged. 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.
481
483
 
482
484
  ## Contributing
483
485
 
@@ -101,12 +101,13 @@ agent_settled
101
101
  session_before_compact
102
102
  -> map Pi preparation messages to exact canonical entry IDs
103
103
  -> privacy-sanitize discarded text/instructions/file lists for the active provider
104
- -> serialize only the newly discarded segment and preserve Pi's retained boundary
105
- -> generate and validate an immutable segment node
104
+ -> preflight the complete sanitized request against the calibrated model input budget
105
+ -> when needed, split at contiguous message boundaries while keeping matching tool calls/results atomic
106
+ -> generate and validate each immutable segment against only its own sanitized evidence
106
107
  -> resolve the prior root from the active Pi branch only
107
- -> generate and validate a bounded aggregate node when a prior root exists
108
+ -> recursively generate and validate bounded ordered aggregate layers until one root remains
108
109
  -> wrap generated nodes with their highest inherited classification for provider-switch safety
109
- -> atomically persist prepared nodes/edges and return only the active root to Pi
110
+ -> atomically persist the complete prepared graph and return only one active root to Pi
110
111
 
111
112
  session_compact / session_compact_failed
112
113
  -> commit or fail prepared summary lifecycle
@@ -7,13 +7,13 @@ DS4 intercepts Pi's `session_before_compact` event but preserves Pi's cut-point
7
7
  1. Pi determines `messagesToSummarize`, optional split-turn prefix, and `firstKeptEntryId`.
8
8
  2. DS4 maps every source message by exact fingerprint to a canonical branch entry ID.
9
9
  3. Pi's serializer converts the newly discarded span to bounded conversation text; enabled privacy policy sanitizes conversation, custom instructions, and file paths for the active provider.
10
- 4. The active model generates and validates an immutable segment summary against sanitized evidence with cache retention disabled and a fresh routing session ID.
11
- 5. If the active branch has a previous DS4 root, a second bounded call aggregates only that root's content with the new segment content; DS4-generated IDs, hashes, kinds, and graph levels remain outside model-visible evidence. A Pi-native predecessor is imported as an explicitly unverified branch node.
12
- 6. The highest input classification is wrapped around each generated node, then all nodes are persisted atomically as `prepared`; Pi receives only the active segment or aggregate text.
13
- 7. Pi appends its normal `CompactionEntry` with `fromHook: true`.
14
- 8. `session_compact` commits all nodes and associates the active root with the Pi entry; failure marks the prepared batch `failed`.
10
+ 4. DS4 estimates the complete sanitized summary request against the calibrated active-model input budget. If the whole request does not fit, it partitions the source into ordered contiguous segments. Individual messages are indivisible, and every tool call remains in the same atomic group as all matching results; an exceptionally large turn may split only between such groups.
11
+ 5. The active model generates and validates each immutable segment summary only against that segment's sanitized evidence, with cache retention disabled and a fresh routing session ID per call.
12
+ 6. DS4 recursively aggregates ordered child summaries in bounded fan-in calls until one root remains. The ordered roots include the previous branch summary, when present, followed by every new segment. DS4-generated IDs, hashes, kinds, and graph levels remain outside model-visible evidence. A Pi-native predecessor is imported as an explicitly unverified branch node.
13
+ 7. The highest input classification is wrapped around each generated node, then all nodes are persisted atomically as one `prepared` graph batch. Usage is summed across every segment and aggregate request; Pi receives only the final root text and still appends exactly one canonical `CompactionEntry` with `fromHook: true`.
14
+ 8. `session_compact` commits all nodes and associates the active root with the Pi entry; failure marks the complete prepared batch `failed`.
15
15
 
16
- Any mapping, model, output-limit, validation, or storage error returns `undefined` from the hook, allowing Pi's default compaction to run.
16
+ Fan-out and fan-in are bounded to 32 segment requests, 64 aggregate requests, and 16 aggregate passes. A base prompt, individual message, atomic tool exchange, pair of child summaries, or total operation that cannot fit within those limits fails closed. Any mapping, budget, model, output-limit, validation, abort, or storage error returns `undefined` from the hook, allowing Pi's default compaction to run.
17
17
 
18
18
  ## Required summary contract
19
19
 
@@ -32,7 +32,7 @@ Any mapping, model, output-limit, validation, or storage error returns `undefine
32
32
  ## Critical Exact Values
33
33
  ```
34
34
 
35
- Every section must occur once, in order, and contain content or `- None`. DS4 replaces each unique `Files Read` and `Files Modified` section with one exact path per bullet from Pi's sanitized file-operation inventory before validation; missing or duplicate sections still fail. Backticked exact values must occur in the serialized segment source, ordered child-summary content, or those known file-operation paths. A bounded unsupported exact-value bullet is removed as a whole and recorded as a validation warning; unsupported prose, more than eight affected bullets, or removal above 25% still fails closed to Pi. The prompt explicitly asks the model to omit a bullet whose complete backticked span cannot be copied verbatim. Segment and aggregate outputs are validated independently; either unrepaired failure prevents the whole graph batch from being installed.
35
+ Every section must occur once, in order, and contain content or `- None`. DS4 replaces each unique `Files Read` and `Files Modified` section with one exact path per bullet from Pi's sanitized file-operation inventory before validation; missing or duplicate sections still fail. Backticked exact values must occur in the serialized segment source, ordered child-summary content, or those known file-operation paths. A bounded unsupported exact-value bullet is removed as a whole and recorded as a validation warning; unsupported prose, more than eight affected bullets, or removal above 25% still fails closed to Pi. The prompt explicitly asks the model to omit a bullet whose complete backticked span cannot be copied verbatim. Every segment is validated independently against only its own sanitized source and deterministic file inventory. Every aggregate is validated independently against only the sanitized content of its ordered children and cumulative deterministic file inventory. Any unrepaired failure prevents the whole graph batch from being installed.
36
36
 
37
37
  An unrepaired exact-value failure reports only the stage, issue code, categorical repair status, unsupported-span count, and affected-bullet count. Repair statuses distinguish an unsupported location, more than eight bullets, removal above 25%, and an unexpected invalid second validation. The disputed text is intentionally absent from logs, UI notifications, and diagnostics because it may contain sensitive source material.
38
38
 
@@ -76,4 +76,4 @@ It requests compaction at most once per session leaf. Pi's native threshold and
76
76
  /context summaries
77
77
  ```
78
78
 
79
- The preview reports thresholds and eligibility; Pi remains authoritative for the exact cut point.
79
+ The preview reports thresholds and eligibility; Pi remains authoritative for the exact cut point. Runtime diagnostics additionally report the calibrated input budget, estimated whole-source prompt size, generated segment count, and aggregate-call count without source content. Routine `summary_graph_prepared` and `summary_graph_committed` lifecycle events are emitted only at `debug`; fallback, failure, persistence, and reconciliation problems remain actionable warnings. Oversized-group and bounded-operation errors expose only numeric budgets/counts, never rejected source text. Provider failures are reduced to metadata-only categories such as `input-limit`, `usage-limit`, `rate-limit`, `authentication`, or `transport`; raw provider error details are not logged or shown. The proactive-threshold TUI notification remains a user-visible `info` notice because it explains why an automatic compaction started.
@@ -19,22 +19,24 @@ Memory is quoted durable factual, decision, or historical data. It supports `ses
19
19
 
20
20
  ## Actions
21
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 |
22
+ | Action | Class | Parameters | Purpose |
23
+ | --- | --- | --- | --- |
24
+ | `pins_list` | read | optional `activeOnly`, `maxResults` | List visible Pins with metadata and revisions |
25
+ | `pins_find` | read | `query`; optional `activeOnly`, `maxResults` | Bounded Pin search with sanitized previews |
26
+ | `pin_add` | canonical write | `content`; optional `scope`, `classification` | Append a new Pin |
27
+ | `pin_supersede` | canonical write | `id`, `targetRevision`, `content`; optional `classification` | Replace one exact active Pin immutably |
28
+ | `pin_unpin` | canonical write | `id`, `targetRevision`; optional `reason` | Append a deleted lifecycle status |
29
+ | `memory_list` | read | optional `activeOnly`, `maxResults` | List visible Memory with metadata and revisions |
30
+ | `memory_find` | read | `query`; optional `activeOnly`, `maxResults` | Bounded Memory search with sanitized previews |
31
+ | `memory_add` | canonical write | `content`; optional `scope`, `key`, `classification` | Append session/project Memory |
32
+ | `memory_supersede` | canonical write | `id`, `targetRevision`, `content`; optional `classification` | Replace one exact active Memory item immutably |
33
+ | `memory_invalidate` | canonical write | `id`, `targetRevision`; optional `reason` | Append an invalid lifecycle status |
34
+ | `memory_expire` | canonical write | `id`, `targetRevision`; optional `reason` | Append an expired lifecycle status |
35
+ | `memory_sources` | read | optional `maxResults` | List cross-session sources through volatile references |
36
+ | `memory_source_exclude` | derived write | `id`, `targetRevision`; optional `reason` | Exclude one source in local SQLite policy |
37
+ | `memory_source_include` | derived write | `id`, `targetRevision` | Restore one source in local SQLite policy |
38
+
39
+ The transport schema stays flat for compatibility across supported providers, but DS4 applies the parameter matrix above before runtime access. A known action with an inapplicable field returns `unsupported-parameter`; a known action missing an action-required field returns `missing-required-parameter`. These diagnostics never identify or echo fields or values. Malformed transport input retains the generic `invalid-parameters` category. The output-only egress sentinel is checked before action-specific categorization so it remains `egress-placeholder` even when supplied in an inapplicable field.
38
40
 
39
41
  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
42
 
@@ -1,6 +1,6 @@
1
1
  # Dogfooding DS4 0.3.0 Alpha
2
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.
3
+ This runbook validates the published `ds4-context-engine@0.3.0-alpha.4` package through sustained real Pi use. It complements automated tests and release smoke checks; it does not replace them.
4
4
 
5
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
6
 
@@ -9,7 +9,9 @@ The primary target is the model-callable `context_persistence` surface. Pi JSONL
9
9
  - Use the exact prerelease version, not the mutable `alpha` dist-tag.
10
10
  - Use a disposable trusted project and a dedicated session directory.
11
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.
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 and later reserve that output-only marker and must reject it as `egress-placeholder` before runtime access, confirmation, canonical append, or derived-policy update.
13
+ - Alpha.3 and later keep exact-value summary validation strict. An unrepaired failure may expose only its stage, issue code, repair category, and counts; disputed exact text must not appear in diagnostics.
14
+ - Alpha.4 distinguishes unsupported and missing action parameters without echoing rejected fields or values. Routine successful compaction lifecycle events require `diagnostics.logLevel=debug`; actionable fallback warnings remain visible.
13
15
  - 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
16
  - Do not retry `committed_projection_pending` or `indeterminate`. Inspect state with a read, `/context health`, or `/context rebuild-index` first.
15
17
  - 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.
@@ -26,7 +28,7 @@ mkdir -p /tmp/ds4-alpha-dogfood
26
28
  cd /tmp/ds4-alpha-dogfood
27
29
  git init
28
30
  mkdir -p sessions evidence
29
- pi install -l npm:ds4-context-engine@0.3.0-alpha.2
31
+ pi install -l npm:ds4-context-engine@0.3.0-alpha.4
30
32
  pi list
31
33
  pi --version
32
34
  ```
@@ -46,19 +48,19 @@ Record the Pi version, DS4 version, provider/model, mode, session name, expected
46
48
  Use unique non-sensitive values so duplicates from earlier runs cannot hide a failure. Example run label:
47
49
 
48
50
  ```text
49
- alpha2-run-01
51
+ alpha4-run-01
50
52
  ```
51
53
 
52
54
  Example Pin:
53
55
 
54
56
  ```text
55
- For alpha2-run-01 verification, use Node.js 22 in this disposable project.
57
+ For alpha4-run-01 verification, use Node.js 22 in this disposable project.
56
58
  ```
57
59
 
58
60
  Example Memory:
59
61
 
60
62
  ```text
61
- For alpha2-run-01, the synthetic release channel is amber.
63
+ For alpha4-run-01, the synthetic release channel is amber.
62
64
  ```
63
65
 
64
66
  Never use real credentials, customer data, private paths, or production policy in dogfooding prompts.
@@ -76,7 +78,7 @@ Run these scenarios in order:
76
78
 
77
79
  1. Inspect `/context health`, `/context pins`, `/context memory`, and `/context privacy`.
78
80
  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.
81
+ 3. Explicitly request the synthetic Memory: `Remember for this session that the synthetic release channel for alpha4-run-01 is amber.` Verify that the dialog identifies the action and canonical persistence class. Accept it. Expect one committed Memory mutation.
80
82
  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
83
  5. Explicitly request the synthetic Pin, but reject or close the confirmation dialog. Verify with `/context pins` that it was not created.
82
84
  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.
@@ -115,7 +117,7 @@ Enter one JSON object per line on stdin. First request a read:
115
117
  Wait for the turn to end before sending the next prompt. For a write:
116
118
 
117
119
  ```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."}
120
+ {"id":"write-1","type":"prompt","message":"Persist a session Pin for alpha4-run-01 stating that this disposable project uses Node.js 22 for verification."}
119
121
  ```
120
122
 
121
123
  Pi should emit a request shaped like:
@@ -167,7 +169,7 @@ The read should complete. Then request a write:
167
169
 
168
170
  ```bash
169
171
  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."
172
+ "Use context_persistence to add a session Memory saying that alpha4-run-01 uses the synthetic channel amber."
171
173
  ```
172
174
 
173
175
  Expected behavior:
@@ -197,7 +199,7 @@ Write case:
197
199
 
198
200
  ```bash
199
201
  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." \
202
+ "Use context_persistence to add a session Pin for alpha4-run-01 stating that this disposable project uses Node.js 22." \
201
203
  2>evidence/json-write.stderr.log | tee evidence/json-write.jsonl
202
204
  ```
203
205
 
@@ -1,6 +1,6 @@
1
1
  # DS4 Context Engine 0.3.0-alpha.3
2
2
 
3
- Status: release candidate on 2026-08-30; publication and tag pending.
3
+ Status: published prerelease on 2026-08-30; tag `v0.3.0-alpha.3`.
4
4
 
5
5
  This coordinated prerelease hardens proactive compaction after investigation of an intermittent `unsupported-exact-value` fallback. It preserves strict exact-value grounding and Pi fallback behavior while making repair failures diagnosable without exposing disputed source text.
6
6
 
@@ -30,7 +30,7 @@ ds4-context-reference-adapter
30
30
  ds4-context-engine
31
31
  ```
32
32
 
33
- Both adapters depend exactly on `ds4-context-core@0.3.0-alpha.3`. Publication uses the explicit npm `alpha` dist-tag so `latest` remains `0.2.0`. GitHub Actions remains validation-only with OIDC and package-write permissions denied.
33
+ Both adapters depend exactly on `ds4-context-core@0.3.0-alpha.3`. The packages were published manually under the explicit npm `alpha` dist-tag while `latest` remains `0.2.0`. GitHub Actions remains validation-only with OIDC and package-write permissions denied.
34
34
 
35
35
  ## Validation evidence
36
36
 
@@ -48,7 +48,9 @@ Local candidate verification on Node.js `26.5.1`:
48
48
  - `git diff --check`: passed.
49
49
  - Protected CI, compatibility golden, Pi fixture, migration, canonical Pin/Memory, and persistence-tool contract files: unchanged.
50
50
 
51
- Exact registry verification, annotated tag creation, and GitHub prerelease creation remain pending until all three packages are published.
51
+ - `npm run registry:check -- 0.3.0-alpha.3`: passed against all three exact published versions; `alpha` resolves to `0.3.0-alpha.3` and `latest` remains `0.2.0` for every package.
52
+
53
+ Exact registry verification passed before the annotated tag and GitHub prerelease were created.
52
54
 
53
55
  ## Documentation
54
56
 
@@ -0,0 +1,61 @@
1
+ # DS4 Context Engine 0.3.0-alpha.4
2
+
3
+ Status: published prerelease on 2026-09-02; tag `v0.3.0-alpha.4`.
4
+
5
+ This coordinated prerelease improves model-callable `context_persistence` guidance and categorical validation diagnostics, and removes routine successful compaction lifecycle events from normal `info` output. It preserves strict persistence confirmation, canonical Pi JSONL semantics, privacy-safe egress, compaction validation, and Pi fallback behavior.
6
+
7
+ ## Fixed
8
+
9
+ - Describes the valid parameter set for every `context_persistence` action in the tool guidance and public action matrix.
10
+ - Distinguishes a known action with an inapplicable field as `unsupported-parameter` and a missing action-required field as `missing-required-parameter`.
11
+ - Keeps validation failures categorical: rejected field names and values are absent from current results, sanitized history, diagnostics, and logs.
12
+ - Continues to reject the output-only egress sentinel before action-specific validation, including when it appears in an otherwise inapplicable field.
13
+ - Emits routine `compaction.summary_graph_prepared` and `compaction.summary_graph_committed` lifecycle events only at `debug` instead of the default `info` level.
14
+ - Preserves actionable compaction fallback, failure, persistence, and reconciliation events at `warn`; the proactive-threshold TUI notice remains user-visible because it explains why automatic compaction started.
15
+
16
+ ## Compatibility and persistence
17
+
18
+ The flat tool schema, fourteen actions, `ds4-context-persistence-tool-v1`, and `ds4-context-persistence-result-v1` identifiers are unchanged. The new validation categories are metadata-only and do not add a write path or alter confirmation requirements.
19
+
20
+ Pi JSONL remains canonical and append-only. All model-callable writes still require fresh local UI confirmation and fail closed without UI or canonical persistence. SQLite remains a disposable projection. Schema 15, migrations 1–15, `ds4-context-config-v1`, and `runtime-adapter-v1` are unchanged. Strict compaction validation and fallback to Pi default compaction are unchanged.
21
+
22
+ ## Package/version policy
23
+
24
+ The coordinated version is `0.3.0-alpha.4` for:
25
+
26
+ ```text
27
+ ds4-context-core
28
+ ds4-context-reference-adapter
29
+ ds4-context-engine
30
+ ```
31
+
32
+ Both adapters depend exactly on `ds4-context-core@0.3.0-alpha.4`. The packages were published manually under the explicit npm `alpha` dist-tag while `latest` remains `0.2.0`. GitHub Actions remains validation-only with OIDC and package-write permissions denied.
33
+
34
+ ## Validation evidence
35
+
36
+ Local candidate verification on Node.js `26.5.1`:
37
+
38
+ - `npm ci`: passed.
39
+ - `npm run check`: 64 files and 290 tests passed.
40
+ - Focused persistence coverage: action-field guidance, unsupported/missing parameter categories, egress-sentinel priority, metadata-only failures, and sanitized historical diagnostics passed.
41
+ - Focused compaction coverage: successful lifecycle events are absent at `info`, present at `debug`, and fallback remains `warn`.
42
+ - `npm run quality:compare`: candidate quality `0.9875` versus baseline `0.808156`.
43
+ - `npm run schema:context-persistence`: 1,266 bytes and 317 estimated tokens; below the 1,500 absolute and 320 relative limits.
44
+ - `npm run latency:check -- <exact ds4-context-core@0.1.2>`: passed with ratio `0.923285`, at or below `1.10`.
45
+ - `npm run pack:check`: verified core (203 files), reference adapter (7 files), and Pi adapter (61 files) in a clean consumer.
46
+ - `npm pack --dry-run --json` for all three packages: passed with the same bounded inventories.
47
+ - The committed candidate was replayed from detached clean checkout `6fcf514`; `npm ci`, the 64-file/290-test suite, quality, schema, package verification, tarball review, and `git diff --check` passed.
48
+ - `git diff --check`: passed.
49
+ - Protected CI, compatibility golden, Pi fixture, migration, canonical Pin/Memory, and persistence result-contract files: unchanged.
50
+
51
+ - `npm run registry:check -- 0.3.0-alpha.4`: passed against all three exact published versions; `alpha` resolves to `0.3.0-alpha.4` and `latest` remains `0.2.0` for every package.
52
+
53
+ Exact registry verification passed before the annotated tag and GitHub prerelease were created.
54
+
55
+ ## Documentation
56
+
57
+ - [`../CONTEXT_PERSISTENCE_TOOL.md`](../CONTEXT_PERSISTENCE_TOOL.md)
58
+ - [`../COMPACTION.md`](../COMPACTION.md)
59
+ - [`../PRIVACY.md`](../PRIVACY.md)
60
+ - [`../RELEASING.md`](../RELEASING.md)
61
+ - [`0.3.0-alpha.3.md`](0.3.0-alpha.3.md)
@@ -0,0 +1,58 @@
1
+ # DS4 Context Engine 0.3.0-alpha.5
2
+
3
+ Status: validated release candidate; not yet published.
4
+
5
+ This coordinated prerelease adds overflow-safe hierarchical compaction for discarded source that cannot fit in one active-model summary request. It preserves strict summary validation, privacy sanitization, canonical Pi JSONL semantics, one final Pi compaction entry, and fail-closed fallback to Pi default compaction.
6
+
7
+ ## Added
8
+
9
+ - Preflights the complete sanitized compaction prompt against the calibrated active-model input budget.
10
+ - Partitions oversized discarded source at contiguous message boundaries while keeping matching tool calls and results in the same atomic group.
11
+ - Generates and validates each segment only against that segment's sanitized source and deterministic file inventory.
12
+ - Recursively aggregates ordered child summaries when one fan-in request cannot fit, preserving cumulative provenance and graph topology.
13
+ - Bounds work to 32 segment requests, 64 aggregate requests, and 16 aggregate passes.
14
+ - Exposes metadata-only diagnostics for input budget, whole-source prompt estimate, segment count, and aggregate-call count.
15
+ - Categorizes provider failures as `input-limit`, `usage-limit`, `rate-limit`, `authentication`, `transport`, `aborted`, or `provider-error` without surfacing provider payloads.
16
+
17
+ ## Safety and compatibility
18
+
19
+ An individual message, atomic tool exchange, aggregate pair, or total operation that cannot fit within the bounded limits fails closed to Pi default compaction. Generated segment and aggregate summaries retain strict structural and exact-value validation; bounded unsupported-exact-value bullet repair remains unchanged. Rejected exact values and raw provider error details are never emitted in diagnostics.
20
+
21
+ Pi receives one final canonical compaction entry. The complete prepared summary-graph batch is committed only after Pi installs that entry; failed attempts remain non-destructive. Pi JSONL stays canonical and append-only, while SQLite remains a disposable projection. Schema 15, migrations 1–15, `ds4-context-config-v1`, `runtime-adapter-v1`, `ds4-context-persistence-tool-v1`, and `ds4-context-persistence-result-v1` are unchanged.
22
+
23
+ ## Package/version policy
24
+
25
+ The coordinated version is `0.3.0-alpha.5` for:
26
+
27
+ ```text
28
+ ds4-context-core
29
+ ds4-context-reference-adapter
30
+ ds4-context-engine
31
+ ```
32
+
33
+ Both adapters depend exactly on `ds4-context-core@0.3.0-alpha.5`. Publication must use the explicit npm `alpha` dist-tag so `latest` remains `0.2.0`. GitHub Actions remains validation-only with OIDC and package-write permissions denied.
34
+
35
+ ## Validation evidence
36
+
37
+ Local candidate verification on Node.js `26.5.1`:
38
+
39
+ - `npm run check`: 65 files and 297 tests passed.
40
+ - Focused compaction coverage includes three-segment fan-out, recursive fan-in, tool-exchange atomicity, exact contiguous source slicing, oversized indivisible-source fallback, and privacy-safe provider input-limit categorization.
41
+ - `npm run quality:compare`: candidate quality `0.9875` versus baseline `0.808156`.
42
+ - `npm run schema:context-persistence`: 1,266 bytes and 317 estimated tokens; below the 1,500 absolute and 320 relative limits.
43
+ - `npm run latency:check -- <exact ds4-context-core@0.1.2>`: isolated clean-checkout retry passed with ratio `1.041564`, at or below `1.10`; an immediately preceding noisy sample measured `1.157479`, while the pre-commit local sample measured `0.939056`.
44
+ - `npm run pack:check`: verified core (207 files), reference adapter (7 files), and Pi adapter (62 files) in a clean consumer.
45
+ - `npm pack --dry-run --json` for all three packages passed with the same bounded inventories and no forbidden local/session files.
46
+ - The committed candidate was replayed from detached clean checkout `8b609c0`; `npm ci`, the 65-file/297-test suite, quality, schema, package verification, tarball review, latency retry, and `git diff --check` passed.
47
+ - `git diff --check`: passed.
48
+ - Protected CI, compatibility golden, Pi fixture, migration, canonical Pin/Memory, persistence confirmation, and persistence result-contract files are unchanged.
49
+
50
+ Exact registry verification is required before tag or GitHub prerelease creation.
51
+
52
+ ## Documentation
53
+
54
+ - [`../COMPACTION.md`](../COMPACTION.md)
55
+ - [`../ARCHITECTURE.md`](../ARCHITECTURE.md)
56
+ - [`../PRIVACY.md`](../PRIVACY.md)
57
+ - [`../RELEASING.md`](../RELEASING.md)
58
+ - [`0.3.0-alpha.4.md`](0.3.0-alpha.4.md)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ds4-context-engine",
3
- "version": "0.3.0-alpha.3",
3
+ "version": "0.3.0-alpha.5",
4
4
  "description": "Non-destructive, provider-independent context management for Pi.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -58,7 +58,7 @@
58
58
  ]
59
59
  },
60
60
  "dependencies": {
61
- "ds4-context-core": "0.3.0-alpha.3"
61
+ "ds4-context-core": "0.3.0-alpha.5"
62
62
  },
63
63
  "peerDependencies": {
64
64
  "@earendil-works/pi-ai": "0.84.3",
@@ -734,6 +734,10 @@ function formatCompaction(diagnostics: RuntimeDiagnostics, preview: boolean): st
734
734
  `Last trigger: ${compaction.trigger ?? "n/a"}`,
735
735
  `Summary ID: ${compaction.summaryId ?? "n/a"}`,
736
736
  `Source entries: ${count(compaction.sourceEntries)}`,
737
+ `Input budget: ${count(compaction.inputBudgetTokens)}`,
738
+ `Whole-source prompt: ${count(compaction.sourcePromptTokens)}`,
739
+ `Generated segments: ${count(compaction.segmentCount)}`,
740
+ `Aggregate calls: ${count(compaction.aggregateCalls)}`,
737
741
  `Validation: ${compaction.validationStatus ?? "n/a"}`,
738
742
  `First kept entry: ${compaction.firstKeptEntryId ?? "n/a"}`,
739
743
  `Tokens before: ${count(compaction.tokensBefore)}`,
@@ -4,12 +4,13 @@ export const CONTEXT_PERSISTENCE_TOOL_CONTRACT = "ds4-context-persistence-tool-v
4
4
  export const CONTEXT_PERSISTENCE_RESULT_CONTRACT = "ds4-context-persistence-result-v1" as const;
5
5
  export const CONTEXT_PERSISTENCE_EGRESS_SENTINEL = "[omitted-by-ds4-egress-policy]" as const;
6
6
  export const CONTEXT_PERSISTENCE_TOOL_NAME = "context_persistence" as const;
7
- export const CONTEXT_PERSISTENCE_DESCRIPTION = "Inspect DS4 Pins/Memory. Write only after an explicit user request; writes require local user confirmation." as const;
7
+ export const CONTEXT_PERSISTENCE_DESCRIPTION = "Inspect DS4 Pins/Memory. Use action fields only. Writes require explicit user request and local UI confirmation." as const;
8
8
  export const CONTEXT_PERSISTENCE_PROMPT_SNIPPET = "Inspect or manage user-confirmed DS4 pins and durable memory" as const;
9
9
  export const CONTEXT_PERSISTENCE_PROMPT_GUIDELINES = [
10
10
  "Use context_persistence only to inspect DS4 persistent state or when the user explicitly requests a persistence mutation.",
11
11
  "After an explicit persistence request, call the write action directly; context_persistence itself obtains the required local UI confirmation, so do not ask for separate confirmation in chat.",
12
12
  "Never reuse an egress omission marker as tool input; use fresh user-provided text or ask the user to restate it.",
13
+ "Send only fields valid for the selected action: find requires query; add requires content; supersede requires id, targetRevision, and content; lifecycle and source-policy changes require id and targetRevision.",
13
14
  "Never create a pin or memory merely because information appears useful.",
14
15
  "Use pins for confirmed constraints or instructions that must remain prominent. Use memory for durable facts, decisions, and historical knowledge.",
15
16
  "Default new persistence to session scope. Use project or branch scope only when explicitly requested or unambiguous; durable Memory does not support branch scope.",
@@ -58,9 +59,17 @@ export const CONTEXT_PERSISTENCE_PARAMS = Type.Object({
58
59
  })),
59
60
  id: Type.Optional(Type.String({ minLength: 1, maxLength: 128 })),
60
61
  targetRevision: Type.Optional(Type.String({ minLength: 1, maxLength: 64 })),
61
- content: Type.Optional(Type.String({ minLength: 1, maxLength: 20_000 })),
62
+ content: Type.Optional(Type.String({
63
+ minLength: 1,
64
+ maxLength: 20_000,
65
+ description: "Add/replace only",
66
+ })),
62
67
  key: Type.Optional(Type.String({ minLength: 1, maxLength: 256 })),
63
- query: Type.Optional(Type.String({ minLength: 2, maxLength: 200 })),
68
+ query: Type.Optional(Type.String({
69
+ minLength: 2,
70
+ maxLength: 200,
71
+ description: "Find; required",
72
+ })),
64
73
  reason: Type.Optional(Type.String({
65
74
  minLength: 1,
66
75
  maxLength: 500,
@@ -114,6 +123,8 @@ const REQUIRED_FIELDS = {
114
123
 
115
124
  export type ContextPersistenceValidationCode =
116
125
  | "invalid-parameters"
126
+ | "missing-required-parameter"
127
+ | "unsupported-parameter"
117
128
  | "invalid-scope"
118
129
  | "egress-placeholder";
119
130
 
@@ -139,19 +150,19 @@ export function validateContextPersistenceParams(
139
150
  ): ContextPersistenceValidation {
140
151
  if (!params || !isAction(params.action)) return { ok: false, errorCode: "invalid-parameters" };
141
152
  const keys = Object.keys(params) as (keyof ContextPersistenceParams)[];
142
- const allowed = new Set<keyof ContextPersistenceParams>(ALLOWED_FIELDS[params.action]);
143
- if (keys.some((key) => !allowed.has(key))) {
144
- return { ok: false, errorCode: "invalid-parameters" };
145
- }
146
- if (REQUIRED_FIELDS[params.action].some((key) => params[key] === undefined)) {
147
- return { ok: false, errorCode: "invalid-parameters" };
148
- }
149
153
  if (keys.some((key) => {
150
154
  const value = params[key];
151
155
  return typeof value === "string" && value.includes(CONTEXT_PERSISTENCE_EGRESS_SENTINEL);
152
156
  })) {
153
157
  return { ok: false, errorCode: "egress-placeholder" };
154
158
  }
159
+ const allowed = new Set<keyof ContextPersistenceParams>(ALLOWED_FIELDS[params.action]);
160
+ if (keys.some((key) => !allowed.has(key))) {
161
+ return { ok: false, errorCode: "unsupported-parameter" };
162
+ }
163
+ if (REQUIRED_FIELDS[params.action].some((key) => params[key] === undefined)) {
164
+ return { ok: false, errorCode: "missing-required-parameter" };
165
+ }
155
166
  if (params.scope === "branch" && params.action === "memory_add") {
156
167
  return { ok: false, errorCode: "invalid-scope" };
157
168
  }