turtle1999 d225dbba50 Remove nonessential remnants of Cordis PR 932 1 неделя назад
..
cordis d225dbba50 Remove nonessential remnants of Cordis PR 932 1 неделя назад
cosmokit 6af96785b5 release(vendor): cordis 4.0.2, cosmokit 1.8.3, group 1.0.2, hmr 1.0.17, include 1.0.7, loader 1.0.3, logger-console 1.0.2, schemastery 3.18.2, timer 1.1.4 3 недель назад
group 6af96785b5 release(vendor): cordis 4.0.2, cosmokit 1.8.3, group 1.0.2, hmr 1.0.17, include 1.0.7, loader 1.0.3, logger-console 1.0.2, schemastery 3.18.2, timer 1.1.4 3 недель назад
hmr d225dbba50 Remove nonessential remnants of Cordis PR 932 1 неделя назад
include d225dbba50 Remove nonessential remnants of Cordis PR 932 1 неделя назад
loader d225dbba50 Remove nonessential remnants of Cordis PR 932 1 неделя назад
logger-console 6af96785b5 release(vendor): cordis 4.0.2, cosmokit 1.8.3, group 1.0.2, hmr 1.0.17, include 1.0.7, loader 1.0.3, logger-console 1.0.2, schemastery 3.18.2, timer 1.1.4 3 недель назад
schemastery 6af96785b5 release(vendor): cordis 4.0.2, cosmokit 1.8.3, group 1.0.2, hmr 1.0.17, include 1.0.7, loader 1.0.3, logger-console 1.0.2, schemastery 3.18.2, timer 1.1.4 3 недель назад
timer 6af96785b5 release(vendor): cordis 4.0.2, cosmokit 1.8.3, group 1.0.2, hmr 1.0.17, include 1.0.7, loader 1.0.3, logger-console 1.0.2, schemastery 3.18.2, timer 1.1.4 3 недель назад
AGENTS.md 066f94c7e0 docs: unwrap hard-wrapped Markdown to one line per paragraph 3 месяцев назад
CLAUDE.md 7f024a1a9d Document the codebase thoroughly and tighten type safety 3 месяцев назад
README.md d225dbba50 Remove nonessential remnants of Cordis PR 932 1 неделя назад

README.md

Vendored Packages

This directory contains source-vendored copies of the Cordis framework and its foundation libraries. They are copied into this monorepo instead of being depended on via npm, so that the harness fully owns its framework layer (auditable, patchable, pinned).

All vendored packages use the @deepseek-ai scope (cordis@deepseek-ai/cordis, @cordisjs/plugin-<x>@deepseek-ai/cordis-plugin-<x>). The manifest table records upstream versions and source commits; each package manifest carries its Harness release version and publication metadata. Repository-owned runtime dependencies use workspace:^, so local builds resolve the pinned workspace packages and publication substitutes release ranges. Upstream MIT LICENSE files are preserved in each package directory.

This file covers the manifest, the local-modification log, and the procedure for updating an existing vendored package. To add a new one, see the cookbook guide: docs/cookbook/adding-a-vendored-package.md.

Manifest

Upstream workspace: cordis-workspace (local checkout: ~/repos/cordis-workspace).

Directory npm name Upstream name Version Upstream repo Commit
cosmokit/ @deepseek-ai/cosmokit cosmokit 1.8.1 https://github.com/deepseek-harness/cosmokit 16f6fc058ade66e8ac5da0033d35a8d0f279f544
schemastery/ @deepseek-ai/schemastery schemastery 3.18.0 https://github.com/deepseek-harness/schemastery (packages/core) e67cee00ad725bd1534aee930a979ea3eec6f698
cordis/ @deepseek-ai/cordis cordis 4.0.0-rc.7 https://github.com/cordiverse/cordis (packages/core) 56b3d4f725681cf4556c1a8695a709cc3b6eed74
loader/ @deepseek-ai/cordis-plugin-loader @cordisjs/plugin-loader 1.0.0-rc.5 https://github.com/cordiverse/cordis (packages/loader) 56b3d4f725681cf4556c1a8695a709cc3b6eed74
include/ @deepseek-ai/cordis-plugin-include @cordisjs/plugin-include 1.0.4 https://github.com/deepseek-harness/cordis (packages/include) abb0a307cb1d3b0947f455d590cf5ba922d4caa4
group/ @deepseek-ai/cordis-plugin-group @cordisjs/plugin-group 1.0.0 https://github.com/deepseek-harness/cordis (packages/group) abb0a307cb1d3b0947f455d590cf5ba922d4caa4
timer/ @deepseek-ai/cordis-plugin-timer @cordisjs/plugin-timer 1.1.2 https://github.com/deepseek-harness/cordis (packages/timer) abb0a307cb1d3b0947f455d590cf5ba922d4caa4
hmr/ @deepseek-ai/cordis-plugin-hmr @cordisjs/plugin-hmr 1.0.15 https://github.com/deepseek-harness/cordis (packages/hmr) abb0a307cb1d3b0947f455d590cf5ba922d4caa4
logger-console/ @deepseek-ai/cordis-plugin-logger-console @cordisjs/plugin-logger-console 1.0.0 https://github.com/deepseek-harness/cordis (packages/logger-console) abb0a307cb1d3b0947f455d590cf5ba922d4caa4

Third-party dependencies of the vendored packages stay on npm: @standard-schema/spec, js-yaml, chokidar, picomatch, @babel/code-frame, supports-color, node-addon-require-builtin.

Intentionally not vendored (verified unused by this set): reggol, @cordisjs/utils, @cordisjs/element, @cordisjs/unyaml (dev-time YAML import hook only).

Local modifications

Keep this log exhaustive — every divergence from upstream must be listed.

  1. hmr/src/index.ts: removed the ./locales/en-US.yml / ./locales/zh-CN.yml imports, the .i18n({...}) call on the Config schema, and the src/locales/ directory. Rationale: those imports require a runtime YAML loader hook (@cordisjs/unyaml) that we do not vendor; the i18n texts only localize config descriptions.
  2. All package.json files: regenerated for Harness releases with scoped names, release versions, publication metadata, precise bundled-runtime and lib/types/**/*.d.ts / .d.ts.map file entries, source exports where applicable, and declaration metadata pointing at lib/types. Repository-owned dependencies use the workspace protocol. HMR declares esbuild as a direct dev dependency for its imported BuildFailure type, and Loader requires node-addon-require-builtin@^0.1.4 to match published app runtimes.
  3. All tsconfig.json files: regenerated to extend the repo-root tsconfig.base.json, emit TypeScript intermediates to lib/types, and declare project references.
  4. Vendored TypeScript source internal specifiers: changed local relative imports/exports from upstream's specifier shape to explicit .ts specifiers so TypeScript rewrites emitted JS to .js while declarations keep explicit, NodeNext-safe .ts specifiers. This includes loader/src/config/isolate.ts using declare module './entry.ts'. Type-only dependencies use import type or inline type modifiers so ESM output does not retain erased interfaces.
  5. schemastery/tsdown.config.ts and logger-console/tsdown.config.ts: ours, not upstream files — per-package build-shape overrides (dual ESM+CJS output; separate node/browser entries) for the repo-root tsdown build. They read the JS emitted under lib/types and then write the publish runtime entries under lib/. Like the regenerated tsconfigs, they are not part of the upstream sync surface.
  6. cordis/src/fiber.ts lifecycle hardening: locally closes three reentrant disposal gaps. An effect's owner-list wrapper is registered before its setup body runs, so an unload begun from inside setup awaits setup and every collected cleanup; synchronous setup failure removes the wrapper and rolls back collected cleanup. Async cleanup stays owner-visible until quiescence, and Cordis's internal effect composition joins an already-running cleanup while repeated public disposer calls retain their upstream single-shot result. Effect creation is rejected while the owner is UNLOADING (while PENDING and LOADING remain legal), preventing cleanup-time registrations from escaping the unload snapshot. Child fibers register and receive their parent-owned disposer before internal/plugin publication, resolve dependency declarations added by that notification before activation, drain effects attached while pending, skip plugin execution when reentrant disposal invalidates the load epoch before its first checkpoint, and contain teardown-notification failures per observer so one callback cannot starve peers or interrupt ownership cleanup.
  7. Cordis and Loader JSDoc enrichment: added @param/@returns tags and contract documentation (disposal semantics, waterfall veto, bail conditions, error cases) across the public plugin-author surface — Context (class, statics, and the Context interface properties incl. root), module re-exports, shared utility helpers, EventsService, Fiber, RegistryService, ReflectService, Service, LoggerService and their declare module './context.ts' overloads. Loader documentation covers loader/src/{index,internal,config/entry,config/group,config/isolate,config/tree,config/utils}.ts, including entry ownership, tree mutation methods, and the !!js discriminator. Comment-only; no code changes. Motivation: the website API-reference generator renders these docs and hard-errors on undocumented members. Retire this entry when the enrichment is upstreamed to the fork.
  8. include/src/index.ts resilient file refresh and patch reapplication: #514 validates a top-level entry array before caching parsed content, logs refresh failures, reapplies patches after file or Include-config edits, updates the Include config when it vetoes a restart, and uses initial only after ENOENT. These parse protections retain the running tree after an invalid file; plugin activation failures can leave a partially applied tree. Loader entry/group/tree mutations follow the pinned eager, non-transactional implementation and do not restore previous plugins or options. Covered by packages/boot/app-boot/tests/{config-reload,user-patches}.spec.ts.
  9. hmr/src/index.ts module-watcher readiness and native paths: realpath the existing watch base, classify framework modules and attach listeners before reporting readiness, and compare config paths using both canonical and configured spellings. This preserves Node module-cache identity across Windows short-name paths and filesystem aliases. The main watcher uses ignoreInitial: true so startup reads do not trigger another refresh; exact profile patch watching is owned by packages/boot/app-boot/src/watch-config.ts. Covered by packages/boot/app-boot/tests/watch-config.spec.ts.
  10. Vendored Node-compatible TypeScript: marked erased imports explicitly across cordis, loader, include, hmr, and schemastery so Node's native TypeScript transform does not request types as runtime exports. Schemastery's source uses an ESM default export and its package declares type: module. Conditional exports select .mjs for import and .cjs for require; without them, concurrent imports under module-hook hosts reach the CJS entry and can race its require of ESM Cosmokit (ERR_REQUIRE_ESM_RACE_CONDITION).
  11. include/src/index.ts patch-semantics export: extracted the private applyPatches body into the exported pure function applyEntryPatches(data, patches, warn) (the method delegates to it) and exported the !!js YAML dialect as entryListSchema, so dsh --dump-config composes and prints exactly what the include would mount without booting a tree. The entry list is deep-cloned when patches are present; without patches, the returned array retains the entry objects. Public patch and Include fields carry JSDoc for config tooling. Behavior-preserving for mounting; the extraction exists because config tooling must never reimplement (and drift from) the patch algorithm. applyEntryPatches also indexes each inserted entry as it is added, so a later patch in the same list can configure or disable a row an earlier patch inserted; upstream built the id index once before the patch loop, leaving inserted rows silently unpatchable. That matters because dsh composes an empty profile root with each bundle's patch layer, the profile's and the home-level cordis.patch.yml, and any --patch overlays as sibling patch lists at one include level — patches never cross an include boundary, so surface-only rows would otherwise be unreachable from user config. Covered by packages/boot/app-boot/tests/config-reload.spec.ts.
  12. loader/src/config/entry.ts activation observer: the detached Entry.init() completion observer handles both outcomes; the fiber retains its activation error for explicit consumer audits. Covered by packages/boot/app-boot/tests/user-patches.spec.ts.
  13. include/src/index.ts writeTask type: widened the optional writeTask?: NodeJS.Timeout property to NodeJS.Timeout | undefined — the debounced writer assigns undefined on flush, which exactOptionalPropertyTypes rejects on a plain optional. Type-only; no behavior change.
  14. include/src/index.ts durable debounced writes: serialized and tracked config-file writes, retried transient EACCES/EBUSY/EPERM rename failures with a bounded backoff, observed asynchronous timer rejections, and drained writes before and after child removal during Include teardown. The first drain preserves an existing terminal write failure even if child removal schedules a later write. Missing-file initialization awaits the write and forces a fresh parse before mounting the initial entries. Windows can briefly retain a destination handle after a Loader child disposes; the upstream fire-and-forget rename escaped as an unhandled rejection and could lose the persisted disabled state. A terminal failure is logged by the asynchronous writer and remains on the queue so Include.stop() rethrows it instead of silently declaring persistence complete; Cordis's ordinary fiber teardown retains its separate error-containment contract. Covered by packages/host/directory-picker-auto/tests/loader-composition.spec.ts with injected transient and terminal rename failures.
  15. Lazy Loader config resolution across cordis/src/{events,fiber}.ts, loader/src/{index,config/entry}.ts, include/src/index.ts, and hmr/src/index.ts: ports cordiverse/cordis#41, retaining raw fiber config and resolving it through internal/config only after declared injections are active. Provider replacement re-resolves the raw expression, pending updates retain it, and HMR transfers it. Resolution applies only to the entry root, so child plugins mounted by a row keep caller-owned config identity. Include declares the EntryGroup.key tree-carrier marker (as Group does): its config is entry and patch lists, so interpolation keeps it literal and a !!js expression inside a nested row's config resolves lazily in that row's own fiber (Include's own path therefore stays literal too). Deferred failures retain the owning row diagnostic, and tree teardown does not persist failure-driven self-disposal. Covered by packages/boot/app-boot/tests/{app-boot,user-patches}.spec.ts, packages/boot/cmdline/tests/cmdline.spec.ts, apps/cli/tests/web-agent-presets.e2e.ts, and the built custom-profile cases in apps/cli/tests/built-bin.e2e.ts.
  16. cordis/package.json publishes src: added src to the files list, joining the other eight vendored packages. Cordis declares "./src/*": "./src/*" in its exports, so a tarball without src publishes an export map pointing at absent files; the release change judgement also reads files to decide whether a diff reaches the payload, and a package whose only published paths are build output has no tracked path to match.
  17. @deepseek-ai rescope: every vendored manifest name, every internal dependency entry among the vendored set, and every module specifier that reaches them use the scoped names in the manifest table's npm name column. Directory names, version numbers, and dependency ranges are unchanged, and no upstream runtime identifier is renamed — Symbol.for('schemastery') and Schemastery's vendor: metadata field keep their upstream values. Re-apply with pnpm run rescope-vendor --apply after a sync; the table's two name columns are the mapping, restated for consumers in docs/rescope.md.
  18. Entry disabled interpolation in loader/src/config/entry.ts: a disabled: !!js expression evaluates against the loader context at every mount decision; the raw node stays in the options, so write-back keeps the !!js form. disabled is the only interpolated metadata field. Covered by packages/boot/app-boot/tests/user-patches.spec.ts and apps/cli/tests/windows-shell.spec.ts.
  19. loader/src/internal.ts runtime shape detection: ModuleLoader.fromInternal() classifies the internal loader by which module-job API it owns — getOrCreateModuleJob for v2, getModuleJobForImport for v1 — instead of by Node major version. Upstream tags every major >= 24 as v2, but the v2 interface arrived in Node 24.12.0, so 24.0–24.11.1 report major 24 while still carrying the v1 loader; consumers then called resolveSync with reversed parameters and every call threw. dsh web served an empty client graph (__DSH_BOOT__.entries: []) and HMR partial reload resolved no entry URL, both behind swallowed or warn-level errors. Arity cannot discriminate the two shapes, because each reports resolveSync.length === 2. A loader owning neither API is left unclassified rather than guessed, so consumers take their documented no-internals path. Covered on the node-compat Node version matrix, which pins 24.9 for the mistagged range.

Sync procedure

To update a vendored package from upstream:

  1. In the upstream workspace, note git rev-parse HEAD of the relevant submodule.
  2. Copy the package's src/ (and bin.js, README.md, LICENSE if changed) over the vendored directory.
  3. Re-apply the local modifications listed above (or drop them if upstream made them unnecessary — update the log either way).
  4. Update the version and commit hash in the manifest table.
  5. Run pnpm install && pnpm run test && pnpm run build at the repo root.