Divergence index
English | 中文
Delorun changes some files of upstream DeepSeek Harness. The divergence ledger accounts for each of those files, so the difference from upstream stays measured and reviewable. This page defines the ledger, its entries and path rules, how to read, write and measure it, and the divergence budget that limits how far it may grow in one release.
Contents
The ledger
The ledger is delorun/upstream-patches.json, described by its delorun/upstream-patches.schema.json. Every file outside Delorun's own trees that differs from the upstream commit it pins is either an entry under patches or covered by a path rule under rules. Delorun's own trees are delorun/, the .agents/skills/delorun-*/ skills and the .agents/notes/**/*-delorun-* notes. Those files are Delorun's, not upstream edits, so the ledger does not account for them.
An entry names one upstream file with its class and the reason for the change, whatever its number of hunks. Every differing upstream source file is an entry, and so is every file whose change moves a gate. A path rule covers a group of files that are not upstream source, such as specs, translations and documentation, with one reason. When upstream absorbs a change, its entry moves to retired, which names the upstream commit that absorbed it and the hunks it had. The retired entry stays in the ledger and is credited in the divergence budget.
A path is upstream source when it lies under a src/ directory of packages/ or apps/, under native/, is a Python file under python/, or is a .ts or .mjs file under scripts/ outside scripts/tests/, and it is not a spec or test file (*.spec.*, *.test.*), not under a tests/, __tests__/, fixtures/ or snapshots/ directory, not Markdown and not a .i18n.yaml consistency record. Every path under vendor/ is upstream source. A differing source file needs an entry; no path rule covers it, except that an exact generated rule may name a generated source file outside vendor/.
Each path rule has a pattern, a kind and a reason. The pattern is a glob over repository-relative paths, matched whole and case-sensitively by Node's path.posix.matchesGlob: * matches within one path segment, ** across segments, and neither matches a segment that starts with ., so a rule for .github/ or .agents/ names that directory. The kinds are tests, recorded-sessions, translations, documentation, tooling and generated.
The checks refuse a rule that would cover source: a bare **, and any rule whose pattern matches a source path in the tree or one of the checks' own source probes, naming the pattern and one such path. A vendor/ path that is a spec, lies in a test, fixture or recorded-session tree, or is Markdown or a consistency record does not make a rule an error, because no rule covers a vendor/ path. A generated rule that names a source file must name it exactly, and the file must hold Generated by scripts/ in its first five lines.
A rule needs no check that its paths still differ. The boundary check prints how many differing paths each rule covers, and a warning for a rule that covers none.
Tooling writes entries and digests, not people or agents. node_modules/.bin/tsx delorun/apps/tools/src/ledger-record.ts compares the working tree with the pinned commit. It adds a stub entry for each differing path that neither an entry nor a rule covers, with TODO as its feature and reason, removes each entry whose path no longer differs, and re-records the digest of each security entry whose file changed, printing each one. The checks refuse a TODO value until the lead writes the class, feature and reason. A re-recorded digest makes the command exit 3, because a changed security file needs the lead's re-review. --check changes nothing and exits 1 when the command would change the ledger; agents run only --check. The lead writes the path rules.
Classes
| Class | Meaning |
|---|---|
delorun-feature | The change serves a Delorun feature. |
generic-fix | The change fixes something upstream could take. Each generic fix has its own commit. |
security | The change moves an approval, a refusal or an escalation. It carries a lead's verdict and a denial test that fails before the change and passes after it. |
A file whose change moves a gate is a security entry, whether it is source, a spec or a page; no path rule replaces a security entry, and a path rule that also matches one leaves it an entry. A security entry records sha256, the SHA-256 digest of its file, which binds the lead's verdict to the content reviewed; it names no feature. Only a security entry may list nonModelVisibleHunks, the digests of diff hunks the lead reviewed as not model-visible inside a statement that registers a model-visible contribution, which ledger-record.ts --non-model-visible-hunk writes and the delorun/apps/tools/README.md passes one hunk per record. A delorun-feature or generic-fix entry names the feature it serves and records no digest. A non-security entry that a path rule also covers is refused as listed and ruled.
Each delorun-feature and generic-fix entry names one feature by a kebab-case id. The table lists the ids, what each covers and the Delorun package, command or lane on v5 that uses it. Features that serve only parked packages are the first candidates to cut when an upstream merge costs more than the owner accepts; host-qualified-keys is the one such feature.
| Feature | What the edits do | Serves |
|---|---|---|
changes | The boot page's recovery screen and the /recovery index path (C21) | shipped plugin-changes |
code-refusal-switch | The loader's refuseCode option and the boot's forwarding of it | a switch, off; no Delorun composition turns it on |
settings-by-chat | The config editor's edited event (C4) and its before-save hook (C1) | shipped cli, which refuses a value for a secret-role field |
container-denial-marker | The sandbox, shell and PTC fields that mark a denial by the environment | shipped confinement, behind a C16 switch |
custom-chat-display | The Custom work-details mode and the presentation policy the chat renderers read | the studio lane |
default-workspace-directory | The operator-named path of the first-use Workspace | shipped bundle-local and cli (delorun start), behind a C16 switch |
delorun-launcher | runCli takes its arguments from the launcher, and the CLI's argument parser and plugin command are built as entries a launcher imports | shipped cli |
doctor | The doctor checks, app, bundle and profile template | shipped cli |
fork-gates | Upstream's documentation and repository gates run over Delorun's tree | repository tooling |
home-process-signals | runProfile's signals and failLoud options, which leave the termination-signal handlers and the last-resort error listeners to a caller that owns them, and its prepare option, which registers a caller's listeners before the first row mounts | shipped cli (the home process, and its secret-field refusals) |
host-qualified-keys | Browser storage keys qualified by the host (C10) | parked contract-host-qualified-keys only |
instruction-consent | Instruction files and skill roots named for the consent check | shipped plugin-instruction-consent |
late-projection-keys | Projection keys registered after a Session's baseline reach open control streams | no Delorun consumer on v5 |
parity-replay | The snapshot harness applies the parity overlay (C16) | the parity replay lane of tools |
permission-defaults | Whether a Session holds no permission preset | shipped plugin-permission-defaults |
plugin-manager-improvements | Plugin-manager diagnostic reasons, opening a plugin's page, and the build-script approval steps operations exports for a launcher's command line | shipped cli (delorun plugin) |
plugin-version-axis | A plugin's engines.delorun range (C17) | shipped update and contract-plugin-versions |
project-identity | Delo Run's copyright line in the root LICENSE, under upstream's notice | the repository |
preset-inspect | The preset_inspect tool, its preset rows and its catalogue entry | a C16 switch, off |
product-name | The build title in the iOS home-screen title and the web manifest | the Web build of tools and release |
profile-history | Profile history, safe mode and the plugin audit on install | shipped cli (delorun recover) and profile-safety |
scheduled-task-consent | The consent asked before a scheduled task wakes its Session | shipped plugin-schedule-consent |
session-created-at | Session list rows carry createdAt | shipped plugin-sidebar (sort by created) |
studio-seams | Settings layout, onboarding, theme, sidebar and one-list workspace seams (WP1.6) | the studio lane; bundle-local sets welcomeNotice |
terminal-card-controls | The terminal card's copy-command control, duration and open start | the studio lane |
trash-purge | Forgetting purged Sessions in the search index and projection cache (C8) | shipped trash |
vendor-rescope | The vendor rescope script's postcondition and skip list | repository tooling |
wsl-hosts | Fixes for WSL hosts in the open-in-app resolver and the non-loopback address test | generic fixes |
Reading the ledger
upstream.repository,upstream.refandupstream.commitpin the upstream commit that every entry is measured against. The pin changes when an upstream release is merged.forkOwnedlists the paths and globs that Delorun owns outright.ruleslists the path rules, each with its pattern, kind and reason.patcheslists each entry with its class, its feature or digest, and a reason that states what the change does and why.retiredlists entries that upstream absorbed, with the absorbing commit and the hunks each one had.
Measuring the ledger
pnpm --filter @delorun/tools check runs the ledger checks and exits 1 on any violation. The checks run against the pinned commit and the working tree. The full list of what they refuse is in the delorun/apps/tools/README.md.
node_modules/.bin/tsx delorun/apps/tools/src/check-fork-boundary.ts --count runs the same checks and prints the divergence: the number of listed entries and their hunks, and the number of rule-covered paths and their hunks. A hunk is one @@ header of git diff --unified=0 against the pinned commit, and an untracked file counts as one hunk. Retired entries are listed separately and are not part of the count.
Divergence budget
The budget limits how far the ledger may grow in one release, and it names the checks that enforce that limit.
- Count. A release's count is the ledger's entries and hunks per class, and the rule-covered paths and hunks as the class
ruled; generated paths are counted underruled. A retired entry is credited against the count: growth is measured net of the entries and hunks that retired entries record. - Growth cap. Growth per release is capped at the larger of 20 entries or 10 % of release 0.1.0's baseline entries. Growth in hunks is capped at the larger of 150 hunks or 10 % of release 0.1.0's baseline hunks.
- Breach. A breach of either cap needs a maintainer decision, recorded in the release notes.
- Rehearsal merge. Delorun's budget requires that the rehearsal merge onto upstream's newest tag fail when conflicted hunks exceed 15 % of the ledger's hunks at that tag. It also fails when any
security-class file conflicts without a recorded maintainer decision.node_modules/.bin/tsx delorun/apps/tools/src/rehearse-upstream.ts --tag <tag>runs the rehearsal merge in a scratch worktree and also holds the growth to the caps;--ref <ref>rehearses a commit or branch already in the clone, such asupstream/master, instead. Thedelorun/apps/tools/README.mddescribes its output. - Baseline. The baseline is the ledger's entries and hunks at release 0.1.0, recorded in that release's notes. Without a recorded baseline, the caps are the floors, 20 entries and 150 hunks.
- Current count.
node_modules/.bin/tsx delorun/apps/tools/src/check-fork-boundary.ts --countprints the ledger's entries and hunks against the base tag.
Divergence records
A substantial change to one upstream area gets its own divergence record, a page in this directory that explains how to merge the next upstream release for that area. The change that creates the divergence adds the page. No records exist yet.
Upstream merges follow the fork boundary rules in the root guide.
Where to go next
The parity checklist records the status and evidence of each difference that the ledger accounts for. The glossary defines the terms on this page. The reference index lists the other developer pages.