Keeps the apply_patch toolview registration with master's file-menu inject,
takes master's shortened slot JSDoc, re-adds the seven filesystem type-equiv
manifest entries, regenerates the event matrix and client catalogs, moves the
fs-observation-policy upgrade guide under v0.2.2-alpha.2 with the matching
fs-patch version, and refreshes the two SDK scenarios master added for the
write and edit guidance change.
Takes master's re-measured npm install-layout budget, which covers this
branch's graph, and regenerates the Cordis API, event matrix, client slot,
and tool catalogs on the merged tree.
Resolves the headless snapshot runner (keeps both the readonly-patch-directory
and cua-script-guidance workspace setups), regenerates the client slot and tool
catalogs with their pairing record, adds the apply_patch tool title to the five
locales master introduced, and refreshes the apply-patch system-prompt pin for
master's subagent guidance change.
* fix(agent-instructions): budget the user-global and project chains separately
The user-global and project instruction files shared one maxBytes and the user-global files were the broadest, so a large project chain omitted them first. Each chain now renders under maxBytes on its own and the results share one system-reminder frame: unchanged output when everything fits or one chain is empty, at most twice maxBytes otherwise. The project chain keeps its omit-broadest-first, truncate-last rule; reconciliation batches follow the same split; the maxBytes key and the baseline identity are unchanged.
Tests cover the fast paths, both chains fitting only separately, each chain over its own budget, the 2 × maxBytes boundary at exact and tiny limits, multibyte content, reconciliation batches, and a resumed single-budget baseline receiving the user-global file as one transition. The agent-instructions-budget snapshot is refreshed and agent-instructions-budget-chains is added. README, Config.maxBytes JSDoc, the configuration catalog, a new Agent Note, and an upgrade guide state the per-chain bound.
* fix(agent-instructions): keep loaded order in merged frames and note the unshared chain budget
A merged frame now lists sections, omissions and truncations in the loaded order, so a reconciliation batch renders its items in one order whether or not it fits a single budget. The guard comment states only the invariant and points to the Agent Note; the intro selection states its rule. The README names the unshared budget between chains.
---------
Co-authored-by: ZiyaZhang <[email protected]>
Add @deepseek-ai/dsh-agent-model. It provides ctx.agentModel
(resolveForNextStep, select, applyConfiguredRoute) and owns the
modelSelection projection, which the Agent registry no longer registers.
dsh-agent-loop now injects agentModel; the base and SDK-minimal bundles
and the Python SDK runtime include it.
The provider keeps the projection registered until consumers that are
still unloading finish their cleanup. The model-switch notice becomes an
opt-in per-Agent plugin at @deepseek-ai/dsh-agent-model/notice, and
agent/request now also rejects reasoning-effort changes after step
preparation.
Mount the provider in every composition that loads dsh-agent-loop, and
update consumers, the switch-notice snapshot driver, docs, and the
upgrade guide.
Regenerate config/tool/module/event catalogs, Cordis API and client slot catalogs; re-record reviewed bilingual hashes instead of merging generated bytes.
Accept deleted filesystem invariant companions. Master has no replacement event-invariant registration; keep delete-intent in typed events, policy guards, and behavior tests.
Adopt master workspace-changes intent waterfalls and tool-execution recorder association, add a prepended delete-intent listener that delegates before capture, remove argument parsing and the fs-patch dependency, and retain the real-tool Review matrix.
Keep master filesystem mutation-result metadata and tool switches alongside opt-in apply_patch. Await current-directory resolution in plan and no-follow preflight; store patch diffs as processPath. Adapt native/PTC fixtures to the supported modes.
Preserve client patch diffs and stopped states with master partial arguments and absolute navigation. Use master's rewritten ProviderEditor, including its remaining repeated model validation.
Regenerate the lockfile with pnpm install and align the new fs-patch package version. Clean retired package build outputs. Update exact rescope exceptions for verified preset and event identifiers from master; old package names remain rejected.
When a visible shared file became a content duplicate, reconciliation emitted
a removal notice and discarded its metadata. Its durable state then remained
remove, while the metadata fast path accepted only candidates without any
previous record. Every subsequent unchanged pass therefore reread the file,
even after a later read had populated the cache. This also affected the path
where an edited earlier winner made an unchanged later file a duplicate.
Retain the still-present duplicate's metadata with the removal's deferred
version update. Pass the already-cached state when removal follows an unchanged
metadata probe, and the newly read state when the duplicate's content changed.
Apply this metadata only when the associated removal survives rendering, using
the existing exact-transition filter; confirmed absence still clears metadata.
Allow both never-rendered candidates and previous removals to skip content reads
when unchanged provider metadata and an earlier kept digest identify the file as
a duplicate. Continue probing metadata. Once the winner changes or disappears,
read and promote the shared file normally, then suppress unchanged follow-ups.
Document the metadata guarantee in the local cache types and bilingual README.
Model-visible messages, source records, ordering, and byte budgets stay the same.
Add four production-plugin regressions covering duplication after either file
changes, then promotion after the winner is edited or deleted. They inspect the
provider's actual content reads across two unchanged passes and require exactly
one shared read for promotion, rather than trusting the context's self-report.
Validation:
- All four new cases failed before the fix because each unchanged pass reread
the shared file despite unchanged metadata.
- pnpm exec vitest run packages/context/agent-instructions/tests/agent-instructions.spec.ts -t 'caches a removed duplicate': 4 passed after the fix.
- README pairing was rerecorded; git diff --check passed.
- The removal regression narrows its source kind and compares the change as a
plain typed value; no matcher carrying any is assigned into an expected record.
- Type-aware Oxlint passed for the three affected packages and the new
metadata-failure fixture; focused cache regressions passed again after the
assertion correction.
A content-deduplicated shared file has no visible change record. If its
metadata became unavailable while the harness-home winner changed or vanished,
the reconciler skipped the failed candidate and still published the winner's
replacement or removal. Guidance that remained in the shared file disappeared
from the model's effective instructions. Content-read failures had the same
partial-group behavior even when metadata probing succeeded.
Rollback the probed candidate group whenever any metadata probe is unavailable
or its bounded content read cannot complete. Include candidates without a
visible predecessor and candidates previously removed as duplicates. Reuse
one rollback operation for proposed messages, deferred version updates,
metadata mutations, and retained digest bookkeeping, so a later successful pass
can reconstruct the complete group independent of cache warmth.
A filesystem path can also appear as a project instruction when the Harness
home is the project root. Releasing observed paths on rollback let that later
alias publish the very content withheld by the failed global group. A transient
failure of the first member also left failed and unvisited paths unreserved.
Factor the existing scope-to-file path calculation and reserve every eligible
member's absolute path for the rest of that pass when its group rolls back.
Project aliases therefore cannot bypass group preservation, without additional
filesystem operations. The shared resolver keeps probing and rollback path
calculations identical. Add metadata, content-read, and one-shot first-member
failure regressions for this supported same-file layout and its recovery.
Keep cancellation propagating to the caller. Keep explicit baseline-budget
exclusions outside observation rollback, because their removals are deliberate
policy decisions. No new session fields, baseline identities, polling, retries,
or process-global state are needed. Clarify the metadata/content and hidden
candidate guarantee in the bilingual README.
Add four real-plugin outage/recovery tests for metadata or content failure while
the retained home file is edited or deleted, plus a cold-cache reconciliation
regression. Add an authored headless session scenario with instance-local
provider failure injection: request two keeps baseline A while shared metadata
is unavailable; request three receives the home B replacement and shared A
addition together after recovery. The fixture restores the provider method on
disposal and asserts the real home/shared files before restoring observation.
Declare its test-only filesystem dependency without changing runtime packages.
Regenerate the persistence catalog's source anchors after the shared path
helper import shifts AgentInstructionSource by one line. Its persisted fields
and SHA-256 type fingerprint remain unchanged; no type acknowledgement or
Session migration is required for a source-location-only update.
Validation:
- All five new regressions failed with the intended partial-group emissions
before the source fix.
- pnpm exec vitest run packages/context/agent-instructions/tests/agent-instructions.spec.ts -t 'hidden duplicate has|cold global group|unavailable active candidate|unavailable scope': 8 passed.
- pnpm exec vitest run packages/context/agent-instructions: 174 passed.
- The focused authored headless snapshot refresh and replay passed.
- Restoring the early skip for an unavailable hidden candidate makes the
headless snapshot fail with the premature harness-home replacement.
- README translations were updated together and their pairing rerecorded.
- Three project-alias regressions failed on the initial group rollback fix,
then passed after reserving failed and unvisited candidate paths.
- pnpm exec vitest run packages/context/agent-instructions/tests/agent-instructions.spec.ts -t 'frozen across a project alias|hidden duplicate has|cold global group|caches a removed duplicate': 12 passed.
A baseline can deduplicate identical harness/shared instructions before the
byte renderer omits their retained winner. Removing every deduplicated scope
from excludedScopes then made the shared copy eligible on the next unchanged
step. It injected the broader instructions the baseline had deliberately
omitted, contradicting the retained-baseline budget policy. Project sibling
copies had the same problem.
Allow a duplicate to leave the exclusion set only when the included baseline
contains its candidate group and trimmed digest. Match the digest as well as
the group: a different sibling may fit the budget while the duplicate's winner
does not. Use the included files' original content so truncated and empty
represented winners retain their ordinary duplicate-promotion behavior.
Copies of omitted content inherit that omission for the visible baseline.
Duplicates of represented content remain probed and can be promoted when their
winner changes or disappears. Keep both README languages, the existing shared
root decision, and the local result-field documentation consistent with this
rule. No durable event fields or baseline identities change.
Add plugin regressions for identical global copies across repeated steps and
resumes, and an omitted project digest with a different retained sibling. Add
an authored recorded-session scenario that runs the shipped headless profile
with identical 1900-byte global files and a 700-byte budget: its two model
requests retain one project-only baseline and never inject the shared copy.
Validation:
- Both new plugin regressions failed on the reviewed implementation with two
contexts instead of one, then passed with the fix.
- pnpm exec vitest run packages/context/agent-instructions/tests/agent-instructions.spec.ts -t 'duplicate budget-omitted|different digest fits|content-deduplicated shared|changed shared file': 4 passed.
- pnpm run test:snapshot:refresh snapshots/session/headless.snapshot.ts -t agent-instructions-budget: passed.
- pnpm run test:snapshot snapshots/session/headless.snapshot.ts -t agent-instructions-budget: passed.
- Reverting only src/index.ts to the reviewed head makes that snapshot fail
with an extra agents-global set and 304 bytes of omitted global content.
- pnpm run test:snapshot scripts/session-snapshot-corpus.corpus.ts: 3 passed.
- Scoped bilingual pairing was rerecorded and verified; git diff --check passed.
The user-global instruction scope now reads two roots: $DSH_HOME/AGENTS.md
first, then the shared agents root that other agent tools use
($DSH_AGENTS_HOME, else ~/.agents). Both resolve from the process environment
through @deepseek-ai/dsh-home-paths; no config field is added, because the
stack base (PR #5718) removed the per-row home override.
The two files are candidates of one candidate group: identical trimmed content
renders once from the harness home, an unobservable candidate preserves the
group's last-good state, and reconciliation probes both roots so external
edits, removals, and new files become visible change notices. A candidate
dropped as a duplicate keeps being reconciled, so deleting or changing the
retained candidate promotes it. The harness-home file keeps its recorded
`user-global` scope key; the shared file carries `agents-global`.
A user-global delta states `These user-global instructions apply to all work.`
instead of naming its reconciliation scope, and a project path whose first
component would collide with a user-global scope directory renders with a
leading `.` so it keeps its own scope.
The removed dshHome row key still redirected instruction loading away from
DSH_HOME. Schemastery's non-strict object validator preserves unknown keys,
and resolveConfig forwarded the validated row wholesale to the library
discovery normalizer, which intentionally accepts an already-resolved home.
Removing the public field and schema entry therefore left the old runtime
override active and contradicted the upgrade guide.
Copy only the declared discovery controls when normalizing a plugin row.
Home resolution now follows process policy even when the row retains a stale
dshHome or another undeclared home field such as agentsHome. This allowlist
also applies when the shared-agents-root stack layer adds its internal home
parameter, without widening the deployment-facing configuration.
Keep the exported discovery and baseline-loading helpers' explicit home
parameter: it carries a library owner's already-resolved path, rather than
granting a plugin row its own home. Extend that regression through baseline
loading to preserve this distinction. Document the ignored stale row key in
both package READMEs and refresh their pairing record. No Session format,
candidate ordering, budget, or instruction rendering changes are required.
Add a production Cordis/schema regression that mounts a row with both stale
home keys and checks model-visible baseline and refresh content. Before the
fix, its baseline contained the stale row instruction instead of the process
home instruction. Both stages now use the process home, and the same test
will reject an agentsHome leak after propagation into the upper stack layer.
Validation:
- pnpm exec vitest run packages/context/agent-instructions/tests/agent-instructions.spec.ts -t 'ignores a stale row home'
failed before the source fix with the intended content mismatch.
- pnpm exec vitest run packages/context/agent-instructions/tests/agent-instructions.spec.ts -t 'ignores a stale row home|uses an already-resolved home'
passed both focused tests after the fix.
- pnpm exec vitest run packages/context/agent-instructions/tests/agent-instructions.spec.ts
passed all 157 tests with both stale row keys present.
- pnpm exec tsc -b packages/context/agent-instructions/tsconfig.json passed.
- pnpm run doc-sync passed all 42 gates.
- pnpm run test:snapshot snapshots/session/headless.snapshot.ts -t 'agent-instructions'
passed the selected recorded-session replay.
- pnpm run verify-translation-pairing --write packages/context/agent-instructions/README.md
refreshed the bilingual record; doc-sync verified it.
- git diff --check passed.
`resolveDiscoveryConfig` accepted `DiscoverOptions.dshHome` but resolved the
home from the environment alone, so a caller passing an already-resolved home
silently received the process home while the option comment claimed otherwise.
It now normalizes the passed value, which keeps the plugin's mount-time
resolution authoritative for discovery and reconciliation. A test pins that an
owner-resolved home wins over `$DSH_HOME`.
Review follow-ups:
- The guide claimed the removed field was the last per-row home override;
other providers (skill-filesystem, shell-env, credentials-local,
subagent-dsh-sdk, attachment-local) keep their own fields, so it now states
that the removal covers the instruction loader, and step 1 also names the
home-level `$DSH_HOME/cordis.patch.yml` layer.
- `DiscoverOptions` regains an already-resolved `dshHome` that `apply()` passes
from its mount-time `resolveConfig()`, so baseline discovery and
reconciliation share one resolution point instead of reading the environment
separately.
- The package README says the loader reads the process home rather than "the
same home as sessions, skills, and storage", and the resolver Agent Note
states what the skill provider's fields actually select.
- `discoverBaselineInstructionFiles` JSDoc no longer lists a removed option.