dev-flow-deepseek 0.1.0 → 0.5.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.
@@ -0,0 +1,43 @@
1
+ export const DEV_FLOW_SERVER_NAME = "dev_flow";
2
+ export const DEV_FLOW_TOOL_NAMESPACE_PREFIX = `mcp__${DEV_FLOW_SERVER_NAME}__`;
3
+
4
+ export const DEV_FLOW_RAW_TOOL_NAMES = Object.freeze([
5
+ "dev_flow_server_info",
6
+ "dev_flow_open_task",
7
+ "dev_flow_get_task",
8
+ "dev_flow_get_next_action",
9
+ "dev_flow_apply_action",
10
+ "dev_flow_cancel_task",
11
+ ]);
12
+
13
+ export const DEV_FLOW_QUALIFIED_TOOL_NAMES = Object.freeze(
14
+ DEV_FLOW_RAW_TOOL_NAMES.map((rawName) => `${DEV_FLOW_TOOL_NAMESPACE_PREFIX}${rawName}`),
15
+ );
16
+
17
+ const expectedQualifiedTools = new Set(DEV_FLOW_QUALIFIED_TOOL_NAMES);
18
+
19
+ export function isDevFlowNamespaceTool(name) {
20
+ return typeof name === "string" && name.startsWith(DEV_FLOW_TOOL_NAMESPACE_PREFIX);
21
+ }
22
+
23
+ export function isExpectedDevFlowTool(name) {
24
+ return expectedQualifiedTools.has(name);
25
+ }
26
+
27
+ export function assertQualifiedToolCatalog(toolNames, { allowUnavailable = false } = {}) {
28
+ const namespaceTools = [...toolNames]
29
+ .filter(isDevFlowNamespaceTool)
30
+ .sort();
31
+ if (allowUnavailable && namespaceTools.length === 0) return Object.freeze([]);
32
+
33
+ const expected = [...DEV_FLOW_QUALIFIED_TOOL_NAMES].sort();
34
+ if (
35
+ namespaceTools.length !== expected.length
36
+ || namespaceTools.some((name, index) => name !== expected[index])
37
+ ) {
38
+ throw new Error(
39
+ `Dev Flow tool catalog mismatch: received ${JSON.stringify(namespaceTools)}; expected ${JSON.stringify(expected)}`,
40
+ );
41
+ }
42
+ return DEV_FLOW_QUALIFIED_TOOL_NAMES;
43
+ }
package/package.json CHANGED
@@ -1,58 +1,55 @@
1
1
  {
2
2
  "name": "dev-flow-deepseek",
3
- "version": "0.1.0",
4
- "description": "DeepSeek Harness bundle for the external Dev Flow Orchestrator MCP runtime.",
5
- "type": "module",
3
+ "version": "0.5.1",
4
+ "private": false,
5
+ "description": "Explicit DeepSeek Harness adapter for the Dev Flow process graph.",
6
6
  "license": "Apache-2.0",
7
- "keywords": [
8
- "deepseek",
9
- "deepseek-harness",
10
- "dev-flow",
11
- "mcp",
12
- "plugin"
7
+ "type": "module",
8
+ "main": "lib/index.mjs",
9
+ "files": [
10
+ "LICENSE",
11
+ "README.md",
12
+ "cordis.patch.yml",
13
+ "lib/authorization.mjs",
14
+ "lib/index.mjs",
15
+ "lib/paths.mjs",
16
+ "lib/runtime.mjs",
17
+ "lib/tool-names.mjs",
18
+ "runtime/darwin-arm64/dev-flow",
19
+ "skills/dev-flow/SKILL.md",
20
+ "skills/dev-flow/references/method-profiles.md",
21
+ "skills/dev-flow/references/node-payloads.md"
13
22
  ],
14
- "repository": {
15
- "type": "git",
16
- "url": "git+https://github.com/Innocent-children/dev-flow-deepseek.git"
17
- },
18
- "bugs": {
19
- "url": "https://github.com/Innocent-children/dev-flow-deepseek/issues"
20
- },
21
- "homepage": "https://github.com/Innocent-children/dev-flow-deepseek#readme",
22
- "publishConfig": {
23
- "access": "public",
24
- "tag": "latest"
23
+ "scripts": {
24
+ "test": "node --test tests/*.test.mjs",
25
+ "test:package": "node --test tests/package-contract.test.mjs",
26
+ "test:bundle": "node --test tests/bundle-contract.test.mjs",
27
+ "pack:dry": "pnpm pack --dry-run --json"
25
28
  },
26
29
  "engines": {
27
- "node": "^22.19.0 || >=24.0.0"
30
+ "node": ">=24"
28
31
  },
29
- "files": [
30
- "lib/",
31
- "cordis.patch.yml",
32
- "skills/",
33
- "README.md",
34
- "LICENSE"
32
+ "os": [
33
+ "darwin"
35
34
  ],
36
- "dependencies": {
37
- "@modelcontextprotocol/sdk": "1.12.0"
38
- },
39
- "devDependencies": {
40
- "@types/js-yaml": "4.0.9",
41
- "@types/node": "22.15.3",
42
- "js-yaml": "4.1.0",
43
- "tsdown": "0.15.4",
44
- "typescript": "5.8.3"
35
+ "cpu": [
36
+ "arm64"
37
+ ],
38
+ "publishConfig": {
39
+ "access": "public",
40
+ "registry": "https://registry.npmjs.org/"
45
41
  },
46
42
  "dsh": {
47
43
  "bundle": {
48
44
  "patch": "./cordis.patch.yml"
49
45
  }
50
46
  },
51
- "scripts": {
52
- "build": "tsdown && chmod 755 lib/proxy.js",
53
- "typecheck": "tsc --noEmit",
54
- "test": "node --test tests/unit/*.test.mjs tests/integration/proxy.test.mjs tests/package/package-contract.test.mjs",
55
- "test:real": "node --test tests/integration/real-runtime.test.mjs",
56
- "verify:package": "node scripts/verify-package.mjs"
47
+ "dependencies": {
48
+ "@deepseek-ai/dsh-mcp-client": ">=0.1.0-rc.6"
49
+ },
50
+ "peerDependencies": {
51
+ "@deepseek-ai/cordis": ">=4.0.1 <5.0.0",
52
+ "@deepseek-ai/dsh-skill": ">=0.1.0-rc.6",
53
+ "@deepseek-ai/dsh-tools": ">=0.1.0-rc.6"
57
54
  }
58
- }
55
+ }
Binary file
@@ -1,59 +1,414 @@
1
- ---
2
- name: dev-flow
3
- description: Start or resume a governed single-repository Dev Flow lite task.
4
- whenToUse: Use only when the user explicitly invokes /dev-flow for substantive repository work.
5
- disable-model-invocation: true
6
- user-invocable: true
7
- ---
8
-
9
1
  # Dev Flow
10
2
 
11
- Use this Skill only after the user explicitly invokes `/dev-flow` with a
12
- substantive repository task. Never activate it for an ordinary coding request.
13
-
14
- Read [activation-and-routing.md](references/activation-and-routing.md) before
15
- discovering, selecting, starting, or applying a task.
16
-
17
- ## Entry checks
18
-
19
- Before task discovery or mutation:
20
-
21
- 1. Verify that all and only the required Dev Flow surface is available to this
22
- Skill under these six model-facing names:
23
- `mcp__dev-flow__dev_flow_server_info`,
24
- `mcp__dev-flow__dev_flow_find_tasks_for_path`,
25
- `mcp__dev-flow__dev_flow_get_task`,
26
- `mcp__dev-flow__dev_flow_get_next_action`,
27
- `mcp__dev-flow__dev_flow_start_task`, and
28
- `mcp__dev-flow__dev_flow_apply_action`.
29
- 2. Call `mcp__dev-flow__dev_flow_server_info` and parse its complete canonical
30
- JSON text. Require server `dev-flow`, release `0.6.12`, model version and
31
- model namespace `0.4.0`, interface `dev-flow-mcp/1.0.0`, result schema
32
- `dev-flow-mcp-result/1.0.0`, transport `stdio`, and health status `ready`.
33
- Stop and name the exact incompatible field when any value differs; never
34
- infer compatibility from a version range.
35
- 3. Require a substantive task after `/dev-flow`. Ask for the missing task and
36
- do not create anything when the invocation is empty or conversational.
37
- 4. Resolve the current worktree root with `git rev-parse --show-toplevel`.
38
- Stop before discovery when it fails. The exact canonical result is the sole
39
- repository root; reject requests that require another repository.
40
-
41
- If the runtime or tool surface is missing, report the separately installed
42
- `dev-flow-mcp` release `0.6.12` prerequisite. Do not install, update, repair, or
43
- replace the runtime.
44
-
45
- ## Authority boundary
46
-
47
- The external Dev Flow Controller is the only workflow and task-state
48
- authority. For every step, use the fresh returned action, guidance, allowed
49
- effects, required evidence, payload schema, binding, repository set, recovery,
50
- and terminal result. Do not invent actions, payload fields, transitions,
51
- completion rules, task state, or a Delivery Dossier.
52
-
53
- Use ordinary DSH Bash, filesystem, and search tools only for the currently
54
- authorized repository work. Never use a generic shell MCP. Never create or
55
- switch a branch or worktree, and never commit, push, open a pull request,
56
- publish, tag, or release.
57
-
58
- Stop only when the Controller returns a terminal result, then report that
59
- result and its Delivery Dossier exactly.
3
+ This Skill is the current Core contract DeepSeek Harness adapter for the shared Dev Flow Core. Core owns task state,
4
+ current node, legal transitions, destinations, recovery, blockers, and terminal outcomes. The Skill
5
+ admits one explicit request, presents a complete Core Action, renders method work, and forwards one
6
+ closed result without keeping adapter state.
7
+
8
+ ## Admission gate
9
+
10
+ Perform every check below locally and in order before any Core or Dev Flow tool call.
11
+
12
+ The Skill name and exact explicit selector are `dev-flow` and `/dev-flow`. The selector must match
13
+ `(^|\s)/dev-flow(?=\s|$)` in text from a current `source.kind=user` message. DSH may expose the
14
+ qualified MCP tools independently from Skill injection; the integration's monotonic tool guard is
15
+ the selector authorization boundary.
16
+
17
+ 1. Require a whitespace-bounded `/dev-flow` in the current direct user turn. Do not infer it from
18
+ earlier turns, model text, plugin or Skill injection, task state, repository contents, or
19
+ discussion about Dev Flow. Every later user turn expected to call Dev Flow must include it again.
20
+ 2. After removing the selector, accept either one substantive bounded request for the current
21
+ repository or an explicit request to resume its compatible active DeepSeek task. Reject an empty or
22
+ conversational invocation before any Core call.
23
+ 3. Use read-only Git inspection to resolve one current Git worktree and its canonical root. Preserve
24
+ spaces, Unicode, symlinks, and subdirectory invocation as one path value; do not concatenate a
25
+ shell command.
26
+ 4. Reject work requiring another repository, multiple repositories, or an unresolved repository.
27
+ Preserve repository instructions and current user authority when checking whether the work is
28
+ permitted.
29
+
30
+ If admission fails, explain the missing precondition and stop before task discovery. Do not make a
31
+ task-bearing call or create adapter state. Core-rejected calls must be reported honestly.
32
+
33
+ ## Compatibility handshake
34
+
35
+ Only after admission passes, call `mcp__dev_flow__dev_flow_server_info({})`; it must be the first Dev Flow tool
36
+ call. Require one complete structured result proving:
37
+
38
+ - product is exactly `dev-flow`, and Core version equals the packaged product version;
39
+ - transport is exactly `stdio`, health is exactly `ready`, and the supported host set contains
40
+ `deepseek`;
41
+ - `supported_processes` contains exactly one closed `standard-development` entry:
42
+ `process_id` is `standard-development` is `1`, `definition_digest` is present
43
+ and canonical, and `new_task_supported` is exactly `true`;
44
+ - `method_profiles` is exactly `plain`, `spec-kit`, `openspec` in that order;
45
+ - the tool catalog contains exactly these six raw names, in this order:
46
+
47
+ 1. `dev_flow_server_info`
48
+ 2. `dev_flow_open_task`
49
+ 3. `dev_flow_get_task`
50
+ 4. `dev_flow_get_next_action`
51
+ 5. `dev_flow_apply_action`
52
+ 6. `dev_flow_cancel_task`
53
+
54
+ Any other schema, unsupported process version, absent process digest, false new-task support,
55
+ incomplete method-profile set, missing/additional/reordered tool, or incomplete, truncated, malformed,
56
+ or incompatible result fails the handshake. Stop without task discovery or undocumented probing. Do
57
+ not inspect local source or an installed binary, and do not start a second MCP server to bypass a
58
+ failed handshake.
59
+
60
+ ## Task discovery
61
+
62
+ After the handshake, call `mcp__dev_flow__dev_flow_open_task` with `host=deepseek` and the canonical current worktree.
63
+
64
+ - For an explicit resume, omit `new_task` or send `new_task=null`. Do not resend a guessed intent or
65
+ select another profile; accept the immutable profile returned by Core.
66
+ - For a new request, select one profile from explicit current user intent. An explicit `plain`,
67
+ `spec-kit`, or `openspec` request selects that exact profile. An explicit request to use Spec Kit
68
+ selects `spec-kit`; an explicit request to use OpenSpec selects `openspec`; otherwise use the
69
+ conservative `plain` profile.
70
+ - Installed tooling does not select or switch a profile. Never change the profile after creation. If
71
+ the user explicitly requests conflicting profiles, report the profile conflict and stop.
72
+ - Derive the new-task contract only from the admitted user request, repository instructions, known
73
+ initial bounds, known acceptance, and granted verification authority. Formal acceptance does not
74
+ need to be complete at creation; the current requirements work forms that authority.
75
+ - Forward `new_task` with exactly the members `request`, `initial_scope`,
76
+ `initial_out_of_scope`, `known_acceptance_criteria`, `verification_budget`, and `method_profile`,
77
+ with no additional members. Forward `verification_budget` with exactly `level`,
78
+ `max_automatic_commands`, `allow_full_suite`, and `allow_manual_handoff`.
79
+ - `request` is a JSON string. `initial_scope`, `initial_out_of_scope`, and
80
+ `known_acceptance_criteria` are JSON arrays of strings and may be empty. Never collapse an array
81
+ into prose. `verification_budget.level` is exactly `minimal`, `targeted`, or `full`.
82
+
83
+ Use this exact `new_task` JSON shape, changing only values derived from the admitted request:
84
+
85
+ <!-- new-task-example:start -->
86
+ ```json
87
+ {
88
+ "request": "Return the requested field from the bounded endpoint.",
89
+ "initial_scope": ["Update the endpoint response"],
90
+ "initial_out_of_scope": ["Change unrelated endpoints"],
91
+ "known_acceptance_criteria": ["The response contains the requested field"],
92
+ "verification_budget": {
93
+ "level": "targeted",
94
+ "max_automatic_commands": 4,
95
+ "allow_full_suite": false,
96
+ "allow_manual_handoff": true
97
+ },
98
+ "method_profile": "plain"
99
+ }
100
+ ```
101
+ <!-- new-task-example:end -->
102
+
103
+ Ask before opening only when a material request, initial-bound, verification, or profile choice
104
+ cannot be derived without changing user intent. Let Core decide whether a compatible intent creates
105
+ or resumes a task. Report an ownership or contract conflict unchanged in meaning and stop.
106
+
107
+ ## Governed action loop
108
+
109
+ The inseparable Action fields are exactly `task_id`, `revision`, `action_id`, `action_kind`,
110
+ `process_id`, `process_definition_digest`, `current_node`, `node_purpose`,
111
+ `entry_conditions`, `completion_conditions`, `allowed_effects`, `required_evidence`,
112
+ `method_profile`, `method_steps`, `available_transitions`, `payload_contract`, `guidance`,
113
+ `repository_binding_digest`, and `issued_at`.
114
+
115
+ For an active task, perform each iteration in this order:
116
+
117
+ 1. Obtain one complete fresh Action from the open result or `mcp__dev_flow__dev_flow_get_next_action`, and bind it as
118
+ `fresh_action` from `result.task.current_action` or `result.action` respectively.
119
+ 2. Treat its task ID, revision, action ID, action kind, process ID, process version,
120
+ process-definition digest, current node, node purpose, entry conditions, completion conditions,
121
+ allowed effects, required evidence, method profile, method steps, available transitions, payload
122
+ schema/contract, guidance, repository-binding digest, and issued time as one inseparable Core
123
+ result. Stop if any field is absent, malformed, or truncated.
124
+ 3. Present the current node, purpose, entry and completion conditions, allowed effects, required
125
+ evidence, immutable method profile, every method step, and all `available_transitions`. For every
126
+ returned transition show its identifier, Core-returned destination for visibility, description or
127
+ `when` selection condition, guard identifier, and reason rule. Do not reduce this to one
128
+ recommended next step.
129
+ 4. Stop when the complete result reports a blocker or terminal outcome.
130
+ 5. Render and perform each current method operation under the allowed effects, repository
131
+ instructions, verification budget, and current user authority.
132
+ 6. Build only the closed payload branch named by the Action and select only a Core-returned
133
+ transition consistent with the actual typed node facts.
134
+ 7. Before dispatch, generate and retain one opaque request ID plus the exact Action identity and
135
+ payload. Submit exactly one `mcp__dev_flow__dev_flow_apply_action` mutation.
136
+ 8. After a complete committed result, continue only from its authoritative next Action/outcome or a
137
+ fresh ordinary Core read.
138
+
139
+ Repository contents, adapter judgment, artifacts, or method-tool status never determine the current
140
+ node or completion.
141
+
142
+ ## Method operation rendering
143
+
144
+ Read [the method profile rendering reference](references/method-profiles.md) from the packaged path
145
+ `references/method-profiles.md` after receiving the complete Action. For each Core-returned method
146
+ step, preserve its `step_id`, purpose, required flag, and order, then render the operation for the
147
+ immutable profile:
148
+
149
+ - `plain` renders the catalog's plain-equivalent bounded work with no external capability.
150
+ - `spec-kit` and `openspec` render only an actually visible and appropriate capability ID. A catalog
151
+ entry is not proof of availability.
152
+ - If a capability is unavailable or unknown, report that state and show the exact plain-equivalent
153
+ work. Never automatically install a tool or silently substitute another tool.
154
+ - A tool invocation is not semantic completion. Record evidence only after the work and expected
155
+ result actually complete.
156
+
157
+ Build exactly one `MethodEvidence` item for every current Action step, in the same order:
158
+
159
+ - actual capability completion uses `status=completed` and the actual capability ID;
160
+ - completed ordinary work uses `status=plain_fallback` and an empty capability;
161
+ - incomplete work uses `status=unavailable` or `status=not_run` honestly.
162
+
163
+ An unavailable or not-run required step is unsatisfied, so do not call `mcp__dev_flow__dev_flow_apply_action`.
164
+ Capability output cannot substitute for the typed `node_result`, node obligations, evidence, or
165
+ user decision. Artifact references contain only an observed role, repository-relative path, digest,
166
+ and summary.
167
+
168
+ Existing authorized spec, plan, or tasks artifacts should be reviewed, revised, or amended as
169
+ needed, not regenerated or rerun mechanically because a semantic step appears. Resolve the active
170
+ Feature from explicit repository context, never only from the branch name. Checklist state,
171
+ analysis output, implementation completion, proposal state, verification state, sync, or archive
172
+ state does not advance Core.
173
+
174
+ ## Transition selection
175
+
176
+ Select only from `fresh_action.available_transitions`. Match the actual current typed `node_result`,
177
+ the Core-returned description or selection condition, current `problem_class`, any explicit user
178
+ decision, and the returned reason rule. Submit the matching transition identifier; Core validates
179
+ the facts and owns/derives the destination.
180
+
181
+ Never infer an edge from a fixed stage sequence, artifact checkbox, AI belief, profile, method-tool
182
+ result, or capability status. A checkbox or method tool cannot advance, select, or complete Core.
183
+ Never submit a transition absent from the fresh Action and never maintain a copied transition list.
184
+
185
+ ## Closed forwarding contract
186
+
187
+ Use the same `fresh_action` already bound from `result.task.current_action` or `result.action`; do
188
+ not construct another Action view.
189
+
190
+ Read [the node payload construction reference](references/node-payloads.md) from the packaged path
191
+ `references/node-payloads.md` before every ordinary apply. The reference is construction guidance;
192
+ the fresh Action, live `mcp__dev_flow__dev_flow_apply_action` `inputSchema`, and Core remain authoritative.
193
+
194
+ Before calling `mcp__dev_flow__dev_flow_apply_action`, perform this order exactly:
195
+
196
+ `fresh_action.payload_contract` identifies the payload branch that must agree with the live schema
197
+ and packaged template.
198
+
199
+ 1. Rebind the complete `fresh_action` and read its `action_kind`, `current_node`, `payload_contract`,
200
+ `method_steps`, and all `available_transitions`.
201
+ 2. Read the live `mcp__dev_flow__dev_flow_apply_action` `inputSchema`; under `allOf`, choose the `oneOf` payload
202
+ branch whose `action_kind.const` matches the current action kind and source node.
203
+ 3. Open the corresponding marked template in `references/node-payloads.md`.
204
+ 4. Preserve the template's complete common envelope and `node_result` wrapper; replace only dynamic
205
+ values with facts from the current Task, Action, user decision, repository work, and actual check.
206
+ 5. Use current baseline revisions, work-item IDs, record IDs, acceptance, and evidence sets; never
207
+ guess or reuse stale values.
208
+ 6. Confirm all six common payload members exist and no seventh member exists.
209
+ 7. Confirm every branch-specific required `node_result` key exists and arrays remain arrays.
210
+ 8. Confirm every ArtifactReference role belongs to the live closed enum. Never convert a
211
+ `required_evidence` kind such as `repository_observation` into an artifact role. Use
212
+ `"artifacts": []` when no real repository-relative process artifact exists.
213
+ 9. Confirm MethodEvidence exactly matches current Action steps in ID, order, and count. Completed
214
+ `plain` work uses `plain_fallback` with an empty capability.
215
+ 10. Confirm the selected transition is present in the fresh Action and its reason rule matches.
216
+ 11. Confirm `destination`, `next_node`, `next_cursor`, caller classification, repository facts,
217
+ payload digest, raw output, and unknown members are absent.
218
+ 12. Map the mutation top-level identity from that same fresh Action.
219
+ 13. Retain the exact request and call `mcp__dev_flow__dev_flow_apply_action` once.
220
+
221
+ If the live schema and packaged reference disagree, stop before mutation and report the packaging
222
+ contract defect. Do not choose whichever shape appears more convenient.
223
+
224
+ Do not derive payload keys from `required_evidence`. Do not search the repository or installed
225
+ package, inspect a binary or log, or start another MCP server to recover a schema. The selected
226
+ payload contains exactly `transition_id`, `summary`, `reason`, `artifacts`, `method_evidence`, and
227
+ `node_result`; put `problem_class` exactly where that node branch's actual schema requires it. Keep
228
+ arrays as arrays and the payload as an object. Do not add unknown fields, caller classification,
229
+ caller digest, authoritative repository facts, command/output/configuration data, `destination`,
230
+ `next_node`, or `next_cursor`, and do not wrap the whole request in an outer `payload`.
231
+
232
+ Map every mutation top-level field from the same fresh Action:
233
+
234
+ - caller-generated opaque identity -> top-level `request_id`;
235
+ - exact value `deepseek` -> top-level `host`;
236
+ - `fresh_action.task_id` -> top-level `task_id`;
237
+ - `fresh_action.revision` -> top-level `revision`;
238
+ - `fresh_action.action_id` -> top-level `action_id`;
239
+ - `fresh_action.action_kind` -> top-level `action_kind`;
240
+ - `fresh_action.process_id` -> top-level `process_id`;
241
+ - `fresh_action.process_definition_digest` -> top-level `process_definition_digest`;
242
+ - `fresh_action.current_node` -> top-level `source_cursor`;
243
+ - `fresh_action.repository_binding_digest` -> top-level `repository_binding_digest`;
244
+ - the selected closed payload -> top-level `payload`.
245
+
246
+ ```text
247
+ apply_arguments = {
248
+ "request_id": caller_request_id,
249
+ "host": "deepseek",
250
+ "task_id": fresh_action.task_id,
251
+ "revision": fresh_action.revision,
252
+ "action_id": fresh_action.action_id,
253
+ "action_kind": fresh_action.action_kind,
254
+ "process_id": fresh_action.process_id,
255
+ "process_definition_digest": fresh_action.process_definition_digest,
256
+ "source_cursor": fresh_action.current_node,
257
+ "repository_binding_digest": fresh_action.repository_binding_digest,
258
+ "payload": payload_for_selected_schema_branch
259
+ }
260
+ ```
261
+
262
+ `revision` remains an integer, not a string. `payload` remains an object, not a string. Do not wrap
263
+ that request inside an outer `payload` object. For an ordinary mutation, omit `recovery_apply` or
264
+ send `recovery_apply=null`.
265
+
266
+ If Core returns `INVALID_ARGUMENT`, treat it as a complete payload-contract rejection. Stop the
267
+ current mutation, report the failing action/payload contract without private data, and do not delete
268
+ fields, submit a second candidate payload for the same Action, automatically retry, or treat the
269
+ result as transport uncertainty.
270
+
271
+ ## Comprehension user interaction
272
+
273
+ At `COMPREHENSION_REVIEW`, present a bounded explanation of current requirements, design, and major
274
+ code paths; list unnecessary abstractions and maintenance risks; explicitly ask whether the
275
+ developer can explain and maintain the result; and wait for an explicit user answer or verdict.
276
+
277
+ A later developer response that may call a Dev Flow tool must include `/dev-flow` again in that
278
+ current direct user turn. The earlier comprehension prompt and earlier selector do not authorize it.
279
+
280
+ Use that answer and only the fresh Core transitions to form a candidate transition and matching
281
+ typed facts. `comprehension_passed` requires explicit current user confirmation. AI must not answer,
282
+ self-confirm, or infer that the user understands. Neither Spec Kit nor OpenSpec can own or replace
283
+ the verdict.
284
+
285
+ When the explicit verdict and fresh Core transitions identify excessive complexity, use only the
286
+ matching Core-returned transition and current typed facts. At `REFACTOR`, perform only the current
287
+ Action's bounded simplification and artifact reconciliation. Submit `refactor_ready_for_test` only
288
+ when it is present in that fresh Action; after Core commits it, continue from Core's returned `TEST`
289
+ Action and run the newly current budgeted checks before considering delivery.
290
+
291
+ ## SCHEMA_UNSUPPORTED
292
+
293
+ When Core returns `SCHEMA_UNSUPPORTED`, explain that the selected data directory contains pre-graph
294
+ or otherwise incompatible data and that Core did not modify or delete the old data. The user must
295
+ act explicitly outside Core by choosing a fresh `DEV_FLOW_DATA_DIR`, manually archiving the old
296
+ directory, manually renaming it, or manually deleting it.
297
+
298
+ Stop current task discovery and do not continue open/create, automatically retry, reset, convert,
299
+ migrate, install a migration tool, or create a substitute task. Never run delete, move, truncate, or
300
+ reset operations for the user. Do not search for a local data directory or database path, and do not
301
+ display, reveal, or expose a private path or location. Report only the stable error code and bounded
302
+ guidance: never include a `HOME` value, username, result-envelope data path, raw SQLite error, or raw
303
+ Git error. After the user completes an explicit external choice, they may invoke the exact Skill
304
+ selector again; no background handling is promised.
305
+
306
+ ## Recovery-before-retry contract
307
+
308
+ A mutation result is uncertain when it is missing, cancelled, malformed, truncated, or
309
+ transport-failed instead of returning one complete structured result. Do not immediately repeat
310
+ `mcp__dev_flow__dev_flow_apply_action` and do not infer the result from repository state or worktree contents.
311
+
312
+ Before calling `mcp__dev_flow__dev_flow_apply_action`, retain the original `request_id`, `task_id`, `process_id`,
313
+ `process_definition_digest`, `source_cursor`, `revision`, `action_id`,
314
+ `action_kind`, `repository_binding_digest`, and exact closed `payload` from the same fresh action and
315
+ the same apply dispatch. Never derive or reconstruct them from an incomplete response or partial
316
+ output.
317
+
318
+ When all required original identity values are retained, construct exactly this closed
319
+ `operation_probe`:
320
+
321
+ ```json
322
+ {
323
+ "operation_id": "<original apply request_id>",
324
+ "process_id": "standard-development",
325
+ "process_definition_digest": "<original process definition digest>",
326
+ "source_cursor": "<original source cursor>",
327
+ "expected_revision": 3,
328
+ "action_id": "<original action id>",
329
+ "action_kind": "<original action kind>",
330
+ "repository_binding_digest": "<original issuance binding digest>",
331
+ "payload": {}
332
+ }
333
+ ```
334
+
335
+ `operation_id` is the original apply `request_id`, never a read request ID.
336
+ `expected_revision` is the original action `revision`. `repository_binding_digest` is the original
337
+ issuance binding. `payload` is the exact original closed payload; when it was not completely
338
+ retained, send JSON `null`. Never reconstruct it from partial output, repository text, or model
339
+ memory.
340
+
341
+ Use the original `task_id` to call `mcp__dev_flow__dev_flow_get_task` with that exact probe. A stale pre-dispatch
342
+ Task snapshot is not an authoritative read-back. Require one complete `recovery_assessment` with the
343
+ original graph operation identity, binding relations, operation evidence, optional committed proof,
344
+ retry flag, `next_advice`, optional unblock condition, and observation time. Stop if it is absent,
345
+ truncated, malformed, or refers to another operation.
346
+
347
+ Then call `mcp__dev_flow__dev_flow_get_next_action` for the same task before considering any mutation.
348
+ Compare the fresh Task and next Action's revision, action identity, current node, last operation, and
349
+ recovery advice with the retained original identity. A missing, malformed, truncated, blocker, or
350
+ terminal next-action result is a safe-stop, not permission to replay.
351
+
352
+ DSH reconnect restores transport and tool registrations only. It never replays, retries, resumes, or
353
+ completes a workflow mutation. After reconnect, the same `get_task` then `get_next_action` sequence
354
+ still applies, and any later user turn that dispatches those reads must contain `/dev-flow` again.
355
+
356
+ Do not implement or branch on the five-class decision table. Obey only Core's complete
357
+ `next_advice`:
358
+
359
+ - `retry_current_action`: retry the ordinary current action only when Core also returns
360
+ `action_retry_safe=true` and the authoritative task still exposes the exact original action;
361
+ - `submit_recovery_apply`: submit the retained original top-level operation identity and payload,
362
+ adding exactly `recovery_apply={"operation_id":<original request_id>,"source_cursor":<original
363
+ source_cursor>}`; do not add a new recovery operation ID, destination, or classification;
364
+ - `read_next_action`: read the authoritative next action and continue only from that result;
365
+ - `resolve_blocker`: stop ordinary work and handle only the Core-returned current
366
+ `RESOLVE_BLOCKER` action;
367
+ - `stop_for_repository_drift`: report the bounded drift condition and stop.
368
+
369
+ Never infer that an unlisted action is safe. A recovery read itself cannot create a blocker or adopt
370
+ work. Only a Core-requested explicit recovery apply may do so, and its result becomes the next
371
+ authority.
372
+
373
+ If any required identity is missing or incomplete, do not construct or send an `operation_probe`;
374
+ send no fabricated or half probe. Do not fill missing values from a partial response, do not assume
375
+ `not_started`, and do not automatically retry. Stop and report that the Skill cannot prove the
376
+ mutation state.
377
+
378
+ Do not branch, decide, or interpret any recovery classification and do not guess from repository
379
+ state. Core owns classification, effect proof, blocker eligibility, and mutation directives.
380
+
381
+ A complete structured `ok=false` result is an authoritative domain error, not transport
382
+ uncertainty. Never convert or treat that domain error as missing or transport failure. Obey Core's
383
+ `code`, `message`, `recovery.retry_safe`, `recovery.action`, and `recovery.message`. When it reports
384
+ `retry_safe=false` and `action=none`, stop; do not call `mcp__dev_flow__dev_flow_get_next_action` or
385
+ `mcp__dev_flow__dev_flow_apply_action`.
386
+
387
+ ## Evidence and verification budget
388
+
389
+ - Count verification commands exactly against Core's immutable budget.
390
+ - Do not run a prohibited full suite. When automatic capacity is exhausted, report the remaining
391
+ permitted work as manual handoff without claiming it ran.
392
+ - Preserve repository instructions and explicit user authority.
393
+ - Keep static inspection, simulated Core execution, user-performed evidence, and native automated
394
+ evidence distinctly labelled.
395
+ - Submit actual sources and outcomes. Never relabel failed, skipped, or unavailable work as passed.
396
+
397
+ ## Blocked and terminal behavior
398
+
399
+ Stop repository work when Core returns authoritative `BLOCKED`, `DONE`, `CANCELLED`, an ownership or
400
+ contract conflict, or another safe-stop. Report Core's blocker and condition, terminal outcome,
401
+ evidence summary, cancellation, or conflict without replacing or merging a task. Use
402
+ `mcp__dev_flow__dev_flow_cancel_task` only after explicit user authority and a fresh current Core identity.
403
+
404
+ Adapter belief that work is complete does not override Core, and a blocker is not success.
405
+
406
+ ## Presentation contract
407
+
408
+ Use complete structured Core results for every decision. A concise user summary still preserves task
409
+ identity, revision, current node, whether a mutation committed, method capability/fallback status,
410
+ verification evidence and limits, every blocker or recovery condition, and the terminal outcome.
411
+ Never request or display private database locations.
412
+
413
+ Treat a truncated preview as uncertainty and follow the recovery-before-retry contract. Never fill
414
+ missing data from a local catalog or discard outcome-bearing fields.