dsh-ops 0.0.0-stage → 0.2.1

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.
Files changed (139) hide show
  1. package/CHANGELOG.md +189 -0
  2. package/LICENSE +30 -0
  3. package/NOTICE +106 -0
  4. package/PROVENANCE.md +417 -0
  5. package/README.en.md +121 -0
  6. package/README.md +113 -2
  7. package/README.zh.md +114 -0
  8. package/bin/dsh-ops.mjs +1216 -0
  9. package/cordis.patch.yml +160 -0
  10. package/docs/manual-validation.md +53 -0
  11. package/docs/schema-baseline.json +64 -0
  12. package/docs/schema-current.json +84 -0
  13. package/docs/schema-measurement.md +17 -0
  14. package/dsh-plugin.json +88 -0
  15. package/icon.svg +12 -0
  16. package/lib/binary.js +409 -0
  17. package/lib/config.js +198 -0
  18. package/lib/handshake.js +252 -0
  19. package/lib/index.js +108 -0
  20. package/lib/jobs.js +42 -0
  21. package/lib/policy.js +64 -0
  22. package/lib/presentation.js +63 -0
  23. package/lib/profile-install.js +61 -0
  24. package/lib/rust.js +194 -0
  25. package/lib/session-shells.js +78 -0
  26. package/lib/shells.js +993 -0
  27. package/lib/tools.js +657 -0
  28. package/locale/en.json +6 -0
  29. package/locale/zh.json +6 -0
  30. package/package.json +114 -4
  31. package/vendor/fastctx/Cargo.lock +3210 -0
  32. package/vendor/fastctx/Cargo.toml +94 -0
  33. package/vendor/fastctx/FORK.md +119 -0
  34. package/vendor/fastctx/LICENSE-APACHE +201 -0
  35. package/vendor/fastctx/NOTICE +40 -0
  36. package/vendor/fastctx/README.md +439 -0
  37. package/vendor/fastctx/THIRD_PARTY_LICENSES.md +17 -0
  38. package/vendor/fastctx/THIRD_PARTY_LICENSES_RUST.md +7914 -0
  39. package/vendor/fastctx/UPSTREAM.md +49 -0
  40. package/vendor/fastctx/build.rs +413 -0
  41. package/vendor/fastctx/src/background_status.rs +403 -0
  42. package/vendor/fastctx/src/binary.rs +75 -0
  43. package/vendor/fastctx/src/bounded_sort.rs +500 -0
  44. package/vendor/fastctx/src/budget.rs +781 -0
  45. package/vendor/fastctx/src/cli/mod.rs +110 -0
  46. package/vendor/fastctx/src/context_guard.rs +289 -0
  47. package/vendor/fastctx/src/control/mod.rs +6 -0
  48. package/vendor/fastctx/src/control/paths.rs +49 -0
  49. package/vendor/fastctx/src/control/settings.rs +753 -0
  50. package/vendor/fastctx/src/control/transaction.rs +531 -0
  51. package/vendor/fastctx/src/edit/document.rs +535 -0
  52. package/vendor/fastctx/src/edit/locks.rs +371 -0
  53. package/vendor/fastctx/src/edit/mod.rs +213 -0
  54. package/vendor/fastctx/src/edit/private_storage/unix.rs +315 -0
  55. package/vendor/fastctx/src/edit/private_storage/windows.rs +793 -0
  56. package/vendor/fastctx/src/edit/private_storage.rs +234 -0
  57. package/vendor/fastctx/src/edit/replace.rs +1030 -0
  58. package/vendor/fastctx/src/edit_server.rs +53 -0
  59. package/vendor/fastctx/src/encoding/reference_v011.rs +587 -0
  60. package/vendor/fastctx/src/encoding/snapshot_pipeline.rs +1678 -0
  61. package/vendor/fastctx/src/encoding.rs +1118 -0
  62. package/vendor/fastctx/src/file_executor.rs +1151 -0
  63. package/vendor/fastctx/src/file_snapshot.rs +1491 -0
  64. package/vendor/fastctx/src/glob_filter.rs +98 -0
  65. package/vendor/fastctx/src/glob_tool.rs +653 -0
  66. package/vendor/fastctx/src/grep_sink.rs +1162 -0
  67. package/vendor/fastctx/src/grep_tool.rs +2449 -0
  68. package/vendor/fastctx/src/lib.rs +45 -0
  69. package/vendor/fastctx/src/main.rs +15 -0
  70. package/vendor/fastctx/src/model.rs +51 -0
  71. package/vendor/fastctx/src/model_guidance.rs +62 -0
  72. package/vendor/fastctx/src/operation.rs +356 -0
  73. package/vendor/fastctx/src/ordered_window.rs +1235 -0
  74. package/vendor/fastctx/src/os_environment.rs +414 -0
  75. package/vendor/fastctx/src/path_codec.rs +850 -0
  76. package/vendor/fastctx/src/paths.rs +244 -0
  77. package/vendor/fastctx/src/process_identity.rs +763 -0
  78. package/vendor/fastctx/src/process_policy.rs +74 -0
  79. package/vendor/fastctx/src/read_tool/batch.rs +496 -0
  80. package/vendor/fastctx/src/read_tool/hex_file.rs +141 -0
  81. package/vendor/fastctx/src/read_tool/image_file.rs +88 -0
  82. package/vendor/fastctx/src/read_tool/mod.rs +245 -0
  83. package/vendor/fastctx/src/read_tool/pdf.rs +470 -0
  84. package/vendor/fastctx/src/read_tool/pdf_disabled.rs +47 -0
  85. package/vendor/fastctx/src/read_tool/pdf_engine.rs +664 -0
  86. package/vendor/fastctx/src/read_tool/text_file.rs +351 -0
  87. package/vendor/fastctx/src/render_plan.rs +468 -0
  88. package/vendor/fastctx/src/runtime/activity.rs +159 -0
  89. package/vendor/fastctx/src/runtime/hosts.rs +99 -0
  90. package/vendor/fastctx/src/runtime/journal.rs +556 -0
  91. package/vendor/fastctx/src/runtime/local_ipc.rs +186 -0
  92. package/vendor/fastctx/src/runtime/mod.rs +746 -0
  93. package/vendor/fastctx/src/runtime/protocol.rs +296 -0
  94. package/vendor/fastctx/src/runtime/session.rs +536 -0
  95. package/vendor/fastctx/src/runtime/windows_process.rs +66 -0
  96. package/vendor/fastctx/src/search_parallelism.rs +106 -0
  97. package/vendor/fastctx/src/search_text.rs +227 -0
  98. package/vendor/fastctx/src/server.rs +359 -0
  99. package/vendor/fastctx/src/server_manifest.rs +468 -0
  100. package/vendor/fastctx/src/server_support.rs +826 -0
  101. package/vendor/fastctx/src/session.rs +629 -0
  102. package/vendor/fastctx/src/shell/apply_patch_hint.rs +41 -0
  103. package/vendor/fastctx/src/shell/bash.rs +263 -0
  104. package/vendor/fastctx/src/shell/buffer.rs +108 -0
  105. package/vendor/fastctx/src/shell/encoding.rs +403 -0
  106. package/vendor/fastctx/src/shell/foreground.rs +115 -0
  107. package/vendor/fastctx/src/shell/jobs/admission.rs +91 -0
  108. package/vendor/fastctx/src/shell/jobs/background.rs +146 -0
  109. package/vendor/fastctx/src/shell/jobs/host.rs +830 -0
  110. package/vendor/fastctx/src/shell/jobs/identity.rs +29 -0
  111. package/vendor/fastctx/src/shell/jobs/mod.rs +1513 -0
  112. package/vendor/fastctx/src/shell/jobs/model.rs +244 -0
  113. package/vendor/fastctx/src/shell/jobs/output_log.rs +1148 -0
  114. package/vendor/fastctx/src/shell/jobs/store.rs +1300 -0
  115. package/vendor/fastctx/src/shell/mod.rs +345 -0
  116. package/vendor/fastctx/src/shell/normalize.rs +389 -0
  117. package/vendor/fastctx/src/shell/output.rs +406 -0
  118. package/vendor/fastctx/src/shell/process.rs +493 -0
  119. package/vendor/fastctx/src/shell_server.rs +156 -0
  120. package/vendor/fastctx/src/skip_report.rs +83 -0
  121. package/vendor/fastctx/src/stdio_transport.rs +177 -0
  122. package/vendor/fastctx/src/tool_schema.rs +204 -0
  123. package/vendor/fastctx/src/traversal.rs +846 -0
  124. package/vendor/fastctx/third-party/pdfium-7763/LICENSE +9 -0
  125. package/vendor/fastctx/third-party/pdfium-7763/licenses/abseil.txt +202 -0
  126. package/vendor/fastctx/third-party/pdfium-7763/licenses/agg23.txt +14 -0
  127. package/vendor/fastctx/third-party/pdfium-7763/licenses/fast_float.txt +27 -0
  128. package/vendor/fastctx/third-party/pdfium-7763/licenses/freetype.txt +169 -0
  129. package/vendor/fastctx/third-party/pdfium-7763/licenses/icu.txt +542 -0
  130. package/vendor/fastctx/third-party/pdfium-7763/licenses/lcms.txt +27 -0
  131. package/vendor/fastctx/third-party/pdfium-7763/licenses/libjpeg_turbo.ijg +260 -0
  132. package/vendor/fastctx/third-party/pdfium-7763/licenses/libjpeg_turbo.md +135 -0
  133. package/vendor/fastctx/third-party/pdfium-7763/licenses/libopenjpeg.txt +32 -0
  134. package/vendor/fastctx/third-party/pdfium-7763/licenses/libpng.txt +134 -0
  135. package/vendor/fastctx/third-party/pdfium-7763/licenses/libtiff.txt +21 -0
  136. package/vendor/fastctx/third-party/pdfium-7763/licenses/llvm-libc.txt +278 -0
  137. package/vendor/fastctx/third-party/pdfium-7763/licenses/pdfium.txt +230 -0
  138. package/vendor/fastctx/third-party/pdfium-7763/licenses/simdutf.txt +18 -0
  139. package/vendor/fastctx/third-party/pdfium-7763/licenses/zlib.txt +29 -0
package/PROVENANCE.md ADDED
@@ -0,0 +1,417 @@
1
+ # Provenance
2
+
3
+ What this repository is, where its parts came from, what was verified, and what
4
+ was not.
5
+
6
+ ## 0.2.1 Windows payload packaging
7
+
8
+ The assembler now builds all three Windows x64 payload packages. Bash carries
9
+ complete, unmodified PortableGit 2.56.0.2 (GNU bash 5.3.15); pwsh carries complete
10
+ PowerShell 7.6.6 under bin/. Original licenses/notices are preserved. Archive
11
+ and executable hashes are pinned in lib/shells.js. All three runtime packages
12
+ are injected into the main publish artifact; no install lifecycle downloads.
13
+
14
+ The maintainer authorized publication after the source-delivery risk was reported.
15
+ The first attempt used an old local npm credential and received E403; explicitly
16
+ selecting the maintainer-provided bypass token succeeded. This was a credential
17
+ selection error, not proof the provided token lacked bypass permission. PortableGit's
18
+ etc/package-versions.txt includes many GPL/LGPL components; complete matching
19
+ source closure/delivery has not been collected or reviewed. Retaining upstream
20
+ licenses does not attest that those obligations have been fulfilled. No source
21
+ offer is invented. Historical 0.2.0 pin-package descriptions below do not describe
22
+ this new payload layout.
23
+
24
+ The profile installer delegates to the official DSH CLI, retaining its locks,
25
+ compatibility checks and rollback rather than cloning them. Live installation
26
+ on each application version has not been attested. Default README is Chinese;
27
+ README.en.md is the English counterpart.
28
+
29
+ ## Current slimming-pass evidence (supersedes historical ladder claims below)
30
+
31
+ This pass changes only plugin presentation, registration, and result projection; no vendored functionality changed. Historical tables below describe the earlier implementation and its earlier tests, not acceptance of the current revision.
32
+
33
+ - Restored three-layer intent: tools → ops_bash → PowerShell 7. `lib/session-shells.js` publishes bash through plugin-owned agent child fibers only with full-access authority and the subprocess service; it is independent of FastCtx availability and enableShellTools. Prompt routing prefers bash for general commands, not PowerShell fallback.
34
+ - Permission authority: host `packages/sandbox/sandbox-policy/src/index.ts:157-186`, `sandboxPolicy.resolve({session})`; durable mode event at `src/session-mode.ts:25-56`.
35
+ - Session mode feed: `ctx.on('session/event', (session, event))`, not client-wire projection change notifications. The plugin reconciles plugin-owned agent child fibers on `sandbox/mode`.
36
+ - Own registration scopes: `packages/core/tools/src/index.ts:1058-1088`; inherited restrictions and own-layer exemption at `:1090-1124,1163-1206`; prompt callbacks use assembly agent plus `ctx.get('tools').schemas(agent)`.
37
+ - Concurrency API: `packages/core/tools/src/index.ts:267-280,1303-1309` requires a pure function, not a boolean. FastCtx's read/search handlers use shared bounded permits and blocking executors (`vendor/fastctx/src/server.rs:198-280`); MCP request IDs isolate pending replies. Only read-only tools opt into sibling overlap.
38
+ - Host timeout metadata requires work quiescence; the current MCP transport removes pending waits but cannot prove server cancellation. No host `timeoutMs` promise is added.
39
+ - Job launch ID is parsed only from FastCtx's successful terminal marker (`vendor/fastctx/src/shell/jobs/mod.rs:232-278`); global durable lists at `:1053-1250` are projected to session-owned IDs. Footer grammar/placement comes from `vendor/fastctx/src/background_status.rs`.
40
+ - Baseline at pre-change plugin HEAD `dee3c57`, runtime FastCtx 0.2.6, is recorded in `docs/schema-baseline.json`. `scripts/measure-schemas.mjs` measures compact name/description/parameters JSON, not use frequency or actual billing.
41
+ - Per operator instruction: no regression tests or CI added, no existing suite updated or run. Syntax checks and schema-list measurements are not runtime acceptance. See `docs/manual-validation.md`.
42
+ - Residual boundaries: file tools remain outside the host filesystem sandbox; shell-mode gating does not confine `ops_replace`. Approval and sandbox state are separate; no new approval escalation is implemented. Reconnect loses job ownership and does not prove durable jobs terminated.
43
+
44
+ ## Two bodies of work
45
+
46
+ | | Author | License | Where |
47
+ | --- | --- | --- | --- |
48
+ | The dsh-ops plugin | this repository | MIT | `lib/`, `bin/`, `scripts/`, `test/`, `cordis.patch.yml`, `dsh-plugin.json`, docs |
49
+ | FastCtx, vendored | [yc-duan](https://github.com/yc-duan) | Apache-2.0 | `vendor/fastctx/` |
50
+
51
+ `vendor/fastctx/UPSTREAM.md` records the exact upstream revision;
52
+ `vendor/fastctx/FORK.md` records every difference from it — the distribution
53
+ machinery removed, the standalone-only code removed, and every source file this
54
+ fork touches (each carries its own Apache-2.0 §4(b) notice at the top). The
55
+ composite licensing statement is in `NOTICE`.
56
+
57
+ ## Distribution and binary sources
58
+
59
+ The plugin reaches a profile as a dependency of that profile — `dsh plugin
60
+ --profile <p> add dsh-ops`, or `plugin_manager { action: "install_bundle" }`. What
61
+ that install brings is this distribution's own work: one payload we build, and two
62
+ pins. The channels and the commands are described in the README under "What an
63
+ install brings".
64
+
65
+ ### What this distribution ships
66
+
67
+ | Artifact | Contents |
68
+ | --- | --- |
69
+ | `dsh-ops@0.2.0` | the plugin itself: JavaScript, the manifest, the bundle patch, and the vendored FastCtx source. 497,013 B packed, 2,339,108 B unpacked, 130 files |
70
+ | `@dsh-ops/fastctx-win32-x64@0.2.0` | **a payload we build**: this fork's FastCtx, `bin/fastctx.exe` |
71
+ | `@dsh-ops/bash-win32-x64@0.2.0` | **a pin only**: upstream URL, release, version, byte count, and SHA-256. No binaries |
72
+ | `@dsh-ops/pwsh-win32-x64@0.2.0` | **a pin only**: the same for PowerShell 7. No binaries |
73
+ | `SHA256SUMS` (release asset) | the digests of those four tarballs, attached to the tag's GitHub Release beside them |
74
+
75
+ ### What this distribution does not ship
76
+
77
+ The Git for Windows and PowerShell archives are **not** redistributed here: no
78
+ tarball, no release asset, and no cache in this repository holds them.
79
+ `dsh-ops provision-shells` reads the pin, downloads the archive from the upstream
80
+ URL on the user's own machine, verifies it against the pinned SHA-256, and unpacks
81
+ it under `<DSH_HOME>/dsh-ops/shells/<name>/<version>/`. Those bytes travel from
82
+ upstream to that machine directly, and the licences below are the ones the user
83
+ obtains them under.
84
+
85
+ ### The pins
86
+
87
+ | Package | Upstream source | Release | Version | Artifact | Bytes | SHA-256 | Licence |
88
+ | --- | --- | --- | --- | --- | --- | --- | --- |
89
+ | `@dsh-ops/fastctx-win32-x64` | this fork's build of `vendor/fastctx/`, upstream `yc-duan/fastctx` at `ccaa157790d02328a60786eb94ee5ad698995a5f` | `v0.2.6` | `0.2.6` | `bin/fastctx.exe`, built here | 49,492,480 | `7f4b494627cf3c0b298dd0b6d36624fd09d35bd1add655c5d55e0372e9e20987` | Apache-2.0 |
90
+ | `@dsh-ops/bash-win32-x64` | [Git for Windows](https://github.com/git-for-windows/git) | `v2.56.0.windows.2` | `2.56.0.2` | `PortableGit-2.56.0.2-64-bit.7z.exe` — fetched by the user, not redistributed here | 60,027,568 | `075e158ef8e1f0ab80b347e245405d3eca735c2dc88fd8e032e137d0ca61f61b` | GPL-2.0-only |
91
+ | `@dsh-ops/pwsh-win32-x64` | [PowerShell](https://github.com/PowerShell/PowerShell) | `v7.6.6` | `7.6.6` | `PowerShell-7.6.6-win-x64.zip` — fetched by the user, not redistributed here | 106,328,873 | `02fe458be20493fbdf43f61ea20610b811ee6c738ab1676c61b9cfcd1a33c860` | MIT |
92
+
93
+ The pin values live in one table — `SHELL_UPSTREAM_PINS` in `lib/shells.js`, which
94
+ `dsh-ops provision-shells` downloads from and the release build imports when it
95
+ publishes the pinned facts beside the packages it assembles — and the release's
96
+ `provenance.json` records what was built from them. The URLs are upstream's own
97
+ release URLs verbatim, so a pin can be checked against the upstream release page
98
+ rather than trusted from here. Each pin also records the digest of the executable
99
+ inside its archive (`bin/bash.exe`, `bin/pwsh.exe`), which the provisioner re-checks
100
+ after unpacking, so an archive that yields something else is refused. Unpacked, the
101
+ bash pin is about 390 MiB and the PowerShell pin about 245 MiB on disk — which is
102
+ why neither is part of an install.
103
+
104
+ Every `@dsh-ops/*` platform package is an optional dependency of the published
105
+ main package, and each one carries its own `LICENSE`, `NOTICE`, and metadata beside
106
+ that payload or pin.
107
+
108
+ ### The licence each pin points at
109
+
110
+ The plugin's composite statement is `MIT AND Apache-2.0`, and it covers the plugin
111
+ alone. The two shell pins point at someone else's distribution:
112
+
113
+ - **`fastctx` — this fork's Apache-2.0, plus upstream's notice.** The payload is
114
+ built here from `vendor/fastctx/`, so it ships `vendor/fastctx/LICENSE-APACHE` and
115
+ `vendor/fastctx/NOTICE`, and every source file this fork touched already carries
116
+ its own §4(b) change notice (`vendor/fastctx/FORK.md` is the enumeration).
117
+ FastCtx's required attribution is reproduced verbatim in `NOTICE` and in both
118
+ READMEs; that text is reproduced, never edited.
119
+ - **`bash` — Git for Windows' GPL-2.0.** The pin names the upstream archive and its
120
+ digest; the download, the extraction, and the resulting copy on disk are the
121
+ user's, and the GPL-2.0 terms (and the corresponding source, published by the Git
122
+ for Windows and Git projects) attach to those bytes. No GPL-2.0-covered component
123
+ is part of this distribution, which is why nothing here carries a GPL text or
124
+ makes a source offer for code it does not ship.
125
+ - **`pwsh` — Microsoft's MIT.** The same shape: the pin points at Microsoft's own
126
+ release asset, the download happens on the user's machine, and the licence text
127
+ and copyright are Microsoft's. Nothing in the plugin's MIT grant covers it.
128
+
129
+ ## Host targeting
130
+
131
+ The plugin targets DSH `0.2.0-rc.2`, the version of the desktop installation this
132
+ was developed against.
133
+
134
+ The source of that exact version is readable on this machine: `dsh-core/v0.2.0-rc.2/`
135
+ is a checkout of tag `dsh-v0.2.0-rc.2` (`639ed015`, commit date 2026-09-29),
136
+ 14,104 files. The installed host itself ships inside `app.asar` and stays
137
+ unreadable from a shell, so the readable copy is what "the host" means below.
138
+
139
+ Each depended-on API is therefore established twice: **read** from that source,
140
+ with the file and line recorded here, and **run** by the suite named in the same
141
+ row. The line numbers are of `dsh-core/v0.2.0-rc.2/` and will move with upstream;
142
+ the file is the durable part.
143
+
144
+ | Depended on | Read from | Run by |
145
+ | --- | --- | --- |
146
+ | `new Context()`, `ctx.plugin`, `ctx.inject`, `ctx.effect`, `ctx.on`, `ctx.waterfall`, `ctx.get` | Cordis source, vendored: `vendor/cordis/src/` | the mount suite boots a real context and disposes it |
147
+ | `tools.register(definition)` — one object argument, returns the unregister disposer | `packages/core/tools/src/index.ts:1057-1088` | the mount suite reads back the nine registered schemas, and the shells suite asserts the `ops_bash` definition and that its disposer removes it |
148
+ | `tools.restrict(filter)` — `{allow?, deny?}` over the global tools of one agent scope; requires a scoped context, rejects unknown names, intersects, lifts on dispose | `packages/core/tools/src/index.ts:1090-1124`, type at `:700-705` | **used by this plugin**: on `agent/created`, and only while a rung of its own is live, it masks the configured host shell tools out of that agent's own view (`lib/index.js` `hideHostShellTools`), and the disposer it returns is handed to the plugin's effect too. The mount suite asserts the masked names leave `schemas(agent)`, stop resolving through `get(name, agent)`, are still refused by the fence, stay registered globally, and come back when the plugin unloads; a name the agent registered itself makes `restrict()` throw, which the plugin reports once and leaves visible |
149
+ | `tools.guard(guard)` — monotonic denial registered after the pre-execute waterfall; the guard returns a denial reason or `undefined` | `packages/core/tools/src/index.ts:1126-1142`, type at `:723-731` | not used by this plugin yet: the fence at `tools/pre-execute` — with its model-readable reason and its `next()` delegation — plus the per-agent mask already implement `deny-host-shell` |
150
+ | `tools.get(name, scope?)` — the definition one scope resolves, or undefined; the lookup half of "visibility, lookup, and execution agree" | `packages/core/tools/src/index.ts:1230` | the mount suite only: a masked host shell name must not resolve for that agent while it stays registered globally |
151
+ | `ctx.on('agent/created')` and the agent's own scoped context (`agent.ctx`) — the event fires once per agent, after its scope is published and before its queued work is released and its prompt first assembled; the payload is `{agent, source, signal}` | `packages/core/agent/src/runtime-types.ts:261` (the typed event), sequenced at `packages/core/agent/src/index.ts:172-181` and emitted serially at `:550` | the mount suite dispatches the real event (`ctx.serial('agent/created', …)`) into real `@deepseek-ai/dsh-scope` scopes and asserts all three outcomes: hidden while a rung of the plugin's own is live, reported-and-visible when no such rung is live, and reported-and-visible when `restrict()` cannot name the tool |
152
+ | `tools/pre-execute` waterfall, `(exec, next) => PreToolDecision`, `@mode waterfall` | `packages/core/tools/src/index.ts:142-153` | the fence suite dispatches the real waterfall and asserts `{kind:'deny'}` |
153
+ | `systemPrompt.section({name, order, text, interpolate})`, duplicate names throw, returns an effect disposer | `packages/core/system-prompt/src/index.ts:446-463`, `PromptSection` at `:52-76` | the mount suite renders both sections from a real assembly |
154
+ | `systemPrompt.assemble({})` resolves sections in ascending order, equal orders by name | `packages/core/system-prompt/src/index.ts:548-558`, sort at `:237-238` | the mount suite asserts both sections appear in one assembly |
155
+ | `ctx.get('tools').schemas()` — one deep-cloned schema per visible tool, the global view when no scope is passed; the plugin's only answer to "are the `ops_` tools live right now" (asked at every prompt assembly) and to "which host shell names does this agent actually see" (asked when it hides them) | `packages/core/tools/src/index.ts:1252-1262` | the mount suite renders the tooling section from a real assembly and asserts it names exactly the live tools; it also reads `schemas(agent)` before and after a mask |
156
+ | `ctx.get('subprocess')` — the abstract `SubprocessRuntime`: `spawn(spec)` with a fully explicit `argv`, `cwd`, per-stream stdio, `graceMs`, cancellation, and `env` overrides merged after the service's own credential scrub; `argv` is never shell-interpreted | `packages/subprocess/subprocess/README.md:28` (mount and consume), `:44-46` (the call shape), `docs/subsystems/subprocess.md:91-104` (the fully-explicit spec), `:267-269` (`ctx.subprocess` registration) | the shells suite, through a recording subprocess service: `ops_bash` spawns `argv: [<resolved bash>, '-c', <command>]`, forwards exactly the terminal overrides, adds no credential-shaped name of its own, and reports a missing service instead of throwing something opaque. The mount suite is where the service is real, and where the registration is shown to be gated on it: with no `ctx.subprocess`, a resolved bash publishes no rung and installs no mask |
157
+ | the credential rule both spawn paths keep: a child never inherits credential-shaped names or ambient `DSH_*` facts, and a transport that owns its own spawn (the SDK client, MCP) stays outside the service so the policy has one source | `packages/subprocess/subprocess/README.md:80` (the scrub and its merges), `:84` (route around the service when the transport owns the spawn), `:104` (`scrubbedParentEnv`), `packages/subprocess/subprocess-local/README.md:156` (the scrub is a name heuristic, not a guarantee) | the mount suite's `childEnv` check, for the MCP child. That child's rule is restated in `lib/tools.js` `childEnv()` rather than imported, because importing `scrubbedParentEnv` would be the `@deepseek-ai/*` value import this host half forbids; the `ops_bash` child gets the service's own scrub instead (`ctx.get('subprocess')` above) |
158
+ | this plugin's own `ops_` namespace is its conflict domain: a name already registered in the same scope throws, so the whole generation is rolled back rather than half-published | `packages/core/tools/src/index.ts:746-748` (both duplicate branches) | not covered against the real host — no suite publishes a colliding name; the fixture's registry raises on a duplicate (`test/mount.test.mjs`) and `#publish` in `lib/tools.js` is where the rollback lives |
159
+ | a bundle is a package declaring `dsh.bundle.patch`, and a layer replaces a row's whole `config`: | `docs/user/develop/basic/publish.md:11-16`, `:56-64`, `:129-132` | `scripts/validate-manifest.mjs` parses the shipped patch and runs the row's config through the plugin's own validator |
160
+ | Cordis answers every service property read with a fresh traceable wrapper | `vendor/cordis/src/utils.ts:116-125` (`getTraceable`) and `:165-218` (`createTraceable`, a new `Proxy` per read) | the incident's regression assertions in the mount suite: the registry carries no own `register` after mount, and the same foreign name registered once in each of two scopes stays out of this plugin's global view |
161
+ | `ctx.pluginManager` (`installBundle`, `removeBundle`, `setBundleEnabled`, `setPluginEnabled`, `inspect`, `registries`, `waitForInstall`, `cancelInstall`, version exemptions) | `docs/subsystems/boot.md:85-180` | not run here; the install path is exercised by hand, not by a suite |
162
+
163
+ One row left this table when the plugin began speaking MCP itself:
164
+ `@deepseek-ai/dsh-mcp-client` and its `mcp__<serverName>__<rawName>` naming
165
+ contract are not part of this plugin's dependency surface — nothing in `lib/`
166
+ imports it, mounts it, or names anything after the names it would have produced.
167
+ The `0.2.0` changelog entry records its removal from `package.json`, together with
168
+ the declaration and the manifest check that went with it.
169
+
170
+ The package versions under test are pinned in `devDependencies`, so the gate is
171
+ reproducible. Because those are npm releases of the same packages rather than the
172
+ copies inside `app.asar`, a host-side API change between `0.2.0-rc.2` and what
173
+ this repository installs surfaces as a red mount suite.
174
+
175
+ Two things the read established that the earlier execution-only record could not:
176
+
177
+ - **`tools.register` takes one object, not `(name, definition)`.** The earlier
178
+ record said "the ToolRuntime `register`", which left the argument form to the
179
+ suite. The signature is `register(definition: ToolDefinition): () => void`
180
+ (`packages/core/tools/src/index.ts:1063`), and it validates `output.schema`,
181
+ `output.render`, and `timeoutMs` before registering.
182
+ - **`restrict` and `guard` exist, with exactly the monotonic semantics this
183
+ plugin's design assumes.** `restrict` narrows what one agent inherits
184
+ (`:1097`), `guard` denies after the waterfall and cannot be turned back into
185
+ permission by a later listener (`:1136`, `:723-731`). The plugin uses `restrict`
186
+ for the visibility half of `deny-host-shell` and is runtime-verified for it; it
187
+ registers no `guard` yet, so that half is read-only here.
188
+
189
+ ### The boundary the 2026-10-08 incident established
190
+
191
+ **What happened.** While the plugin still mounted the harness MCP bridge, it
192
+ renamed that bridge's tools by installing an interceptor on the shared tool
193
+ registry — `interceptBridgeRegistrations` wrote an own `register` property on the
194
+ service object. A Cordis service property read returns a wrapper **bound to the
195
+ reading context** (`vendor/cordis/src/utils.ts:165-218`), so the interceptor's
196
+ `original.call(…)` attributed every later registration — including foreign ones —
197
+ to *this* plugin's host plane. The host's second registration of a name that
198
+ another plugin installs per agent (`subagent`) then collided and **every new
199
+ session failed**: `tool "subagent" is already registered (for a per-agent variant,
200
+ register through that agent's `agent.ctx` instead)`
201
+ (`packages/core/tools/src/index.ts:746-747`, the `scope === undefined` branch,
202
+ i.e. the global layer). A fresh `DSH_HOME` without this plugin did not fail, which
203
+ is what located the fault here rather than in the composition.
204
+
205
+ **What stands now.** The plugin publishes its own tools through its own
206
+ `ctx.tools.register` (`lib/tools.js` for the hosted nine, `lib/shells.js` for
207
+ `ops_bash`) and rewrites nothing: no own property on the shared registry, no
208
+ replaced service method, no name derived from another component's naming. The one
209
+ place it acts on another context's tools is `agent.ctx.tools.restrict({ deny })` —
210
+ the documented per-agent visibility call, made on that agent's own scoped registry
211
+ to hide the host shell tools this deployment asked to deny. The symptoms, the
212
+ mechanism, and the regression contract are stated in the plugin's `AGENTS.md`,
213
+ "上游兼容 (upstream compatibility)"; that section is the authority for the
214
+ boundary, and `test/mount.test.mjs` is the executable form of it.
215
+
216
+ Rules that follow, and that this repository must not regress:
217
+
218
+ - **Do not replace a shared service method to observe or reshape it.** Reading a
219
+ service method is not identity-stable, and the wrapper carries the caller's
220
+ context, so re-entering through a saved `original` changes whose registration it
221
+ is.
222
+ - **The public namespace is this plugin's own registrations.** `ops_<name>` comes
223
+ from `publicToolName()` in `lib/policy.js` and is registered into this plugin's
224
+ scope, so no other component's naming can change or claim it.
225
+ - **Release only through the disposers the surface collected.**
226
+ `ctx.get('tools').register` is not identity-stable across two reads
227
+ (`ctx.get('tools').register !== ctx.get('tools').register`), so a registration
228
+ cannot be recognized by function identity; one generation is published and
229
+ released as one unit.
230
+ - **Foreign registrations are none of this plugin's business.** A name in another
231
+ server's namespace, a lookalike of this plugin's own, or the same name in two
232
+ scopes must survive a mount, an unload, and each other — `test/mount.test.mjs`
233
+ is what keeps that true.
234
+ - **Act on another context's tools only through its documented API, on that
235
+ context.** The per-agent mask is `agent.ctx.tools.restrict({ deny })`, called on
236
+ the agent's own scoped registry and released through the plugin's effect as well;
237
+ the plugin never reaches into a registry instance and never names a tool that
238
+ agent registered itself.
239
+
240
+ ### Not verified here
241
+
242
+ - **A real `dsh plugin add` into a live profile.** The profile that booted the
243
+ session which produced this record is the one that installed the plugin by
244
+ `link:`, so the install did happen — but through a manual profile edit, not
245
+ through `dsh plugin`. The *installation path* (`dsh plugin --profile … add`, the
246
+ profile's `dsh.profile.bundles` ordering, the host compatibility gate reading
247
+ `peerDependencies`) is documented from the harness sources above, not exercised
248
+ by a suite in this repository.
249
+ - **Hot reload of a replaced package.** `ctx.hmr` is read
250
+ (`docs/subsystems/boot.md:56-83`) and the upstream rule that replacing an
251
+ installed package needs a restart is quoted in the README
252
+ (`packages/preset/agent-preset/skills/cordis-plugin-development/references/host-plugin.md:60`),
253
+ but no suite here replaces a mounted package and observes the new module
254
+ generation.
255
+ - **A conflicting registration against the real host.** `lib/tools.js` publishes
256
+ one whole generation and rolls a partial one back when a name is already taken,
257
+ but no suite publishes a name that collides with this plugin's `ops_` namespace
258
+ against the real registry: only the fixture's own registry in
259
+ `test/mount.test.mjs` raises on a duplicate.
260
+ - **The platform packages and the pins, against a real tag.** The release step
261
+ declares `@dsh-ops/fastctx-<platform>-<arch>` and the two pins, and the shell
262
+ layouts they can resolve to are exercised against a temporary install in
263
+ `test/shells.test.mjs` — including the L3 expression agreeing with the plugin's own
264
+ probe on every layout. What has never run is the release pipeline itself: no tag has
265
+ been pushed and nothing has been published, so no tarball and no Release asset has
266
+ been fetched from a release, and no deployment has yet resolved a runtime from one.
267
+ The first real tag is what has to prove that path end to end.
268
+ - **A `provision-shells` download against upstream's live assets.** The pin values
269
+ are read from `SHELL_UPSTREAM_PINS` in `lib/shells.js`, and the digests there were
270
+ checked against the archives this machine downloaded while the release build was
271
+ assembled — but that was a build-time fetch here, not `dsh-ops provision-shells`
272
+ fetching into `<DSH_HOME>/dsh-ops/shells/` on a user's machine, and not a
273
+ re-download of the pinned bytes after upstream had served them again. Whether
274
+ upstream still serves the pinned URL, and whether the extracted tree is the one the
275
+ plugin's probe accepts, is what the first run of that command has to establish.
276
+ - **A real DSH boot running the L3 override.** The patch's `!!js` expression is
277
+ parsed from `cordis.patch.yml` and evaluated the way the vendored loader does it
278
+ (`with (ctx) { return eval(expr) }`, `vendor/loader/src/config/utils.ts:5-9`) —
279
+ inert without a bundled pwsh, resolving one with it — but no DSH boot has mounted
280
+ the patched `pwsh-sandbox` row.
281
+
282
+ ## Design decisions worth recording
283
+
284
+ ### Two spawn paths, one credential policy
285
+
286
+ The plugin reaches every host service through `ctx.inject([...])` / `ctx.get()` and
287
+ imports no `@deepseek-ai/*` value at any point. That leaves two ways to start a
288
+ process, and the credential rule is kept on both.
289
+
290
+ **The FastCtx server is the plugin's own spawn** (`lib/handshake.js`,
291
+ `node:child_process.spawn`), because it is the plugin's transport, and the harness's
292
+ own guidance for that case is to stay outside the subprocess service — "when a
293
+ transport owns its own spawn (the SDK client, MCP), route around the service and
294
+ import `scrubbedParentEnv` directly so environment policy stays single-sourced"
295
+ (`packages/subprocess/subprocess/README.md:84`). Importing `scrubbedParentEnv` is
296
+ exactly the value import this host half forbids, so the rule is restated in
297
+ `lib/tools.js` `childEnv()`: credential-shaped names (`*KEY*` / `*PASSWORD*` /
298
+ `*SECRET*` / `*TOKEN*`) and ambient `DSH_*` facts are dropped, tool configuration
299
+ locations such as `GH_CONFIG_DIR` survive, and the mount suite pins that behaviour.
300
+ The heuristic has the limits upstream documents
301
+ (`packages/subprocess/subprocess-local/README.md:156`): a differently named secret
302
+ passes through.
303
+
304
+ **`ops_bash` goes through the service** (`lib/shells.js`). It has no reason to own a
305
+ spawn, so it takes the harness's real credential scrub, output spilling, and
306
+ process-range termination, and supplies only the argv, the directory, the budgets,
307
+ the terminal overrides, and its cancellation — read with `ctx.get('subprocess')`
308
+ rather than imported. Nothing in the plugin writes `process.env`, `PATH`, or the
309
+ working directory.
310
+
311
+ ### One question decides the ladder and the mask
312
+
313
+ `ladderLevels({published, pwsh})` (`lib/policy.js`, a pure function) turns the
314
+ published `ops_` names plus one resolution fact into the three rungs: rung 1 is live
315
+ when any published name is not one of this plugin's own in-process tools — so the
316
+ shell tools cannot stand in for a server that is not there — rung 2 when `ops_bash`
317
+ is among them, and rung 3 when this plugin has a pwsh of its own on this platform.
318
+ `hostShellEnforcement({shellPolicy, levels})` then asks the same object whether
319
+ `deny-host-shell` may hide the host shell tools, and it is asked again as each agent
320
+ appears. Both answers therefore follow "what the model can reach"; `resolveShells()`
321
+ supplies the detail and the report and never the decision. The `tools/pre-execute`
322
+ fence is installed by the mode alone, so the guarantee does not depend on either
323
+ answer.
324
+
325
+ ### Rung 3 is a bundle patch; rung 2 is a tool
326
+
327
+ The two bundled rungs are implemented differently because the host leaves two
328
+ different seams open, and both were read from the host source rather than assumed:
329
+
330
+ - **Rung 2 must be a tool.** `bash-local` has no executable field — its config is
331
+ `cwd`/`timeoutMs`/`maxTimeoutMs`/`maxOutputBytes`/`maxSpillBytes`/`graceMs`
332
+ (`packages/shell/bash-local/src/index.ts`) — so the only zero-internal-dependency
333
+ way to run the plugin's own bash is to publish `ops_bash` and execute through
334
+ `ctx.subprocess`. The rung is therefore the published tool, not the resolved
335
+ executable: a bash that resolved without that service is a rung the model cannot
336
+ reach, so `lib/shells.js` publishes nothing, names the resolved bash in its report,
337
+ and the ladder has no rung 2.
338
+ - **Rung 3 must be a patch.** `pwsh-sandbox` inherits `pwshPath` verbatim from
339
+ `pwsh-local` (`packages/shell/pwsh-sandbox/src/index.ts:40`, `type Config =
340
+ LocalConfig`), so pointing that row at the plugin's executable puts the bundled
341
+ pwsh 7 under the host's sandbox, credential scrub, and output governance with no
342
+ custom executor and no patched internals. A bundle patch is evaluated before any
343
+ `dsh-ops` row is mounted, which is also why there is no config key for it: a key
344
+ could never reach the expression, and a key that pretended to would make the
345
+ ladder claim a rung the host row never runs. A patch replaces the target row's
346
+ entire `config`, so every non-default field must be restated — the target row
347
+ declares none (`packages/bundle/base/cordis.patch.yml:241-243`), and the shells
348
+ suite asserts that the shipped patch writes `pwshPath` and nothing else.
349
+ **The expression and the probe are single-sourced by an order, not by an import**
350
+ (a bundle patch is plain YAML and cannot import `lib/shells.js`): both accept
351
+ `PWSH_LAYOUT_ORDER` — the provisioned copy under
352
+ `<DSH_HOME>/dsh-ops/shells/pwsh/<version>/` first, then an installed
353
+ `@dsh-ops/pwsh-<platform>-<arch>` package's `bin/pwsh.exe`, then
354
+ `vendor/pwsh/<platform>-<arch>/pwsh.exe` inside this package — apply the same
355
+ `lstat`-based usability test, and the shells suite asserts that agreement on every
356
+ layout, so the ladder's rung 3 and the host row are one fact rather than two
357
+ guesses.
358
+
359
+ ### No Schemastery `Config`
360
+
361
+ The plugin exports no `Config` schema, so the row's config is validated by
362
+ `lib/config.js` instead. A `Config` export means importing
363
+ `@deepseek-ai/schemastery` — a value import whose resolution the profile loader
364
+ owns — and this host half deliberately imports no `@deepseek-ai/*` value at load
365
+ time. There is no exception now: every host service this plugin needs arrives as
366
+ a service, never as an import.
367
+
368
+ ### Resolution and probing are synchronous
369
+
370
+ `apply` resolves the executable and probes it with `--version` before returning.
371
+ Both are synchronous, so they belong in `apply` rather than behind a service
372
+ injection: `required: true` must reject *activation*, which is only observable if
373
+ the failure happens while the loader is still loading the plugin.
374
+
375
+ ### Prompt section orders 1500 and 3250
376
+
377
+ The harness allocates named section orders centrally, and an external
378
+ contribution supplies its own numbers. Reading the table
379
+ (`packages/core/system-prompt/src/index.ts:125-159`):
380
+
381
+ - **1500 is already claimed** — it is `TOOL_GREP`. The host-shell rule therefore
382
+ shares an order with a first-party section instead of sitting in a gap. Equal
383
+ orders are broken by name, code-unit order (`:231-238`), so
384
+ `dsh-ops:host-shell-policy` sorts before `tool-grep`; the rule still lands after
385
+ `TOOL_BASH` (1000) and before `MCP_SERVERS` (3100), which is the position the
386
+ policy text is written for. `lib/policy.js` states the same allocation in place,
387
+ and `scripts/validate-manifest.mjs` compares both numbers against the manifest.
388
+ - **3250 sits in a real gap** — between `MCP_SERVERS` (3100) and `TOOLS_SDK`
389
+ (5000), which is where the tooling section is meant to sit.
390
+
391
+ ### `ctx.get('tools')`, never `ctx.tools`, from the prompt scope
392
+
393
+ The tooling section's text function asks the registry whether the FastCtx tools
394
+ exist, and `lib/shells.js` asks it where to register `ops_bash`. Both run from
395
+ injection scopes that do not declare `tools`; the `ctx.tools` property proxy is
396
+ topology-sensitive and answered `undefined` there. The mount suite caught this — the
397
+ section rendered empty next to nine registered tools.
398
+
399
+ ## Verification record
400
+
401
+ On Windows x64 with Node 24.18.0, at the commit that carries this record. The
402
+ totals are the output of that run; what has to keep holding is what the suites
403
+ assert, not the count:
404
+
405
+ ```console
406
+ node scripts/validate-manifest.mjs # all 47 checks passed
407
+ node test/run.mjs # 7 suites, 122 checks, passed in 9s
408
+ node bin/dsh-ops.mjs status # fastctx 0.2.6 from the managed runtime, 9 tools
409
+ ```
410
+
411
+ The vendored source build:
412
+
413
+ ```console
414
+ cargo 1.97.1 (c980f4866 2026-06-30)
415
+ cargo build --release --locked # Finished `release` profile in 7m 05s
416
+ vendor/fastctx/target/release/fastctx.exe --version # fastctx 0.2.6
417
+ ```
package/README.en.md ADDED
@@ -0,0 +1,121 @@
1
+ # dsh-ops
2
+
3
+ Reduce tokens, time and model attention wasted on repeated PowerShell errors in
4
+ Windows DSH. The bundle supplies independent **bash 5.3.15**, **PowerShell 7.6.6**,
5
+ and high-performance Rust repository tools powered by FastCtx.
6
+
7
+ Routing: **file tools → bash → PowerShell 7**. Prefer bash for general commands;
8
+ use pwsh only for necessary Windows-native operations. Fix bash errors in bash.
9
+ Windows x64 only; target DSH `0.2.0-rc.2`. [中文](README.md)
10
+
11
+ ## Install, update and remove
12
+
13
+ In the official marketplace, enter **`dsh-ops`**, install, then enable. This installs
14
+ into the running application's profile. All three Windows runtime packages are
15
+ installed as dependencies: no postinstall downloads and no system PATH changes.
16
+
17
+ ```console
18
+ npx --yes dsh-ops@latest install --profile desktop
19
+ npx --yes dsh-ops@latest install --profile web
20
+ npx --yes dsh-ops@latest install --profile tui
21
+ ```
22
+
23
+ An explicit profile is required. `tui` maps to the dsh-TUI product's **dsh-tui**
24
+ profile, not the old tui directory. Initialize the target application first.
25
+ The wrapper delegates locking, compatibility and rollback to the official DSH CLI.
26
+
27
+ Desktop uses its own `resources/runtime/cli/bin/dsh.cmd`, auto-detected under
28
+ `%LOCALAPPDATA%/Programs/DeepSeek Harness`. For another installation, pass
29
+ `--dsh-cli "<installation>/resources/runtime/cli/bin/dsh.cmd"`. Ordinary DSH CLI
30
+ cannot manage the reserved desktop profile. Web/TUI require an available DSH CLI;
31
+ `--dsh-cli` can also specify that executable explicitly.
32
+
33
+ Equivalent official commands:
34
+
35
+ ```console
36
+ dsh plugin --profile web add dsh-ops
37
+ dsh plugin --profile dsh-tui add dsh-ops
38
+ "<desktop installation>/resources/runtime/cli/bin/dsh.cmd" plugin --profile desktop add dsh-ops
39
+ ```
40
+
41
+ Update by repeating the npx install command, or official `add dsh-ops@latest`.
42
+ Reload/restart as the application requests; replacing loaded code may require restart.
43
+
44
+ ```console
45
+ npx --yes dsh-ops@latest status --profile desktop
46
+ npx --yes dsh-ops@latest uninstall --profile desktop
47
+ ```
48
+
49
+ Use web/tui as appropriate. Marketplace uninstall and official `remove dsh-ops`
50
+ also remove profile dependency references. Runtime files are package dependencies,
51
+ not a new shared provisioned directory. System shells, other profiles and package
52
+ manager caches are never manually deleted. Clean legacy provisioned files separately
53
+ with `npx --yes dsh-ops@latest uninstall --yes`; `~/.fastctx/` is kept unless
54
+ `--purge-fastctx` is explicit. Unload/downgrade does not prove durable jobs stopped.
55
+
56
+ ## Configuration and tools
57
+
58
+ Edit the dsh-ops row's `config` in the DSH configuration editor. Unknown keys fail.
59
+
60
+ ```yaml
61
+ config:
62
+ enableShellTools: true
63
+ publishBashTool: true
64
+ promptPolicy: true
65
+ toolCallTimeoutMs: 300000
66
+ required: false
67
+ shellPolicy: advise
68
+ allowSystemShellFallback: true
69
+ # binaryPath: 'C:\tools\fastctx.exe'
70
+ # bashPath: 'C:\tools\bash.exe'
71
+ ```
72
+
73
+ `enableShellTools` controls the FastCtx command/job group; `publishBashTool` controls
74
+ bash. Both additionally require authoritative session `danger-full-access`; bash
75
+ also requires the host subprocess service. `promptPolicy` controls compact routing;
76
+ `extraGuidance` appends text. RPC wait timeout does not prove server termination.
77
+ `required` fails activation on unavailable runtime. Explicit binary/bash paths are
78
+ authoritative. `shellPolicy: deny-host-shell` blocks `deniedHostTools` (default
79
+ `[pwsh, bash, pwsh_persistent]`), including the third-layer pwsh; use cautiously.
80
+
81
+ | Tools | Purpose | Full access |
82
+ | --- | --- | --- |
83
+ | ops_inspect_local_file | Batch text ranges, encoding, PDF text and hex | No command gate¹ |
84
+ | ops_grep | Rust regex, file filters, counts/summaries | No command gate¹ |
85
+ | ops_glob | Multiple path patterns and exclusions | No command gate¹ |
86
+ | ops_replace | Mechanical cross-file replacement; host edit for precise edits | No command gate¹ |
87
+ | ops_bash | Preferred general bash executor | Required |
88
+ | ops_run | Bounded bash result | Required |
89
+ | ops_run_background | Start background jobs | Required |
90
+ | ops_job_output / ops_job_list / ops_job_kill | Operate on this session's owned jobs | Required |
91
+ | Host pwsh | Bundled PowerShell 7 Windows-native operations | Host policy |
92
+
93
+ ¹ File tools are **not host filesystem-confined**, including ops_replace. Do not
94
+ use this bundle as a security boundary for untrusted restricted deployments.
95
+ Images belong to host read_image. Permissions are reconciled dynamically and
96
+ rechecked on execution; job ownership is per session and connection, lost on reconnect.
97
+ See [manual validation](docs/manual-validation.md) and [schema measurements](docs/schema-measurement.md).
98
+
99
+ ## License
100
+
101
+ Plugin source: **MIT AND Apache-2.0**. Outside vendor/fastctx: MIT; vendored FastCtx:
102
+ Apache-2.0. See [NOTICE](NOTICE), vendor/fastctx/LICENSE-APACHE and vendor/fastctx/NOTICE.
103
+ The independent Windows payload packages retain upstream component licenses:
104
+ Git for Windows includes GPL components; PowerShell includes MIT and third-party
105
+ components. The plugin's MIT does not relicense them. See [PROVENANCE](PROVENANCE.md).
106
+
107
+ ## Acknowledgements
108
+
109
+ The Rust tools use source from yc-duan's FastCtx Codex plugin. Distribution changes
110
+ are recorded in vendor/fastctx/FORK.md and vendor/fastctx/UPSTREAM.md. Required notice:
111
+
112
+ > This product includes FastCtx
113
+ > (https://github.com/yc-duan/fastctx), Copyright (c) 2026 yc-duan,
114
+ > used under the Apache License 2.0.
115
+ >
116
+ > FastCtx is redistributed and/or modified here by the maintainer of
117
+ > this distribution. Any such change is that maintainer's own work
118
+ > and their sole responsibility. It is not endorsed by, not
119
+ > supported by, and not attributable to the author of FastCtx, who
120
+ > accepts no liability of any kind arising from this distribution or
121
+ > from anything built on top of it.