ds4-context-engine 0.4.3 → 0.4.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 +3 -1
- package/docs/ADR/065-exact-value-escaped-equivalence.md +56 -0
- package/docs/ADR/066-quoting-downgrade-and-span-adjacency.md +77 -0
- package/docs/ADR/README.md +2 -0
- package/docs/COMPACTION.md +3 -3
- package/docs/releases/0.4.3.md +16 -5
- package/docs/releases/0.4.4.md +103 -0
- package/docs/releases/0.4.5.md +126 -0
- package/package.json +2 -2
- 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:** The coordinated `0.4.0` release adds `storage.scope: "agent" | "project"`, now defaulting to per-project SQLite projections with shared token calibration in the agent database (opt out with `storage.scope: "agent"`). The opt-in BPE estimation and bounded auto-tuning from `0.3.10` keep `chars-v1` and disabled auto-tuning as their defaults. The bounded compaction controls from `0.3.9` remain in place; canonical history, SQLite schema 16 and runtime contracts are unchanged. Pi remains pinned to `0.84.3`. Patch `0.4.1` states the contiguous-span rule for compaction summaries in the summarizer prompt while leaving validation strictness, the eight-bullet repair bound and every provider-facing default unchanged. Patch `0.4.2` adds class-only diagnostics for rejected exact-value spans: the existing `custom_fallback` warning carries `unsupportedSpanClasses` as class names and counters, never span text, with validation, repair bounds and provider-facing defaults unchanged. Patch `0.4.3` makes those diagnostics interpretable: every distinct span receives the cheap transformed-form lookups before the bounded near-miss analysis starts, each near-miss candidate may spend only an equal share of what remains, and spans that were not analysed report `not-classified-length`, `not-classified-partial` or `not-classified-budget` instead of `no-near-miss`. See the [0.4.3 release record](docs/releases/0.4.3.md), the [0.4.2 release record](docs/releases/0.4.2.md), the [0.4.1 release record](docs/releases/0.4.1.md) and the [0.4.0 release record](docs/releases/0.4.0.md), [ADR 064](docs/ADR/064-per-project-databases-with-shared-calibration.md) and [model-awareness validation](docs/MODEL_AWARENESS.md).
|
|
19
|
+
> **Project status:** The coordinated `0.4.0` release adds `storage.scope: "agent" | "project"`, now defaulting to per-project SQLite projections with shared token calibration in the agent database (opt out with `storage.scope: "agent"`). The opt-in BPE estimation and bounded auto-tuning from `0.3.10` keep `chars-v1` and disabled auto-tuning as their defaults. The bounded compaction controls from `0.3.9` remain in place; canonical history, SQLite schema 16 and runtime contracts are unchanged. Pi remains pinned to `0.84.3`. Patch `0.4.1` states the contiguous-span rule for compaction summaries in the summarizer prompt while leaving validation strictness, the eight-bullet repair bound and every provider-facing default unchanged. Patch `0.4.2` adds class-only diagnostics for rejected exact-value spans: the existing `custom_fallback` warning carries `unsupportedSpanClasses` as class names and counters, never span text, with validation, repair bounds and provider-facing defaults unchanged. Patch `0.4.3` makes those diagnostics interpretable: every distinct span receives the cheap transformed-form lookups before the bounded near-miss analysis starts, each near-miss candidate may spend only an equal share of what remains, and spans that were not analysed report `not-classified-length`, `not-classified-partial` or `not-classified-budget` instead of `no-near-miss`. Patch `0.4.4` accepts a backticked exact value whose canonical JSON-escaped rendering is literally present in the evidence — the decoded rendering a summarizer produces when it quotes serialized JSON — while absent values, the reverse escape direction, span composition and single-character variants stay rejected; the diagnostics probe budget rises from 4000 to 24000 evidence-source scans. Patch `0.4.5` grades the summarizer quoting fallback: the prompt requires one contiguous excerpt per backticked span, tells the model to backtick only the fragments that are themselves contiguous or to keep the fact as ordinary text without backticks instead of composing a span, and reserves bullet omission for facts with no support in the evidence; diagnostics split composition into `composed-adjacent-present` (both parts next to each other in one source, so the span may be a re-rendering of a contiguous region) and `composed-two-present-parts` (parts found at unrelated positions), with validation strictness, the eight-bullet and 25% repair bounds and every provider-facing default unchanged. See the [0.4.5 release record](docs/releases/0.4.5.md), the [0.4.4 release record](docs/releases/0.4.4.md), the [0.4.3 release record](docs/releases/0.4.3.md), the [0.4.2 release record](docs/releases/0.4.2.md), the [0.4.1 release record](docs/releases/0.4.1.md) and the [0.4.0 release record](docs/releases/0.4.0.md), [ADR 066](docs/ADR/066-quoting-downgrade-and-span-adjacency.md), [ADR 065](docs/ADR/065-exact-value-escaped-equivalence.md), [ADR 064](docs/ADR/064-per-project-databases-with-shared-calibration.md) and [model-awareness validation](docs/MODEL_AWARENESS.md).
|
|
20
20
|
|
|
21
21
|
**Current compaction defaults:** `compaction.directUpdate=true`, `compaction.inputBudget="context"`, `compaction.segmentTargetTokens=30000`, `compaction.maxRequestInputTokens=64000`, `compaction.maxOperationInputTokens=2000000`, `compaction.maxConcurrentSegments=2`. Every DS4 provider attempt is bounded by the effective request limit, and the operation limit includes retries; `inputBudget="summary"` remains an explicit throughput-oriented opt-in. Existing compaction/master switches still apply. See [latency controls and compatibility](docs/COMPACTION.md#latency-controls). No real-provider speedup is claimed from mock tests. The five optional editing/reading/artifact/job features introduced in `0.3.4` remain default-off.
|
|
22
22
|
|
|
@@ -515,6 +515,8 @@ scripts package and release-readiness checks
|
|
|
515
515
|
- [Roadmap 0.2.0](docs/ROADMAP_0.2.0.md)
|
|
516
516
|
- [Release process](docs/RELEASING.md)
|
|
517
517
|
- [0.2.0 release readiness](docs/RELEASE_READINESS_0.2.0.md)
|
|
518
|
+
- [0.4.5 release notes](docs/releases/0.4.5.md)
|
|
519
|
+
- [0.4.4 release notes](docs/releases/0.4.4.md)
|
|
518
520
|
- [0.4.3 release notes](docs/releases/0.4.3.md)
|
|
519
521
|
- [0.4.2 release notes](docs/releases/0.4.2.md)
|
|
520
522
|
- [0.4.1 release notes](docs/releases/0.4.1.md)
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# 065 — Accept canonical JSON-escaped exact values in compaction summary validation
|
|
2
|
+
|
|
3
|
+
**Date:** 2026-09-27
|
|
4
|
+
**Status:** Accepted
|
|
5
|
+
**Related:** [061](061-compaction-latency.md)
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
|
|
9
|
+
Every compaction summary is validated against the segment evidence: a backticked
|
|
10
|
+
exact value is accepted only when it occurs literally in the sanitized segment
|
|
11
|
+
source, in the ordered child-summary content, or in Pi's file-operation
|
|
12
|
+
inventory. Production sessions on separate hosts failed closed with
|
|
13
|
+
`compaction.custom_fallback`, `unsupported-exact-value`,
|
|
14
|
+
`repair=too-many-bullets` and observed counts of 30/20, 23/19, 19/15 and 17/11
|
|
15
|
+
unsupported spans and affected bullets, so each run fell back to Pi default
|
|
16
|
+
compaction unmodified.
|
|
17
|
+
|
|
18
|
+
The class-only report added in 0.4.2, made interpretable in 0.4.3, attributed
|
|
19
|
+
the next observed run (16 spans across 12 bullets): `escaped-form-present` 11,
|
|
20
|
+
`not-classified-partial` 4, `not-classified-length` 1, and no `no-near-miss`
|
|
21
|
+
entry. Shapes (`quote` 11, `colon` 11, `json-punctuation` 9, no `backslash`) and
|
|
22
|
+
the absence of escapes inside the rejected spans show decoded values, not
|
|
23
|
+
identifiers: the summarizer quoted the readable value while the evidence holds
|
|
24
|
+
its JSON-encoded rendering. The prompt rule added in 0.4.1 could not address
|
|
25
|
+
that, and it should not have to: decoding JSON escapes while quoting a value is
|
|
26
|
+
a reasonable rendering choice, not a fabrication.
|
|
27
|
+
|
|
28
|
+
## Decision
|
|
29
|
+
|
|
30
|
+
`unsupportedExactMatches` accepts a backticked value when it occurs literally in
|
|
31
|
+
the evidence, either as written or in its canonical JSON-escaped rendering
|
|
32
|
+
(`jsonEscaped`, the same transform the diagnostics classifier uses for
|
|
33
|
+
`escaped-form-present`). The rule is unconditional and adds no configuration
|
|
34
|
+
key. The reverse direction is deliberately not accepted: an escaped span whose
|
|
35
|
+
raw form is present stays unsupported and is still reported as
|
|
36
|
+
`unescaped-form-present`.
|
|
37
|
+
|
|
38
|
+
Canonical JSON escaping is injective and reversible, so a decoded value can only
|
|
39
|
+
pass when its encoded text is literally present in the evidence. The decision
|
|
40
|
+
widens the accepted rendering, never the evidence: invented values, spans
|
|
41
|
+
assembled from separately present parts, single-character variants, the
|
|
42
|
+
eight-bullet and 25% repair bounds and the fail-closed fallback are unchanged.
|
|
43
|
+
|
|
44
|
+
## Consequences
|
|
45
|
+
|
|
46
|
+
- A span whose evidence is stored JSON-encoded now validates, and its bullet
|
|
47
|
+
survives instead of being pruned or forcing the bounded repair.
|
|
48
|
+
- `escaped-form-present` becomes unreachable in practice: validation and the
|
|
49
|
+
classifier share the predicate, so such spans no longer reach the classifier.
|
|
50
|
+
The class stays in the taxonomy for compatibility, and new reports are not
|
|
51
|
+
expected to contain it.
|
|
52
|
+
- The classifier's shared probe budget rises from 4000 to 24000 evidence-source
|
|
53
|
+
scans, so a report after this change can finish the near-miss analysis for the
|
|
54
|
+
spans that remain unsupported.
|
|
55
|
+
- No SQLite migration, schema change, canonical JSONL change, privacy consent
|
|
56
|
+
change, provider-facing default change or new configuration key.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# 066 — Grade the summarizer quoting fallback and separate adjacent from unrelated span composition
|
|
2
|
+
|
|
3
|
+
**Date:** 2026-09-27
|
|
4
|
+
**Status:** Accepted
|
|
5
|
+
**Related:** [061](061-compaction-latency.md), [065](065-exact-value-escaped-equivalence.md)
|
|
6
|
+
|
|
7
|
+
## Context
|
|
8
|
+
|
|
9
|
+
Compaction summary validation is fail-closed: a backticked exact value must occur
|
|
10
|
+
literally in the evidence, and a bounded repair removes at most eight whole
|
|
11
|
+
affected bullets. Production sessions kept failing closed with
|
|
12
|
+
`compaction.custom_fallback`, `unsupported-exact-value`, `repair=too-many-bullets`
|
|
13
|
+
and 30/20, 23/19, 19/15, 17/11, then 16/12 unsupported spans and affected
|
|
14
|
+
bullets.
|
|
15
|
+
|
|
16
|
+
The class-only report (§ 0.4.2–0.4.3) made the next observed run interpretable,
|
|
17
|
+
and ADR 065 removed 11 of its 16 spans as JSON-escape renderings. The production
|
|
18
|
+
report produced by 0.4.4 — 14 spans across 14 bullets, `spansClassifiedCheap: 0`,
|
|
19
|
+
`probesUsed: 11671` of 24000, `classificationComplete: true` — closed the
|
|
20
|
+
remaining attribution:
|
|
21
|
+
|
|
22
|
+
| Relation | Count |
|
|
23
|
+
| --- | --- |
|
|
24
|
+
| `composed-two-present-parts` | 9 |
|
|
25
|
+
| `no-near-miss` | 2 |
|
|
26
|
+
| `single-deletion-present` | 2 |
|
|
27
|
+
| `not-classified-length` | 1 |
|
|
28
|
+
|
|
29
|
+
No rendering class remained, so the escape path was exhausted; the dominant
|
|
30
|
+
residual cause is span composition, which is exactly what the 0.4.1 prompt rule
|
|
31
|
+
forbids. That rule is present in the prompt that produced the report and the
|
|
32
|
+
model still composes, which is why another repetition of the prohibition was not
|
|
33
|
+
the fix.
|
|
34
|
+
|
|
35
|
+
Composition mixes two situations that need opposite treatments. When the two
|
|
36
|
+
parts sit next to each other in one source, the span is a re-rendering of a
|
|
37
|
+
contiguous evidence region — the same shape of problem ADR 065 solved for
|
|
38
|
+
escapes. When the parts are found at unrelated positions, the span is an
|
|
39
|
+
association the evidence never contains, and accepting it would let a
|
|
40
|
+
plausible-looking but false pairing (`path: wrong-range`) through validation.
|
|
41
|
+
|
|
42
|
+
The prompt offered the model exactly one escape hatch from composing: omit the
|
|
43
|
+
whole bullet. Discarding a fact is expensive, so composing was the cheaper
|
|
44
|
+
choice. The instrumented evidence cannot by itself tell which composition kind
|
|
45
|
+
occurs, because the classifier only established that both parts are present
|
|
46
|
+
somewhere.
|
|
47
|
+
|
|
48
|
+
## Decision
|
|
49
|
+
|
|
50
|
+
1. The summarizer prompt keeps the prohibition but replaces the single drastic
|
|
51
|
+
fallback with a graded ladder: backtick only the fragments that are themselves
|
|
52
|
+
contiguous, with the joining text outside the backticks; if no fragment is
|
|
53
|
+
contiguous on its own, write the value as ordinary text without backticks and
|
|
54
|
+
keep the bullet; omit the bullet only when the fact itself has no support in
|
|
55
|
+
the evidence.
|
|
56
|
+
2. Diagnostics split the composition class: `composed-adjacent-present` when one
|
|
57
|
+
corpus source holds the two parts with nothing but joining punctuation and
|
|
58
|
+
spaces between them (at most the span's own separator length plus two
|
|
59
|
+
characters, and no letters, digits or line breaks), and
|
|
60
|
+
`composed-two-present-parts` otherwise. Both are class-only, bounded, and
|
|
61
|
+
observation-only.
|
|
62
|
+
3. The eight-bullet repair bound and the 25% removal bound are unchanged. A
|
|
63
|
+
larger unsupported set still fails closed to Pi default compaction: pruning
|
|
64
|
+
more of a summary than the operator accepts is not a fallback remedy.
|
|
65
|
+
|
|
66
|
+
## Consequences
|
|
67
|
+
|
|
68
|
+
- The ladder can reduce the number of backticked exact values in a summary. That
|
|
69
|
+
is a change in what the model chooses to quote, not in what validation accepts:
|
|
70
|
+
the contract, the repair bounds and the fail-closed decision are untouched.
|
|
71
|
+
- The effect on the observed fallback is not verified by this change. The next
|
|
72
|
+
production report decides whether composition persists, and the new adjacency
|
|
73
|
+
class says whether a rendering-normalization rule on the ADR 065 pattern is
|
|
74
|
+
even possible: `composed-adjacent-present` is the only class for which it could
|
|
75
|
+
be safe, while `composed-two-present-parts` must never be accepted.
|
|
76
|
+
- No configuration key, no SQLite migration, no schema change, and no
|
|
77
|
+
provider-facing default change.
|
package/docs/ADR/README.md
CHANGED
|
@@ -68,5 +68,7 @@ The initial decisions from the development plan are accepted:
|
|
|
68
68
|
| [062](062-cache-aware-context-planning.md) | Opt-in cache-aware tail planning using model pricing and observed cache shares | Accepted |
|
|
69
69
|
| [063](063-fts-rowid-key-mappings.md) | Resolve FTS key deletes through rowid mapping tables | Accepted |
|
|
70
70
|
| [064](064-per-project-databases-with-shared-calibration.md) | Split project state into per-project databases and keep token calibration shared | Accepted |
|
|
71
|
+
| [065](065-exact-value-escaped-equivalence.md) | Accept canonical JSON-escaped exact values in compaction summary validation | Accepted |
|
|
72
|
+
| [066](066-quoting-downgrade-and-span-adjacency.md) | Grade the summarizer quoting fallback and separate adjacent from unrelated span composition | Accepted |
|
|
71
73
|
|
|
72
74
|
Each decision will receive a dedicated record when implementation pressure introduces alternatives or consequences not already covered by the development plan.
|
package/docs/COMPACTION.md
CHANGED
|
@@ -32,13 +32,13 @@ Fan-out and fan-in are bounded to 32 segment requests, 64 aggregate requests, an
|
|
|
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
|
|
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 literally in the serialized segment source, ordered child-summary content, or those known file-operation paths, either as written or in the canonical JSON-escaped rendering of the value. A decoded value whose encoded text is present in the evidence is accepted ([ADR 065](ADR/065-exact-value-escaped-equivalence.md)); the reverse direction — an escaped span whose raw form is present — remains unsupported and is reported as `unescaped-form-present`. 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 requires every backticked span to be one contiguous excerpt copied as-is and forbids assembling one span from separately supported values (a setting name with its value, a path with a line range, a command with its flags), and it gives the model a cheaper alternative than composing: backtick only the fragments that are themselves contiguous with the joining text outside the backticks, or write the value as ordinary text without backticks, keeping the bullet. A bullet is omitted only when the fact itself has no support in the evidence ([ADR 066](ADR/066-quoting-downgrade-and-span-adjacency.md)). 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. A direct update is validated against both the sanitized previous summary and new source, plus cumulative sanitized file evidence; previous-summary-only exact values remain valid evidence. Custom focus instructions are not factual evidence. 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
|
|
|
39
|
-
The same failure carries a class-only span report on the fallback warning (`unsupportedSpanClasses`): rejected-span count, affected bullets, length buckets, character shapes (spaces, backslashes, escape sequences, separators, quotes, typographic characters, JSON punctuation), and how each distinct span relates to the evidence — escaped or unescaped rendering, collapsed whitespace, case or typographic variant, one-character deletion, two separately present values joined into one span
|
|
39
|
+
The same failure carries a class-only span report on the fallback warning (`unsupportedSpanClasses`): rejected-span count, affected bullets, length buckets, character shapes (spaces, backslashes, escape sequences, separators, quotes, typographic characters, JSON punctuation), and how each distinct span relates to the evidence — escaped or unescaped rendering, collapsed whitespace, case or typographic variant, one-character deletion, two separately present values joined into one span — adjacent in one source with nothing but joining punctuation and spaces between them (`composed-adjacent-present`) or found at unrelated positions (`composed-two-present-parts`) — or no near-miss (every applicable lookup ran and found nothing). The adjacency question separates a join that re-renders a contiguous evidence region from an association the evidence never contains: a joiner gap holds no letters, digits or line breaks, so two parts on separate lines are not adjacent. The report contains class names and counters only, never span text, and the classifier is observation-only: it cannot change validation, repair bounds, or the fail-closed decision. It exists to separate a summarizer that invents values from one whose rendering or composition rules differ from the validation domain, which require opposite fixes. The first production report produced by the 0.4.4 diagnostics attributed 9 of 14 rejected spans to composition, 2 to a one-character deviation, 2 to absence and 1 to the length limit, with no rendering class left at all.
|
|
40
40
|
|
|
41
|
-
Three relations mark spans that were *not* analysed, and they must never be read as invention. `not-classified-length` means the span exceeds the near-miss length limit (96 characters); `not-classified-partial` means its share of the budget ran out; `not-classified-budget` means the shared budget was already exhausted. To keep the histogram interpretable, transformed-form lookups cover every distinct span before any near-miss analysis starts, and each near-miss candidate may spend only an equal share of what remains (at least 32 lookups, never more than the budget left). The report also carries `spansClassifiedCheap` (span occurrences attributed by a transformed-form relation), `corpusSources`, `probeBudget` and `probesUsed`, so a run can be read without guessing how much of the budget was consumed. `classificationComplete` is false when the shared budget or a per-span share stopped an analysis; a `not-classified-length` span does not clear it, because that limit is deterministic rather than a resource shortfall.
|
|
41
|
+
Three relations mark spans that were *not* analysed, and they must never be read as invention. `not-classified-length` means the span exceeds the near-miss length limit (96 characters); `not-classified-partial` means its share of the budget ran out; `not-classified-budget` means the shared budget was already exhausted. To keep the histogram interpretable, transformed-form lookups cover every distinct span before any near-miss analysis starts, and each near-miss candidate may spend only an equal share of what remains (at least 32 lookups, never more than the budget left). The report also carries `spansClassifiedCheap` (span occurrences attributed by a transformed-form relation), `corpusSources`, `probeBudget` and `probesUsed`, so a run can be read without guessing how much of the budget was consumed. The shared budget defaults to 24000 evidence-source scans, where one lookup scans every corpus source once. `escaped-form-present` is not expected in reports from 0.4.4 on: validation accepts the canonical escaped rendering and the classifier consumes the same predicate, so such spans no longer reach it; the class stays in the taxonomy for compatibility. `classificationComplete` is false when the shared budget or a per-span share stopped an analysis; a `not-classified-length` span does not clear it, because that limit is deterministic rather than a resource shortfall.
|
|
42
42
|
|
|
43
43
|
## Provenance and recovery
|
|
44
44
|
|
package/docs/releases/0.4.3.md
CHANGED
|
@@ -152,8 +152,19 @@ Limitations that remain:
|
|
|
152
152
|
requires a natural failure and is expected to appear on the next
|
|
153
153
|
`compaction.custom_fallback` warning.
|
|
154
154
|
|
|
155
|
-
## Publication
|
|
156
|
-
|
|
157
|
-
Published manually in dependency order
|
|
158
|
-
`
|
|
159
|
-
|
|
155
|
+
## Publication and registry verification
|
|
156
|
+
|
|
157
|
+
Published manually in dependency order from `928f1a4`: `ds4-context-core@0.4.3`,
|
|
158
|
+
then `ds4-context-reference-adapter@0.4.3`, then `ds4-context-engine@0.4.3`, all
|
|
159
|
+
with the default `latest` tag, after `npm run pack:check` on the same commit.
|
|
160
|
+
|
|
161
|
+
A first `npm run registry:check -- 0.4.3` failed with `ETARGET` because the local
|
|
162
|
+
npm cache still served the previous packument; `npm view --prefer-online`
|
|
163
|
+
already reported 0.4.3 with `latest` resolving to it for all three packages, and
|
|
164
|
+
the check passed when re-run against an empty cache directory: "Verified all DS4
|
|
165
|
+
registry packages at exact version 0.4.3".
|
|
166
|
+
|
|
167
|
+
Annotated tag `v0.4.3` and the GitHub Release were created from `928f1a4`. No
|
|
168
|
+
provider calls are involved in this release procedure; the classifier runs only
|
|
169
|
+
after a validation failure has already been decided, and no session data,
|
|
170
|
+
credentials, or provider payloads were read or written while preparing it.
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# Release 0.4.4 — Accept canonical JSON-escaped exact values
|
|
2
|
+
|
|
3
|
+
**Coordinated packages:** `ds4-context-core`, `ds4-context-reference-adapter`, and `ds4-context-engine` 0.4.4.
|
|
4
|
+
**Implementation commit:** `ad6e4c8`.
|
|
5
|
+
|
|
6
|
+
## Summary
|
|
7
|
+
|
|
8
|
+
Behavior patch. Compaction summary validation now accepts a backticked exact
|
|
9
|
+
value that occurs literally in the evidence in its canonical JSON-escaped
|
|
10
|
+
rendering, not only as written. The accepted rendering widens; the evidence does
|
|
11
|
+
not: canonical JSON escaping is injective, so a decoded value passes only when
|
|
12
|
+
its encoded text is literally present. The diagnostics probe budget rises from
|
|
13
|
+
4000 to 24000 evidence-source scans. The eight-bullet and 25% repair bounds, the
|
|
14
|
+
fail-closed fallback to Pi default compaction, the summarizer prompt, the SQLite
|
|
15
|
+
schema and every provider-facing default are unchanged.
|
|
16
|
+
|
|
17
|
+
## Changes
|
|
18
|
+
|
|
19
|
+
- `packages/core/src/compaction/summary-contract.ts`:
|
|
20
|
+
- `unsupportedExactMatches` also accepts a span whose `jsonEscaped` rendering
|
|
21
|
+
occurs literally in the segment source, the ordered child-summary content or
|
|
22
|
+
the file-operation inventory. `jsonEscaped` is the transform the diagnostics
|
|
23
|
+
classifier already used for `escaped-form-present`, so the accepted domain
|
|
24
|
+
and the reported class agree.
|
|
25
|
+
- `UNSUPPORTED_SPAN_PROBE_BUDGET` rises from 4000 to 24000 source scans.
|
|
26
|
+
- `tests/unit/summary-contract.test.ts`: acceptance for a decoded value whose
|
|
27
|
+
escaped rendering is present; continued rejection when the escaped rendering
|
|
28
|
+
is absent and for an escaped span whose raw form is present; the default budget
|
|
29
|
+
is 24000 and an explicit 4000 budget still saturates without overspending.
|
|
30
|
+
- `tests/integration/compaction.test.ts`: a segment whose evidence carries
|
|
31
|
+
literal JSON escapes and a summary that quotes the decoded value commits with
|
|
32
|
+
`validationStatus: "valid"` instead of falling back.
|
|
33
|
+
- `docs/COMPACTION.md`: the summary contract and the diagnostics section.
|
|
34
|
+
- `docs/ADR/065-exact-value-escaped-equivalence.md` records the decision.
|
|
35
|
+
|
|
36
|
+
## Why
|
|
37
|
+
|
|
38
|
+
Production sessions failed closed on `unsupported-exact-value` /
|
|
39
|
+
`repair=too-many-bullets` with 30/20, 23/19, 19/15, 17/11 and 16/12 unsupported
|
|
40
|
+
spans and affected bullets. The report added in 0.4.2 and made interpretable in
|
|
41
|
+
0.4.3 attributed the last observed run: 11 of 16 spans were
|
|
42
|
+
`escaped-form-present`, no span was established as absent (`no-near-miss` was
|
|
43
|
+
zero), and the shape histogram (`quote` 11, `colon` 11, `json-punctuation` 9, no
|
|
44
|
+
`backslash`) showed decoded values rather than identifiers. The values were
|
|
45
|
+
present in the evidence; only the rendering differed. The remaining candidates
|
|
46
|
+
for the five unanalysed spans were model-dependent and unverifiable offline,
|
|
47
|
+
while escape equivalence is deterministic and testable: the new integration test
|
|
48
|
+
fails on 0.4.3 and passes on 0.4.4.
|
|
49
|
+
|
|
50
|
+
## Privacy and safety
|
|
51
|
+
|
|
52
|
+
- Acceptance still requires a literal occurrence in the evidence, and canonical
|
|
53
|
+
JSON escaping is injective, so no invented value can pass; the validation path
|
|
54
|
+
reads the same sanitized sources as before.
|
|
55
|
+
- Diagnostics stay class-only: the budget change alters how many lookups the
|
|
56
|
+
classifier may spend, never what it emits. The probe runs only after a
|
|
57
|
+
validation failure has already been decided.
|
|
58
|
+
- No provider call, network access or configuration change is involved in this
|
|
59
|
+
release.
|
|
60
|
+
|
|
61
|
+
## Compatibility and persistence
|
|
62
|
+
|
|
63
|
+
- No migrations, no schema change (still 16), no new configuration key, and no
|
|
64
|
+
change to any provider-facing default.
|
|
65
|
+
- The summarizer prompt is unchanged; only the accepted rendering widens.
|
|
66
|
+
- `escaped-form-present` stays in the report taxonomy but is no longer expected
|
|
67
|
+
in reports, because validation accepts the same canonical rendering that the
|
|
68
|
+
classifier probes.
|
|
69
|
+
|
|
70
|
+
## Measured scope and limitations
|
|
71
|
+
|
|
72
|
+
The effect on a real session is not verified by this release. If escape
|
|
73
|
+
equivalence was the binding cause, the next production compaction should not
|
|
74
|
+
produce `compaction.custom_fallback`; if one appears, its report now covers only
|
|
75
|
+
spans that are not canonical-escape-equivalent, with a budget large enough to
|
|
76
|
+
finish the near-miss analysis for a handful of candidates. The 25% removal bound
|
|
77
|
+
and the fail-closed fallback remain in force, so an unsupported set that exceeds
|
|
78
|
+
the repair bounds still falls back to Pi default compaction.
|
|
79
|
+
|
|
80
|
+
## Validation
|
|
81
|
+
|
|
82
|
+
On Node 26.5.1 the release passed `npm run check` (99 Vitest files, 632 tests,
|
|
83
|
+
TypeScript builds and root typecheck), deterministic `npm run quality:compare`
|
|
84
|
+
(candidate `0.9875` against baseline `0.808156`), `npm run schema:context-persistence`
|
|
85
|
+
(`passed: true`), and `npm run pack:check` in a clean consumer for all three
|
|
86
|
+
packages at 0.4.4 (247 core files, 7 reference-adapter files, 103 extension
|
|
87
|
+
files). No provider calls are involved in this release procedure.
|
|
88
|
+
|
|
89
|
+
## Publication and registry verification
|
|
90
|
+
|
|
91
|
+
Published manually in dependency order from `10f0e0c`: `ds4-context-core@0.4.4`,
|
|
92
|
+
then `ds4-context-reference-adapter@0.4.4`, then `ds4-context-engine@0.4.4`, all
|
|
93
|
+
with the default `latest` tag, after `npm run pack:check` on the same commit.
|
|
94
|
+
|
|
95
|
+
The first seven `npm run registry:check -- 0.4.4` attempts failed while the
|
|
96
|
+
published metadata was still propagating; the eighth, some minutes later,
|
|
97
|
+
reported "Verified all DS4 registry packages at exact version 0.4.4". For all
|
|
98
|
+
three packages `npm view <package> dist-tags.latest` resolves to 0.4.4.
|
|
99
|
+
|
|
100
|
+
Annotated tag `v0.4.4` and the GitHub Release were created from `10f0e0c`. No
|
|
101
|
+
provider calls are involved in this release procedure; the classifier runs only
|
|
102
|
+
after a validation failure has already been decided, and no session data,
|
|
103
|
+
credentials, or provider payloads were read or written while preparing it.
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# Release 0.4.5 — Graded quoting fallback and adjacent-vs-unrelated composition
|
|
2
|
+
|
|
3
|
+
**Coordinated packages:** `ds4-context-core`, `ds4-context-reference-adapter`, and `ds4-context-engine` 0.4.5.
|
|
4
|
+
**Implementation commit:** `91a700a`.
|
|
5
|
+
|
|
6
|
+
## Summary
|
|
7
|
+
|
|
8
|
+
Behavior and diagnostics patch. The compaction summarizer prompt no longer
|
|
9
|
+
forces an all-or-nothing choice between quoting a composite span and dropping the
|
|
10
|
+
bullet: it now tells the model to backtick only the fragments that are themselves
|
|
11
|
+
contiguous, and otherwise to keep the fact as ordinary text without backticks.
|
|
12
|
+
The diagnostics report separates `composed-adjacent-present` — the two parts sit
|
|
13
|
+
next to each other in one evidence source with nothing but joining punctuation
|
|
14
|
+
and spaces between them — from `composed-two-present-parts`, where the parts are
|
|
15
|
+
found at unrelated positions. Validation strictness, the eight-bullet and 25%
|
|
16
|
+
repair bounds, the 25% removal bound, the fail-closed fallback to Pi default
|
|
17
|
+
compaction, the SQLite schema and every provider-facing default are unchanged.
|
|
18
|
+
|
|
19
|
+
## Changes
|
|
20
|
+
|
|
21
|
+
- `packages/core/src/compaction/summary-contract.ts`:
|
|
22
|
+
- `buildSummaryPrompt` replaces the single "omit the whole bullet" escape with a
|
|
23
|
+
graded ladder: keep every backticked span one contiguous excerpt; when the
|
|
24
|
+
complete value is not one contiguous excerpt, backtick only the fragments
|
|
25
|
+
that are themselves contiguous with the joining text outside the backticks;
|
|
26
|
+
if no fragment is contiguous on its own, write the value as ordinary text
|
|
27
|
+
without backticks and keep the bullet; omit the bullet only when the fact
|
|
28
|
+
itself has no support in the evidence. The prohibition on assembling a span
|
|
29
|
+
from separately present values is unchanged and now carries the explicit
|
|
30
|
+
counter-examples (`a setting name with its value`, `a path with a line
|
|
31
|
+
range`, `a command with its flags`).
|
|
32
|
+
- The diagnostics classifier adds the relation `composed-adjacent-present`. A
|
|
33
|
+
composition is adjacent when one corpus source holds the two parts with at
|
|
34
|
+
most the span's own separator length plus two characters between them, in a
|
|
35
|
+
gap that contains no letters, digits or line breaks — so two parts on
|
|
36
|
+
separate lines are not adjacent. Adjacency lookups are bounded
|
|
37
|
+
(`MAX_ADJACENT_JOIN_PROBES` 8 per span, `MAX_JOIN_OCCURRENCES` 64
|
|
38
|
+
occurrences per source) and cost the same budget unit as every other lookup.
|
|
39
|
+
- `composed-two-present-parts` keeps its meaning for non-adjacent joins; both
|
|
40
|
+
classes are class-only and observation-only.
|
|
41
|
+
- `tests/unit/summary-contract.test.ts`: prompt assertions follow the new
|
|
42
|
+
wording, plus two cases that pin the sub-classification — a JSON-rendered pair
|
|
43
|
+
(`{"compaction.model": "deepseek-flash"}` against
|
|
44
|
+
`compaction.model: deepseek-flash`) reports `composed-adjacent-present`, and
|
|
45
|
+
the same span against a source holding the two parts on separate lines reports
|
|
46
|
+
`composed-two-present-parts`.
|
|
47
|
+
- `docs/COMPACTION.md`: the summary contract and the diagnostics section.
|
|
48
|
+
- `docs/ADR/066-quoting-downgrade-and-span-adjacency.md` records the decision.
|
|
49
|
+
|
|
50
|
+
## Why
|
|
51
|
+
|
|
52
|
+
The class-only report added in 0.4.2, made interpretable in 0.4.3 and re-budgeted
|
|
53
|
+
in 0.4.4, produced its first fully analysed production run: 14 rejected spans
|
|
54
|
+
across 14 bullets, `spansClassifiedCheap: 0`, `probesUsed: 11671` of 24000,
|
|
55
|
+
`classificationComplete: true`, `trigger: manual`.
|
|
56
|
+
|
|
57
|
+
| Relation | Count |
|
|
58
|
+
| --- | --- |
|
|
59
|
+
| `composed-two-present-parts` | 9 |
|
|
60
|
+
| `no-near-miss` | 2 |
|
|
61
|
+
| `single-deletion-present` | 2 |
|
|
62
|
+
| `not-classified-length` | 1 |
|
|
63
|
+
|
|
64
|
+
No rendering class remained, so ADR 065 exhausted the escape path. The dominant
|
|
65
|
+
residual cause is composition — the exact conduct the 0.4.1 prompt rule forbids —
|
|
66
|
+
and that rule was in the prompt this model ran with, so repeating the prohibition
|
|
67
|
+
was not the fix. The remaining hypothesis is the cost asymmetry: composing was
|
|
68
|
+
the only alternative to discarding a whole fact. This release removes that
|
|
69
|
+
asymmetry and, at the same time, adds the one measurement that decides whether a
|
|
70
|
+
safe acceptance rule can ever exist for composition: adjacent joins are
|
|
71
|
+
contiguous evidence regions the span re-rendered, while unrelated joins are
|
|
72
|
+
associations the evidence never contains, and only the first kind could be
|
|
73
|
+
accepted on the ADR 065 pattern.
|
|
74
|
+
|
|
75
|
+
The eight-bullet repair bound is deliberately untouched. It was the mechanism
|
|
76
|
+
that turned 14 affected bullets into a total fallback, and an explicit operator
|
|
77
|
+
decision on 2026-09-27 kept it: removing invalid bullets without a count limit
|
|
78
|
+
could silently delete a large share of a summary, and with these counts the 25%
|
|
79
|
+
removal bound would likely refuse as well, so the change would not reliably end
|
|
80
|
+
the fallback.
|
|
81
|
+
|
|
82
|
+
## Privacy and safety
|
|
83
|
+
|
|
84
|
+
- The report stays class-only. The new relation is one more fixed class name; no
|
|
85
|
+
span text, fragment text, evidence text or hash of either is added to logs,
|
|
86
|
+
warnings, or errors.
|
|
87
|
+
- The prompt change alters what the model is instructed to quote. It does not
|
|
88
|
+
change what validation accepts, the repair bounds, the fail-closed decision, or
|
|
89
|
+
the privacy path; no provider call, network access or configuration change is
|
|
90
|
+
involved in this release.
|
|
91
|
+
- Fewer backticked spans is a possible outcome of the ladder. That is a rendering
|
|
92
|
+
choice made by the summarizer, not a validator relaxation: an unsupported
|
|
93
|
+
backticked value is still rejected exactly as before.
|
|
94
|
+
|
|
95
|
+
## Compatibility and persistence
|
|
96
|
+
|
|
97
|
+
- No migrations, no schema change (still 16), no new configuration key, and no
|
|
98
|
+
change to any provider-facing default.
|
|
99
|
+
- The report shape is additive: `composed-adjacent-present` is a new key in
|
|
100
|
+
`relations`, and existing readers keep working. A reader that previously saw
|
|
101
|
+
only `composed-two-present-parts` will now see the adjacent cases split out.
|
|
102
|
+
- `chars-v1` remains the default estimator, `modelAwareness.autoTune` and DS4
|
|
103
|
+
native continuation stay disabled, `storage.scope` keeps its `project` default.
|
|
104
|
+
|
|
105
|
+
## Measured scope and limitations
|
|
106
|
+
|
|
107
|
+
The effect on the observed fallback is not verified in a real session by this
|
|
108
|
+
release. The change is a prompt instruction, so the outcome depends on the
|
|
109
|
+
summarizer model's compliance: 0.4.1 already showed that a prohibition alone is
|
|
110
|
+
not followed. Expected observations for the next production compaction:
|
|
111
|
+
|
|
112
|
+
| Observation | Reading |
|
|
113
|
+
| --- | --- |
|
|
114
|
+
| `compaction.custom_fallback` absent | the graded fallback ended the composition |
|
|
115
|
+
| composition still present, mostly `composed-adjacent-present` | composition persists and a rendering-normalization rule is technically possible |
|
|
116
|
+
| composition still present, mostly `composed-two-present-parts` | composition persists and no acceptance rule can be safe; only the summarizer model, its reasoning level or the repair policy remain |
|
|
117
|
+
| fewer backticked values overall | the ladder worked, with the expected rendering cost in the summary |
|
|
118
|
+
|
|
119
|
+
## Validation
|
|
120
|
+
|
|
121
|
+
On Node 26.5.1 the release passed `npm run check` (99 Vitest files, 634 tests,
|
|
122
|
+
TypeScript builds and root typecheck), deterministic `npm run quality:compare`
|
|
123
|
+
(candidate `0.9875` against baseline `0.808156`), `npm run schema:context-persistence`
|
|
124
|
+
(`passed: true`), and `npm run pack:check` in a clean consumer for all three
|
|
125
|
+
packages at 0.4.5 (247 core files, 7 reference-adapter files, 104 extension
|
|
126
|
+
files). No provider calls are involved in this release procedure.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ds4-context-engine",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.5",
|
|
4
4
|
"description": "Non-destructive, provider-independent context management for Pi.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
]
|
|
64
64
|
},
|
|
65
65
|
"dependencies": {
|
|
66
|
-
"ds4-context-core": "0.4.
|
|
66
|
+
"ds4-context-core": "0.4.5",
|
|
67
67
|
"js-tiktoken": "1.0.21"
|
|
68
68
|
},
|
|
69
69
|
"peerDependencies": {
|