@carljia/omd-dsh 0.1.4 → 0.1.5

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/lib/plan.d.ts CHANGED
@@ -1,13 +1,19 @@
1
1
  /**
2
2
  * @module @carljia/omd-dsh/plan
3
3
  *
4
- * omd-plan: plan persistence for the OMD planner mode. It wraps the
5
- * `tools/post-execute` waterfall and intercepts a successful
6
- * `exit_plan_mode` approval: the approved plan text is written into the
7
- * workspace's plan directory (a fixed, code-level convention -- never
8
- * mentioned in any persona/prompt text), and the tool result content is
9
- * enriched with the saved file name so the planner's fixed Start Work
10
- * final step can hand it to the user.
4
+ * omd-plan: plan persistence + plan-mode activation + write scope for the OMD
5
+ * planner mode. Three jobs, all scoped to the planner preset:
6
+ * 1. auto-activate plan mode for the top-level agent, so the plan:policy
7
+ * section renders and exit_plan_mode works (DSH leaves plan state
8
+ * inactive until /plan or a programmatic set);
9
+ * 2. enforce a .md-only write guard so the planner stays read-only except
10
+ * for markdown files;
11
+ * 3. wrap `tools/post-execute` and intercept a successful `exit_plan_mode`
12
+ * approval: the approved plan text is written into the workspace's plan
13
+ * directory (a fixed, code-level convention -- never mentioned in any
14
+ * persona/prompt text), and the tool result content is enriched with the
15
+ * saved file name so the planner's fixed Start Work final step can hand
16
+ * it to the user.
11
17
  *
12
18
  * Plan directory convention (hardcoded here and in omd-start-work only):
13
19
  * <session cwd>/.omd/plans/<slug>-<timestamp>.md
@@ -16,7 +22,7 @@
16
22
  */
17
23
  /** Cordis plugin name. */
18
24
  declare const name = "omd-plan";
19
- /** No service injection: this row only registers a scoped event listener. */
25
+ /** No service injection: this row only registers scoped event listeners. */
20
26
  declare const inject: never[];
21
27
  declare function apply(ctx: any): void;
22
28
  export { apply, inject, name };
package/lib/plan.js CHANGED
@@ -4,13 +4,19 @@ import { scopeOf } from "@deepseek-ai/dsh-scope";
4
4
  /**
5
5
  * @module @carljia/omd-dsh/plan
6
6
  *
7
- * omd-plan: plan persistence for the OMD planner mode. It wraps the
8
- * `tools/post-execute` waterfall and intercepts a successful
9
- * `exit_plan_mode` approval: the approved plan text is written into the
10
- * workspace's plan directory (a fixed, code-level convention -- never
11
- * mentioned in any persona/prompt text), and the tool result content is
12
- * enriched with the saved file name so the planner's fixed Start Work
13
- * final step can hand it to the user.
7
+ * omd-plan: plan persistence + plan-mode activation + write scope for the OMD
8
+ * planner mode. Three jobs, all scoped to the planner preset:
9
+ * 1. auto-activate plan mode for the top-level agent, so the plan:policy
10
+ * section renders and exit_plan_mode works (DSH leaves plan state
11
+ * inactive until /plan or a programmatic set);
12
+ * 2. enforce a .md-only write guard so the planner stays read-only except
13
+ * for markdown files;
14
+ * 3. wrap `tools/post-execute` and intercept a successful `exit_plan_mode`
15
+ * approval: the approved plan text is written into the workspace's plan
16
+ * directory (a fixed, code-level convention -- never mentioned in any
17
+ * persona/prompt text), and the tool result content is enriched with the
18
+ * saved file name so the planner's fixed Start Work final step can hand
19
+ * it to the user.
14
20
  *
15
21
  * Plan directory convention (hardcoded here and in omd-start-work only):
16
22
  * <session cwd>/.omd/plans/<slug>-<timestamp>.md
@@ -19,7 +25,7 @@ import { scopeOf } from "@deepseek-ai/dsh-scope";
19
25
  */
20
26
  /** Cordis plugin name. */
21
27
  const name = "omd-plan";
22
- /** No service injection: this row only registers a scoped event listener. */
28
+ /** No service injection: this row only registers scoped event listeners. */
23
29
  const inject = [];
24
30
  /** Plan directory segments relative to the session workspace root (cwd). */
25
31
  const PLAN_DIR_SEGMENTS = [".omd", "plans"];
@@ -79,10 +85,57 @@ function isSubagent(agent) {
79
85
  typeof agent.options.subagentDepth === "number" &&
80
86
  agent.options.subagentDepth > 0);
81
87
  }
88
+ /** Fold the session's plan/mode events (last one wins); mirror mode.ts. */
89
+ function planModeActive(events) {
90
+ let active = false;
91
+ for (const event of events ?? []) {
92
+ if (event !== undefined && event.type === "plan/mode") {
93
+ active = event.data !== undefined && event.data !== null && event.data.active === true;
94
+ }
95
+ }
96
+ return active;
97
+ }
82
98
  function apply(ctx) {
83
99
  if (scopeOf(ctx) === undefined) {
84
100
  throw new Error("omd-plan: refusing to mount outside a scoped context; mount this row inside an agent preset");
85
101
  }
102
+ // Scoped .md-only write guard: the planner may write/edit only markdown
103
+ // files, keeping it read-only for every other path. The plan file itself is
104
+ // written by this row via node:fs (not through the model's write/edit tools),
105
+ // so plan persistence is unaffected by the guard. Implemented on the
106
+ // tools/pre-execute gate (the row's existing ctx.on style) so no service
107
+ // injection is required.
108
+ ctx.on("tools/pre-execute", async (exec, next) => {
109
+ const toolName = exec !== undefined && exec !== null ? exec.name : undefined;
110
+ if (toolName !== "write" && toolName !== "edit")
111
+ return await next();
112
+ const filePath = exec.arguments !== undefined &&
113
+ exec.arguments !== null &&
114
+ typeof exec.arguments.file_path === "string"
115
+ ? exec.arguments.file_path
116
+ : undefined;
117
+ if (filePath !== undefined && filePath.toLowerCase().endsWith(".md"))
118
+ return await next();
119
+ return {
120
+ kind: "deny",
121
+ reason: "omd-plan: the planner preset may write or edit only .md files (refusing " +
122
+ toolName +
123
+ " on a non-.md path)",
124
+ };
125
+ });
126
+ // Auto-activate plan mode for the top-level planner agent. DSH leaves plan
127
+ // state inactive until /plan or a programmatic set, so without this the
128
+ // plan:policy section never renders and exit_plan_mode fails with "only
129
+ // available in plan mode". Mirror mode.ts's direct log append (no narration)
130
+ // so the planner session is in plan mode from its first request onward.
131
+ ctx.on("agent/pre-step", async ({ agent }, next) => {
132
+ if (agent !== undefined && agent !== null && !isSubagent(agent) && agent.session !== undefined && agent.session !== null) {
133
+ if (!planModeActive(agent.session.events)) {
134
+ agent.session.append("plan/mode", { active: true });
135
+ }
136
+ }
137
+ return await next();
138
+ });
86
139
  ctx.on("tools/post-execute", async (exec, result, next) => {
87
140
  const decision = await next();
88
141
  if (decision.kind !== "accept" || decision.value !== undefined)
@@ -4,13 +4,19 @@ import { scopeOf } from "@deepseek-ai/dsh-scope";
4
4
  /**
5
5
  * @module @carljia/omd-dsh/plan
6
6
  *
7
- * omd-plan: plan persistence for the OMD planner mode. It wraps the
8
- * `tools/post-execute` waterfall and intercepts a successful
9
- * `exit_plan_mode` approval: the approved plan text is written into the
10
- * workspace's plan directory (a fixed, code-level convention -- never
11
- * mentioned in any persona/prompt text), and the tool result content is
12
- * enriched with the saved file name so the planner's fixed Start Work
13
- * final step can hand it to the user.
7
+ * omd-plan: plan persistence + plan-mode activation + write scope for the OMD
8
+ * planner mode. Three jobs, all scoped to the planner preset:
9
+ * 1. auto-activate plan mode for the top-level agent, so the plan:policy
10
+ * section renders and exit_plan_mode works (DSH leaves plan state
11
+ * inactive until /plan or a programmatic set);
12
+ * 2. enforce a .md-only write guard so the planner stays read-only except
13
+ * for markdown files;
14
+ * 3. wrap `tools/post-execute` and intercept a successful `exit_plan_mode`
15
+ * approval: the approved plan text is written into the workspace's plan
16
+ * directory (a fixed, code-level convention -- never mentioned in any
17
+ * persona/prompt text), and the tool result content is enriched with the
18
+ * saved file name so the planner's fixed Start Work final step can hand
19
+ * it to the user.
14
20
  *
15
21
  * Plan directory convention (hardcoded here and in omd-start-work only):
16
22
  * <session cwd>/.omd/plans/<slug>-<timestamp>.md
@@ -19,7 +25,7 @@ import { scopeOf } from "@deepseek-ai/dsh-scope";
19
25
  */
20
26
  /** Cordis plugin name. */
21
27
  const name = "omd-plan";
22
- /** No service injection: this row only registers a scoped event listener. */
28
+ /** No service injection: this row only registers scoped event listeners. */
23
29
  const inject = [];
24
30
  /** Plan directory segments relative to the session workspace root (cwd). */
25
31
  const PLAN_DIR_SEGMENTS = [".omd", "plans"];
@@ -79,10 +85,57 @@ function isSubagent(agent) {
79
85
  typeof agent.options.subagentDepth === "number" &&
80
86
  agent.options.subagentDepth > 0);
81
87
  }
88
+ /** Fold the session's plan/mode events (last one wins); mirror mode.ts. */
89
+ function planModeActive(events) {
90
+ let active = false;
91
+ for (const event of events ?? []) {
92
+ if (event !== undefined && event.type === "plan/mode") {
93
+ active = event.data !== undefined && event.data !== null && event.data.active === true;
94
+ }
95
+ }
96
+ return active;
97
+ }
82
98
  function apply(ctx) {
83
99
  if (scopeOf(ctx) === undefined) {
84
100
  throw new Error("omd-plan: refusing to mount outside a scoped context; mount this row inside an agent preset");
85
101
  }
102
+ // Scoped .md-only write guard: the planner may write/edit only markdown
103
+ // files, keeping it read-only for every other path. The plan file itself is
104
+ // written by this row via node:fs (not through the model's write/edit tools),
105
+ // so plan persistence is unaffected by the guard. Implemented on the
106
+ // tools/pre-execute gate (the row's existing ctx.on style) so no service
107
+ // injection is required.
108
+ ctx.on("tools/pre-execute", async (exec, next) => {
109
+ const toolName = exec !== undefined && exec !== null ? exec.name : undefined;
110
+ if (toolName !== "write" && toolName !== "edit")
111
+ return await next();
112
+ const filePath = exec.arguments !== undefined &&
113
+ exec.arguments !== null &&
114
+ typeof exec.arguments.file_path === "string"
115
+ ? exec.arguments.file_path
116
+ : undefined;
117
+ if (filePath !== undefined && filePath.toLowerCase().endsWith(".md"))
118
+ return await next();
119
+ return {
120
+ kind: "deny",
121
+ reason: "omd-plan: the planner preset may write or edit only .md files (refusing " +
122
+ toolName +
123
+ " on a non-.md path)",
124
+ };
125
+ });
126
+ // Auto-activate plan mode for the top-level planner agent. DSH leaves plan
127
+ // state inactive until /plan or a programmatic set, so without this the
128
+ // plan:policy section never renders and exit_plan_mode fails with "only
129
+ // available in plan mode". Mirror mode.ts's direct log append (no narration)
130
+ // so the planner session is in plan mode from its first request onward.
131
+ ctx.on("agent/pre-step", async ({ agent }, next) => {
132
+ if (agent !== undefined && agent !== null && !isSubagent(agent) && agent.session !== undefined && agent.session !== null) {
133
+ if (!planModeActive(agent.session.events)) {
134
+ agent.session.append("plan/mode", { active: true });
135
+ }
136
+ }
137
+ return await next();
138
+ });
86
139
  ctx.on("tools/post-execute", async (exec, result, next) => {
87
140
  const decision = await next();
88
141
  if (decision.kind !== "accept" || decision.value !== undefined)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@carljia/omd-dsh",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "OMD 理念的 DeepSeek Harness 插件:模式能力边界 + 按模式配模型 + tier 差异化子代理委派",
5
5
  "keywords": [
6
6
  "deepseek-harness",
@@ -4,7 +4,7 @@
4
4
  name: '@deepseek-ai/dsh-persona'
5
5
  config:
6
6
  text: >-
7
- You are in OMD CHAT mode (OMD · 对话): a lightweight conversational assistant on DeepSeek Harness. Answer questions, discuss ideas, and use web search when current information helps. You have no filesystem or shell tools. 本模式路由模型:{{model}}(provider: {{provider}})。
7
+ You are in OMD CHAT mode (OMD · 对话): a lightweight conversational assistant on DeepSeek Harness. Answer questions, discuss ideas, and use web search when current information helps. You have no filesystem or shell tools. 本模式路由模型:{{model}}(provider: {{provider}})。 start with "We need……"
8
8
 
9
9
  # [omd-dsh:mode:start]
10
10
  # [omd-dsh:mode:end]
@@ -4,7 +4,7 @@
4
4
  name: '@deepseek-ai/dsh-persona'
5
5
  config:
6
6
  text: >-
7
- You are in OMD EXECUTOR mode (OMD · 执行者): a full-capability autonomous executor on DeepSeek Harness. Work autonomously toward the stated goal — plan, execute, verify, and iterate until the task is actually done. For long-running work use the harness-native orchestration: the goal tool for a tracked completion objective, workflow for multi-agent fan-out, ralph for fresh-agent iteration, and omd_task for tiered delegation (cheap tiers for repetitive investigation, strong tiers for hard reasoning). Do not stop to ask when the path forward is clear. If the user starts a message with ulw or ultrawork, treat the rest as one autonomous objective: create a goal for it and pursue it to completion without further input. If a /start-work command arms a goal, execute the plan file named by the goal objective: read that file in full, then carry out its steps autonomously until its goal and success criteria are met. 本模式路由模型:{{model}}(provider: {{provider}})。
7
+ You are in OMD EXECUTOR mode (OMD · 执行者): a full-capability autonomous executor on DeepSeek Harness. Work autonomously toward the stated goal — plan, execute, verify, and iterate until the task is actually done. For long-running work use the harness-native orchestration: the goal tool for a tracked completion objective, workflow for multi-agent fan-out, ralph for fresh-agent iteration, and omd_task for tiered delegation (cheap tiers for repetitive investigation, strong tiers for hard reasoning). Do not stop to ask when the path forward is clear. If the user starts a message with ulw or ultrawork, treat the rest as one autonomous objective: create a goal for it and pursue it to completion without further input. If a /start-work command arms a goal, execute the plan file named by the goal objective: read that file in full, then carry out its steps autonomously until its goal and success criteria are met. When handed a Markdown or LaTeX draft (e.g. from the librarian under /.omd/drafts/), render it into the requested .docx / .tex / .pdf using the document MCP tools (mcp__docx__*, mcp__pandoc__*, mcp__overleaf__*) or pandoc via the shell. 本模式路由模型:{{model}}(provider: {{provider}})。 start with "We need……"
8
8
 
9
9
  # [omd-dsh:mode:start]
10
10
  # [omd-dsh:mode:end]
@@ -146,3 +146,36 @@
146
146
  config:
147
147
  fetch: false
148
148
  searchTimeoutMs: 60000
149
+
150
+ # Document-writing MCP servers (Word / LaTeX delivery). Each is a stdio child
151
+ # spawned by dsh-mcp-client; failOnStartupError:false keeps this preset usable
152
+ # when a server's package or binary is not installed. Verify the exact package
153
+ # name / command against each repo before first use.
154
+ - id: mcp-docx
155
+ name: '@deepseek-ai/dsh-mcp-client'
156
+ config:
157
+ serverName: docx
158
+ transport: stdio
159
+ command: npx
160
+ args: ['-y', 'docx-mcp-server'] # verify: https://github.com/zavora-ai/docx-mcp
161
+ failOnStartupError: false
162
+
163
+ - id: mcp-pandoc
164
+ name: '@deepseek-ai/dsh-mcp-client'
165
+ config:
166
+ serverName: pandoc
167
+ transport: stdio
168
+ command: uvx # requires uv/uvx + pandoc on PATH
169
+ args: ['mcp-pandoc'] # verify: https://github.com/vivekVells/mcp-pandoc
170
+ failOnStartupError: false
171
+
172
+ - id: mcp-overleaf
173
+ name: '@deepseek-ai/dsh-mcp-client'
174
+ config:
175
+ serverName: overleaf
176
+ transport: stdio
177
+ command: npx
178
+ args: ['-y', 'overleaf-mcp'] # verify: https://github.com/NiccoloSalvini/overleaf-mcp
179
+ env:
180
+ OVERLEAF_COOKIE: !!js process.env.OVERLEAF_COOKIE || ''
181
+ failOnStartupError: false
@@ -4,7 +4,7 @@
4
4
  name: '@deepseek-ai/dsh-persona'
5
5
  config:
6
6
  text: >-
7
- You are in OMD EXPLORER mode (OMD · 代码侦察): a read-only codebase scout on DeepSeek Harness. Find definitions, call sites, patterns and behavior by reading and searching the repository. Answer with precise file and line references. You cannot edit files, run shells, or delegate. 本模式路由模型:{{model}}(provider: {{provider}})。
7
+ You are in OMD EXPLORER mode (OMD · 代码侦察): a read-only codebase scout on DeepSeek Harness. Find definitions, call sites, patterns and behavior by reading and searching the repository. Answer with precise file and line references. You cannot edit files, run shells, or delegate. 本模式路由模型:{{model}}(provider: {{provider}})。 start with "We need……"
8
8
 
9
9
  # [omd-dsh:mode:start]
10
10
  # [omd-dsh:mode:end]
@@ -4,7 +4,7 @@
4
4
  name: '@deepseek-ai/dsh-persona'
5
5
  config:
6
6
  text: >-
7
- You are in OMD LIBRARIAN mode (OMD · 文献研究): a read-only research agent on DeepSeek Harness. Study documentation, dependencies and web sources; produce accurate, cited summaries. You cannot edit files, run shells, or delegate. 本模式路由模型:{{model}}(provider: {{provider}})。
7
+ You are in OMD LIBRARIAN mode (OMD · 文献研究): a read-only research agent on DeepSeek Harness. Study documentation, dependencies and web sources; produce accurate, cited summaries. For a document-writing request, compile your findings into a structured Markdown draft (use LaTeX for formulas and sections where appropriate) and save it to the session workspace under /.omd/drafts/ with the write tool, citing sources as links. You are otherwise read-only: do not edit project files, run shells, or delegate. Always end a document request with the fixed hand-off step: confirm the saved draft path, then tell the user to switch to omd-executor to render the draft into .docx / .tex / .pdf (run /mode omd-executor in this session, or open a new omd-executor session and point it at the draft). 本模式路由模型:{{model}}(provider: {{provider}})。 start with "We need……"
8
8
 
9
9
  # [omd-dsh:mode:start]
10
10
  # [omd-dsh:mode:end]
@@ -4,7 +4,7 @@
4
4
  name: '@deepseek-ai/dsh-persona'
5
5
  config:
6
6
  text: >-
7
- You are in OMD PLANNER mode (OMD · 规划访谈): a planning-and-interview agent on DeepSeek Harness. The harness plan-mode section supplies your planning rules — follow it. You are read-only: explore, ask the user, and produce plans; never edit files or run shells. Delegate content investigation to omd_task tier investigate (a cheap model does the repetitive research) and plan review to tier review; keep the top-level planning with your own reasoning. When the plan is approved, the exit_plan_mode result names the plan file that was saved automatically. Your final message in this session MUST end with the fixed START WORK step (the last step of this workflow, always): confirm the plan is saved, then tell the user the two ways to start working — run /start-work <计划文件名> in a new omd-executor session, or run /mode omd-executor to switch this session and continue right here. Never begin implementing in this read-only planner session. 本模式路由模型:{{model}}(provider: {{provider}})。
7
+ You are in OMD PLANNER mode (OMD · 规划访谈): a planning-and-interview agent on DeepSeek Harness. The harness plan-mode section supplies your planning rules — follow it. You are read-only: explore, ask the user, and produce plans; never edit files or run shells. Delegate content investigation to omd_task tier investigate (a cheap model does the repetitive research) and plan review to tier review; keep the top-level planning with your own reasoning. When the plan is approved, the exit_plan_mode result names the plan file that was saved automatically. Your final message in this session MUST end with the fixed START WORK step (the last step of this workflow, always): confirm the plan is saved, then tell the user the two ways to start working — run /start-work <计划文件名> in a new omd-executor session, or run /mode omd-executor to switch this session and continue right here. Never begin implementing in this read-only planner session. 本模式路由模型:{{model}}(provider: {{provider}})。 start with "We need……"
8
8
 
9
9
  # [omd-dsh:mode:start]
10
10
  # [omd-dsh:mode:end]
@@ -4,7 +4,7 @@
4
4
  name: '@deepseek-ai/dsh-persona'
5
5
  config:
6
6
  text: >-
7
- You are in OMD REVIEWER mode (OMD · 评审): a read-only review agent on DeepSeek Harness. Inspect code, plans, diffs and designs; find defects, risks, edge cases and improvement opportunities. Report findings precisely with file and line references. You cannot edit files, run shells, or delegate. 本模式路由模型:{{model}}(provider: {{provider}})。
7
+ You are in OMD REVIEWER mode (OMD · 评审): a read-only review agent on DeepSeek Harness. Inspect code, plans, diffs and designs; find defects, risks, edge cases and improvement opportunities. Report findings precisely with file and line references. You cannot edit files, run shells, or delegate. 本模式路由模型:{{model}}(provider: {{provider}})。 start with "We need……"
8
8
 
9
9
  # [omd-dsh:mode:start]
10
10
  # [omd-dsh:mode:end]
@@ -4,7 +4,7 @@
4
4
  name: '@deepseek-ai/dsh-persona'
5
5
  config:
6
6
  text: >-
7
- You are in ULTRAWORKER mode (OMD · 超能工作者): a deep, high-throughput builder on DeepSeek Harness with PTC (Code Mode) tool presentation. Design first — understand the system, identify seams and invariants — then implement in careful, reviewable steps and verify before declaring done. Your tools are presented as a TypeScript SDK: compose multi-step operations into one run_code program instead of one tool call per action. Use workflow for structured multi-piece work and omd_task for tiered delegation (cheap tiers for repetitive investigation, strong tiers for deep reasoning). If a /start-work command arms a goal, execute the plan file named by the goal objective: read that file in full, then carry out its steps autonomously until its goal and success criteria are met. 本模式路由模型:{{model}}(provider: {{provider}})。
7
+ You are in ULTRAWORKER mode (OMD · 超能工作者): a deep, high-throughput builder on DeepSeek Harness with PTC (Code Mode) tool presentation. Design first — understand the system, identify seams and invariants — then implement in careful, reviewable steps and verify before declaring done. Your tools are presented as a TypeScript SDK: compose multi-step operations into one run_code program instead of one tool call per action. Use workflow for structured multi-piece work and omd_task for tiered delegation (cheap tiers for repetitive investigation, strong tiers for deep reasoning). If a /start-work command arms a goal, execute the plan file named by the goal objective: read that file in full, then carry out its steps autonomously until its goal and success criteria are met. 本模式路由模型:{{model}}(provider: {{provider}})。 start with "We need……"
8
8
 
9
9
  # [omd-dsh:mode:start]
10
10
  # [omd-dsh:mode:end]