dev-flow-deepseek 0.5.2 → 0.6.0

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/README.md CHANGED
@@ -11,25 +11,30 @@ macOS arm64 Core executable。
11
11
 
12
12
  | 项目 | 当前支持 |
13
13
  | --- | --- |
14
- | Package | `dev-flow-deepseek@0.5.2` |
14
+ | Package | `dev-flow-deepseek@0.6.0` |
15
15
  | Bundled Core | `0.5.1` |
16
16
  | Platform | macOS arm64 |
17
17
  | Node.js | `>=24` |
18
18
  | DSH | `>=0.1.0-rc.6` |
19
- | Release | [deepseek-v0.5.2](https://github.com/Innocent-children/dev-flow/releases/tag/deepseek-v0.5.2) |
19
+ | Release | [deepseek-v0.6.0](https://github.com/Innocent-children/dev-flow/releases/tag/deepseek-v0.6.0) |
20
20
 
21
- `0.5.2` 的 normal release 已通过 registry package 安装、显式触发、Core handshake、
21
+ `0.6.0` 的 normal release 已通过 registry package 安装、显式触发、Core handshake、
22
22
  restart/resume、`DONE`、remove、uninstall、retained reopen 和 repository-unchanged 门禁。上表
23
23
  记录已验证的精确公开版本;下面的安装命令使用 npm `latest` dist-tag 获取当前最新稳定 package。
24
24
 
25
- ## 安装到 DSH profile
25
+ ## 安装与验证
26
26
 
27
- 在一个可写目录中运行:
27
+ 先安装 DSH,再在一个可写目录中把 Dev Flow 安装到真实 profile。下面使用 `web`;需要其他
28
+ profile 时修改 `PROFILE` 的值,不要把 `<profile>` 原样输入 shell。
28
29
 
29
30
  ```bash
31
+ npm install -g @deepseek-ai/dsh@latest
30
32
  dsh --version
33
+ PROFILE=web
31
34
  TARBALL="$(npm pack dev-flow-deepseek@latest --silent)"
32
- dsh plugin --profile <profile> add "$PWD/$TARBALL"
35
+ dsh plugin --profile "$PROFILE" add "$PWD/$TARBALL"
36
+ rm -f "$PWD/$TARBALL"
37
+ dsh --profile "$PROFILE" --dump-config
33
38
  ```
34
39
 
35
40
  `npm pack` 把 `latest` 指向的官方 package 下载为当前目录中的 tarball,并将实际文件名保存到
@@ -46,12 +51,22 @@ process、Skill、guard 和 MCP child 合成到指定 profile。安装后按照
46
51
  | --- | --- |
47
52
  | `dsh --version` | 输出当前 DSH 版本,用于确认满足 Support Matrix 中的最低兼容版本。 |
48
53
  | `TARBALL="$(npm pack dev-flow-deepseek@latest --silent)"` | 从 npm 获取 `latest` package,并把生成的 tarball 文件名保存到 shell 变量。 |
49
- | `dsh plugin --profile <profile> add "$PWD/$TARBALL"` | 将绝对 tarball 路径安装到指定 DSH profile。最终 registry Journey 使用的就是这一命令形态。 |
50
- | `dsh --profile <profile> --dump-config` | 输出 profile 的有效配置,用于检查 `dev-flow-deepseek` bundle contribution 是否存在;不会修改 Dev Flow Task。 |
51
- | `dsh plugin --profile <profile> remove dev-flow-deepseek` | 从指定 profile 移除 package 与 bundle contribution;保留 Task data、目标 Git 仓库和 Codex-owned state。 |
54
+ | `dsh plugin --profile "$PROFILE" add "$PWD/$TARBALL"` | 将绝对 tarball 路径安装到 `PROFILE` 指定的 DSH profile。最终 registry Journey 使用的就是这一命令形态。 |
55
+ | `dsh --profile "$PROFILE" --dump-config` | 输出 profile 的有效配置,用于检查 `dev-flow-deepseek` bundle contribution 是否存在;不会修改 Dev Flow Task。 |
56
+ | `dsh plugin --profile "$PROFILE" remove dev-flow-deepseek` | 从指定 profile 移除 package 与 bundle contribution;保留 Task data、目标 Git 仓库和 Codex-owned state。 |
52
57
 
53
- 更新或重新安装时,按照 profile lifecycle 停止使用该 profile,执行 remove,然后重新获取
54
- `@latest` tarball 并 add。不要复用来源不明或未审查的旧 tarball。
58
+ 更新或重新安装时,按照 profile lifecycle 停止使用该 profile,然后执行:
59
+
60
+ ```bash
61
+ PROFILE=web
62
+ dsh plugin --profile "$PROFILE" remove dev-flow-deepseek
63
+ TARBALL="$(npm pack dev-flow-deepseek@latest --silent)"
64
+ dsh plugin --profile "$PROFILE" add "$PWD/$TARBALL"
65
+ rm -f "$PWD/$TARBALL"
66
+ dsh --profile "$PROFILE" --dump-config
67
+ ```
68
+
69
+ 随后重启 profile。更新 DSH 本身可执行 `npm install -g @deepseek-ai/dsh@latest`。
55
70
 
56
71
  完整的 Codex、DeepSeek、Core 和 MCP 命令目录见
57
72
  [命令参考](../../docs/COMMANDS.md)。
@@ -74,6 +89,36 @@ Task 可选择 `plain`、`spec-kit` 或 `openspec` profile。Core 管理 current
74
89
  destination、Recovery、blocker 和 terminal outcome;Adapter 负责执行当前节点工作、呈现完整 Action
75
90
  并转发 closed payload。
76
91
 
92
+ ## 两仓声明、Workspace Root 与可选索引
93
+
94
+ 启动 DSH 时的 canonical `Workspace Root` 是完整权限边界,可以是两个 Git 仓库的非 Git 共同父
95
+ 目录。主仓库、附加仓库和 symlink 解析结果都必须位于该 Root 内。以 `/workspace` 为 Root、
96
+ `/workspace/core` 和 `/workspace/docs` 为两个仓库时,可以发送:
97
+
98
+ ```text
99
+ /dev-flow Use /workspace/core as primary repository key core and add repository key docs at /workspace/docs. Update core::internal/api.go and docs::reference/api.md, then run only the targeted checks.
100
+ ```
101
+
102
+ 路径必须替换为真实绝对路径。Scope 总数为一至八,创建后不可变;Adapter 在 task-bearing open 前
103
+ 拒绝 Root 外路径和 symlink escape。系统不扫描父目录、相邻目录、依赖或索引结果来发现仓库。
104
+ 单仓库请求不需要 key,继续使用普通相对路径;从任一参与仓库恢复仍返回同一 Task。
105
+ DeepSeek 与 Codex 共用同一 Repository Scope、scoped path、Action 和唯一
106
+ `repository_binding_digest` Core 合同;Host 权限检查不创建第二套流程状态。
107
+
108
+ 可选代码索引偏好来自只读配置:
109
+
110
+ ```json
111
+ {
112
+ "codex": { "codebase_memory": false },
113
+ "deepseek": { "codebase_memory": true }
114
+ }
115
+ ```
116
+
117
+ 文件路径固定为 `$HOME/.dev-flow/config.json`。文件不存在时偏好为 false,Dev Flow 不创建或修改
118
+ 它。true 只允许使用当前 DSH 会话中已经可见且可用的 codebase-memory;缺失、不完整或中途不可用
119
+ 时,DeepSeek 每个 Dev Flow 会话最多提示一次并立即回退到内置检索,不阻塞 Task,也不安装、配置
120
+ 或启动索引能力。索引覆盖不能放宽 Workspace Root,也不能决定 Scope、权限、Recovery 或流程流转。
121
+
77
122
  ## MCP 工具
78
123
 
79
124
  DeepSeek Adapter 暴露与 Codex 相同的六工具 Core catalog;在 DSH 中会使用限定后的 tool name,
@@ -81,8 +126,8 @@ DeepSeek Adapter 暴露与 Codex 相同的六工具 Core catalog;在 DSH 中
81
126
 
82
127
  | MCP 工具 | 作用 |
83
128
  | --- | --- |
84
- | `dev_flow_server_info` | 读取 Core identity、能力、process、method profile 和工具目录;有效 admission 后必须首先调用。 |
85
- | `dev_flow_open_task` | 为当前 canonical repository 创建新 Task,或恢复其现有 Task。 |
129
+ | `dev_flow_server_info` | 读取 Core identity、能力、process、method profile、工具目录和 DeepSeek 有效索引偏好;有效 admission 后必须首先调用。 |
130
+ | `dev_flow_open_task` | Workspace Root 内显式声明的主/附加仓库创建一个 Task,或从任一参与仓库恢复同一 Task。 |
86
131
  | `dev_flow_get_task` | 读取持久化 Task;可附带 operation probe 获取 Recovery assessment。 |
87
132
  | `dev_flow_get_next_action` | 读取当前节点的权威 Action、验证预算、method steps 和全部合法 transition。 |
88
133
  | `dev_flow_apply_action` | 使用当前 revision、Action identity、repository binding 和 closed payload 应用一次 Core 声明的 transition。 |
@@ -99,16 +144,30 @@ Recovery 结论,再决定恢复动作。它不盲目重试,也不自行选
99
144
  当前 Core 只接受当前 SQLite Schema。不兼容或 pre-graph data 会返回
100
145
  `SCHEMA_UNSUPPORTED` 并保持零写入;用户可以选择新的数据目录,或在 Core 外部手工处理旧目录。
101
146
 
102
- ## 移除
147
+ ## 卸载与彻底清理
103
148
 
104
149
  ```bash
105
- dsh plugin --profile <profile> remove dev-flow-deepseek
106
- dsh --profile <profile> --dump-config
150
+ PROFILE=web
151
+ dsh plugin --profile "$PROFILE" remove dev-flow-deepseek
152
+ dsh --profile "$PROFILE" --dump-config
107
153
  ```
108
154
 
109
155
  移除后按照 DSH profile lifecycle 重启,再通过有效配置确认 bundle contribution 已消失。重新安装
110
156
  时重新执行 npm `@latest` pack 和 DSH add 命令。
111
157
 
158
+ 对每个安装过 Dev Flow 的 profile 分别执行一次。不再使用 DSH 时,可另行运行
159
+ `npm uninstall -g @deepseek-ai/dsh`;这会保留 `$HOME/.dsh` 中的 profile、会话和其他插件。
160
+
161
+ 确认 Codex Adapter 也已移除,并且不再需要任何 Task 后,可以删除两个 Host 共享的默认数据:
162
+
163
+ ```bash
164
+ rm -rf "$HOME/Library/Application Support/dev-flow"
165
+ ```
166
+
167
+ 这是不可恢复操作。使用过 `DEV_FLOW_DATA_DIR` 时,请确认准确绝对路径后单独删除。只有在还要
168
+ 删除全部 DSH profile、会话和其他插件时,才在卸载 DSH 后删除 `$HOME/.dsh`;它不是 Dev Flow
169
+ 专用目录。
170
+
112
171
  ## Package 内容
113
172
 
114
173
  Package 只包含一个 `cordis.patch.yml` layer、Adapter libraries、`dev-flow` Skill、references、
@@ -1,4 +1,8 @@
1
+ import { realpathSync } from "node:fs";
2
+ import { isAbsolute, relative } from "node:path";
3
+
1
4
  import {
5
+ DEV_FLOW_QUALIFIED_TOOL_NAMES,
2
6
  isDevFlowNamespaceTool,
3
7
  isExpectedDevFlowTool,
4
8
  } from "./tool-names.mjs";
@@ -8,6 +12,8 @@ export const DENIAL_CODES = Object.freeze({
8
12
  UNEXPECTED_TOOL: "DEV_FLOW_UNEXPECTED_TOOL",
9
13
  NO_AGENT: "DEV_FLOW_NO_AGENT",
10
14
  NO_OPEN_TURN: "DEV_FLOW_NO_OPEN_TURN",
15
+ REPOSITORY_PATH_INVALID: "DEV_FLOW_REPOSITORY_PATH_INVALID",
16
+ REPOSITORY_OUTSIDE_WORKSPACE: "DEV_FLOW_REPOSITORY_OUTSIDE_WORKSPACE",
11
17
  });
12
18
 
13
19
  const selectorPattern = /(^|\s)\/dev-flow(?=\s|$)/u;
@@ -42,7 +48,10 @@ export function deriveCurrentTurn(execution) {
42
48
  }
43
49
  }
44
50
 
45
- export function authorizeDevFlowExecution(execution) {
51
+ export function authorizeDevFlowExecution(execution, {
52
+ workspaceRoot = process.cwd(),
53
+ realpathImpl = realpathSync,
54
+ } = {}) {
46
55
  if (!isDevFlowNamespaceTool(execution?.name)) return undefined;
47
56
  if (!isExpectedDevFlowTool(execution.name)) {
48
57
  return `${DENIAL_CODES.UNEXPECTED_TOOL}: the Dev Flow namespace permits only the six contracted tools.`;
@@ -58,11 +67,76 @@ export function authorizeDevFlowExecution(execution) {
58
67
  if (!turn.selectorPresent) {
59
68
  return `${DENIAL_CODES.SELECTOR_REQUIRED}: ${selectorInstruction}.`;
60
69
  }
70
+ if (execution.name === DEV_FLOW_QUALIFIED_TOOL_NAMES[1]) {
71
+ return authorizeRepositoryScope(execution.arguments, { workspaceRoot, realpathImpl });
72
+ }
61
73
  return undefined;
62
74
  }
63
75
 
64
- export function registerDevFlowGuard(ctx) {
65
- return ctx.tools.guard(authorizeDevFlowExecution);
76
+ export function registerDevFlowGuard(ctx, {
77
+ workspaceRoot = process.cwd(),
78
+ realpathImpl = realpathSync,
79
+ } = {}) {
80
+ let canonicalWorkspaceRoot;
81
+ try {
82
+ canonicalWorkspaceRoot = realpathImpl(workspaceRoot);
83
+ } catch {
84
+ canonicalWorkspaceRoot = null;
85
+ }
86
+ return ctx.tools.guard((execution) => authorizeDevFlowExecution(execution, {
87
+ workspaceRoot: canonicalWorkspaceRoot ?? workspaceRoot,
88
+ realpathImpl,
89
+ }));
90
+ }
91
+
92
+ function authorizeRepositoryScope(arguments_, { workspaceRoot, realpathImpl }) {
93
+ if (!isPlainObject(arguments_)) {
94
+ return `${DENIAL_CODES.REPOSITORY_PATH_INVALID}: open-task arguments must be an object.`;
95
+ }
96
+ let canonicalRoot;
97
+ try {
98
+ canonicalRoot = realpathImpl(workspaceRoot);
99
+ } catch {
100
+ return `${DENIAL_CODES.REPOSITORY_PATH_INVALID}: Workspace Root is not accessible.`;
101
+ }
102
+
103
+ const declared = [{ key: arguments_.primary_repository_key ?? "primary", path: arguments_.repository_path }];
104
+ if (arguments_.additional_repositories !== undefined) {
105
+ if (!Array.isArray(arguments_.additional_repositories)) {
106
+ return `${DENIAL_CODES.REPOSITORY_PATH_INVALID}: additional_repositories must be an array.`;
107
+ }
108
+ for (const entry of arguments_.additional_repositories) {
109
+ if (!isPlainObject(entry)) {
110
+ return `${DENIAL_CODES.REPOSITORY_PATH_INVALID}: an additional repository declaration is invalid.`;
111
+ }
112
+ declared.push({ key: entry.key, path: entry.repository_path });
113
+ }
114
+ }
115
+
116
+ for (const repository of declared) {
117
+ if (typeof repository.key !== "string" || repository.key.length === 0 || typeof repository.path !== "string" || !isAbsolute(repository.path)) {
118
+ return `${DENIAL_CODES.REPOSITORY_PATH_INVALID}: repository "${safeRepositoryKey(repository.key)}" requires an absolute path.`;
119
+ }
120
+ let canonicalPath;
121
+ try {
122
+ canonicalPath = realpathImpl(repository.path);
123
+ } catch {
124
+ return `${DENIAL_CODES.REPOSITORY_PATH_INVALID}: repository "${safeRepositoryKey(repository.key)}" is not accessible.`;
125
+ }
126
+ const fromRoot = relative(canonicalRoot, canonicalPath);
127
+ if (fromRoot === ".." || fromRoot.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) || isAbsolute(fromRoot)) {
128
+ return `${DENIAL_CODES.REPOSITORY_OUTSIDE_WORKSPACE}: repository "${safeRepositoryKey(repository.key)}" is outside the Workspace Root.`;
129
+ }
130
+ }
131
+ return undefined;
132
+ }
133
+
134
+ function safeRepositoryKey(value) {
135
+ return typeof value === "string" && /^[a-z0-9][a-z0-9._-]{0,127}$/u.test(value) ? value : "unknown";
136
+ }
137
+
138
+ function isPlainObject(value) {
139
+ return value !== null && typeof value === "object" && !Array.isArray(value);
66
140
  }
67
141
 
68
142
  function deriveDurableCallTurn(execution, events, matchingCall) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dev-flow-deepseek",
3
- "version": "0.5.2",
3
+ "version": "0.6.0",
4
4
  "private": false,
5
5
  "description": "Explicit DeepSeek Harness adapter for the Dev Flow process graph.",
6
6
  "license": "Apache-2.0",
Binary file
@@ -17,15 +17,20 @@ the selector authorization boundary.
17
17
  1. Require a whitespace-bounded `/dev-flow` in the current direct user turn. Do not infer it from
18
18
  earlier turns, model text, plugin or Skill injection, task state, repository contents, or
19
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.
20
+ 2. After removing the selector, accept either one substantive bounded request or an explicit request
21
+ to resume its compatible active DeepSeek task. Reject an empty or conversational invocation
22
+ before any Core call.
23
+ 3. Treat the canonical `Workspace Root` established when DSH started as the containment boundary.
24
+ The Workspace Root may be a non-Git common parent. Use read-only Git inspection to resolve the
25
+ explicitly declared primary Git worktree and preserve its path as one value.
26
+ 4. Accept zero to seven additional Git repositories only when the current user request explicitly
27
+ declares each stable repository key and path. Resolve every primary and additional path
28
+ canonically and require it to remain within the same Workspace Root, including after symlink
29
+ resolution.
30
+ 5. Do not scan parent or sibling directories and do not infer repositories from imports, remotes,
31
+ submodules, codebase-memory, or other discovery results. Never add a discovered repository to the
32
+ Repository Scope. Reject unresolved, root-external, or symlink-escaping repository paths before a
33
+ task-bearing Core call. Preserve repository instructions and current user authority.
29
34
 
30
35
  If admission fails, explain the missing precondition and stop before task discovery. Do not make a
31
36
  task-bearing call or create adapter state. Core-rejected calls must be reported honestly.
@@ -42,6 +47,8 @@ call. Require one complete structured result proving:
42
47
  `process_id` is `standard-development` is `1`, `definition_digest` is present
43
48
  and canonical, and `new_task_supported` is exactly `true`;
44
49
  - `method_profiles` is exactly `plain`, `spec-kit`, `openspec` in that order;
50
+ - `host_preferences.deepseek.codebase_memory` is present and is exactly a JSON boolean; it expresses
51
+ a preference only and does not prove that codebase-memory is installed or available;
45
52
  - the tool catalog contains exactly these six raw names, in this order:
46
53
 
47
54
  1. `dev_flow_server_info`
@@ -57,9 +64,39 @@ or incompatible result fails the handshake. Stop without task discovery or undoc
57
64
  not inspect local source or an installed binary, and do not start a second MCP server to bypass a
58
65
  failed handshake.
59
66
 
67
+ ## Optional code discovery
68
+
69
+ After the successful handshake, consume only `host_preferences.deepseek.codebase_memory` and the
70
+ capabilities actually visible in this DeepSeek session:
71
+
72
+ - When the preference is `false`, do not call any codebase-memory tool even when one is visible. Use
73
+ built-in Git inspection, file reads, file search, and text search, and do not prompt for installation.
74
+ - When the preference is `true` and codebase-memory is already visible and usable, it may be
75
+ preferred for cross-repository symbol discovery, relationships, and impact analysis. Repository
76
+ Scope still comes only from the user's declarations, Workspace Root remains the permission
77
+ boundary, and file modification uses ordinary Host file tools.
78
+ - When the preference is `true` but the capability is absent, incomplete, or becomes unavailable,
79
+ notify the user at most once in the current Dev Flow session and immediately fall back to built-in
80
+ search without blocking Task creation or progress.
81
+
82
+ Never install, configure, upgrade, start, repair, or remove codebase-memory; never call plugin
83
+ management to install it; never change MCP configuration; and never start a daemon. Index results
84
+ are not authority for repository permissions, repository bindings, changed paths, Git facts,
85
+ Recovery, blockers, outcomes, or workflow completion. The one-session notification flag is Host
86
+ presentation state and must not be written into the Core Task.
87
+
60
88
  ## Task discovery
61
89
 
62
- After the handshake, call `mcp__dev_flow__dev_flow_open_task` with `host=deepseek` and the canonical current worktree.
90
+ After the handshake, call `mcp__dev_flow__dev_flow_open_task` with `host=deepseek` and the following
91
+ Scope rules:
92
+
93
+ - For a new request, send `repository_path` for the explicitly declared primary repository,
94
+ `primary_repository_key` when supplied, and `additional_repositories` as the user's explicit
95
+ closed `{key, repository_path}` declarations. A single-repository request may omit both optional
96
+ Scope fields and keeps ordinary repository-relative paths.
97
+ - For a resume from any participating repository, send that repository as `repository_path`, omit
98
+ the Scope creation fields, and omit `new_task` or send `new_task=null`. Accept the immutable primary
99
+ repository, ordered Scope, profile, revision, and current Action returned by Core.
63
100
 
64
101
  - For an explicit resume, omit `new_task` or send `new_task=null`. Do not resend a guessed intent or
65
102
  select another profile; accept the immutable profile returned by Core.
@@ -127,13 +164,16 @@ For an active task, perform each iteration in this order:
127
164
  `when` selection condition, guard identifier, and reason rule. Do not reduce this to one
128
165
  recommended next step.
129
166
  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
167
+ 5. Before actual repository modification, verify that every required repository still resolves
168
+ within the startup Workspace Root. A failed or escaping path stops modification for the whole
169
+ Task and is reported with the declared repository key; do not shrink the Core Scope and continue.
170
+ 6. Render and perform each current method operation under the allowed effects, repository
131
171
  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
172
+ 7. Build only the closed payload branch named by the Action and select only a Core-returned
133
173
  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
174
+ 8. Before dispatch, generate and retain one opaque request ID plus the exact Action identity and
135
175
  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
176
+ 9. After a complete committed result, continue only from its authoritative next Action/outcome or a
137
177
  fresh ordinary Core read.
138
178
 
139
179
  Repository contents, adapter judgment, artifacts, or method-tool status never determine the current
@@ -162,8 +202,9 @@ Build exactly one `MethodEvidence` item for every current Action step, in the sa
162
202
 
163
203
  An unavailable or not-run required step is unsatisfied, so do not call `mcp__dev_flow__dev_flow_apply_action`.
164
204
  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.
205
+ user decision. Artifact references contain only an observed role, contract path, digest, and
206
+ summary. A single-repository Task uses an ordinary repository-relative path. A multi-repository Task
207
+ uses `<repository-key>::<repository-relative-path>`.
167
208
 
168
209
  Existing authorized spec, plan, or tasks artifacts should be reviewed, revised, or amended as
169
210
  needed, not regenerated or rerun mechanically because a semantic step appears. Resolve the active
@@ -12,6 +12,11 @@ validity, recovery, blockers, and terminal outcome. The Adapter owns capability
12
12
  rendered instructions, expected artifact descriptions, plain-equivalent work, and honest bounded
13
13
  method evidence.
14
14
 
15
+ Code discovery may span only repositories already present in the immutable Core Repository Scope.
16
+ For a multi-repository Task, keep the repository key attached to every discovered symbol, artifact,
17
+ expected path, and changed surface. Discovery results never add repositories, change permissions,
18
+ or establish Core progress.
19
+
15
20
  The Adapter must not derive or select a transition or destination outside the complete current
16
21
  Action. A command result, artifact checkbox, proposal status, verification status, or archive status
17
22
  does not advance or mutate Core. Only a valid Core apply using one returned transition can do that.
@@ -129,7 +134,9 @@ in Action order. Each item contains only `step_id`, `status`, `capability`, and
129
134
 
130
135
  ## Artifact references
131
136
 
132
- Submit artifact evidence only as `role`, repository-relative `path`, `digest`, and `summary`. Refer
137
+ Submit artifact evidence only as `role`, contract `path`, `digest`, and `summary`. A single-repository
138
+ Task uses an ordinary repository-relative path; a multi-repository Task uses
139
+ `<repository-key>::<repository-relative-path>`. Refer
133
140
  only to a file actually observed by the Host. Never submit full contents, command output, prompts,
134
141
  token data, runtime configuration, or private locations. An artifact digest does not replace the
135
142
  repository binding. File existence, checkboxes, validation, sync, or archive status never advances
@@ -15,10 +15,16 @@ Before every ordinary apply:
15
15
  3. Select the matching `dev_flow_apply_action` `inputSchema` branch and use exactly the six common
16
16
  payload members: `transition_id`, `summary`, `reason`, `artifacts`, `method_evidence`, and
17
17
  `node_result`.
18
+ Set `reason=""` whenever the selected transition has `reason_required=false`; provide a nonempty
19
+ reason only when the selected transition has `reason_required=true`.
18
20
  4. `required_evidence` and `artifacts` are different concepts. `repository_observation` is a Core evidence requirement, not an ArtifactReference role. When no real repository-relative process
19
21
  artifact exists, submit `"artifacts": []`.
20
22
  5. Allowed ArtifactReference roles are only `requirements`, `design`, `task_plan`,
21
23
  `implementation`, `test`, `comprehension`, `refactor`, `delivery`, and `other_process`.
24
+ For every ArtifactReference path, work-item `expected_paths`, Implementation `changed_paths`, and
25
+ Refactor `changed_paths`, use an ordinary repository-relative path for a single-repository Task
26
+ and `<repository-key>::<repository-relative-path>` for a multi-repository Task. The key must
27
+ already belong to the immutable Core Scope. Do not add a payload field or a second digest.
22
28
  6. Preserve the complete `node_result` branch wrapper. Never flatten baseline fields or encode an
23
29
  array as prose.
24
30
  7. Submit exactly one MethodEvidence item for every current Action method step, in Action order.
@@ -61,6 +67,8 @@ Before every ordinary apply:
61
67
 
62
68
  Never use `repository_observation` as an artifact role, place goal/scope beside `node_result`, or
63
69
  omit `problem_class`, `baseline`, or `unresolved_questions`.
70
+ `unresolved_questions` is a sibling of `baseline` inside `node_result`; it is never a member of the
71
+ closed `baseline` object.
64
72
 
65
73
  <!-- node-payload-template:design:start -->
66
74
  ```json