@devcxl/opencode-cabbage 0.3.1 → 1.0.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.
Files changed (177) hide show
  1. package/README.md +34 -19
  2. package/README.zh.md +34 -19
  3. package/assets/agents/dev-lifecycle.md +60 -41
  4. package/assets/agents/team/architect.md +36 -1
  5. package/assets/agents/team/developer.md +89 -0
  6. package/assets/agents/team/goal-verify.md +5 -1
  7. package/assets/agents/team/reviewer.md +42 -1
  8. package/assets/commands/code.md +3 -2
  9. package/assets/commands/design.md +3 -2
  10. package/assets/commands/release.md +3 -2
  11. package/assets/commands/requirements.md +3 -2
  12. package/assets/commands/review.md +3 -2
  13. package/assets/commands/setup.md +3 -2
  14. package/assets/commands/tasks.md +2 -1
  15. package/assets/prompts/bootstrap.md +9 -8
  16. package/assets/prompts/stage-contract.md +55 -0
  17. package/assets/skills/flow-code/SKILL.md +38 -140
  18. package/assets/skills/flow-design/SKILL.md +33 -74
  19. package/assets/skills/flow-release/SKILL.md +31 -51
  20. package/assets/skills/flow-requirements/SKILL.md +47 -45
  21. package/assets/skills/flow-review/SKILL.md +26 -112
  22. package/assets/skills/flow-setup/SKILL.md +40 -43
  23. package/assets/skills/flow-tasks/SKILL.md +30 -139
  24. package/assets/skills/flow-tdd/SKILL.md +30 -31
  25. package/dist/kernel/caller.d.ts +48 -0
  26. package/dist/kernel/caller.js +88 -0
  27. package/dist/kernel/caller.js.map +1 -0
  28. package/dist/kernel/context.d.ts +27 -0
  29. package/dist/kernel/context.js +73 -0
  30. package/dist/kernel/context.js.map +1 -0
  31. package/dist/kernel/flow.d.ts +166 -0
  32. package/dist/kernel/flow.js +387 -0
  33. package/dist/kernel/flow.js.map +1 -0
  34. package/dist/kernel/legacy.d.ts +19 -0
  35. package/dist/kernel/legacy.js +34 -0
  36. package/dist/kernel/legacy.js.map +1 -0
  37. package/dist/kernel/mutex.d.ts +8 -0
  38. package/dist/kernel/mutex.js +23 -0
  39. package/dist/kernel/mutex.js.map +1 -0
  40. package/dist/kernel/permission.d.ts +21 -0
  41. package/dist/kernel/permission.js +37 -0
  42. package/dist/kernel/permission.js.map +1 -0
  43. package/dist/kernel/profile.d.ts +35 -0
  44. package/dist/kernel/profile.js +144 -0
  45. package/dist/kernel/profile.js.map +1 -0
  46. package/dist/kernel/records.d.ts +87 -0
  47. package/dist/kernel/records.js +197 -0
  48. package/dist/kernel/records.js.map +1 -0
  49. package/dist/kernel/release.d.ts +104 -0
  50. package/dist/kernel/release.js +229 -0
  51. package/dist/kernel/release.js.map +1 -0
  52. package/dist/kernel/review.d.ts +34 -0
  53. package/dist/kernel/review.js +81 -0
  54. package/dist/kernel/review.js.map +1 -0
  55. package/dist/kernel/session-index.d.ts +43 -0
  56. package/dist/kernel/session-index.js +120 -0
  57. package/dist/kernel/session-index.js.map +1 -0
  58. package/dist/kernel/setup.d.ts +70 -0
  59. package/dist/kernel/setup.js +324 -0
  60. package/dist/kernel/setup.js.map +1 -0
  61. package/dist/kernel/slug.d.ts +23 -0
  62. package/dist/kernel/slug.js +67 -0
  63. package/dist/kernel/slug.js.map +1 -0
  64. package/dist/kernel/task.d.ts +208 -0
  65. package/dist/kernel/task.js +788 -0
  66. package/dist/kernel/task.js.map +1 -0
  67. package/dist/{flowrun → kernel/tdd}/adapter.d.ts +1 -1
  68. package/dist/kernel/tdd/adapter.js.map +1 -0
  69. package/dist/{flowrun → kernel/tdd}/digest.d.ts +1 -1
  70. package/dist/kernel/tdd/digest.js.map +1 -0
  71. package/dist/{flowrun → kernel/tdd}/evaluator.d.ts +1 -1
  72. package/dist/kernel/tdd/evaluator.js.map +1 -0
  73. package/dist/kernel/tdd/evidence.d.ts +42 -0
  74. package/dist/kernel/tdd/evidence.js +48 -0
  75. package/dist/kernel/tdd/evidence.js.map +1 -0
  76. package/dist/{flowrun → kernel/tdd}/state.d.ts +1 -1
  77. package/dist/kernel/tdd/state.js.map +1 -0
  78. package/dist/kernel/types.d.ts +180 -0
  79. package/dist/kernel/types.js +2 -0
  80. package/dist/kernel/types.js.map +1 -0
  81. package/dist/kernel/worktree.d.ts +45 -0
  82. package/dist/kernel/worktree.js +127 -0
  83. package/dist/kernel/worktree.js.map +1 -0
  84. package/dist/plugin/agents.d.ts +5 -17
  85. package/dist/plugin/agents.js +0 -23
  86. package/dist/plugin/agents.js.map +1 -1
  87. package/dist/plugin/flow-control.d.ts +80 -0
  88. package/dist/plugin/flow-control.js +254 -0
  89. package/dist/plugin/flow-control.js.map +1 -0
  90. package/dist/plugin/goal.d.ts +7 -46
  91. package/dist/plugin/goal.js +32 -116
  92. package/dist/plugin/goal.js.map +1 -1
  93. package/dist/plugin/prompt-lint.js +78 -5
  94. package/dist/plugin/prompt-lint.js.map +1 -1
  95. package/dist/plugin/release-control.d.ts +37 -0
  96. package/dist/plugin/release-control.js +304 -0
  97. package/dist/plugin/release-control.js.map +1 -0
  98. package/dist/plugin/server.d.ts +19 -0
  99. package/dist/plugin/server.js +147 -302
  100. package/dist/plugin/server.js.map +1 -1
  101. package/dist/plugin/setup-control.d.ts +45 -0
  102. package/dist/plugin/setup-control.js +80 -0
  103. package/dist/plugin/setup-control.js.map +1 -0
  104. package/dist/plugin/shell.d.ts +7 -34
  105. package/dist/plugin/shell.js +12 -137
  106. package/dist/plugin/shell.js.map +1 -1
  107. package/dist/plugin/skills.d.ts +1 -1
  108. package/dist/plugin/skills.js +16 -17
  109. package/dist/plugin/skills.js.map +1 -1
  110. package/dist/plugin/task-control.d.ts +90 -0
  111. package/dist/plugin/task-control.js +201 -0
  112. package/dist/plugin/task-control.js.map +1 -0
  113. package/dist/plugin/tdd-checkpoint.d.ts +118 -0
  114. package/dist/plugin/tdd-checkpoint.js +581 -0
  115. package/dist/plugin/tdd-checkpoint.js.map +1 -0
  116. package/dist/util/paths.d.ts +0 -2
  117. package/dist/util/paths.js +1 -7
  118. package/dist/util/paths.js.map +1 -1
  119. package/package.json +1 -1
  120. package/assets/agents/team/backend.md +0 -66
  121. package/assets/agents/team/frontend.md +0 -63
  122. package/assets/commands/handoff.md +0 -4
  123. package/assets/commands/test.md +0 -4
  124. package/assets/context/CONTEXT.md +0 -40
  125. package/assets/skills/flow-handoff/SKILL.md +0 -76
  126. package/assets/skills/flow-requirements/references/interview-guide.md +0 -35
  127. package/assets/skills/flow-test/SKILL.md +0 -75
  128. package/dist/flowrun/adapter.js.map +0 -1
  129. package/dist/flowrun/audit.d.ts +0 -5
  130. package/dist/flowrun/audit.js +0 -67
  131. package/dist/flowrun/audit.js.map +0 -1
  132. package/dist/flowrun/ci.d.ts +0 -64
  133. package/dist/flowrun/ci.js +0 -184
  134. package/dist/flowrun/ci.js.map +0 -1
  135. package/dist/flowrun/coverage.d.ts +0 -70
  136. package/dist/flowrun/coverage.js +0 -207
  137. package/dist/flowrun/coverage.js.map +0 -1
  138. package/dist/flowrun/digest.js.map +0 -1
  139. package/dist/flowrun/evaluator.js.map +0 -1
  140. package/dist/flowrun/gate.d.ts +0 -28
  141. package/dist/flowrun/gate.js +0 -139
  142. package/dist/flowrun/gate.js.map +0 -1
  143. package/dist/flowrun/github.d.ts +0 -24
  144. package/dist/flowrun/github.js +0 -154
  145. package/dist/flowrun/github.js.map +0 -1
  146. package/dist/flowrun/index.d.ts +0 -14
  147. package/dist/flowrun/index.js +0 -15
  148. package/dist/flowrun/index.js.map +0 -1
  149. package/dist/flowrun/merge.d.ts +0 -57
  150. package/dist/flowrun/merge.js +0 -180
  151. package/dist/flowrun/merge.js.map +0 -1
  152. package/dist/flowrun/migration.d.ts +0 -11
  153. package/dist/flowrun/migration.js +0 -276
  154. package/dist/flowrun/migration.js.map +0 -1
  155. package/dist/flowrun/resilience.d.ts +0 -18
  156. package/dist/flowrun/resilience.js +0 -80
  157. package/dist/flowrun/resilience.js.map +0 -1
  158. package/dist/flowrun/state.js.map +0 -1
  159. package/dist/flowrun/transitions.d.ts +0 -66
  160. package/dist/flowrun/transitions.js +0 -168
  161. package/dist/flowrun/transitions.js.map +0 -1
  162. package/dist/flowrun/types.d.ts +0 -356
  163. package/dist/flowrun/types.js +0 -21
  164. package/dist/flowrun/types.js.map +0 -1
  165. package/dist/flowrun/validator.d.ts +0 -19
  166. package/dist/flowrun/validator.js +0 -209
  167. package/dist/flowrun/validator.js.map +0 -1
  168. package/dist/plugin/broker.d.ts +0 -73
  169. package/dist/plugin/broker.js +0 -140
  170. package/dist/plugin/broker.js.map +0 -1
  171. package/dist/plugin/tdd-tool.d.ts +0 -62
  172. package/dist/plugin/tdd-tool.js +0 -336
  173. package/dist/plugin/tdd-tool.js.map +0 -1
  174. /package/dist/{flowrun → kernel/tdd}/adapter.js +0 -0
  175. /package/dist/{flowrun → kernel/tdd}/digest.js +0 -0
  176. /package/dist/{flowrun → kernel/tdd}/evaluator.js +0 -0
  177. /package/dist/{flowrun → kernel/tdd}/state.js +0 -0
@@ -0,0 +1,45 @@
1
+ import { type CallerSessionClient } from "../kernel/caller.js";
2
+ import { type SetupProbeReport } from "../kernel/setup.js";
3
+ /** setup_control 工具依赖:项目目录 + caller 判定所需的 session client */
4
+ export interface SetupControlDeps {
5
+ projectDir: string;
6
+ sessionClient: CallerSessionClient;
7
+ }
8
+ export type SetupControlResponse = {
9
+ ok: boolean;
10
+ readiness?: SetupProbeReport;
11
+ profileConfirmed?: boolean;
12
+ created?: string[];
13
+ prNumber?: number | null;
14
+ error?: {
15
+ code: string;
16
+ message: string;
17
+ };
18
+ };
19
+ /**
20
+ * setup_control 工具工厂(spec §2.3)。
21
+ * 三 op:probe(readiness 报告) / generate-workflows(缺失时生成草案 + Setup PR) / confirm-profile(Profile 写回 AGENTS.md)。
22
+ * caller:primary。server.ts 接线由后续批次统一处理(本批不注册,避免文件冲突)。
23
+ */
24
+ export declare function createSetupControlTool(deps: SetupControlDeps): {
25
+ description: string;
26
+ args: {
27
+ op: import("zod").ZodEnum<{
28
+ probe: "probe";
29
+ "generate-workflows": "generate-workflows";
30
+ "confirm-profile": "confirm-profile";
31
+ }>;
32
+ pr_title: import("zod").ZodOptional<import("zod").ZodString>;
33
+ profile_overrides: import("zod").ZodOptional<import("zod").ZodString>;
34
+ };
35
+ execute(args: {
36
+ op: "probe" | "generate-workflows" | "confirm-profile";
37
+ pr_title?: string | undefined;
38
+ profile_overrides?: string | undefined;
39
+ }, context: import("@opencode-ai/plugin/tool").ToolContext): Promise<import("@opencode-ai/plugin/tool").ToolResult>;
40
+ };
41
+ /**
42
+ * 独立注册辅助:把 setup_control 挂到工具注册表。
43
+ * 供后续批次(批 8-11 或最终接线)在 server.ts 统一接线时调用。
44
+ */
45
+ export declare function registerSetupControl(registry: Record<string, unknown>, deps: SetupControlDeps): void;
@@ -0,0 +1,80 @@
1
+ import { tool } from "@opencode-ai/plugin/tool";
2
+ import { requireCaller, CALLER_NOT_AUTHORIZED } from "../kernel/caller.js";
3
+ import { probe, generateWorkflows, confirmProjectProfile, } from "../kernel/setup.js";
4
+ const DEFAULT_PR_TITLE = "chore: add CI/release workflow drafts";
5
+ /**
6
+ * setup_control 工具工厂(spec §2.3)。
7
+ * 三 op:probe(readiness 报告) / generate-workflows(缺失时生成草案 + Setup PR) / confirm-profile(Profile 写回 AGENTS.md)。
8
+ * caller:primary。server.ts 接线由后续批次统一处理(本批不注册,避免文件冲突)。
9
+ */
10
+ export function createSetupControlTool(deps) {
11
+ return tool({
12
+ description: `Detect project setup readiness, generate missing CI/release workflow drafts, and confirm the project profile.
13
+
14
+ Operations:
15
+ - probe: Detect git/gh availability, AGENTS.md Profile, CI/release workflows, and branch protection. Returns a readiness report (development-ready / release-ready).
16
+ - generate-workflows: Generate missing CI/release workflow drafts under .github/workflows/ (tech-stack agnostic), then create a chore/setup-workflows branch, commit, push, and open a Setup PR for manual merge.
17
+ - confirm-profile: After user confirmation, write the Project Profile block (from profile_overrides) back to the root AGENTS.md.
18
+
19
+ Caller: primary.`,
20
+ args: {
21
+ op: tool.schema.enum(["probe", "generate-workflows", "confirm-profile"]).describe("Setup operation"),
22
+ pr_title: tool.schema.string().optional().describe("PR title for generate-workflows"),
23
+ profile_overrides: tool.schema.string().optional().describe("JSON of user-confirmed profile fields for confirm-profile"),
24
+ },
25
+ async execute(args, ctx) {
26
+ const op = args.op;
27
+ const denied = await requireCaller(ctx, ["primary"], op, deps.sessionClient);
28
+ if (denied)
29
+ return errorResponse(CALLER_NOT_AUTHORIZED, denied);
30
+ try {
31
+ switch (op) {
32
+ case "probe": {
33
+ const readiness = await probe(deps.projectDir);
34
+ return okResponse({ readiness });
35
+ }
36
+ case "generate-workflows": {
37
+ const prTitle = args.pr_title ?? DEFAULT_PR_TITLE;
38
+ const result = await generateWorkflows(deps.projectDir, { prTitle });
39
+ if (!result.ok) {
40
+ return errorResponse("SETUP_FAILED", result.error ?? "failed to generate workflows");
41
+ }
42
+ return okResponse({ created: result.created, prNumber: result.prNumber });
43
+ }
44
+ case "confirm-profile": {
45
+ const overrides = args.profile_overrides;
46
+ if (!overrides) {
47
+ return errorResponse("POLICY_INVALID", "profile_overrides is required for confirm-profile");
48
+ }
49
+ const result = await confirmProjectProfile(deps.projectDir, overrides);
50
+ if (!result.ok) {
51
+ return errorResponse(result.code ?? "POLICY_INVALID", result.message ?? "failed to confirm profile");
52
+ }
53
+ return okResponse({ profileConfirmed: true });
54
+ }
55
+ default:
56
+ return errorResponse("UNKNOWN_OP", `Unknown op: "${op}"`);
57
+ }
58
+ }
59
+ catch (err) {
60
+ return errorResponse("INTERNAL_ERROR", String(err));
61
+ }
62
+ },
63
+ });
64
+ }
65
+ /**
66
+ * 独立注册辅助:把 setup_control 挂到工具注册表。
67
+ * 供后续批次(批 8-11 或最终接线)在 server.ts 统一接线时调用。
68
+ */
69
+ export function registerSetupControl(registry, deps) {
70
+ registry.setup_control = createSetupControlTool(deps);
71
+ }
72
+ function okResponse(overrides = {}) {
73
+ const resp = { ok: true, ...overrides };
74
+ return JSON.stringify(resp, null, 2);
75
+ }
76
+ function errorResponse(code, message) {
77
+ const resp = { ok: false, error: { code, message } };
78
+ return JSON.stringify(resp, null, 2);
79
+ }
80
+ //# sourceMappingURL=setup-control.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup-control.js","sourceRoot":"","sources":["../../src/plugin/setup-control.ts"],"names":[],"mappings":"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"}
@@ -1,37 +1,10 @@
1
- import type { AgentEntry } from "./agents.js";
2
- export interface AmbientCredentialSource {
3
- source: string;
4
- /** "env" | "config_file" | "credential_helper" */
5
- kind: "env" | "config_file" | "credential_helper";
6
- /** 具体位置(如 "GH_TOKEN" 或 "~/.config/gh/hosts.yml") */
7
- location: string;
8
- }
9
- export interface AmbientCredentialReport {
10
- hasWriteCredentials: boolean;
11
- hasGitCredentialHelper: boolean;
12
- sources: AmbientCredentialSource[];
13
- }
14
1
  /**
15
- * 检测宿主环境中的 GitHub 写凭证。
2
+ * 为 Agent 生成 shell 环境变量。
16
3
  *
17
- * 检查内容:
18
- * - GH_TOKEN / GITHUB_TOKEN / GH_ENTERPRISE_TOKEN 环境变量
19
- * - ~/.config/gh/hosts.yml(GitHub CLI OAuth token)
20
- * - ~/.gitconfig 中的 credential helper
21
- *
22
- * 注意:这只能检测常见模式,不是完备的安全审计。
23
- */
24
- export declare function detectAmbientCredentials(): AmbientCredentialReport;
25
- /**
26
- * 为 Worker agent 创建隔离 shell 环境变量。
27
- *
28
- * 隔离措施:
29
- * - HOME 设为临时目录(避免访问宿主 ~/.ssh, ~/.gitconfig 等)
30
- * - GH_CONFIG_DIR 设为临时目录下的隔离路径
31
- * - GH_TOKEN / GITHUB_TOKEN 显式清空
32
- * - GIT_CONFIG_PARAMETERS 不传递(避免继承宿主 git config)
33
- *
34
- * 重要:shell.env 只作为附加措施,不作为唯一隔离边界。
35
- * 真正的权限控制来自 agent permission 字段 + ambient credential 检测。
4
+ * 复用宿主 gh auth:不再清空 GH_TOKEN/GITHUB_TOKEN、不替换 HOME/GH_CONFIG_DIR,
5
+ * Agent shell 内只读 gh/git 可用(PRD R4「模型可直接只读 git/gh」)。
6
+ * 安全边界:写操作凭据与模型 shell 共享宿主 auth,因此**写操作靠 permission 规则
7
+ * (deny 置尾、最后匹配优先、auto 模式 deny 生效)收敛到生命周期工具**,
8
+ * 而非依赖凭据隔离——见 spec §7.3 的取舍说明。
36
9
  */
37
- export declare function createIsolatedShellEnv(agent: AgentEntry): Record<string, string>;
10
+ export declare function createAgentShellEnv(): Record<string, string>;
@@ -1,144 +1,19 @@
1
- import fs from "node:fs";
2
- import path from "node:path";
3
- import os from "node:os";
4
- // ─── 凭证检测 ───
5
- const GITHUB_WRITE_TOKEN_PATTERNS = [
6
- /^ghp_/, // classic PAT
7
- /^github_pat_/, // fine-grained PAT
8
- /^gho_/, // OAuth token
9
- /^ghu_/, // user-to-server token
10
- /^ghs_/, // server-to-server token
11
- /^ghr_/, // refresh token
12
- ];
1
+ // ─── Shell 环境 ───
13
2
  /**
14
- * 检测 token 值是否看起来是 GitHub 写凭证。
15
- */
16
- function looksLikeGithubToken(value) {
17
- const trimmed = value.trim();
18
- if (!trimmed)
19
- return false;
20
- return GITHUB_WRITE_TOKEN_PATTERNS.some(p => p.test(trimmed));
21
- }
22
- /**
23
- * 检测环境变量中的 GitHub API 凭证。
24
- */
25
- function detectEnvTokens() {
26
- const sources = [];
27
- const keys = ["GH_TOKEN", "GITHUB_TOKEN", "GH_ENTERPRISE_TOKEN"];
28
- for (const key of keys) {
29
- const value = process.env[key];
30
- if (value && looksLikeGithubToken(value)) {
31
- sources.push({
32
- source: key,
33
- kind: "env",
34
- location: `$${key}`,
35
- });
36
- }
37
- }
38
- return sources;
39
- }
40
- /**
41
- * 检测 ~/.config/gh/hosts.yml 中的 oauth_token。
42
- */
43
- function detectGhHostsConfig() {
44
- const sources = [];
45
- const home = process.env.HOME || os.homedir();
46
- const hostsPath = path.join(home, ".config", "gh", "hosts.yml");
47
- try {
48
- if (!fs.existsSync(hostsPath))
49
- return sources;
50
- const content = fs.readFileSync(hostsPath, "utf8");
51
- // 简单检测 oauth_token 字段
52
- if (/oauth_token\s*:\s*\S+/.test(content)) {
53
- sources.push({
54
- source: "gh_hosts_config",
55
- kind: "config_file",
56
- location: hostsPath,
57
- });
58
- }
59
- }
60
- catch {
61
- // 读取失败时静默忽略
62
- }
63
- return sources;
64
- }
65
- /**
66
- * 检测 git credential helper 配置。
67
- * 检查 ~/.gitconfig 中是否配置了 credential.helper。
68
- */
69
- function detectGitCredentialHelper() {
70
- const sources = [];
71
- const home = process.env.HOME || os.homedir();
72
- const gitconfigPath = path.join(home, ".gitconfig");
73
- let hasHelper = false;
74
- try {
75
- if (!fs.existsSync(gitconfigPath))
76
- return { hasHelper, sources };
77
- const content = fs.readFileSync(gitconfigPath, "utf8");
78
- if (/credential\s*\]\s*\n\s*helper\s*=/.test(content) || /\[credential\s+"[^"]*"\]/.test(content)) {
79
- hasHelper = true;
80
- sources.push({
81
- source: "git_credential_helper",
82
- kind: "credential_helper",
83
- location: gitconfigPath,
84
- });
85
- }
86
- }
87
- catch {
88
- // 读取失败静默忽略
89
- }
90
- return { hasHelper, sources };
91
- }
92
- /**
93
- * 检测宿主环境中的 GitHub 写凭证。
94
- *
95
- * 检查内容:
96
- * - GH_TOKEN / GITHUB_TOKEN / GH_ENTERPRISE_TOKEN 环境变量
97
- * - ~/.config/gh/hosts.yml(GitHub CLI OAuth token)
98
- * - ~/.gitconfig 中的 credential helper
3
+ * 为 Agent 生成 shell 环境变量。
99
4
  *
100
- * 注意:这只能检测常见模式,不是完备的安全审计。
5
+ * 复用宿主 gh auth:不再清空 GH_TOKEN/GITHUB_TOKEN、不替换 HOME/GH_CONFIG_DIR,
6
+ * Agent shell 内只读 gh/git 可用(PRD R4「模型可直接只读 git/gh」)。
7
+ * 安全边界:写操作凭据与模型 shell 共享宿主 auth,因此**写操作靠 permission 规则
8
+ * (deny 置尾、最后匹配优先、auto 模式 deny 生效)收敛到生命周期工具**,
9
+ * 而非依赖凭据隔离——见 spec §7.3 的取舍说明。
101
10
  */
102
- export function detectAmbientCredentials() {
103
- const envSources = detectEnvTokens();
104
- const ghConfigSources = detectGhHostsConfig();
105
- const { hasHelper, sources: helperSources } = detectGitCredentialHelper();
106
- const allSources = [...envSources, ...ghConfigSources, ...helperSources];
107
- const hasWriteCredentials = allSources.length > 0;
11
+ export function createAgentShellEnv() {
108
12
  return {
109
- hasWriteCredentials,
110
- hasGitCredentialHelper: hasHelper,
111
- sources: allSources,
112
- };
113
- }
114
- // ─── Shell 隔离 ───
115
- /**
116
- * 为 Worker agent 创建隔离 shell 环境变量。
117
- *
118
- * 隔离措施:
119
- * - HOME 设为临时目录(避免访问宿主 ~/.ssh, ~/.gitconfig 等)
120
- * - GH_CONFIG_DIR 设为临时目录下的隔离路径
121
- * - GH_TOKEN / GITHUB_TOKEN 显式清空
122
- * - GIT_CONFIG_PARAMETERS 不传递(避免继承宿主 git config)
123
- *
124
- * 重要:shell.env 只作为附加措施,不作为唯一隔离边界。
125
- * 真正的权限控制来自 agent permission 字段 + ambient credential 检测。
126
- */
127
- export function createIsolatedShellEnv(agent) {
128
- const shellHome = fs.mkdtempSync(path.join(os.tmpdir(), "cabbage-shell-"));
129
- const ghConfigDir = path.join(shellHome, ".config", "gh");
130
- fs.mkdirSync(ghConfigDir, { recursive: true });
131
- const env = {
132
- HOME: shellHome,
133
- GH_CONFIG_DIR: ghConfigDir,
13
+ // 防系统 gitconfig 干扰
14
+ GIT_CONFIG_NOSYSTEM: "1",
15
+ // 禁止交互式凭据提示(失败即失败,不挂起等待输入)
16
+ GIT_TERMINAL_PROMPT: "0",
134
17
  };
135
- // 清除所有 GitHub API token 环境变量
136
- // shell.env 是附加措施 — 主要隔离由 agent permission 提供
137
- env.GH_TOKEN = "";
138
- env.GITHUB_TOKEN = "";
139
- env.GH_ENTERPRISE_TOKEN = "";
140
- // 不传递宿主 git config(隔离 HOME 已处理此问题,但显式清空更安全)
141
- env.GIT_CONFIG_NOSYSTEM = "1";
142
- return env;
143
18
  }
144
19
  //# sourceMappingURL=shell.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"shell.js","sourceRoot":"","sources":["../../src/plugin/shell.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,MAAM,SAAS,CAAA;AAmBxB,eAAe;AAEf,MAAM,2BAA2B,GAAG;IAClC,OAAO,EAAS,cAAc;IAC9B,cAAc,EAAE,mBAAmB;IACnC,OAAO,EAAS,cAAc;IAC9B,OAAO,EAAS,uBAAuB;IACvC,OAAO,EAAS,yBAAyB;IACzC,OAAO,EAAS,gBAAgB;CACjC,CAAA;AAED;;GAEG;AACH,SAAS,oBAAoB,CAAC,KAAa;IACzC,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAA;IAC5B,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAA;IAC1B,OAAO,2BAA2B,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAA;AAC/D,CAAC;AAED;;GAEG;AACH,SAAS,eAAe;IACtB,MAAM,OAAO,GAA8B,EAAE,CAAA;IAC7C,MAAM,IAAI,GAAG,CAAC,UAAU,EAAE,cAAc,EAAE,qBAAqB,CAAC,CAAA;IAEhE,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAC9B,IAAI,KAAK,IAAI,oBAAoB,CAAC,KAAK,CAAC,EAAE,CAAC;YACzC,OAAO,CAAC,IAAI,CAAC;gBACX,MAAM,EAAE,GAAG;gBACX,IAAI,EAAE,KAAK;gBACX,QAAQ,EAAE,IAAI,GAAG,EAAE;aACpB,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAA;AAChB,CAAC;AAED;;GAEG;AACH,SAAS,mBAAmB;IAC1B,MAAM,OAAO,GAA8B,EAAE,CAAA;IAC7C,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,CAAA;IAC7C,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,CAAC,CAAA;IAE/D,IAAI,CAAC;QACH,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC;YAAE,OAAO,OAAO,CAAA;QAE7C,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;QAClD,sBAAsB;QACtB,IAAI,uBAAuB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAC1C,OAAO,CAAC,IAAI,CAAC;gBACX,MAAM,EAAE,iBAAiB;gBACzB,IAAI,EAAE,aAAa;gBACnB,QAAQ,EAAE,SAAS;aACpB,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,YAAY;IACd,CAAC;IAED,OAAO,OAAO,CAAA;AAChB,CAAC;AAED;;;GAGG;AACH,SAAS,yBAAyB;IAChC,MAAM,OAAO,GAA8B,EAAE,CAAA;IAC7C,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,OAAO,EAAE,CAAA;IAC7C,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,CAAA;IAEnD,IAAI,SAAS,GAAG,KAAK,CAAA;IAErB,IAAI,CAAC;QACH,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC;YAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,CAAA;QAEhE,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC,CAAA;QACtD,IAAI,mCAAmC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,0BAA0B,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAClG,SAAS,GAAG,IAAI,CAAA;YAChB,OAAO,CAAC,IAAI,CAAC;gBACX,MAAM,EAAE,uBAAuB;gBAC/B,IAAI,EAAE,mBAAmB;gBACzB,QAAQ,EAAE,aAAa;aACxB,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,WAAW;IACb,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,CAAA;AAC/B,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,wBAAwB;IACtC,MAAM,UAAU,GAAG,eAAe,EAAE,CAAA;IACpC,MAAM,eAAe,GAAG,mBAAmB,EAAE,CAAA;IAC7C,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,aAAa,EAAE,GAAG,yBAAyB,EAAE,CAAA;IAEzE,MAAM,UAAU,GAAG,CAAC,GAAG,UAAU,EAAE,GAAG,eAAe,EAAE,GAAG,aAAa,CAAC,CAAA;IACxE,MAAM,mBAAmB,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC,CAAA;IAEjD,OAAO;QACL,mBAAmB;QACnB,sBAAsB,EAAE,SAAS;QACjC,OAAO,EAAE,UAAU;KACpB,CAAA;AACH,CAAC;AAED,mBAAmB;AAEnB;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAAiB;IACtD,MAAM,SAAS,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAA;IAC1E,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,IAAI,CAAC,CAAA;IACzD,EAAE,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAE9C,MAAM,GAAG,GAA2B;QAClC,IAAI,EAAE,SAAS;QACf,aAAa,EAAE,WAAW;KAC3B,CAAA;IAED,6BAA6B;IAC7B,8CAA8C;IAC9C,GAAG,CAAC,QAAQ,GAAG,EAAE,CAAA;IACjB,GAAG,CAAC,YAAY,GAAG,EAAE,CAAA;IACrB,GAAG,CAAC,mBAAmB,GAAG,EAAE,CAAA;IAE5B,4CAA4C;IAC5C,GAAG,CAAC,mBAAmB,GAAG,GAAG,CAAA;IAE7B,OAAO,GAAG,CAAA;AACZ,CAAC"}
1
+ {"version":3,"file":"shell.js","sourceRoot":"","sources":["../../src/plugin/shell.ts"],"names":[],"mappings":"AAAA,mBAAmB;AAEnB;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB;IACjC,OAAO;QACL,mBAAmB;QACnB,mBAAmB,EAAE,GAAG;QACxB,2BAA2B;QAC3B,mBAAmB,EAAE,GAAG;KACzB,CAAA;AACH,CAAC"}
@@ -1 +1 @@
1
- export declare function setupSkillsDir(sourceSkillsDir: string, contextDir?: string, promptsDir?: string): Promise<string>;
1
+ export declare function setupSkillsDir(sourceSkillsDir: string, promptsDir?: string): Promise<string>;
@@ -1,23 +1,22 @@
1
- import { cp, mkdtemp, readdir, readFile, rm, writeFile } from "node:fs/promises";
2
- import { tmpdir } from "node:os";
1
+ import { cp, mkdir, readdir, readFile, rm, writeFile } from "node:fs/promises";
2
+ import { homedir } from "node:os";
3
3
  import path from "node:path";
4
- const _tempDirs = new Set();
5
- process.once("exit", () => {
6
- for (const dir of _tempDirs) {
7
- rm(dir, { recursive: true, force: true }).catch(() => { });
4
+ /**
5
+ * skills 固定安装路径,确保跨会话稳定。
6
+ * 用 env CABBAGE_SKILLS_DIR 可覆盖,方便测试。
7
+ */
8
+ function resolveSkillsPath() {
9
+ if (process.env.CABBAGE_SKILLS_DIR) {
10
+ return process.env.CABBAGE_SKILLS_DIR;
8
11
  }
9
- });
10
- export async function setupSkillsDir(sourceSkillsDir, contextDir, promptsDir) {
11
- const baseDir = await mkdtemp(path.join(tmpdir(), "opencode-cabbage-skills-"));
12
- _tempDirs.add(baseDir);
13
- const destDir = path.join(baseDir, "skills");
12
+ return path.join(homedir(), ".config", "opencode", "cabbage", "skills");
13
+ }
14
+ export async function setupSkillsDir(sourceSkillsDir, promptsDir) {
15
+ const destDir = resolveSkillsPath();
16
+ // 清理旧内容,确保与插件版本一致
17
+ await rm(destDir, { recursive: true, force: true });
18
+ await mkdir(destDir, { recursive: true });
14
19
  await cp(sourceSkillsDir, destDir, { recursive: true });
15
- if (contextDir) {
16
- try {
17
- await cp(contextDir, path.join(destDir, "_context"), { recursive: true });
18
- }
19
- catch { }
20
- }
21
20
  if (promptsDir) {
22
21
  try {
23
22
  await cp(promptsDir, path.join(destDir, "_prompts"), { recursive: true });
@@ -1 +1 @@
1
- {"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/plugin/skills.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAChF,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAChC,OAAO,IAAI,MAAM,WAAW,CAAA;AAE5B,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAA;AAEnC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE;IACxB,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;QAC5B,EAAE,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;IAC3D,CAAC;AACH,CAAC,CAAC,CAAA;AAEF,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,eAAuB,EAAE,UAAmB,EAAE,UAAmB;IACpG,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,0BAA0B,CAAC,CAAC,CAAA;IAC9E,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IACtB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;IAE5C,MAAM,EAAE,CAAC,eAAe,EAAE,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAEvD,IAAI,UAAU,EAAE,CAAC;QACf,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QAC3E,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;IACZ,CAAC;IAED,IAAI,UAAU,EAAE,CAAC;QACf,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QAC3E,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;IACZ,CAAC;IAED,KAAK,UAAU,UAAU,CAAC,GAAW;QACnC,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAA;QAC3D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAA;YAC3C,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAA;gBAC1B,SAAQ;YACV,CAAC;YACD,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gBAC9B,IAAI,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;gBAC9C,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,mBAAmB,EAAE,GAAG,OAAO,GAAG,CAAC,CAAA;gBAChE,MAAM,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAA;YAC5C,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,UAAU,CAAC,OAAO,CAAC,CAAA;IAEzB,OAAO,OAAO,CAAA;AAChB,CAAC"}
1
+ {"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/plugin/skills.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAC9E,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACjC,OAAO,IAAI,MAAM,WAAW,CAAA;AAE5B;;;GAGG;AACH,SAAS,iBAAiB;IACxB,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,CAAC;QACnC,OAAO,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAA;IACvC,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAA;AACzE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,eAAuB,EAAE,UAAmB;IAC/E,MAAM,OAAO,GAAG,iBAAiB,EAAE,CAAA;IAEnC,kBAAkB;IAClB,MAAM,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;IACnD,MAAM,KAAK,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAEzC,MAAM,EAAE,CAAC,eAAe,EAAE,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAEvD,IAAI,UAAU,EAAE,CAAC;QACf,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QAC3E,CAAC;QAAC,MAAM,CAAC,CAAA,CAAC;IACZ,CAAC;IAED,KAAK,UAAU,UAAU,CAAC,GAAW;QACnC,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAA;QAC3D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAA;YAC3C,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAA;gBAC1B,SAAQ;YACV,CAAC;YACD,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;gBAC9B,IAAI,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;gBAC9C,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,mBAAmB,EAAE,GAAG,OAAO,GAAG,CAAC,CAAA;gBAChE,MAAM,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,MAAM,CAAC,CAAA;YAC5C,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,UAAU,CAAC,OAAO,CAAC,CAAA;IAEzB,OAAO,OAAO,CAAA;AAChB,CAAC"}
@@ -0,0 +1,90 @@
1
+ /** task_control 工具依赖 */
2
+ export interface TaskControlDeps {
3
+ projectDir: string;
4
+ sessionClient: {
5
+ session: {
6
+ get(input: {
7
+ sessionID: string;
8
+ }): Promise<{
9
+ data?: {
10
+ parentID?: string | null;
11
+ };
12
+ }>;
13
+ };
14
+ };
15
+ }
16
+ export type TaskControlResponse = {
17
+ ok: boolean;
18
+ task?: {
19
+ parentIssueNumber?: number;
20
+ taskId?: string;
21
+ issueNumber?: number;
22
+ };
23
+ issueNumber?: number;
24
+ branch?: string;
25
+ worktreePath?: string;
26
+ policy?: unknown;
27
+ baseline?: unknown;
28
+ prNumber?: number;
29
+ evidenceRevision?: number;
30
+ verdict?: string;
31
+ risk?: string;
32
+ warning?: string;
33
+ reason?: string;
34
+ report?: unknown;
35
+ missing?: string[];
36
+ error?: {
37
+ code: string;
38
+ message: string;
39
+ };
40
+ };
41
+ /**
42
+ * task_control 工具工厂(spec §2.3)。
43
+ * caller 门禁:primary 全量;developer 拒绝(无门禁绕过面)。
44
+ */
45
+ export declare function createTaskControlTool(deps: TaskControlDeps): {
46
+ description: string;
47
+ args: {
48
+ op: import("zod").ZodEnum<{
49
+ "create-task": "create-task";
50
+ "start-task": "start-task";
51
+ "submit-task": "submit-task";
52
+ "submit-review": "submit-review";
53
+ "merge-task": "merge-task";
54
+ "cancel-task": "cancel-task";
55
+ "destroy-worktree": "destroy-worktree";
56
+ "status-task": "status-task";
57
+ }>;
58
+ title: import("zod").ZodOptional<import("zod").ZodString>;
59
+ parent_issue_number: import("zod").ZodOptional<import("zod").ZodNumber>;
60
+ task_id: import("zod").ZodOptional<import("zod").ZodString>;
61
+ acceptance_criteria: import("zod").ZodOptional<import("zod").ZodString>;
62
+ depends_on: import("zod").ZodOptional<import("zod").ZodString>;
63
+ pr_number: import("zod").ZodOptional<import("zod").ZodNumber>;
64
+ risk: import("zod").ZodOptional<import("zod").ZodEnum<{
65
+ low: "low";
66
+ high: "high";
67
+ }>>;
68
+ verdict: import("zod").ZodOptional<import("zod").ZodEnum<{
69
+ approve: "approve";
70
+ "request-changes": "request-changes";
71
+ }>>;
72
+ comment: import("zod").ZodOptional<import("zod").ZodString>;
73
+ user_confirmed: import("zod").ZodOptional<import("zod").ZodBoolean>;
74
+ };
75
+ execute(args: {
76
+ op: "create-task" | "start-task" | "submit-task" | "submit-review" | "merge-task" | "cancel-task" | "destroy-worktree" | "status-task";
77
+ title?: string | undefined;
78
+ parent_issue_number?: number | undefined;
79
+ task_id?: string | undefined;
80
+ acceptance_criteria?: string | undefined;
81
+ depends_on?: string | undefined;
82
+ pr_number?: number | undefined;
83
+ risk?: "low" | "high" | undefined;
84
+ verdict?: "approve" | "request-changes" | undefined;
85
+ comment?: string | undefined;
86
+ user_confirmed?: boolean | undefined;
87
+ }, context: import("@opencode-ai/plugin/tool").ToolContext): Promise<import("@opencode-ai/plugin/tool").ToolResult>;
88
+ };
89
+ /** 独立注册辅助:把 task_control 挂到工具注册表(后续接线批次使用) */
90
+ export declare function registerTaskControl(registry: Record<string, unknown>, deps: TaskControlDeps): void;