ds4-context-engine 0.3.3 → 0.3.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 +47 -6
- package/docs/ADR/059-optional-anchored-editing.md +51 -0
- package/docs/ADR/060-optional-portable-agent-tools.md +38 -0
- package/docs/ADR/061-compaction-latency.md +21 -0
- package/docs/ADR/README.md +3 -0
- package/docs/ANCHORED_EDITING.md +144 -0
- package/docs/ARCHITECTURE.md +38 -0
- package/docs/COMPACTION.md +33 -11
- package/docs/PORTABLE_AGENT_TOOLS.md +86 -0
- package/docs/releases/0.3.3.md +22 -2
- package/docs/releases/0.3.4.md +81 -0
- package/docs/releases/0.3.5.md +70 -0
- package/package.json +2 -2
- package/src/extension/adaptive-read-tool.ts +47 -0
- package/src/extension/anchored-edit-tool.ts +157 -0
- package/src/extension/anchored-edit.ts +53 -0
- package/src/extension/bash-job-tool.ts +149 -0
- package/src/extension/commands.ts +12 -0
- package/src/extension/index.ts +18 -0
- package/src/extension/post-edit-report.ts +134 -0
- package/src/extension/runtime.ts +10 -5
- package/src/pi-adapter/compaction-coordinator.ts +168 -76
- package/src/pi-adapter/compaction-workers.ts +43 -0
- package/src/pi-adapter/summary-generator.ts +5 -6
- package/src/pi-adapter/version.ts +1 -1
- package/src/tools/bash-job-manager.ts +176 -0
package/README.md
CHANGED
|
@@ -16,7 +16,9 @@ bounded active context with provenance
|
|
|
16
16
|
Pi provider
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
> **Project status:**
|
|
19
|
+
> **Project status:** The coordinated `0.3.5` release adds bounded compaction optimizations: one validated previous-summary/source update when the complete prompt fits, a dedicated calibrated input budget, up to two concurrent segments, and metadata-only phase timings in `/context compaction`. Canonical history, SQLite schema 15 and runtime contracts remain unchanged; Pi remains pinned to `0.84.3`. See the [0.3.5 release record](docs/releases/0.3.5.md) for validation and publication status.
|
|
20
|
+
|
|
21
|
+
**New compaction defaults:** `compaction.directUpdate=true`, `compaction.inputBudget="summary"`, `compaction.maxConcurrentSegments=2`. Existing compaction/master switches still apply. See [latency controls and compatibility](docs/COMPACTION.md#latency-controls) for the legacy-path settings. 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.
|
|
20
22
|
|
|
21
23
|
## Why DS4
|
|
22
24
|
|
|
@@ -87,12 +89,12 @@ Install the latest stable public npm package with:
|
|
|
87
89
|
pi install npm:ds4-context-engine
|
|
88
90
|
```
|
|
89
91
|
|
|
90
|
-
The
|
|
92
|
+
The three packages (`ds4-context-engine`, `ds4-context-core`, and `ds4-context-reference-adapter`) are released together with the same exact version. Both adapters require the matching core version. See [0.3.5](docs/releases/0.3.5.md) for this release's changes and compatibility.
|
|
91
93
|
|
|
92
94
|
To dogfood the beta without replacing a global stable installation, pin the exact version in a disposable project:
|
|
93
95
|
|
|
94
96
|
```bash
|
|
95
|
-
pi install -l npm:ds4-context-engine@0.3.0-beta.
|
|
97
|
+
pi install -l npm:ds4-context-engine@0.3.0-beta.3
|
|
96
98
|
```
|
|
97
99
|
|
|
98
100
|
Follow the [0.3 beta dogfooding runbook](docs/DOGFOODING_0.3.0_BETA.md); use synthetic data and a dedicated session directory.
|
|
@@ -209,7 +211,7 @@ Valid privacy classifications are `normal`, `internal`, `sensitive` and `local-o
|
|
|
209
211
|
|
|
210
212
|
### LLM-callable tools
|
|
211
213
|
|
|
212
|
-
DS4 registers two model-callable tools:
|
|
214
|
+
DS4 registers two model-callable tools by default:
|
|
213
215
|
|
|
214
216
|
| Tool | Purpose |
|
|
215
217
|
| --- | --- |
|
|
@@ -220,6 +222,24 @@ DS4 registers two model-callable tools:
|
|
|
220
222
|
|
|
221
223
|
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
224
|
|
|
225
|
+
**Optional anchored editing:** `/context config set editing.anchored true`, then
|
|
226
|
+
`/reload`, enables a same-name `edit` wrapper. Use `head[upto]tail` in `oldText` to
|
|
227
|
+
replace an inclusive range without repeating its intermediate old content. Exact
|
|
228
|
+
anchors are validated inside Pi's native mutation queue; ordinary calls and diff
|
|
229
|
+
feedback remain native. All edits in a batch containing anchors must match exactly.
|
|
230
|
+
Use per-edit `literal: true` for real marker text.
|
|
231
|
+
Disabled by default; no inference-time forcer or provider change is involved.
|
|
232
|
+
See [`docs/ANCHORED_EDITING.md`](docs/ANCHORED_EDITING.md) for semantics and limits.
|
|
233
|
+
|
|
234
|
+
**Other optional agent tools:** `editing.postEditReport` adds bounded old/new line
|
|
235
|
+
ranges and updated context; `reading.adaptive` chooses model-window-aware default
|
|
236
|
+
read limits; `artifacts.adaptiveBudget` lowers inline/excerpt caps under context
|
|
237
|
+
pressure; `jobs.enabled` exposes confirmed, session-owned local `bash_job`
|
|
238
|
+
start/status/stop/list operations. All default off and require session reload after
|
|
239
|
+
configuration changes. Jobs are a separate module, not a replacement for `bash`.
|
|
240
|
+
See [`docs/PORTABLE_AGENT_TOOLS.md`](docs/PORTABLE_AGENT_TOOLS.md) for activation,
|
|
241
|
+
limits, privacy and lifecycle behavior.
|
|
242
|
+
|
|
223
243
|
Learned-ranking feedback and local training are explicit:
|
|
224
244
|
|
|
225
245
|
```text
|
|
@@ -250,6 +270,16 @@ The following example shows the main configuration groups. Omitted values use th
|
|
|
250
270
|
"maxProjectTokens": 20000,
|
|
251
271
|
"maxSummaryTokens": 12000
|
|
252
272
|
},
|
|
273
|
+
"editing": {
|
|
274
|
+
"anchored": false,
|
|
275
|
+
"postEditReport": false
|
|
276
|
+
},
|
|
277
|
+
"reading": {
|
|
278
|
+
"adaptive": false
|
|
279
|
+
},
|
|
280
|
+
"jobs": {
|
|
281
|
+
"enabled": false
|
|
282
|
+
},
|
|
253
283
|
"retrieval": {
|
|
254
284
|
"exact": true,
|
|
255
285
|
"fts": true,
|
|
@@ -287,6 +317,7 @@ The following example shows the main configuration groups. Omitted values use th
|
|
|
287
317
|
},
|
|
288
318
|
"artifacts": {
|
|
289
319
|
"enabled": true,
|
|
320
|
+
"adaptiveBudget": false,
|
|
290
321
|
"maxInlineToolResultChars": 12000,
|
|
291
322
|
"maxArtifactBytes": 100000000,
|
|
292
323
|
"maxSearchBytes": 50000000,
|
|
@@ -299,7 +330,10 @@ The following example shows the main configuration groups. Omitted values use th
|
|
|
299
330
|
"mode": "hierarchical",
|
|
300
331
|
"validate": true,
|
|
301
332
|
"segmentTargetTokens": 30000,
|
|
302
|
-
"preserveRecentVerbatim": true
|
|
333
|
+
"preserveRecentVerbatim": true,
|
|
334
|
+
"directUpdate": true,
|
|
335
|
+
"inputBudget": "summary",
|
|
336
|
+
"maxConcurrentSegments": 2
|
|
303
337
|
},
|
|
304
338
|
"privacy": {
|
|
305
339
|
"enabled": false,
|
|
@@ -477,8 +511,15 @@ scripts package and release-readiness checks
|
|
|
477
511
|
- [Roadmap 0.2.0](docs/ROADMAP_0.2.0.md)
|
|
478
512
|
- [Release process](docs/RELEASING.md)
|
|
479
513
|
- [0.2.0 release readiness](docs/RELEASE_READINESS_0.2.0.md)
|
|
514
|
+
- [0.3.5 release notes](docs/releases/0.3.5.md)
|
|
515
|
+
- [0.3.4 release notes](docs/releases/0.3.4.md)
|
|
516
|
+
- [0.3.3 release notes](docs/releases/0.3.3.md)
|
|
517
|
+
- [0.3.2 release notes](docs/releases/0.3.2.md)
|
|
518
|
+
- [0.3.1 release notes](docs/releases/0.3.1.md)
|
|
519
|
+
- [0.3.0 release notes](docs/releases/0.3.0.md)
|
|
480
520
|
- [0.2.0 release notes](docs/releases/0.2.0.md)
|
|
481
521
|
- [0.2.0-rc.1 release notes](docs/releases/0.2.0-rc.1.md)
|
|
522
|
+
- [0.3.0-beta.3 prerelease notes](docs/releases/0.3.0-beta.3.md)
|
|
482
523
|
- [0.3.0-beta.2 prerelease notes](docs/releases/0.3.0-beta.2.md)
|
|
483
524
|
- [0.3.0-beta.1 prerelease notes](docs/releases/0.3.0-beta.1.md)
|
|
484
525
|
- [0.3.0-alpha.5 prerelease notes](docs/releases/0.3.0-alpha.5.md)
|
|
@@ -493,7 +534,7 @@ scripts package and release-readiness checks
|
|
|
493
534
|
|
|
494
535
|
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.
|
|
495
536
|
|
|
496
|
-
The [0.2.0 roadmap](docs/ROADMAP_0.2.0.md) is complete.
|
|
537
|
+
The [0.2.0 roadmap](docs/ROADMAP_0.2.0.md) is complete. The stable 0.3 line carries forward the [context persistence tool](docs/CONTEXT_PERSISTENCE_TOOL.md), privacy-safe [compaction](docs/COMPACTION.md), bounded persisted manifests, cooperative client leases and recoverable offline maintenance. Version 0.3.5 adds bounded compaction updates, summary input headroom, concurrent segments and phase timings. The opt-in [anchored editing](docs/ANCHORED_EDITING.md) and [portable agent tools](docs/PORTABLE_AGENT_TOOLS.md) from 0.3.4 remain default-off, without backend rewind, forced sampling or operational KV integration. Confirmation, provenance, Pi fallback and canonical/configuration/SQLite/runtime contracts remain unchanged. The [0.2 readiness record](docs/RELEASE_READINESS_0.2.0.md) remains the compatibility baseline; the lexical planner stays available as the deterministic fallback.
|
|
497
538
|
|
|
498
539
|
## Contributing
|
|
499
540
|
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# ADR 059 — Optional execution-time anchored editing
|
|
2
|
+
|
|
3
|
+
Status: Accepted
|
|
4
|
+
|
|
5
|
+
## Context
|
|
6
|
+
|
|
7
|
+
DS4's standalone agent supports `head[upto]tail` replacement and an optional
|
|
8
|
+
inference-time marker forcer. The former is portable tool semantics; the latter
|
|
9
|
+
requires backend control over generation state. Pi already provides batch edits,
|
|
10
|
+
mutation serialization, normalization, cancellation and diff feedback.
|
|
11
|
+
|
|
12
|
+
## Decision
|
|
13
|
+
|
|
14
|
+
- Add the default-off `editing.anchored` configuration key, gated by the DS4 master
|
|
15
|
+
switch and loaded through existing trusted configuration handling.
|
|
16
|
+
- Register a same-name `edit` override only when enabled and native edit is not
|
|
17
|
+
already replaced. Do not introduce an additional tool or force tool activation.
|
|
18
|
+
- Support one marker between nonempty, non-whitespace exact anchors, inclusive
|
|
19
|
+
replacement and suffix-only tail uniqueness. Add per-edit `literal: true` to
|
|
20
|
+
escape real marker text. Preserve native edit behavior without marker syntax.
|
|
21
|
+
- Expand anchors using private copies inside native `EditOperations.readFile`,
|
|
22
|
+
under Pi's own mutation queue, then delegate batch validation and writing to
|
|
23
|
+
`createEditToolDefinition`. Do not copy Pi's editing implementation or expand in
|
|
24
|
+
an unqueued `tool_call` hook.
|
|
25
|
+
- Require exact matching for all edits in a batch containing anchors: native
|
|
26
|
+
fuzzy fallback changes the whole batch's coordinate space and can relocate an
|
|
27
|
+
exact anchored span. Marker-free calls retain native fuzzy behavior.
|
|
28
|
+
- Keep native normalized ambiguity checks, even when stricter than exact anchor
|
|
29
|
+
validation. Invalid anchored edits fail closed, without a fallback to a broader
|
|
30
|
+
match. ADR 008's context-planning fallback is not permission to guess file edits.
|
|
31
|
+
- Preserve native diff results and append compact original-line range metadata.
|
|
32
|
+
Skip marker-unaware native previews until the actual result diff is available.
|
|
33
|
+
- Restore the native definition if the same extension instance later loads
|
|
34
|
+
disabled configuration; a fresh disabled load registers no editing override.
|
|
35
|
+
|
|
36
|
+
## Consequences
|
|
37
|
+
|
|
38
|
+
No provider change, Pi fork or dependency upgrade is required for execution-time
|
|
39
|
+
anchors. Only the configuration shape enters the portable core; filesystem/tool
|
|
40
|
+
integration stays in the Pi extension. Existing configuration defaults otherwise
|
|
41
|
+
remain unchanged, and the additive compatibility golden is updated.
|
|
42
|
+
|
|
43
|
+
The adapter relies on native edit reading through the supplied operations before
|
|
44
|
+
matching the provided edit array, while holding its shared queue. Tests against
|
|
45
|
+
Pi 0.84.3 pin that ordering and cancellation behavior. Dependency upgrades must
|
|
46
|
+
re-run these contracts. Other edit overrides, external editors/processes, atomic
|
|
47
|
+
writes and backend generation-state control remain outside the guarantee.
|
|
48
|
+
|
|
49
|
+
See [usage and limitations](../ANCHORED_EDITING.md). No automatic marker forcer,
|
|
50
|
+
constrained grammar, live configuration activation or measured provider savings
|
|
51
|
+
are part of this decision.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# ADR 060 — Optional portable DS4 agent improvements
|
|
2
|
+
|
|
3
|
+
Status: accepted and implemented; included in the coordinated 0.3.4 release. Backend integration remains excluded.
|
|
4
|
+
|
|
5
|
+
## Boundary
|
|
6
|
+
|
|
7
|
+
Pi remains the agent runtime and JSONL remains canonical history. These changes add optional tool behavior, not another agent loop. No inference rewind, forced sampling, native KV handles, database migration or dependency upgrade is included.
|
|
8
|
+
|
|
9
|
+
Four independently default-off switches, also gated by `enabled`:
|
|
10
|
+
|
|
11
|
+
- `editing.postEditReport`: bounded report from the actual native unified patch, including changed old/new ranges, line delta and post-edit context. Works independently of `editing.anchored`.
|
|
12
|
+
- `reading.adaptive`: choose the default `read` limit from the execution-time model window (120 / 240 / 500 lines at <=8192 / <=16384 / larger windows). Explicit limits, images, cancellation and native byte caps remain native. No shared `more` cursor.
|
|
13
|
+
- `artifacts.adaptiveBudget`: lower inline/excerpt limits according to the calibrated context budget after output/safety reserves and estimated fixed overhead. Never increase configured limits. Preserve minimum reference metadata, canonical results, provenance, privacy, atomic tool groups and normal planner fallback. This is an estimate, not a guaranteed fit or reentrant compaction trigger.
|
|
14
|
+
- `jobs.enabled`: opt-in `bash_job` module in this repository, separate from the portable core and existing `bash`. A single start/status/stop/list tool manages local jobs through Pi's public local BashOperations.
|
|
15
|
+
|
|
16
|
+
## Editing and reading
|
|
17
|
+
|
|
18
|
+
Do not take over missing or visibly overridden native tools. Restore native definitions when an already-enabled instance loads disabled configuration. Fresh disabled loads register no override. Render the real native diff; report failures must not turn a successful write into an apparent failure. Limit report regions, context and escaped text; never re-read a potentially changed file for reporting. Retain ADR 059's strict mixed-anchor batch behavior.
|
|
19
|
+
|
|
20
|
+
## Adaptive artifacts
|
|
21
|
+
|
|
22
|
+
Use provider-facing privacy-sanitized messages only, and the same calibrated model budget as the planner. Keep all configured storage/search caps. Share the available text budget among candidate results, with a metadata floor bounded by the configured maximum. Missing/invalid budget data keeps static behavior. Rebuild uses the conservative adaptive floor so artifacts from earlier small-budget contexts remain reconstructible. No policy values or canonical messages are mutated. Do not replace a result with a larger estimated result.
|
|
23
|
+
|
|
24
|
+
## Local jobs
|
|
25
|
+
|
|
26
|
+
- Require an active built-in local `bash`, no conflicting `bash_job`, explicit configuration, project trust, and local UI confirmation for every start. No UI means no start. This separate tool does not inherit other extensions' bash-only permission policies or SDK shell options.
|
|
27
|
+
- Use opaque job IDs, not arbitrary PIDs. Owner is the current session plus the originating branch entry. Status/stop/list never cross that boundary.
|
|
28
|
+
- At most 4 concurrent jobs and 16 retained records. Default timeout 300 seconds, hard maximum 3600 seconds. Cap each log at 8 MiB and stop on overflow or log-write failure.
|
|
29
|
+
- Logs are raw local files in a private temporary directory, not SQLite state. Responses contain bounded quoted head/tail excerpts and a local output path. Keep completed jobs until bounded eviction or session cleanup; explicitly report output truncation and stop reason.
|
|
30
|
+
- Cancellation while start is pending stops the new job. Once start returns, the job has an independent lifetime; cancelling status does not stop it. Stop and shutdown use native process-tree cancellation. No promise of rollback, daemon ownership or restart survival.
|
|
31
|
+
- Stop jobs and remove temporary logs on session replacement, reload and shutdown. Stop jobs made invisible by branch navigation. Compaction preserves processes and appends a bounded canonical metadata snapshot without launching another model turn; status must be refreshed before acting on old snapshots.
|
|
32
|
+
- Completion marks project indexing dirty. Never launch automatic follow-up turns.
|
|
33
|
+
|
|
34
|
+
## Verification
|
|
35
|
+
|
|
36
|
+
Cover independent opt-ins/default-off paths, legacy missing config, argument mutation, native matching and line endings, explicit read limits/images/model changes, estimated budgets/provenance/privacy/rebuild, process caps/timeouts/aborts/ownership/cleanup/compaction, and clean-consumer packaging. Linux process tests do not establish successful Windows execution; the native Pi backend owns platform-specific process handling.
|
|
37
|
+
|
|
38
|
+
Implementation validation: `npm run check` passed 78 files / 485 tests, including real local bash execution, stop and timeout. Quality comparison and persistence schema gates passed. Clean-consumer packaging passed with Pi 0.84.3 and eight real registry scenarios (core 231 files, reference adapter 7, engine 83). Packaging used a staging copy with the canonical root package manifest; pre-existing user `package.json` changes and `.serena/` were excluded. No provider-token/latency benchmark or Windows execution claim is made. That implementation validation preceded release preparation. See the [0.3.4 release record](../releases/0.3.4.md) for final release gates and publication evidence.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# ADR-061 — Bounded compaction latency optimizations
|
|
2
|
+
|
|
3
|
+
Status: accepted and implemented; coordinated 0.3.5 publication explicitly authorized by the user on 2026-09-05. See the [release record](../releases/0.3.5.md) for validation and publication evidence.
|
|
4
|
+
|
|
5
|
+
## Context
|
|
6
|
+
|
|
7
|
+
Pi normally updates previous summary plus discarded messages in one request. DS4 previously always summarized new segments first and then generated an aggregate when a predecessor existed. Independent segments ran sequentially and summary inputs reused the ordinary context fill target. This can add avoidable calls; provider latency and summary quality still require controlled real-provider comparisons.
|
|
8
|
+
|
|
9
|
+
## Decision
|
|
10
|
+
|
|
11
|
+
- Add `compaction.directUpdate` (default true): estimate the complete sanitized update prompt, including previous summary, cumulative file evidence, custom instructions, split-turn instructions and output contract. If it fits, generate and validate one immutable `task-state` node with the predecessor as a child, canonical source IDs from both spans, and a hash bound to both the new source and predecessor identity/hash/content. With no predecessor, the existing one-segment path remains sufficient. Oversized updates use bounded hierarchical segmentation/aggregation, not truncation.
|
|
12
|
+
- Add `compaction.inputBudget` (`summary` default, or `context`). Summary mode uses the calibrated hard input limit instead of the ordinary active/fill target. Additionally bound input by model context minus safety margin and the actual summary output cap, converted to estimator units. Do not raise model/configured hard limits, remove calibration, reduce safety margins, or reuse ordinary context space reserved for output. Context mode preserves the old active target (also respecting actual summary output headroom).
|
|
13
|
+
- Add `compaction.maxConcurrentSegments` (default 2, range 1–2). Only independent segment requests overlap. Allocate identities and assemble graph/usage in source order, not completion order. On failure stop scheduling, abort siblings, await their settlement before fallback, and persist no partial graph. Cancellation remains cooperative; provider work already accepted may still be billed. Aggregation remains ordered and bounded.
|
|
14
|
+
- Expose process-local metadata-only timings for preparation, segment/direct generation, aggregation, graph preparation/persistence and total DS4 hook duration, plus chosen path, effective provider/model, direct prompt size and concurrency. Timings use a monotonic clock, include retries and local validation within generation, and are wall times (not sums of overlapping calls). They are not canonical evidence, are not persisted in JSONL, and do not measure a subsequent native Pi fallback.
|
|
15
|
+
- Preserve schema-v2 compaction metadata, the existing `task-state` kind, source/classification/validation contracts, Pi cut points, atomic tool exchanges, fresh routing IDs, retry policy, canonical JSONL and all-or-nothing graph preparation. `segmentSummaryId` refers to the update node itself on a direct update; do not invent a segment that was never generated.
|
|
16
|
+
|
|
17
|
+
## Compatibility and validation
|
|
18
|
+
|
|
19
|
+
Configuration is additive; absent fields use the new defaults. The old scheduling path can be compared using `directUpdate=false`, `inputBudget=context`, and `maxConcurrentSegments=1`. The compaction master switch still delegates to Pi when disabled. The original local implementation excluded versioning and publication; the user subsequently authorized the coordinated 0.3.5 release. No dependency upgrade, live database maintenance or Pi upgrade is part of this change.
|
|
20
|
+
|
|
21
|
+
Cover exact budget boundaries and calibration/output reserve, predecessor-only exact evidence and privacy, native predecessor warnings, source ordering/provenance/hash/rebuild, bounded concurrency and out-of-order completion, cancellation/failure/transport retry drainage, and no graph persistence before full success. Retain hierarchical regression coverage explicitly even where default routing now chooses a direct update. Automated call counts and synchronization tests establish scheduling behavior, not a promise of 40-second compactions or unchanged semantic quality on real provider outputs.
|
package/docs/ADR/README.md
CHANGED
|
@@ -62,5 +62,8 @@ The initial decisions from the development plan are accepted:
|
|
|
62
62
|
| 056 | Keep project-memory source exclusion as disposable derived SQLite policy | Accepted |
|
|
63
63
|
| 057 | Derive mutation provenance from the active branch and exclude model-supplied source IDs from V1 | Accepted |
|
|
64
64
|
| [058](058-bounded-manifest-storage.md) | Bound persisted manifests and defer compression to a versioned migration | Accepted |
|
|
65
|
+
| [059](059-optional-anchored-editing.md) | Opt in to anchored edit expansion inside Pi's native mutation queue | Accepted |
|
|
66
|
+
| [060](060-optional-portable-agent-tools.md) | Opt in to edit reports, adaptive reads/results and session-owned local jobs | Accepted |
|
|
67
|
+
| [061](061-compaction-latency.md) | Bound compaction update calls, input budgets, concurrent segments and phase timings | Accepted |
|
|
65
68
|
|
|
66
69
|
Each decision will receive a dedicated record when implementation pressure introduces alternatives or consequences not already covered by the development plan.
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# Optional anchored editing
|
|
2
|
+
|
|
3
|
+
DS4 can replace Pi's native `edit` definition with a compatible, opt-in wrapper.
|
|
4
|
+
This is execution-time editing, not a generation-time forcer. It works with any
|
|
5
|
+
provider that can call Pi tools; it does not require a custom inference backend.
|
|
6
|
+
|
|
7
|
+
## Enable or disable
|
|
8
|
+
|
|
9
|
+
Default: `editing.anchored: false`. In a trusted project:
|
|
10
|
+
|
|
11
|
+
```text
|
|
12
|
+
/context config set editing.anchored true
|
|
13
|
+
/reload
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Use `--global` on the config command to target the agent-directory configuration.
|
|
17
|
+
As with other DS4 config writes, the active session configuration is not changed
|
|
18
|
+
by `set`/`unset`; it is loaded on session startup/replacement or reload.
|
|
19
|
+
|
|
20
|
+
When updating a development checkout, rebuild the core (`npm run build:core`)
|
|
21
|
+
and fully restart Pi. Reloading extension TypeScript can retain previously loaded
|
|
22
|
+
compiled core modules. A core configuration without `editing` safely leaves this
|
|
23
|
+
feature disabled, but the updated core must be loaded to recognize the option.
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"editing": { "anchored": true }
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
`enabled: false` also disables this override. `context.mode` still controls context
|
|
32
|
+
planning, not explicitly opted-in editing. Project configuration is ignored when
|
|
33
|
+
Pi does not trust the project; global configuration continues to apply.
|
|
34
|
+
|
|
35
|
+
On a fresh disabled load DS4 does not register `edit` at all. If an enabled
|
|
36
|
+
extension instance later loads disabled configuration, it restores Pi's native
|
|
37
|
+
edit definition, schema and guidelines. Pi has no public `unregisterTool`; a
|
|
38
|
+
reload while disabled removes DS4's registration entirely.
|
|
39
|
+
|
|
40
|
+
Registration is skipped if native `edit` is unavailable or already owned by
|
|
41
|
+
another extension/SDK tool, with a UI warning when available. DS4 does not enable
|
|
42
|
+
an inactive native edit tool. Only ownership reported by Pi can be checked: SDK
|
|
43
|
+
custom base tools labeled as built-ins cannot be distinguished through this API.
|
|
44
|
+
Do not enable this feature with other edit replacements or remote/sandbox edit
|
|
45
|
+
implementations; the registered wrapper uses local filesystem operations.
|
|
46
|
+
|
|
47
|
+
## Tool input
|
|
48
|
+
|
|
49
|
+
The tool name remains `edit`, with `path` and `edits[]`:
|
|
50
|
+
|
|
51
|
+
```json
|
|
52
|
+
{
|
|
53
|
+
"path": "src/example.ts",
|
|
54
|
+
"edits": [{
|
|
55
|
+
"oldText": "function oldImplementation() {\n[upto]\n}\n// end oldImplementation\n",
|
|
56
|
+
"newText": "function oldImplementation() {\n return improved();\n}\n// end oldImplementation\n"
|
|
57
|
+
}]
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Each anchored `oldText` must contain exactly one `[upto]` marker:
|
|
62
|
+
|
|
63
|
+
- The **head**, before the marker, must occur exactly once in the original file.
|
|
64
|
+
- The **tail**, after the marker, must occur exactly once after the end of the
|
|
65
|
+
head. The same tail occurring before the head is allowed.
|
|
66
|
+
- Both anchors must contain non-whitespace text. Spaces are significant.
|
|
67
|
+
- Newlines immediately after the marker are separators and are removed from the
|
|
68
|
+
tail needle, matching DS4's marker-line convention. Other whitespace is not
|
|
69
|
+
trimmed. Anchors may be inline; full distinctive lines are usually clearer.
|
|
70
|
+
- Replacement is **inclusive**: head, intermediate content and tail are all
|
|
71
|
+
replaced. Put anchors in `newText` if they should be retained.
|
|
72
|
+
- All edits refer to the original file, not previous replacements in the batch.
|
|
73
|
+
Overlaps (including mixed ordinary/anchored overlaps), missing or ambiguous
|
|
74
|
+
anchors and no-op batches are rejected without a write.
|
|
75
|
+
- No 64-byte/two-line threshold applies to manually supplied anchors; those DS4
|
|
76
|
+
thresholds belong to automatic marker forcing, which is not implemented here.
|
|
77
|
+
|
|
78
|
+
A marker is special only in `oldText`, never in `newText`. To match literal marker
|
|
79
|
+
text, set `literal: true` **on that edit**:
|
|
80
|
+
|
|
81
|
+
```json
|
|
82
|
+
{
|
|
83
|
+
"path": "notes.md",
|
|
84
|
+
"edits": [{ "oldText": "[upto]", "newText": "range marker", "literal": true }]
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Calls without anchored edits use native Pi matching, including its normalized
|
|
89
|
+
fuzzy fallback (also for `literal: true` edits). **Every edit in a batch containing
|
|
90
|
+
anchors must match exactly**, ordinary edits included. Pi's fuzzy fallback changes
|
|
91
|
+
the coordinate space for the entire batch and can relocate an otherwise exact
|
|
92
|
+
anchored span; mixed fuzzy batches therefore fail closed. Re-read and correct the
|
|
93
|
+
ordinary oldText, or perform the ordinary edit separately and re-read before
|
|
94
|
+
anchored edits.
|
|
95
|
+
|
|
96
|
+
Exact matching uses BOM-free, LF-normalized original content. Expanded spans then
|
|
97
|
+
pass through native batch checks, including Pi's stricter normalized-ambiguity
|
|
98
|
+
check. Thus a range can be rejected even if its literal anchors pass, when the
|
|
99
|
+
expanded text is ambiguous under Pi's normalization. Re-read and disambiguate;
|
|
100
|
+
do not silently broaden the range.
|
|
101
|
+
|
|
102
|
+
## Execution and feedback
|
|
103
|
+
|
|
104
|
+
`src/extension/anchored-edit-tool.ts` uses public Pi `createEditToolDefinition` and
|
|
105
|
+
`EditOperations`. Its per-call read operation expands anchors only after native
|
|
106
|
+
edit has entered `withFileMutationQueue`. Native edit then performs batch matching,
|
|
107
|
+
overlap checks, cancellation checks, BOM/line-ending restoration, writing and
|
|
108
|
+
diff generation. It is deliberately **not** a `tool_call` preflight expansion:
|
|
109
|
+
there is no unqueued read followed by a later queued write.
|
|
110
|
+
|
|
111
|
+
Expansion uses private argument copies: the full old span is not inserted into
|
|
112
|
+
canonical tool-call arguments or sent back as an expanded input. Native results
|
|
113
|
+
and diff/patch details remain available, plus a compact text report of anchored
|
|
114
|
+
ranges in original line numbers. Canonical result details can still contain old
|
|
115
|
+
text through native diffs; this is not an output privacy/filtering feature.
|
|
116
|
+
|
|
117
|
+
The native TUI matcher cannot preview marker syntax. Anchored calls therefore
|
|
118
|
+
skip its pre-execution preview and display the **actual native result diff** after
|
|
119
|
+
execution. Ordinary edits retain their native preview behavior.
|
|
120
|
+
|
|
121
|
+
The shared Pi queue serializes cooperating edits/writes in the same runtime,
|
|
122
|
+
including symlink aliases. It is not a cross-process file lock, transaction with
|
|
123
|
+
external editors, atomic filesystem write or rollback guarantee. Cancellation
|
|
124
|
+
retains native behavior; once a write has begun it may still complete. Existing
|
|
125
|
+
`tool_call`/`tool_result` hooks continue to see the `edit` tool, not a new tool name.
|
|
126
|
+
Hooks that interpret `oldText` themselves must understand the opt-in syntax.
|
|
127
|
+
|
|
128
|
+
## Scope and verification
|
|
129
|
+
|
|
130
|
+
The implementation targets the project's Pi **0.84.3** dependency. No dependency
|
|
131
|
+
upgrade, provider grammar, streaming interception, KV rewind or forced continuation
|
|
132
|
+
is included. The reference adapter does not implement this Pi editing capability.
|
|
133
|
+
|
|
134
|
+
Tests cover exact matching, suffix-only tail uniqueness, overlapping matches,
|
|
135
|
+
malformed markers, literal escaping, mixed batches, fuzzy-fallback compatibility,
|
|
136
|
+
BOM/CRLF/Unicode, unchanged arguments, result diffs, cancellation, queue ordering,
|
|
137
|
+
symlinks, permissions, working-directory selection and session-bound registration.
|
|
138
|
+
The package smoke check also inspects the real Pi tool registry offline with the
|
|
139
|
+
flag absent, enabled, master-disabled and enabled while native edit is inactive
|
|
140
|
+
or unavailable.
|
|
141
|
+
A deterministic large-block fixture compares serialized request bytes and verifies
|
|
142
|
+
the same output as native editing. Real-provider reliability, token usage and
|
|
143
|
+
latency improvements have **not** been measured; shorter oldText can save generated
|
|
144
|
+
text, while the opt-in tool schema/instructions also add prompt overhead.
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -165,6 +165,44 @@ Pin and Memory mutations resolve provenance from the active Pi branch, revalidat
|
|
|
165
165
|
|
|
166
166
|
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.
|
|
167
167
|
|
|
168
|
+
## Optional anchored editing
|
|
169
|
+
|
|
170
|
+
After trusted configuration loads at `session_start`, `editing.anchored` can
|
|
171
|
+
register a same-name native `edit` wrapper (default off, also gated by `enabled`).
|
|
172
|
+
The Pi extension resolves exact `head[upto]tail` ranges inside the native edit read
|
|
173
|
+
operation, under Pi's shared file mutation queue, then delegates batch checks,
|
|
174
|
+
cancellation, BOM/EOL handling, writing and diffs to native edit. Expansion never
|
|
175
|
+
rewrites canonical tool-call arguments. Calls without anchors retain native fuzzy
|
|
176
|
+
matching; every edit in an anchored batch must match exactly to prevent native
|
|
177
|
+
fuzzy rematching from moving its ranges. Invalid anchored edits fail closed.
|
|
178
|
+
No inference-state control is involved.
|
|
179
|
+
See [anchored editing](ANCHORED_EDITING.md) and [ADR 059](ADR/059-optional-anchored-editing.md).
|
|
180
|
+
|
|
181
|
+
## Other optional portable agent tools
|
|
182
|
+
|
|
183
|
+
`editing.postEditReport` derives bounded old/new coordinates, line deltas and
|
|
184
|
+
updated context from the actual native patch, independently of anchored editing.
|
|
185
|
+
`reading.adaptive` wraps native read with execution-time model-aware default line
|
|
186
|
+
limits; explicit limits and image/byte handling stay native. Both wrappers restore
|
|
187
|
+
native definitions when disabled and do not initially claim other tool overrides.
|
|
188
|
+
|
|
189
|
+
`artifacts.adaptiveBudget` is a pure portable-core policy applied per context to
|
|
190
|
+
privacy-prepared messages. It uses the calibrated planner budget and estimated
|
|
191
|
+
fixed overhead to lower inline/excerpt caps, never raises configured limits, and
|
|
192
|
+
preserves source identities and canonical history. Rebuild uses a conservative
|
|
193
|
+
floor to reconstruct earlier adaptive references. Normal planner fallback remains
|
|
194
|
+
responsible for oversized mandatory context.
|
|
195
|
+
|
|
196
|
+
`src/tools/bash-job-manager.ts` and `src/extension/bash-job-tool.ts` form a separate
|
|
197
|
+
optional local job module. It delegates process execution/cancellation to Pi's
|
|
198
|
+
public BashOperations, limits concurrency/log storage, enforces session/branch
|
|
199
|
+
ownership and requires local confirmation for starts. Jobs survive compaction but
|
|
200
|
+
not session replacement/reload/shutdown; compaction appends bounded metadata only.
|
|
201
|
+
There is no new agent loop, SQLite state, automatic model turn or backend KV control.
|
|
202
|
+
|
|
203
|
+
All new switches are default-off and master-gated. See [portable agent tools](PORTABLE_AGENT_TOOLS.md)
|
|
204
|
+
and [ADR 060](ADR/060-optional-portable-agent-tools.md).
|
|
205
|
+
|
|
168
206
|
## Boundaries
|
|
169
207
|
|
|
170
208
|
Dependency direction is one-way:
|
package/docs/COMPACTION.md
CHANGED
|
@@ -6,14 +6,14 @@ DS4 intercepts Pi's `session_before_compact` event but preserves Pi's cut-point
|
|
|
6
6
|
|
|
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
|
-
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
|
|
10
|
-
4. DS4 estimates the complete sanitized
|
|
11
|
-
5. The
|
|
12
|
-
6.
|
|
13
|
-
7. The highest input classification
|
|
9
|
+
3. Pi's serializer converts the newly discarded span to bounded conversation text; enabled privacy policy sanitizes conversation, previous summary, custom instructions, and file paths for the effective compaction provider (dedicated model when configured and eligible).
|
|
10
|
+
4. DS4 estimates the **complete** sanitized request against a calibrated summary-specific input budget, including framing, instructions, file inventories and output contract. With `compaction.directUpdate` enabled, a previous summary plus new source that fits is updated and validated in **one call**, producing an immutable `task-state` node. No predecessor needs only the existing one-segment call. Oversized updates fall through to hierarchical planning; no additional source is truncated to force a fit.
|
|
11
|
+
5. The hierarchical path partitions oversized source into ordered contiguous segments. Individual messages are indivisible, and every tool call remains in the same atomic group as all matching results. Up to `compaction.maxConcurrentSegments` independent segment requests run concurrently (default 2). Each summary is validated against only its own sanitized evidence. Identities, source/child order and usage accumulation follow source order, not completion order. Cache retention stays disabled and every attempt has a fresh routing session ID.
|
|
12
|
+
6. Hierarchical requests recursively aggregate ordered children until one root remains: previous branch summary first, then new segments. Aggregation stays sequential and budget-checked. Direct updates instead link their single node to the predecessor and new canonical source IDs, without generating a synthetic segment or a separate aggregate. DS4-generated IDs, hashes, kinds, and graph levels never become model-visible evidence. A Pi-native predecessor is imported as an explicitly unverified branch node.
|
|
13
|
+
7. The highest input classification wraps each generated node, then all nodes are persisted atomically as one `prepared` graph batch. Usage includes every returned direct/segment/aggregate request and transport replay. Pi receives only the final root text and still appends exactly one canonical `CompactionEntry` with `fromHook: true`.
|
|
14
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
|
-
Fan-out and fan-in are bounded to 32 segment requests, 64 aggregate requests, and 16 aggregate passes.
|
|
16
|
+
Fan-out and fan-in are bounded to 32 segment requests, 64 aggregate requests, and 16 aggregate passes. The DS4 transport replay policy is: `compaction.transport.maxAttempts` (default 3) total attempts and `compaction.transport.baseDelayMs` (default 2000 ms, capped at 60 s) backoff, doubling per attempt, abort-aware. Replay never applies to input, usage, rate, authentication, validation, or output-limit failures. 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. On segment failure or cancellation DS4 stops scheduling, aborts siblings and awaits all started workers before fallback; no partial graph is installed. Cancellation is cooperative: accepted provider work may still cost tokens, and a provider that ignores abort can delay settlement.
|
|
17
17
|
|
|
18
18
|
## Required summary contract
|
|
19
19
|
|
|
@@ -32,7 +32,7 @@ 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 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.
|
|
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. 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
|
|
|
@@ -49,7 +49,7 @@ An unrepaired exact-value failure reports only the stage, issue code, categorica
|
|
|
49
49
|
- trigger, split-turn flag, source message count;
|
|
50
50
|
- generation time, provider, and model.
|
|
51
51
|
|
|
52
|
-
For aggregate compactions, details also embed every non-active node created by that operation. The active node content remains `CompactionEntry.summary`; prior ancestors remain in earlier canonical entries. SQLite stores content, ordered edges, direct/transitive sources, graph level, and lifecycle as a disposable projection. On resume or after deleting the database, DS4 replays Pi entries in append order and recreates the complete graph.
|
|
52
|
+
For aggregate and direct-update compactions, details also embed every non-active node created by that operation. Direct updates reuse the schema-v2 `task-state` kind, set `segmentSummaryId` to their own node ID, increment the predecessor's level, and include the union of previous/new canonical source IDs. Their hash binds the new source hash to predecessor ID, hash, content and level. Prior nodes are never rewritten; no unused segment is fabricated. The active node content remains `CompactionEntry.summary`; prior ancestors remain in earlier canonical entries. SQLite stores content, ordered edges, direct/transitive sources, graph level, and lifecycle as a disposable projection. On resume or after deleting the database, DS4 replays Pi entries in append order and recreates the complete graph.
|
|
53
53
|
|
|
54
54
|
Memory and pin custom entries do not participate directly in Pi's LLM context and are not replaced by summary text. Their append-only mutations remain in the session tree, so durable decisions and explicit classifications replay after any number of compactions without depending exclusively on a summary.
|
|
55
55
|
|
|
@@ -78,9 +78,31 @@ Semantics:
|
|
|
78
78
|
- `compaction.summary.thinking` defaults to `off` and applies only to summary requests: `off` keeps the pre-existing request shape (no thinking fields), while other levels map per API (`thinkingEnabled`/`effort` for `anthropic-messages`, `samplingParams.reasoning_effort` for OpenAI-compatible APIs) and are ignored for unsupported providers;
|
|
79
79
|
- `context.maxSummaryTokens` remains a session-level limit and does not rise for the dedicated model; the minimum with the model's `maxTokens` still applies.
|
|
80
80
|
|
|
81
|
+
## Latency controls
|
|
82
|
+
|
|
83
|
+
The coordinated `0.3.5` release introduces these additive defaults (absent from `0.3.4`):
|
|
84
|
+
|
|
85
|
+
```json
|
|
86
|
+
{
|
|
87
|
+
"compaction": {
|
|
88
|
+
"directUpdate": true,
|
|
89
|
+
"inputBudget": "summary",
|
|
90
|
+
"maxConcurrentSegments": 2
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
- `directUpdate`: one validated previous-summary plus new-source request when the entire prompt fits. Set false to always retain the segment-then-aggregate route. Validation or provider failures still fall back to Pi, not an unvalidated update.
|
|
96
|
+
- `inputBudget`: `summary` uses calibrated `hardInputLimit` rather than the ordinary context fill target (`activeInputBudget`). `context` selects that legacy fill target. Both are additionally capped by `(context window - safety margin - actual summary output cap) / calibration ratio`, rounded down, and never exceed the configured/model hard limit. Existing output reservations remain conservative; ordinary session planning and proactive thresholds are unchanged. This reduces avoidable fragmentation, not a guarantee of provider fit or faster processing for a larger prompt.
|
|
97
|
+
- `maxConcurrentSegments`: integer **1–2**, default 2. Only independent segments overlap, including their retries. Aggregates do not run until their children have completed. Use 1 for sequential execution or providers with restrictive concurrent-request limits. Rate-limit failures are not transport-retried.
|
|
98
|
+
|
|
99
|
+
For an old-path comparison set `directUpdate=false`, `inputBudget=context`, `maxConcurrentSegments=1`. All features remain behind the existing compaction/master switches. Settings are applied on session load; after upgrading the package or rebuilding a development checkout, fully restart Pi to avoid stale compiled-core modules. No schema migration is required.
|
|
100
|
+
|
|
101
|
+
Mock-provider regression tests verify fewer calls, bounded overlap, exact budget boundaries, validation, privacy, immutable provenance and JSONL rebuild. They do **not** establish real-provider wall-time gains, semantic equivalence of generated summaries, or a guaranteed completion time. See [ADR-061](ADR/061-compaction-latency.md).
|
|
102
|
+
|
|
81
103
|
## Transport retry policy
|
|
82
104
|
|
|
83
|
-
Summary requests are replayed only for transport-classified failures (thrown transport errors or `stopReason: "error"` responses whose message matches network/timeout patterns). The replay policy
|
|
105
|
+
Summary requests are replayed only for transport-classified failures (thrown transport errors or `stopReason: "error"` responses whose message matches network/timeout patterns). The DS4 replay policy uses **three total attempts**, not three retries after the initial call, and can be tuned per deployment:
|
|
84
106
|
|
|
85
107
|
```json
|
|
86
108
|
{
|
|
@@ -93,7 +115,7 @@ Summary requests are replayed only for transport-classified failures (thrown tra
|
|
|
93
115
|
}
|
|
94
116
|
```
|
|
95
117
|
|
|
96
|
-
- `compaction.transport.maxAttempts`: total attempts per segment or aggregate call, integer 1–10, default 3. With 1, no transport failure is retried.
|
|
118
|
+
- `compaction.transport.maxAttempts`: total attempts per direct update, segment or aggregate call, integer 1–10, default 3. With 1, no transport failure is retried.
|
|
97
119
|
- `compaction.transport.baseDelayMs`: base backoff before the first replay, integer 0–60000, default 2000. The delay doubles per attempt (2000, 4000, 8000, …) and is capped at 60 s.
|
|
98
120
|
- Replays use a fresh routing session per attempt; diagnostics expose only stage, failed/next attempt, max attempts, and delay.
|
|
99
121
|
- Aborts (including during backoff) never trigger replay; non-transport failures are never retried; usage is summed across replayed responses.
|
|
@@ -117,4 +139,4 @@ It requests compaction at most once per session leaf. Pi's native threshold and
|
|
|
117
139
|
/context summaries
|
|
118
140
|
```
|
|
119
141
|
|
|
120
|
-
The preview reports thresholds and eligibility; Pi remains authoritative for the exact cut point. Runtime diagnostics additionally report the calibrated input budget, estimated
|
|
142
|
+
The preview reports thresholds and eligibility; Pi remains authoritative for the exact cut point. Runtime diagnostics additionally report the effective provider/model, chosen path (`direct-update` or `hierarchical`), budget mode, calibrated input budget, estimated new-source and full-update prompt sizes, logical summary calls (excluding retries), generated segment count, aggregate-call count, concurrency cap, and completed transport-retry count without source content. Monotonic wall timings cover preparation, generation (direct or parallel segments, including validation and retries), aggregation, graph preparation/persistence, and total DS4 hook time. Parallel generation time is elapsed wall time, not a sum of overlapping requests. Total time excludes Pi's subsequent canonical append or native fallback. Timings survive the in-process commit/fallback notification, but are not persisted in JSONL or reconstructed as fake durations after restart. Metadata-only `compaction.timings` is emitted at `debug` for successful and failed attempts. Each retry emits only stage, failed/next attempt, maximum attempts, and delay at `debug`. Routine `summary_graph_prepared` and `summary_graph_committed` lifecycle events are also 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.
|