@xuanling-rs/xuanling-dsh-skills 0.2.2 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README-ZH.md +21 -0
- package/README.md +26 -0
- package/cordis.patch.yml +28 -0
- package/package.json +25 -2
- package/skills/xuanling-file-workflow/SKILL.md +93 -0
- package/skills/xuanling-file-workflow/agents/openai.yaml +4 -0
- package/skills/xuanling-memory-workflow/SKILL.md +85 -0
- package/skills/xuanling-memory-workflow/agents/openai.yaml +4 -0
- package/strict-overwrite-policy.mjs +45 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 umbrella22 and XuanLing contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README-ZH.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# xuanling-dsh-skills
|
|
2
|
+
|
|
3
|
+
[English](README.md) | 简体中文
|
|
4
|
+
|
|
5
|
+
该 DeepSeek Harness bundle 包含两个按需 XuanLing 工作流 Skill 和严格整文件覆盖 policy。
|
|
6
|
+
它不注册 MCP server,也不依赖 `@xuanling-rs/xuanling-mcp`。
|
|
7
|
+
|
|
8
|
+
```sh
|
|
9
|
+
dsh plugin --profile web add @xuanling-rs/xuanling-dsh-skills@0.2.4
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
该命令会扩展 DSH 内置的 Web profile。内置 Headless profile 应使用 `--profile headless`。
|
|
13
|
+
未知 profile 名称只包含 base bundle,本身不会提供可运行的 Web 或 Headless 应用。
|
|
14
|
+
|
|
15
|
+
请与且仅与一个 XuanLing 工具 bundle 组合使用。只有 fs 工具族可见时,
|
|
16
|
+
`xuanling-file-workflow` 才在 Harness 原生与 XuanLing 文件工具之间路由,并覆盖 CAS overwrite、
|
|
17
|
+
复合后缀、原子多 hunk patch、确定性重复验证和 Host 后台任务。`xuanling-memory-workflow` 将项目
|
|
18
|
+
局部 L1 事实与共享 XuanLing L2 事实分开,按显式指针 pull recall,并保持 proposal/review 边界。
|
|
19
|
+
Policy 会在 MCP dispatch 前拒绝缺少 `expected_sha256` 的既有文件覆盖。
|
|
20
|
+
|
|
21
|
+
要求 Node.js 22.14 或更高版本。使用 MIT License。
|
package/README.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# xuanling-dsh-skills
|
|
2
|
+
|
|
3
|
+
English | [Simplified Chinese](README-ZH.md)
|
|
4
|
+
|
|
5
|
+
DeepSeek Harness bundle containing two on-demand XuanLing workflow Skills and
|
|
6
|
+
the strict whole-file overwrite policy. It registers no MCP server and has no
|
|
7
|
+
dependency on `@xuanling-rs/xuanling-mcp`.
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
dsh plugin --profile web add @xuanling-rs/xuanling-dsh-skills@0.2.4
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
This command augments DSH's shipped Web profile. Use `--profile headless` for
|
|
14
|
+
the shipped Headless profile. Unknown profile names start with the base bundle
|
|
15
|
+
only and do not provide a runnable Web or Headless application by themselves.
|
|
16
|
+
|
|
17
|
+
Use it with exactly one XuanLing tool bundle. `xuanling-file-workflow` routes
|
|
18
|
+
between Harness-native and XuanLing file tools only when the fs family is
|
|
19
|
+
visible; it also covers CAS overwrite, compound suffixes, atomic multi-hunk
|
|
20
|
+
patches, deterministic repeated validation, and host background jobs.
|
|
21
|
+
`xuanling-memory-workflow` keeps project-local L1 facts separate from shared
|
|
22
|
+
XuanLing L2 facts, uses explicit pointer-driven pull recall, and preserves the
|
|
23
|
+
proposal/review boundary. The policy rejects an existing-file overwrite
|
|
24
|
+
without `expected_sha256` before MCP dispatch.
|
|
25
|
+
|
|
26
|
+
Node.js 22.14 or newer is required. Licensed under the MIT License.
|
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# XuanLing on-demand skills for DeepSeek Harness.
|
|
2
|
+
#
|
|
3
|
+
# One insert block mounts a dedicated @deepseek-ai/dsh-skill-filesystem
|
|
4
|
+
# provider that sees ONLY this bundle's skills/ directory and the strict
|
|
5
|
+
# XuanLing overwrite policy from this installed package:
|
|
6
|
+
# - providerName is unique ("xuanling-dsh-skills"), so it never clashes
|
|
7
|
+
# with the preset's own "filesystem" provider registration;
|
|
8
|
+
# - includeDefaultRoots stays false: no dependence on ~/.dsh/skills or any
|
|
9
|
+
# project skill root — the two skills travel with the bundle;
|
|
10
|
+
# - watch stays false: the shipped contents are static, so the catalog
|
|
11
|
+
# digest and request history stay stable.
|
|
12
|
+
#
|
|
13
|
+
# An installed profile resolves the skill directory and policy module through
|
|
14
|
+
# this package. XUANLING_DSH_SKILLS_ROOT remains a development override for the
|
|
15
|
+
# content root; the policy module itself must be profile-installed so Loader
|
|
16
|
+
# resolves one stable package specifier.
|
|
17
|
+
|
|
18
|
+
- insert:
|
|
19
|
+
- id: xuanling-skills
|
|
20
|
+
name: '@deepseek-ai/dsh-skill-filesystem'
|
|
21
|
+
config:
|
|
22
|
+
providerName: xuanling-dsh-skills
|
|
23
|
+
includeDefaultRoots: false
|
|
24
|
+
watch: false
|
|
25
|
+
customSkillDirs:
|
|
26
|
+
- !!js process.env.XUANLING_DSH_SKILLS_ROOT ?? process.getBuiltinModule('node:path').join(process.getBuiltinModule('node:path').dirname(process.getBuiltinModule('node:module').createRequire(baseUrl).resolve('@xuanling-rs/xuanling-dsh-skills/package.json')), 'skills')
|
|
27
|
+
- id: xuanling-file-policy
|
|
28
|
+
name: '@xuanling-rs/xuanling-dsh-skills/strict-overwrite-policy.mjs'
|
package/package.json
CHANGED
|
@@ -1,9 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xuanling-rs/xuanling-dsh-skills",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"description": "XuanLing
|
|
3
|
+
"version": "0.2.4",
|
|
4
|
+
"description": "DeepSeek Harness bundle: mounts isolated XuanLing workflow skills and the strict MCP overwrite policy.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"private": false,
|
|
7
|
+
"dependencies": {
|
|
8
|
+
"@deepseek-ai/dsh-skill-filesystem": "^0.1.0-rc.5"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"LICENSE",
|
|
12
|
+
"README.md",
|
|
13
|
+
"README-ZH.md",
|
|
14
|
+
"cordis.patch.yml",
|
|
15
|
+
"strict-overwrite-policy.mjs",
|
|
16
|
+
"skills/xuanling-file-workflow/SKILL.md",
|
|
17
|
+
"skills/xuanling-file-workflow/agents/openai.yaml",
|
|
18
|
+
"skills/xuanling-memory-workflow/SKILL.md",
|
|
19
|
+
"skills/xuanling-memory-workflow/agents/openai.yaml"
|
|
20
|
+
],
|
|
21
|
+
"dsh": {
|
|
22
|
+
"bundle": {
|
|
23
|
+
"patch": "./cordis.patch.yml"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
7
26
|
"engines": {
|
|
8
27
|
"node": ">=22.14.0"
|
|
9
28
|
},
|
|
@@ -18,6 +37,10 @@
|
|
|
18
37
|
},
|
|
19
38
|
"publishConfig": {
|
|
20
39
|
"access": "public",
|
|
40
|
+
"provenance": true,
|
|
21
41
|
"registry": "https://registry.npmjs.org"
|
|
42
|
+
},
|
|
43
|
+
"xuanlingRelease": {
|
|
44
|
+
"sourceCommit": "3fc3e6304a4839de292bf7470f0dbf3f6a7ebe59"
|
|
22
45
|
}
|
|
23
46
|
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: xuanling-file-workflow
|
|
3
|
+
description: Guides DeepSeek Harness agents in choosing between harness-native file tools and a visible XuanLing mcp__xuanling__fs_ family. Use when both families are available and file work needs sha256/CAS guards, strict patches, complete pagination, explicit byte budgets, compound-suffix search, or deterministic repeated validation.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# XuanLing File Workflow
|
|
7
|
+
|
|
8
|
+
This workspace exposes two file-tool families. Pick one deliberately for each
|
|
9
|
+
operation; both are first-class, and neither is a fallback for the other.
|
|
10
|
+
Apply this workflow only when the named `mcp__xuanling__fs_*` tools are
|
|
11
|
+
visible. A memory-only bundle does not provide file or process tools; keep
|
|
12
|
+
using the native family there instead of inferring unavailable tools.
|
|
13
|
+
|
|
14
|
+
## Families
|
|
15
|
+
|
|
16
|
+
- **Native file tools** (`read`, `write`, `edit`, `grep`, `glob`, ...): deeply
|
|
17
|
+
integrated with the harness. They carry the read-before-edit observation
|
|
18
|
+
guard, native diff/read UI cards, and the workspace sandbox policy.
|
|
19
|
+
- **XuanLing tools** (`mcp__xuanling__fs_*`, for example
|
|
20
|
+
`mcp__xuanling__fs_read_text`, `mcp__xuanling__fs_edit`,
|
|
21
|
+
`mcp__xuanling__fs_search`): typed cross-platform filesystem tools with
|
|
22
|
+
sha256 preimage guards, explicit byte budgets, strict patches, and
|
|
23
|
+
resumable pagination. Results are structured JSON, identical on every OS.
|
|
24
|
+
|
|
25
|
+
## Routing rules
|
|
26
|
+
|
|
27
|
+
1. Prefer the native file tools for routine small edits and ordinary reads:
|
|
28
|
+
their observation policy and editor cards are part of the harness UX, and
|
|
29
|
+
they avoid extra ceremony for one-line changes.
|
|
30
|
+
2. Choose the XuanLing family when the operation needs what only it provides:
|
|
31
|
+
- **Hash/CAS-protected writes**: verify the file is unchanged since your
|
|
32
|
+
last read with `expected_sha256` / `expected_preimage_sha256` before
|
|
33
|
+
replacing or patching it.
|
|
34
|
+
- **Explicit output limits**: request a bounded result with an `output`
|
|
35
|
+
byte budget (`max_bytes`) and continue later through the returned
|
|
36
|
+
cursor or resume token instead of truncating silently.
|
|
37
|
+
- **Strict edits**: apply a verified unified diff with
|
|
38
|
+
`mcp__xuanling__fs_patch` (preimage-hash guarded), or a unique-match
|
|
39
|
+
replacement with `mcp__xuanling__fs_edit` / `mcp__xuanling__fs_replace_text`.
|
|
40
|
+
For one file with multiple hunks, prefer `mcp__xuanling__fs_patch` in a
|
|
41
|
+
single atomic call with the full preimage hash; do not split the change
|
|
42
|
+
into independently committed edits or invent another batch tool.
|
|
43
|
+
- **Full pagination**: list or search with a bounded window and page
|
|
44
|
+
through every remaining entry with the typed cursor.
|
|
45
|
+
- **Whole-file creation or replacement**: use `mode: "create"` for a new
|
|
46
|
+
file. To replace an existing file, obtain its hash with
|
|
47
|
+
`mcp__xuanling__fs_read_text` (`include_sha256: true`) or
|
|
48
|
+
`mcp__xuanling__fs_hash`, then pass both `mode: "overwrite"` and the
|
|
49
|
+
returned `expected_sha256`. Never omit `mode` for a whole-file write.
|
|
50
|
+
3. Do not use the shell tools (bash, pwsh, terminals) for any file operation
|
|
51
|
+
this skill covers; the two file families are sufficient, and shell output
|
|
52
|
+
is not portable evidence.
|
|
53
|
+
4. Read what you need, then act. Avoid re-reading a file you just verified by
|
|
54
|
+
sha256; avoid issuing the same search twice without consuming the cursor.
|
|
55
|
+
|
|
56
|
+
## Schema gotchas that bite in practice
|
|
57
|
+
|
|
58
|
+
- `mcp__xuanling__fs_search` takes the search term in `pattern`; `literal` is
|
|
59
|
+
a boolean, not a string. There is no `query` field.
|
|
60
|
+
- `mcp__xuanling__fs_glob` takes `patterns` (plural array); `*.mjs` matches
|
|
61
|
+
one level only, use `**/*.mjs` to recurse.
|
|
62
|
+
- `mcp__xuanling__fs_search.file_extensions` uses exact simple or compound
|
|
63
|
+
suffixes. Pass `d.ts` and `d.mts` directly (and simple values such as
|
|
64
|
+
`java` or `.c`); never reduce a compound suffix to its last `ts` or `mts`
|
|
65
|
+
segment, which would broaden the search.
|
|
66
|
+
- The `output` selector of any window-capable tool is a tagged object such as
|
|
67
|
+
`{"mode":"bounded","max_bytes":65536}` — never a number or a bare string.
|
|
68
|
+
|
|
69
|
+
## Verification
|
|
70
|
+
|
|
71
|
+
For repeated validation with the same argv through `mcp__xuanling__process_run`,
|
|
72
|
+
`mcp__xuanling__project_run`, or `mcp__xuanling__process_pipeline`, pass
|
|
73
|
+
`deterministic: true`. This omits volatile duration fields so results can be
|
|
74
|
+
byte-stable; it does not cache or skip command execution.
|
|
75
|
+
|
|
76
|
+
For a long build, test suite, or watch process that may exceed the MCP call
|
|
77
|
+
deadline, use the Harness-native background/job mechanism. Do not fabricate
|
|
78
|
+
timeouts, sleep loops, or shell wrappers around a synchronous XuanLing call.
|
|
79
|
+
|
|
80
|
+
## Failure handling
|
|
81
|
+
|
|
82
|
+
- `XUANLING_FS_OVERWRITE_REQUIRES_SHA256` means the DSH policy stopped an
|
|
83
|
+
unsafe whole-file replacement before MCP dispatch. Read or hash the file,
|
|
84
|
+
reconstruct the intended content from that current version, and retry with
|
|
85
|
+
`expected_sha256`. Do not switch to `mode: "create"` for an existing file.
|
|
86
|
+
- Treat every typed tool error as information: a duplicate-match error means
|
|
87
|
+
supply more context or an explicit replace-all decision; a conflict means
|
|
88
|
+
the file changed under you, so re-read and rebuild the edit.
|
|
89
|
+
- You must not silently fall back to the other family when a tool fails.
|
|
90
|
+
Surface the error, correct the request, and retry within the same family;
|
|
91
|
+
switching families because of a failure needs a stated reason.
|
|
92
|
+
- The XuanLing server enforces a workspace root. Paths outside it are denied
|
|
93
|
+
by design; fix the path instead of escalating.
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: xuanling-memory-workflow
|
|
3
|
+
description: Guides DeepSeek Harness agents in routing host file memory (L1) and XuanLing shared lexical memory (L2). Use when recalling an explicit memory pointer, retaining a cross-project fact, preparing a pending candidate, or handling an explicit user review decision. Enforces single-write storage and separate proposal/review turns.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# XuanLing Memory Workflow
|
|
7
|
+
|
|
8
|
+
XuanLing memory is proposal-first: nothing you write becomes a canonical
|
|
9
|
+
record until a human decides on the proposal. Two separate turns, always.
|
|
10
|
+
|
|
11
|
+
## Choose one memory layer
|
|
12
|
+
|
|
13
|
+
For a project-local must-see convention that belongs in every session, write
|
|
14
|
+
only the host file memory (L1). Make zero XuanLing write and do not create a
|
|
15
|
+
candidate for the same content.
|
|
16
|
+
|
|
17
|
+
For a cross-project, team-level, or shared fact that the user wants retained
|
|
18
|
+
in XuanLing L2, call `memory_search` first. If the fact is absent or has no
|
|
19
|
+
match, call `memory_candidate_create` to create a pending candidate; only a
|
|
20
|
+
later explicit user review can make it canonical.
|
|
21
|
+
|
|
22
|
+
At task begin or after a topic switch, follow an explicit L1 memory pointer by
|
|
23
|
+
issuing one scoped `memory_search`. This is a pull trigger, not an instruction
|
|
24
|
+
to search on every turn.
|
|
25
|
+
|
|
26
|
+
## Before writing anything
|
|
27
|
+
|
|
28
|
+
1. Search first with `memory_search` (namespaces, scopes, and tags matter —
|
|
29
|
+
a duplicate record is worse than no record).
|
|
30
|
+
2. Read the exact current content with `memory_get` when a hit looks close.
|
|
31
|
+
Updating means a replace proposal against that record's current revision,
|
|
32
|
+
not a second create.
|
|
33
|
+
|
|
34
|
+
`memory_search` returns complete active `MemoryRecordView` values inside its
|
|
35
|
+
ranked items, not a lightweight manifest. Keep the first query scoped and
|
|
36
|
+
small, then use `memory_get` only when an exact current record is required.
|
|
37
|
+
|
|
38
|
+
## Creating a candidate
|
|
39
|
+
|
|
40
|
+
- Call `memory_candidate_create` with the full payload: kind (`fact`,
|
|
41
|
+
`preference`, `procedure`, `solution`, or `summary`), content, and a
|
|
42
|
+
one-line title/summary. Include an `idempotency_key` you derive from the
|
|
43
|
+
proposal's meaning.
|
|
44
|
+
- The call only creates a pending candidate. Report the returned proposal id
|
|
45
|
+
and its revision to the user, then stop: the terminal state without review
|
|
46
|
+
is awaiting review.
|
|
47
|
+
- To retry a failed candidate call, reuse the same idempotency key with the
|
|
48
|
+
same payload. Changing the payload under a reused key is a conflict; that
|
|
49
|
+
is correct behavior, not an error to work around.
|
|
50
|
+
- Replacing or archiving follows the same shape: `memory_candidate_replace`
|
|
51
|
+
or `memory_candidate_archive` targets a specific record revision, and the
|
|
52
|
+
server refuses to apply it if that revision went stale.
|
|
53
|
+
|
|
54
|
+
## The review gate
|
|
55
|
+
|
|
56
|
+
- Call `memory_review` only after an explicit user instruction — an approval
|
|
57
|
+
or rejection decision that names the concrete proposal. A conversational
|
|
58
|
+
"looks good" during other work is not that decision; ask the user to
|
|
59
|
+
confirm the specific proposal id if in doubt.
|
|
60
|
+
- Never describe yourself or this agent as the human reviewer. You propose;
|
|
61
|
+
the user disposes. When you report a review outcome, attribute the decision
|
|
62
|
+
to the user who made it.
|
|
63
|
+
- Never approve a proposal to finish a task, save tokens, or unblock a
|
|
64
|
+
workflow; an unreviewed candidate is a correct end state.
|
|
65
|
+
|
|
66
|
+
## When not to write
|
|
67
|
+
|
|
68
|
+
- If recall has no match or the store is unavailable during ordinary work,
|
|
69
|
+
continue the main task and make zero canonical write. Do not invent a fact
|
|
70
|
+
or treat a partial candidate as a fallback result.
|
|
71
|
+
- Parse failures, model hiccups, tool errors, or an unavailable store mean
|
|
72
|
+
you skip the write entirely. Do not create partial or best-effort
|
|
73
|
+
candidates to compensate; just continue the user's task and mention the
|
|
74
|
+
skipped save if it matters.
|
|
75
|
+
- Nothing here authorizes writing secrets, raw credentials, or user-private
|
|
76
|
+
content into the shared store.
|
|
77
|
+
- Feedback after recall uses `memory_feedback` on a specific record revision
|
|
78
|
+
and is safe anytime.
|
|
79
|
+
|
|
80
|
+
## Scope and namespace quick reference
|
|
81
|
+
|
|
82
|
+
- `scope` is a tagged object: `{"type":"global"}`,
|
|
83
|
+
`{"type":"project","project_id":...}`, or
|
|
84
|
+
`{"type":"workspace","project_id":...,"workspace_id":...}`.
|
|
85
|
+
- Search walks ancestor scopes only when asked; sibling projects never leak.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const GUARDED_TOOL = "mcp__xuanling__fs_write_text";
|
|
2
|
+
|
|
3
|
+
export const STRICT_OVERWRITE_DENIAL =
|
|
4
|
+
"[XUANLING_FS_OVERWRITE_REQUIRES_SHA256] " +
|
|
5
|
+
"mcp__xuanling__fs_write_text mode=overwrite requires a non-empty " +
|
|
6
|
+
"expected_sha256; read with include_sha256=true or call " +
|
|
7
|
+
"mcp__xuanling__fs_hash, then retry";
|
|
8
|
+
|
|
9
|
+
export const name = "xuanling-strict-overwrite-policy";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Decide only the DSH-specific precondition. XuanLing remains responsible for
|
|
13
|
+
* canonical schema validation, hash format, current-file CAS, and filesystem
|
|
14
|
+
* effects.
|
|
15
|
+
*/
|
|
16
|
+
export function decideStrictOverwrite(toolName, argumentsValue) {
|
|
17
|
+
if (toolName !== GUARDED_TOOL) return { kind: "delegate" };
|
|
18
|
+
if (
|
|
19
|
+
typeof argumentsValue !== "object" ||
|
|
20
|
+
argumentsValue === null ||
|
|
21
|
+
Array.isArray(argumentsValue)
|
|
22
|
+
) {
|
|
23
|
+
return { kind: "delegate" };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const mode = argumentsValue.mode;
|
|
27
|
+
if (mode === "create") return { kind: "delegate" };
|
|
28
|
+
if (mode !== undefined && mode !== "overwrite") {
|
|
29
|
+
return { kind: "delegate" };
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const expectedSha256 = argumentsValue.expected_sha256;
|
|
33
|
+
if (typeof expectedSha256 === "string" && expectedSha256.length > 0) {
|
|
34
|
+
return { kind: "delegate" };
|
|
35
|
+
}
|
|
36
|
+
return { kind: "deny", reason: STRICT_OVERWRITE_DENIAL };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function apply(ctx) {
|
|
40
|
+
ctx.on("tools/pre-execute", (exec, next) => {
|
|
41
|
+
const decision = decideStrictOverwrite(exec.name, exec.arguments);
|
|
42
|
+
if (decision.kind === "deny") return Promise.resolve(decision);
|
|
43
|
+
return next();
|
|
44
|
+
});
|
|
45
|
+
}
|