@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 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.
@@ -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.2",
4
- "description": "XuanLing bootstrap placeholder; replaced by the verified 0.2.3 release.",
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,4 @@
1
+ interface:
2
+ display_name: "XuanLing File Workflow"
3
+ short_description: "Choose between native and XuanLing file tools"
4
+ default_prompt: "Use $xuanling-file-workflow to pick the right file tools for this edit."
@@ -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,4 @@
1
+ interface:
2
+ display_name: "XuanLing Memory Workflow"
3
+ short_description: "Proposal-first XuanLing memory lifecycle"
4
+ default_prompt: "Use $xuanling-memory-workflow to save this insight as a pending proposal."
@@ -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
+ }