omp-fabric 1.3.4 → 1.4.0
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/CHANGELOG.md +13 -0
- package/dist/agents/handoff.d.ts.map +1 -1
- package/dist/chunks/{chunk-WZAH7BO2.js → chunk-2J2GOB4A.js} +30 -11
- package/dist/chunks/chunk-2J2GOB4A.js.map +7 -0
- package/dist/chunks/{chunk-2WDZT27Q.js → chunk-3H5LZWAG.js} +253 -4
- package/dist/chunks/chunk-3H5LZWAG.js.map +7 -0
- package/dist/chunks/{chunk-PYXBHMSL.js → chunk-IMSGR6OW.js} +3 -3
- package/dist/chunks/chunk-IY3IQPRQ.js +308 -0
- package/dist/chunks/chunk-IY3IQPRQ.js.map +7 -0
- package/dist/chunks/{chunk-VSSC4IDU.js → chunk-RTDJFHGH.js} +2 -2
- package/dist/chunks/{chunk-45URY66G.js → chunk-S4I7RMR5.js} +3 -3
- package/dist/chunks/{chunk-ZP3S74LW.js → chunk-SG4GVSWX.js} +49 -26
- package/dist/chunks/chunk-SG4GVSWX.js.map +7 -0
- package/dist/chunks/{chunk-JOWMM3EX.js → chunk-WPU4PKXQ.js} +135 -24
- package/dist/chunks/chunk-WPU4PKXQ.js.map +7 -0
- package/dist/chunks/{chunk-Z5AP4M6K.js → chunk-YOAZ5SO7.js} +12 -2
- package/dist/chunks/{chunk-Z5AP4M6K.js.map → chunk-YOAZ5SO7.js.map} +2 -2
- package/dist/compaction/branch-summary.d.ts +1 -1
- package/dist/compaction/branch-summary.d.ts.map +1 -1
- package/dist/compaction/hook.d.ts +21 -1
- package/dist/compaction/hook.d.ts.map +1 -1
- package/dist/compaction/hook.js +1 -1
- package/dist/compaction/lcm-maintenance.d.ts +103 -0
- package/dist/compaction/lcm-maintenance.d.ts.map +1 -0
- package/dist/compaction/lcm-model.d.ts +41 -0
- package/dist/compaction/lcm-model.d.ts.map +1 -0
- package/dist/compaction/lcm-runtime.d.ts +106 -0
- package/dist/compaction/lcm-runtime.d.ts.map +1 -0
- package/dist/config-migrations.d.ts +1 -1
- package/dist/config-migrations.d.ts.map +1 -1
- package/dist/config.d.ts +7 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/fabric-runtime-state.d.ts +2 -0
- package/dist/fabric-runtime-state.d.ts.map +1 -1
- package/dist/fabric-runtime-state.js +12 -7
- package/dist/fabric-runtime-state.js.map +2 -2
- package/dist/fabric-state.d.ts +2 -1
- package/dist/fabric-state.d.ts.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1030 -108
- package/dist/index.js.map +4 -4
- package/dist/memory/lcm-adapter.d.ts +97 -0
- package/dist/memory/lcm-adapter.d.ts.map +1 -0
- package/dist/providers/memory-provider.d.ts +8 -0
- package/dist/providers/memory-provider.d.ts.map +1 -1
- package/dist/providers/memory-provider.js +2 -1
- package/dist/residency/host.js +6 -5
- package/dist/residency/omp-entry.js +6 -5
- package/dist/residency/omp-entry.js.map +1 -1
- package/dist/runtime/core-override-guest-types.js +1 -1
- package/dist/runtime/guest-types.d.ts +1 -1
- package/dist/runtime/guest-types.d.ts.map +1 -1
- package/dist/runtime/guest-types.js +1 -1
- package/dist/storage/lcm-ledger.d.ts +107 -0
- package/dist/storage/lcm-ledger.d.ts.map +1 -0
- package/dist/storage/lcm-migration.d.ts +67 -0
- package/dist/storage/lcm-migration.d.ts.map +1 -0
- package/dist/ui/settings.js +5 -5
- package/dist/ui/settings.js.map +2 -2
- package/docs/adr/0001-lcm-durable-context-ledger.md +6 -0
- package/docs/agents/domain.md +25 -0
- package/docs/agents/issue-tracker.md +25 -0
- package/docs/agents/triage-labels.md +11 -0
- package/docs/compaction.md +78 -312
- package/docs/configuration.md +3 -3
- package/package.json +1 -1
- package/dist/chunks/chunk-2WDZT27Q.js.map +0 -7
- package/dist/chunks/chunk-JOWMM3EX.js.map +0 -7
- package/dist/chunks/chunk-WZAH7BO2.js.map +0 -7
- package/dist/chunks/chunk-ZP3S74LW.js.map +0 -7
- /package/dist/chunks/{chunk-PYXBHMSL.js.map → chunk-IMSGR6OW.js.map} +0 -0
- /package/dist/chunks/{chunk-VSSC4IDU.js.map → chunk-RTDJFHGH.js.map} +0 -0
- /package/dist/chunks/{chunk-45URY66G.js.map → chunk-S4I7RMR5.js.map} +0 -0
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
---
|
|
2
|
+
status: accepted
|
|
3
|
+
---
|
|
4
|
+
# LCM owns the durable context ledger
|
|
5
|
+
|
|
6
|
+
OMP Fabric's LCM engine owns a project-scoped SQLite context ledger containing every raw conversation entry indefinitely, plus immutable leaf and condensed summary nodes. The OMP session JSONL remains an integration source for on-demand selected-session reconciliation, while the LCM compaction hook reads ready frontier state and returns the standard OMP result without blocking on maintenance. This replaces the old Fabric projection directly because the required durability, hierarchy, and recovery semantics cannot be provided by the derived memory cache or by a compaction hook alone. The deterministic emergency reducer is retained inside LCM for provider outages, and the existing OMP-native engine remains an explicit delegation path.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Domain Docs
|
|
2
|
+
|
|
3
|
+
How the engineering skills should consume this repo's domain documentation when exploring the codebase.
|
|
4
|
+
|
|
5
|
+
## Before exploring, read these
|
|
6
|
+
|
|
7
|
+
- `CONTEXT.md` at the repo root, if it exists.
|
|
8
|
+
- `docs/adr/` for decisions that touch the area being changed, if it exists.
|
|
9
|
+
|
|
10
|
+
If these files do not exist, proceed silently. Create them lazily when domain terms or durable decisions are resolved.
|
|
11
|
+
|
|
12
|
+
## File structure
|
|
13
|
+
|
|
14
|
+
This is a single-context repository:
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
/
|
|
18
|
+
├── CONTEXT.md
|
|
19
|
+
└── docs/
|
|
20
|
+
└── adr/
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Use the glossary vocabulary
|
|
24
|
+
|
|
25
|
+
Use terms from `CONTEXT.md` when naming domain concepts. Flag conflicts instead of silently introducing synonyms.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Issue tracker: GitHub
|
|
2
|
+
|
|
3
|
+
Issues and specs for this repo live as GitHub issues. Use the GitHub CLI for all operations.
|
|
4
|
+
|
|
5
|
+
## Repository
|
|
6
|
+
|
|
7
|
+
- **Repository**: tickernelz/omp-fabric
|
|
8
|
+
- **Create an issue**: `gh issue create --title "..." --body "..."`
|
|
9
|
+
- **Read an issue**: `gh issue view <number> --comments`
|
|
10
|
+
- **List issues**: `gh issue list --state open`
|
|
11
|
+
- **Comment on an issue**: `gh issue comment <number> --body "..."`
|
|
12
|
+
- **Apply or remove labels**: `gh issue edit <number> --add-label "..."` / `--remove-label "..."`
|
|
13
|
+
- **Close**: `gh issue close <number> --comment "..."`
|
|
14
|
+
|
|
15
|
+
## Pull requests as a triage surface
|
|
16
|
+
|
|
17
|
+
**PRs as a request surface: no.**
|
|
18
|
+
|
|
19
|
+
## When a skill says "publish to the issue tracker"
|
|
20
|
+
|
|
21
|
+
Create a GitHub issue and apply the appropriate triage label.
|
|
22
|
+
|
|
23
|
+
## Blocking
|
|
24
|
+
|
|
25
|
+
Use GitHub native issue dependencies when available. Otherwise record each dependency in a `Blocked by` line in the issue body.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Triage Labels
|
|
2
|
+
|
|
3
|
+
The skills speak in terms of five canonical triage roles. This file maps those roles to the labels used in this repository's GitHub tracker.
|
|
4
|
+
|
|
5
|
+
| Label in Matt Pocock skills | Label in GitHub | Meaning |
|
|
6
|
+
| --- | --- | --- |
|
|
7
|
+
| `needs-triage` | `needs-triage` | Maintainer needs to evaluate this issue |
|
|
8
|
+
| `needs-info` | `needs-info` | Waiting on reporter for more information |
|
|
9
|
+
| `ready-for-agent` | `ready-for-agent` | Fully specified and ready for an agent |
|
|
10
|
+
| `ready-for-human` | `ready-for-human` | Requires human implementation |
|
|
11
|
+
| `wontfix` | `wontfix` | Will not be actioned |
|
package/docs/compaction.md
CHANGED
|
@@ -1,332 +1,98 @@
|
|
|
1
|
-
#
|
|
1
|
+
# LCM compaction
|
|
2
2
|
|
|
3
|
-
OMP Fabric
|
|
3
|
+
OMP Fabric uses LCM as its default compaction engine. Set `compaction.engine` to `"omp"` only when OMP's native compaction should own the session.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Model-visible context
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
LCM assembles one bounded OMP compaction result from:
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
"engine": "fabric",
|
|
13
|
-
"targetContextRatio": 0.75
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
```
|
|
9
|
+
- ready summary-frontier nodes;
|
|
10
|
+
- a protected fresh tail selected by OMP's `firstKeptEntryId` preparation;
|
|
11
|
+
- bounded source and lineage metadata.
|
|
17
12
|
|
|
18
|
-
|
|
13
|
+
The hook uses the standard `session_before_compact` contract. It reads committed nodes and produces a valid `CompactionResult`; it does not call or await a summarization model. When semantic maintenance has not produced a ready node, the hook emits a bounded deterministic emergency excerpt with explicit source references.
|
|
19
14
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
15
|
+
## Durable storage
|
|
16
|
+
|
|
17
|
+
LCM stores the complete authoritative OMP `SessionEntry` as canonical UTF-8 JSON in a project-scoped SQLite ledger outside the working tree. Object keys are recursively sorted before hashing. The ledger retains raw entries indefinitely by default and never deletes them during compaction.
|
|
18
|
+
|
|
19
|
+
Each summary node is immutable after publication of its source identity. Leaf nodes cover bounded raw-entry ranges. Condensed nodes cover completed child nodes. Every source reference carries the session, entry ID, revision, and payload hash. Node, edge, frontier, and maintenance-job publication is transactional.
|
|
20
|
+
|
|
21
|
+
SQLite uses WAL, `synchronous=FULL`, a serialized writer, a 5-second busy timeout, and startup integrity verification. Project storage uses canonical recorded cwd/realpath identity with device/inode preference when available. Symlink aliases and renames converge; distinct worktrees remain distinct projects.
|
|
22
|
+
|
|
23
|
+
## Lifecycle
|
|
24
|
+
|
|
25
|
+
`message_end` is only a dirty-session hint because OMP emits a detached message before native persistence. LCM assigns authoritative identity from post-persistence session readback:
|
|
26
|
+
|
|
27
|
+
1. `session_start` reconciles only the selected `getSessionFile()`; unrelated sessions are not scanned.
|
|
28
|
+
2. `agent_end` and `session_compact` read the stable active branch and append complete entries idempotently.
|
|
29
|
+
3. Background maintenance claims leaf and condensation jobs with durable leases and bounded retries.
|
|
30
|
+
4. A later compaction hook reads ready nodes without waiting for maintenance.
|
|
31
|
+
5. `session_shutdown` aborts model work, drains writes, and closes the ledger.
|
|
27
32
|
|
|
28
|
-
|
|
33
|
+
The selected-session reconciler stores a source generation/checkpoint and resumes after interruption. It does not perform a global three-day migration. The old bulk migration command is not part of normal operation.
|
|
29
34
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
+
## Summary maintenance
|
|
36
|
+
|
|
37
|
+
The dedicated model is selected from `compaction.summaryModel` through OMP's public model registry and session-aware resolver. The active session model is the fallback when the dedicated route is unavailable. Leaf and condensed prompts XML-fence transcript evidence and treat it as untrusted data.
|
|
38
|
+
|
|
39
|
+
Maintenance defaults are bounded to 32 model calls, 2,000,000 input tokens, and 128,000 output tokens per project per UTC day, with a nested 16-call session limit. One project model job runs at a time. Jobs use 30-second leases renewed every 10 seconds, 60-second call limits, exponential retry backoff capped at 15 minutes, and three attempts. A failed call does not publish a ready node or increment usage counters.
|
|
40
|
+
|
|
41
|
+
The emergency reducer is deterministic, explicitly nonsemantic, source-addressed, and bounded to 4,096 bytes by UTF-8 size. Provider failure keeps raw entries and pending maintenance recoverable.
|
|
42
|
+
|
|
43
|
+
## Retrieval
|
|
44
|
+
|
|
45
|
+
Use the existing namespaced memory actions:
|
|
46
|
+
|
|
47
|
+
- `memory.recall` returns bounded raw and summary hits. The default LCM scope is the current session when one is bound; explicit session scope remains available. Active-branch results require source references on the live branch. Incomplete or stale coverage is reported and never treated as an authoritative no-match.
|
|
48
|
+
- `memory.expand` follows a stable raw or summary reference. Raw expansion returns the exact structured `SessionEntry` payload, including tool arguments, tool results, custom details, and media fields. Summary expansion returns the summary text and its structured source references.
|
|
49
|
+
- `memory.sessions` remains the session inventory action.
|
|
50
|
+
|
|
51
|
+
Summary text is a navigation aid. Exact action or factual claims should be checked against expanded raw source entries.
|
|
52
|
+
|
|
53
|
+
## Tree and handoff behavior
|
|
54
|
+
|
|
55
|
+
LCM uses the standard `session_before_tree` hook when the user requests a branch summary. The result contains bounded typed branch facts and the abandoned `oldLeafId`; sibling branch prose is not used as source truth.
|
|
56
|
+
|
|
57
|
+
Trajectory handoff compaction has no live `ExtensionContext`, so it uses the LCM deterministic emergency reducer over the discarded prefix, keeps the latest user boundary when one exists, and records source range metadata. It does not invoke the old Fabric compiler or a hidden model call.
|
|
58
|
+
|
|
59
|
+
## Operational controls
|
|
60
|
+
|
|
61
|
+
Raw retention is indefinite but bounded operationally:
|
|
62
|
+
|
|
63
|
+
- 8 GiB per project: warning in status and UI when available;
|
|
64
|
+
- 10 GiB per project: stop new model-maintenance claims while preserving raw appends;
|
|
65
|
+
- ENOSPC: durable degraded state; no successful skip is reported;
|
|
66
|
+
- backup/export: mode-0600 `VACUUM INTO` copy with SHA-256, row counts, and integrity manifest;
|
|
67
|
+
- deletion: explicit typed project confirmation, verified backup, transactional scoped delete, post-delete integrity check, and audit manifest.
|
|
68
|
+
|
|
69
|
+
Automatic raw deletion is disabled.
|
|
70
|
+
|
|
71
|
+
## Configuration
|
|
35
72
|
|
|
36
73
|
```json
|
|
37
74
|
{
|
|
38
75
|
"compaction": {
|
|
39
|
-
"
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"
|
|
44
|
-
|
|
45
|
-
|
|
76
|
+
"engine": "lcm",
|
|
77
|
+
"summaryModel": "provider/model",
|
|
78
|
+
"targetContextRatio": 0.75,
|
|
79
|
+
"lcmMaxInputChars": 48000,
|
|
80
|
+
"lcmMaxOutputTokens": 4096,
|
|
81
|
+
"lcmMaxOutputChars": 16384,
|
|
82
|
+
"lcmMaxLeafEntries": 8,
|
|
83
|
+
"lcmMaxCondenseChildren": 4
|
|
46
84
|
}
|
|
47
85
|
}
|
|
48
86
|
```
|
|
49
87
|
|
|
50
|
-
|
|
51
|
-
to integers bounded to `1,000`–`100,000,000`. When a hand-written config sets
|
|
52
|
-
both for one model, the token threshold wins. A configured threshold makes
|
|
53
|
-
Fabric trigger compaction at a safe settled boundary once the active model
|
|
54
|
-
reaches it. OMP's own automatic compaction keeps its built-in trigger: the
|
|
55
|
-
host's `session_before_compact` event carries no trigger reason, so Fabric
|
|
56
|
-
cannot tell an automatic threshold compaction apart from an overflow or manual
|
|
57
|
-
one and never defers the host's automatic pass.
|
|
58
|
-
|
|
59
|
-
## Invariants
|
|
60
|
-
|
|
61
|
-
1. **The session log is ground truth.** The summary is a bounded continuation view with stable entry-id and file addresses.
|
|
62
|
-
2. **Live cut and cumulative truth are separate.** The cut comes from the window made live by the last compaction. Fabric rebuilds the summary from every raw, typed, content-bearing entry on the supplied active branch prefix before the new kept boundary.
|
|
63
|
-
3. **Rendered summaries are never semantic input.** `compaction` entries, branch-summary prose, custom summary prose, and unknown roles produce no normalized events. A valid Fabric branch-summary details envelope may contribute its typed facts. Its `summary` string never contributes. Top-level OMP `custom_message` entries work differently: OMP puts them in model context, so Fabric preserves their typed `customType`, text content, visibility, and bounded JSON details. `custom` state entries that bear no context remain excluded.
|
|
64
|
-
4. **Structure drives projection.** The core uses entry/message types, roles, content-part types, custom-message fields, tool names, typed `fabric_exec` display fields, JSON arguments, call ids, `isError`, aggregate trace outcomes, exit codes, entry ids, ordering, valid Fabric execution traces, and valid Fabric branch-summary facts. It applies no semantic regex over prose, code, shell commands, or tool output. Whitespace normalization, bounded truncation, exact identity comparisons, and path segmentation stay mechanical.
|
|
65
|
-
5. **Serialization is deterministic and bounded.** Identical branch entries and instructions produce byte-identical output. The rendered result is at most 32 KiB in UTF-8.
|
|
66
|
-
6. **The nominal model window is the safety boundary.** Fabric never treats it as a target to fill. Fabric calibrates OMP's structural token estimate against `preparation.tokensBefore`, retains the largest closure-safe suffix within OMP's bounded `keepRecentTokens` continuity budget, and treats the configured occupancy ratio, OMP response reserve, estimator-error margin, and pre-compaction size as hard ceilings. Undocumented provider headroom never enters the budget.
|
|
67
|
-
|
|
68
|
-
These invariants prevent summary-chain drift and deterministic
|
|
69
|
-
forgetting. OMP replaces the previous rendered summary on each compaction.
|
|
70
|
-
Fabric still re-derives the original goal, cumulative successful file
|
|
71
|
-
addresses, error state, and user scope changes from raw branch history every
|
|
72
|
-
time.
|
|
73
|
-
|
|
74
|
-
## Loss model and memory
|
|
75
|
-
|
|
76
|
-
Fabric compaction is **source-lossless and addressably lossless**. The model's bounded continuation view does not stay byte-for-byte lossless:
|
|
77
|
-
|
|
78
|
-
- Compaction appends a marker. It never deletes or rewrites raw session JSONL. The active parent-linked session branch remains ground truth.
|
|
79
|
-
- The model receives a bounded deterministic projection plus the recent raw continuity tail. Fabric preserves typed goals, declared Fabric run intent paired with aggregate outcomes, file operations, failures, status, and stable addresses through mechanical rules. Arbitrary old prose, tool-output bodies, and thinking may fall out of the inline view.
|
|
80
|
-
- Every sampled omission records a count and source entry-id range. `memory.expand` can re-read exact untruncated source by stable entry ID or operation address with source-hash and lineage checks.
|
|
81
|
-
- The memory index remains derived and disposable. Compaction works without successful indexing, and it never treats an incomplete index as ground truth. Exact expansion reads session JSONL.
|
|
82
|
-
|
|
83
|
-
Near-lossless continuation comes from three layers: dense typed projection for
|
|
84
|
-
normal work, a bounded raw tail for immediate local coherence, and
|
|
85
|
-
integrity-bound source recall for exact old detail. Deleting the source
|
|
86
|
-
session removes the final exact-recall layer.
|
|
87
|
-
|
|
88
|
-
## OMP pipeline
|
|
89
|
-
|
|
90
|
-
```text
|
|
91
|
-
active branch entries ─┬─► live window ─► calibrated token budget ─► closure-safe cut ─► firstKeptEntryId
|
|
92
|
-
└─► raw cumulative prefix ─► normalize ─► project ─► bound/render
|
|
93
|
-
```
|
|
88
|
+
Legacy persisted `compaction.engine: "fabric"` is migrated to `"lcm"` by the config migration. Unknown engine values normalize to the LCM default. OMP native delegation remains the explicit `"omp"` value.
|
|
94
89
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
- `render.ts` independently bounds every rendered block and enforces the global UTF-8 limit.
|
|
99
|
-
- `hook.ts` computes the live cut, selects cumulative source, and emits v2 details for the configured OMP or Fabric engine.
|
|
100
|
-
|
|
101
|
-
## Live cut and closure
|
|
102
|
-
|
|
103
|
-
The last compaction marker identifies the live window:
|
|
104
|
-
|
|
105
|
-
- a valid `firstKeptEntryId` starts the window at that entry.
|
|
106
|
-
- a compact-all marker or missing/orphan kept id starts it after the marker.
|
|
107
|
-
- without a marker, the whole supplied active path is live.
|
|
108
|
-
|
|
109
|
-
When OMP supplies the active model metadata, Fabric chooses the live cut from a calibrated bounded continuity budget:
|
|
110
|
-
|
|
111
|
-
1. Sum OMP's public structural message estimates for the current context.
|
|
112
|
-
2. Calibrate that estimate with `preparation.tokensBefore`, which compensates for provider tokenization, system prompts, tool schemas, and other fixed context that a character heuristic cannot observe directly.
|
|
113
|
-
3. Set the continuity target to calibrated fixed overhead plus OMP's `keepRecentTokens` and the maximum 32 KiB summary reservation. The absolute recent-tail budget does not grow with a 200K, 1M, or proxy-inflated advertised window.
|
|
114
|
-
4. Clamp that target to all independent safety ceilings: `contextWindow × targetContextRatio`, 90% of `contextWindow - reserveTokens`, and 95% of `tokensBefore`. The last ceiling prevents a low-usage manual compaction from expanding context. The advertised window is authoritative for threshold and manual compaction. Overflow recovery treats the failed request as stronger evidence: an API rejection proves the effective window is below `tokensBefore`, so Fabric first clamps the working window to 90% of the observed failed size.
|
|
115
|
-
5. Select the earliest eligible boundary whose retained suffix fits the resulting raw-tail budget. Suffix size decreases monotonically, so this boundary gives the largest legal raw suffix. User/custom boundaries and assistant boundaries are both eligible, which lets Fabric split a single enormous autonomous turn during compaction. On repeated compaction, the kept boundary must follow the previous compaction marker in raw log order. OMP replays entries contiguously from `firstKeptEntryId`, so a boundary before that marker would replay the old rendered summary beside the new one.
|
|
116
|
-
|
|
117
|
-
Fabric computes structural spans for every call id across the supplied branch
|
|
118
|
-
and rejects every candidate cut that separates an actual call/result pair.
|
|
119
|
-
This enforces both directions:
|
|
120
|
-
|
|
121
|
-
- a summarized tool call never has a kept result.
|
|
122
|
-
- a kept tool call never has a summarized result.
|
|
123
|
-
|
|
124
|
-
This pairing check handles parallel calls, delayed results, reverse or
|
|
125
|
-
malformed ordering, and malformed prior boundaries. When no non-crossing
|
|
126
|
-
boundary fits, Fabric uses compact-all (`firstKeptEntryId: ""`), and no kept
|
|
127
|
-
side remains to orphan either half. If the rendered deterministic summary
|
|
128
|
-
itself would push the calibrated projection over the target, Fabric cancels
|
|
129
|
-
the compaction to avoid persisting an expanding or over-budget result. If
|
|
130
|
-
model metadata is unavailable, the legacy latest-turn closure-safe cut remains
|
|
131
|
-
as a compatibility fallback.
|
|
132
|
-
|
|
133
|
-
The live cut determines only what OMP keeps. The summary source is the raw
|
|
134
|
-
active-branch prefix before that new boundary. Normalization skips earlier
|
|
135
|
-
compaction and branch-summary prose within that prefix.
|
|
136
|
-
|
|
137
|
-
## Bounded sections
|
|
138
|
-
|
|
139
|
-
Fabric emits the original first user goal first. Later user scope changes and
|
|
140
|
-
the potentially large file, operation-state, and earlier-turn collections use
|
|
141
|
-
deterministic earliest-plus-latest sampling. Every omission records a count
|
|
142
|
-
and a source entry-id range. File lines also carry the source call entry id.
|
|
143
|
-
|
|
144
|
-
Rendered block limits include their headers:
|
|
145
|
-
|
|
146
|
-
| Block | UTF-8 limit |
|
|
147
|
-
| --- | ---: |
|
|
148
|
-
| `[Session Goal]` | 4096 bytes |
|
|
149
|
-
| `[Compaction Request]` | 3072 bytes |
|
|
150
|
-
| `[Files And Changes]` | 4608 bytes |
|
|
151
|
-
| `[Fabric Activity]` | 2048 bytes |
|
|
152
|
-
| `[Outstanding Context]` | 4608 bytes |
|
|
153
|
-
| `[Earlier Turns]` | 3072 bytes |
|
|
154
|
-
| `[Current Status]` | 2048 bytes |
|
|
155
|
-
| collapsed transcript | 5120 bytes |
|
|
156
|
-
| footer | 1536 bytes |
|
|
157
|
-
|
|
158
|
-
The limits sum below 32 KiB, leaving room for separators. A final UTF-8 guard
|
|
159
|
-
enforces the global limit. Projection limits stay finite: 24 later goals, 24
|
|
160
|
-
file addresses per operation kind, 32 operation-state records, 48 Fabric
|
|
161
|
-
activity records, 32 earlier turns, and 40 transcript events. Omitted source
|
|
162
|
-
remains executable-addressable through entry-id ranges and the footer recall
|
|
163
|
-
pointer.
|
|
164
|
-
|
|
165
|
-
## Sections
|
|
166
|
-
|
|
167
|
-
- **Session Goal**: up to three bounded lines from the original first user message, followed by sampled later user scope changes.
|
|
168
|
-
- **Compaction Request**: canonicalized, bounded custom instructions. See below.
|
|
169
|
-
- **Files And Changes**: successful typed file-tool addresses grouped as Created, Written, Modified, or Read. `edit` counts as Modified. `write` counts as Written unless a typed result explicitly proves creation.
|
|
170
|
-
- **Fabric Activity**: completed named `fabric_exec` runs as bounded `name → outcome` records that place an em dash between the name and the optional description, followed in source order by phases and significant non-file nested operations, including bash, agents, workflow, mesh, state, MCP, and extension refs. Named runs expose the exact assistant call entry ID while sourced raw, and their typed fact address after branch rehydration. Nested phases and operations expose stable `entryId/subordinal` addresses. The name and outcome are mandatory for a rendered run. The optional description decays first under tighter views.
|
|
171
|
-
- **Outstanding Context**: typed tool/bash failures and later exact structural resolutions. File failures require the same action and path, bash failures the same command, and generic failures the same ref and arguments. Fabric quotes explicit error text with bounds and never parses or classifies it. Trace failures use only `operation.outcome` and `operation.error`.
|
|
172
|
-
- **Earlier Turns**: sampled user/custom context one-liners, tool-name counts, and the latest named Fabric run plus outcome for each summarized turn.
|
|
173
|
-
- **Current Status**: the latest summarized user/custom context, modification address, named Fabric run plus outcome, and assistant line.
|
|
174
|
-
- **Transcript**: the latest 40 typed events, including quoted and bounded custom-message content and bounded structural details, plus an omission range when applicable. A completed named `fabric_exec` replaces its generic outer call/result pair with `name → outcome`. The description stays in the richer Activity tier.
|
|
175
|
-
- **Footer**: deterministic source timestamp, cumulative source range, and session-log recall guidance.
|
|
176
|
-
|
|
177
|
-
Fabric omits commit projections. The core ignores `git commit`
|
|
178
|
-
command prefixes, and it never pulls hashes or summaries from shell stdout. A
|
|
179
|
-
caller that needs a commit ID across compaction must provide it explicitly
|
|
180
|
-
through a valid typed `preserve` item or another typed state transition.
|
|
181
|
-
|
|
182
|
-
## Remaining structural text operations
|
|
183
|
-
|
|
184
|
-
The clean core retains only these mechanical text operations:
|
|
185
|
-
|
|
186
|
-
- select text from typed user, assistant, top-level custom-message, tool-result, Fabric display-name/description, command-argument, error, phase, ref, and path fields.
|
|
187
|
-
- split user text on literal newlines for bounded goal lines, or select the first line for one-line views.
|
|
188
|
-
- trim/collapse whitespace and truncate by fixed character or UTF-8 byte limits.
|
|
189
|
-
- quote bounded user/custom/assistant/tool/error text without interpreting its content.
|
|
190
|
-
- compare typed action/path, action/command, or ref/JSON-arguments identities exactly for resolution.
|
|
191
|
-
- segment typed paths on `/` or `\\` to compute display roots.
|
|
192
|
-
- split a typed Fabric ref once on `.` to expose provider/action identity.
|
|
193
|
-
- inspect the explicit typed `created: true` result field for write classification.
|
|
194
|
-
- decode the exact typed Fabric request prefix with a bounded structural JSON parser.
|
|
195
|
-
|
|
196
|
-
The core never recovers command prefixes, stdout/stderr line formats, error
|
|
197
|
-
wording, path-looking prose, commit-looking prose, source code, or tool-result
|
|
198
|
-
renderings into semantic facts.
|
|
199
|
-
|
|
200
|
-
## Custom instructions
|
|
201
|
-
|
|
202
|
-
Plain custom instructions are always explicit user data; Fabric never treats a reserved text sentinel as routing control.
|
|
203
|
-
|
|
204
|
-
Fabric treats every other plain instruction as explicit user data. It
|
|
205
|
-
canonicalizes whitespace, bounds the input, and includes the text in
|
|
206
|
-
`[Compaction Request]` without semantically parsing it.
|
|
207
|
-
|
|
208
|
-
`compact.request` may add typed `preserve: string[]` values. When present, the
|
|
209
|
-
controller forwards an exact versioned prefix followed by JSON. The hook
|
|
210
|
-
accepts only the exact prefix and a strict v1 object. Once that reserved
|
|
211
|
-
prefix is present, malformed JSON or scalars, duplicate protocol keys
|
|
212
|
-
(including escaped-key aliases), unknown fields or versions, invalid types,
|
|
213
|
-
unpaired UTF-16 surrogates, excessive structure, or exceeded bounds produce a
|
|
214
|
-
structured decode error and cancel the operation. Fabric never reinterprets or
|
|
215
|
-
renders the encoded payload as plain instructions. A UI/RPC context receives a
|
|
216
|
-
bounded error notification when available.
|
|
217
|
-
|
|
218
|
-
Fabric enforces the typed v1 limits before value mapping or canonicalization.
|
|
219
|
-
Instructions cap at 8192 characters and 8192 UTF-8 bytes. The `preserve` list
|
|
220
|
-
holds at most 16 items, and each item caps at 2048 characters and 2048 UTF-8
|
|
221
|
-
bytes. The complete prefix-plus-JSON source must fit within 16 KiB. The
|
|
222
|
-
decoder checks the aggregate source limit before invoking its bounded
|
|
223
|
-
recursive-descent parser. While parsing, it rejects duplicate decoded keys and
|
|
224
|
-
validates scalar grammar and surrogate pairing. It checks the preserve count
|
|
225
|
-
before it iterates or canonicalizes values. Plain OMP and manual instructions
|
|
226
|
-
stay explicit bounded text and never run through the typed protocol parser.
|
|
227
|
-
|
|
228
|
-
## Compaction details v2
|
|
229
|
-
|
|
230
|
-
New summaries emit `details.compactor: "fabric"` and `details.version: 2` with:
|
|
231
|
-
|
|
232
|
-
- cumulative source and live-cut ranges.
|
|
233
|
-
- branch, source-entry, event, and live-cut counts.
|
|
234
|
-
- prior recognized Fabric v1/v2 marker counts.
|
|
235
|
-
- per-projection omission counts, the typed preserve count (valid v1 requests cannot exceed the preserve limit), and the structural count of erased assistant thinking blocks.
|
|
236
|
-
- instruction mode, canonicalization, source size, truncation, and preserve counts.
|
|
237
|
-
- stable kept/source entry-id addresses and the source timestamp.
|
|
238
|
-
- when continuity budgeting is active: effective window, occupancy ceiling ratio/tokens, continuity target, reserve and reduction ceilings, the binding constraint, OMP reserve/recent settings, raw estimate, calibration scale, fixed overhead, raw-tail budget, retained raw tokens, and Fabric's `projectedTokensAfter`. OMP core independently recomputes its own `estimatedTokensAfter` after persisting the compaction. Legacy v2 records with `strategy: "adaptive"` remain recognized.
|
|
239
|
-
|
|
240
|
-
Fabric recognizes exact versions 1 and 2 only. v1 details and rendered prose
|
|
241
|
-
never serve as truth. An old session migrates to v2 on the next compaction,
|
|
242
|
-
because Fabric rebuilds the new result from raw active-branch entries. V2
|
|
243
|
-
validation accepts the legacy commit-omission counter for old records. New
|
|
244
|
-
summaries drop the commit projection and its counter.
|
|
245
|
-
|
|
246
|
-
## Nested Fabric execution traces
|
|
247
|
-
|
|
248
|
-
For an outer `fabric_exec` tool result, normalization pairs the result with
|
|
249
|
-
its assistant call by exact `toolCallId`. When that call has a non-empty typed
|
|
250
|
-
`display.name`, Fabric emits a declared-intent record with an internal
|
|
251
|
-
`call-entry-id/call:toolCallId` fact address. Fabric also exposes the
|
|
252
|
-
assistant call entry ID for exact raw-source expansion, or that fact address
|
|
253
|
-
after branch rehydration. Fabric bounds the name to 256 UTF-8 bytes and the
|
|
254
|
-
optional description to 1024 bytes, and the outcome comes from a valid
|
|
255
|
-
aggregate trace outcome or the outer typed `isError` flag when no aggregate
|
|
256
|
-
exists. Fabric
|
|
257
|
-
never treats this metadata as proof of work. The paired outcome and nested
|
|
258
|
-
operations remain the authoritative evidence. Normalization reads nested
|
|
259
|
-
execution only from `message.details.trace` through
|
|
260
|
-
`readFabricExecutionTraceV1`. Emitted operations follow `operation.sequence`
|
|
261
|
-
order with addresses such as `entry-id/0`, and phases use `entry-id/phase:0`.
|
|
262
|
-
Known `omp.read`, `omp.grep`, `omp.find`, `omp.ls`, `omp.edit`, `omp.write`, and
|
|
263
|
-
`omp.bash` and `` calls retain exact typed arguments and outcomes. Other refs remain
|
|
264
|
-
typed Fabric activity.
|
|
265
|
-
|
|
266
|
-
Fabric ignores a present trace version when it is malformed or unknown. It
|
|
267
|
-
never reinterprets such a trace as legacy data. When `trace` is absent, the
|
|
268
|
-
legacy adapter accepts only an audit array whose records have typed `ref`, JSON
|
|
269
|
-
`args`, boolean `success`, and optional string `error`. The adapter never
|
|
270
|
-
reads audit rendering or `result` prose. An unnamed outer tool conversation
|
|
271
|
-
remains generic in the transcript. A completed named run replaces that generic
|
|
272
|
-
call/result pair with its bounded name and outcome. `fabric_exec` source code
|
|
273
|
-
and outer result prose still cannot create file, failure, or activity facts.
|
|
274
|
-
|
|
275
|
-
## Deterministic branch summaries
|
|
276
|
-
|
|
277
|
-
When the Fabric engine is active, the same registration also handles
|
|
278
|
-
`session_before_tree`. The handler returns nothing when `userWantsSummary` is
|
|
279
|
-
false, and it compiles only `preparation.entriesToSummarize` when true. Tree
|
|
280
|
-
custom instructions use the same plain/typed decoder and fail-closed limits as
|
|
281
|
-
compaction. Plain instructions remain ordinary explicit request text on the tree path.
|
|
282
|
-
|
|
283
|
-
`replaceInstructions: true` follows OMP replacement-prompt semantics. A
|
|
284
|
-
deterministic projection cannot execute an arbitrary replacement summarizer
|
|
285
|
-
prompt, so Fabric returns `undefined` and defers to OMP or another handler.
|
|
286
|
-
Fabric produces no summary and no typed Fabric branch details in that explicit
|
|
287
|
-
mode.
|
|
288
|
-
|
|
289
|
-
Branch details use `kind: "omp-fabric.branch-summary"`, current `version: 2`,
|
|
290
|
-
stable source addresses, and at most 256 bounded typed facts in a 128 KiB
|
|
291
|
-
envelope. Facts cover source users, top-level custom messages, named Fabric
|
|
292
|
-
runs, phases, and operations. V2 adds bounded `fabricRun` facts that carry the
|
|
293
|
-
declared name and description with the paired outcome. Strict v1 envelopes
|
|
294
|
-
remain readable, and Fabric never reinterprets them as v2. Newly generated
|
|
295
|
-
details record `source.oldLeafId` from `preparation.oldLeafId`, which is the
|
|
296
|
-
canonical abandoned/from-leaf provenance. Older v1 envelopes without that
|
|
297
|
-
field remain readable. The OMP host writes the generic `BranchSummaryEntry.fromId`
|
|
298
|
-
from the navigation target position, and that position differs from the
|
|
299
|
-
abandoned leaf. A hook cannot correct that core-generated field, so consumers
|
|
300
|
-
must use Fabric's typed `source.oldLeafId` when present.
|
|
301
|
-
|
|
302
|
-
Nested branch summaries re-emit only valid typed facts, and normalization
|
|
303
|
-
never reads branch summary prose. Later compaction can then resolve
|
|
304
|
-
abandoned-branch failures against later exact successes, and custom context, files, and
|
|
305
|
-
activity survive navigation or forks without any prose parsing. OMP supplies
|
|
306
|
-
only the active path or the abandoned `entriesToSummarize` path to each
|
|
307
|
-
compiler, so sibling branches cannot contaminate one another.
|
|
308
|
-
|
|
309
|
-
## OMP compaction precedence
|
|
310
|
-
|
|
311
|
-
Precedence remains:
|
|
312
|
-
|
|
313
|
-
1. the configured compaction engine;
|
|
314
|
-
2. OMP's native compaction behavior when the engine is `"omp"`;
|
|
315
|
-
3. Fabric's deterministic summary when the engine is `"fabric"`.
|
|
316
|
-
|
|
317
|
-
Fabric marks claimed events with `_fabricCompaction`. OMP's public extension contract runs `session_before_*` handlers in extension load order and keeps the latest non-cancelling result. An unrelated handler loaded after Fabric can replace Fabric's compaction or tree result. A later cancellation terminates dispatch. Fabric never monkeypatches OMP's private runner.
|
|
318
|
-
|
|
319
|
-
## Reconstruction QA
|
|
320
|
-
|
|
321
|
-
`src/compaction/qa.ts` derives probes from normalized source events, never
|
|
322
|
-
from rendered sections. QA probes follow the same bounded sampling policy as
|
|
323
|
-
projections. The report checks directly rendered samples for content, and it
|
|
324
|
-
validates omitted collections for count and range addressability. Mutation tests
|
|
325
|
-
remove file, error, turn, latest Fabric run intent/outcome/address, and footer
|
|
326
|
-
information to verify that the report detects loss.
|
|
327
|
-
|
|
328
|
-
Run:
|
|
90
|
+
## Verification
|
|
91
|
+
|
|
92
|
+
Focused LCM tests cover ledger durability, canonical payload identity, branch isolation, model budgets, emergency bounds, on-demand session reconciliation, memory provider routing, tree summaries, and handoff continuity. Run:
|
|
329
93
|
|
|
330
94
|
```sh
|
|
331
|
-
bun
|
|
95
|
+
bun run check
|
|
332
96
|
```
|
|
97
|
+
|
|
98
|
+
This command includes typecheck, a fresh `dist/` build, the lazy-graph assertion, the full test suite, and dead-code lint.
|
package/docs/configuration.md
CHANGED
|
@@ -158,7 +158,7 @@ where absent values do not participate. Orchestration programs (`agents.run` / `
|
|
|
158
158
|
"updateDebounceMs": 100
|
|
159
159
|
},
|
|
160
160
|
"compaction": {
|
|
161
|
-
"engine": "
|
|
161
|
+
"engine": "lcm"
|
|
162
162
|
},
|
|
163
163
|
"retention": {
|
|
164
164
|
"orphanedTempRunMs": 21600000,
|
|
@@ -238,7 +238,7 @@ Each in-place handoff captures Main's active model at the boundary and restores
|
|
|
238
238
|
|
|
239
239
|
`executor.resultFormat` sets the default for `fabric_exec` return values. Find it under `/fabric settings` → **Executor**. `"auto"` keeps strings as text and renders structured values as syntax-highlighted YAML. `"yaml"`, `"json"`, and `"text"` each force their named behavior. A call-level `resultFormat` parameter overrides the configured default.
|
|
240
240
|
|
|
241
|
-
Configure
|
|
241
|
+
Configure compaction under `/fabric settings` → **Compaction**. Select `"lcm"` for durable hierarchical context or `"omp"` to hand compaction to OMP core.
|
|
242
242
|
|
|
243
243
|
## Code modes
|
|
244
244
|
|
|
@@ -483,7 +483,7 @@ Mesh topics, shared state, and the participant directory remain project-scoped.
|
|
|
483
483
|
|
|
484
484
|
## Compaction
|
|
485
485
|
|
|
486
|
-
The
|
|
486
|
+
The LCM compaction engine is on by default. It keeps OMP's bounded `keepRecentTokens` continuity tail and assembles durable summary nodes. `compaction.targetContextRatio` sets a hard occupancy ceiling. Set `compaction.engine` to `"omp"` to use OMP's native compaction. See [compaction](compaction.md) for invariants, loss guarantees, sections, and limits.
|
|
487
487
|
|
|
488
488
|
## Catalog repairs
|
|
489
489
|
|