澄清需求并生成验收脚本,受门禁保护自动执行任务
30/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/10/15 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add bbskye5008/dsh-task-runner该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:待复验
是什么
dsh 原生插件 · dev
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 17 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
可执行外部命令读写/删除本地文件
查看扫描证据(共 146 处,展示前 101 条)
- 写入本地文件index.mjs:20
mkdirSync(home,{recursive:true,mode:0o700});chmodSync(home,0o700); - 写入本地文件index.mjs:20
mkdirSync(home,{recursive:true,mode:0o700});chmodSync(home,0o700); - 读取本地文件index.mjs:34
const snapshot=run=>JSON.parse(readFileSync(join(run.dir,'status.json'),'utf8')); - 读取本地文件index.mjs:116
for(const entry of readdirSync(home,{withFileTypes:true})){ - 读取本地文件index.mjs:118
try{const s=JSON.parse(readFileSync(path,'utf8'));let ownerAlive=false;try{if(s.pid&&s.pid!==process.pid){process.kill(s.pid,0);ownerAlive=true;}}catc - 写入本地文件index.mjs:118
try{const s=JSON.parse(readFileSync(path,'utf8'));let ownerAlive=false;try{if(s.pid&&s.pid!==process.pid){process.kill(s.pid,0);ownerAlive=true;}}catc - 读取本地文件index.mjs:135
else if(req.action==='status')value=req.id?.startsWith('prep-')?preparations.status(req.id):req.id?(live.has(req.id)?snapshot(live.get(req.id)):JSON.p - 写入本地文件index.mjs:143
const listen=()=>server.listen(socketPath,()=>{chmodSync(socketPath,0o600);writeFileSync(receipt,JSON.stringify({socketPath,token,pid:process.pid})+'\ - 写入本地文件index.mjs:143
const listen=()=>server.listen(socketPath,()=>{chmodSync(socketPath,0o600);writeFileSync(receipt,JSON.stringify({socketPath,token,pid:process.pid})+'\ - 读取本地文件index.mjs:144
if(existsSync(socketPath)){ - 删除本地文件index.mjs:145
const probe=createConnection(socketPath);probe.once('connect',()=>{probe.destroy();ctx.logger.error('Task Runner controller already running; CLI contr - 读取本地文件index.mjs:151
try{const current=JSON.parse(readFileSync(receipt,'utf8'));if(current.token===token){unlinkSync(receipt);try{unlinkSync(socketPath);}catch{}}}catch{} - 删除本地文件index.mjs:151
try{const current=JSON.parse(readFileSync(receipt,'utf8'));if(current.token===token){unlinkSync(receipt);try{unlinkSync(socketPath);}catch{}}}catch{} - 读取本地文件guard.mjs:23
if(existsSync(patch)){ - 读取本地文件guard.mjs:25
const rows=yaml.load(readFileSync(patch,'utf8'),{schema})??[]; - 读取本地文件cli.mjs:13
const control=JSON.parse(readFileSync(join(home,'control.json'),'utf8')); - 读取本地文件runtime/input.mjs:23
value.workspace=realpathSync(value.workspace);if(!lstatSync(value.workspace).isDirectory())throw Error('workspace_directory_required'); - 执行外部命令固定命令runtime/input.mjs:27
const syntax=spawnSync('/bin/sh',['-n','-c',value.verify],{timeout:1000,encoding:'utf8'});if(syntax.status!==0)throw Error('invalid_verification_shell - 读取本地文件runtime/input.mjs:38
path=realpathSync(path);const st=lstatSync(path); - 读取本地文件runtime/input.mjs:39
if(st.isDirectory()){if(path===cwd||path===dirname(cwd)||path==='/')throw Error('acceptance_root_too_broad');for(const n of readdirSync(path).sort())a - 读取本地文件runtime/input.mjs:44
path=resolve(cwd,path);if(!existsSync(path))throw Error('frozen_path_missing:'+path); - 读取本地文件runtime/input.mjs:45
const st=lstatSync(path);if(st.isSymbolicLink())throw Error('acceptance_symlink_not_supported:'+path); - 读取本地文件runtime/input.mjs:51
for(const n of ['AGENTS.md','TASK.txt','TASK.md'])if(existsSync(join(cwd,n)))lock(n); - 写入本地文件runtime/run-config.mjs:11
mkdirSync(dir,{recursive:true,mode:0o700}); - 写入本地文件runtime/run-config.mjs:28
const userMessage=join(dir,'user-message.txt');writeFileSync(userMessage,root); - 写入本地文件runtime/run-config.mjs:34
const profile=join(dir,'profile.json');writeFileSync(profile,JSON.stringify(p,null,2)+'\n'); - 读取本地文件runtime/run-config.mjs:36
const pin=path=>{const st=lstatSync(path);if(st.isDirectory())for(const n of readdirSync(path))pin(join(path,n));else if(st.isFile()&&/ (?:mjs|js|jso - 读取本地文件runtime/run-config.mjs:36
const pin=path=>{const st=lstatSync(path);if(st.isDirectory())for(const n of readdirSync(path))pin(join(path,n));else if(st.isFile()&&/ (?:mjs|js|jso - 读取本地文件runtime/run-config.mjs:36
const pin=path=>{const st=lstatSync(path);if(st.isDirectory())for(const n of readdirSync(path))pin(join(path,n));else if(st.isFile()&&/ (?:mjs|js|jso - 写入本地文件runtime/run-config.mjs:39
run.log=(type,data={})=>{appendFileSync(join(dir,'events.jsonl'),JSON.stringify({...data,at:new Date().toISOString(),session:sessionId,run:id,type})+' - 写入本地文件runtime/run-config.mjs:40
run.save=()=>writeFileSync(join(dir,'status.json'),JSON.stringify({id,sessionId,pid:process.pid,workspace:p.cwd,status:run.status,started:run.started, - 读取本地文件runtime/profile-store.mjs:8
const st=lstatSync(path); if(!st.isFile()||st.isSymbolicLink()) throw Error('regular_file_required:'+path); - 读取本地文件runtime/profile-store.mjs:9
return readFileSync(path); - 读取本地文件runtime/profile-store.mjs:14
const walk=path=>{const st=lstatSync(path);const name=path.slice(cwd.length+1);if(st.isSymbolicLink())throw Error('locked_tree_symlink'); - 读取本地文件runtime/profile-store.mjs:15
if(st.isDirectory()){entries[name]='directory';for(const child of readdirSync(path).sort())walk(resolve(path,child));} - 读取本地文件runtime/profile-store.mjs:16
else if(st.isFile())entries[name]='file:'+hash(readFileSync(path));else throw Error('locked_tree_entry');}; - 读取本地文件runtime/profile-store.mjs:62
if(!existsSync(home))return; - 读取本地文件runtime/completion-gate.mjs:14
for (const name of readdirSync(dir).sort()) { - 读取本地文件runtime/completion-gate.mjs:16
const file = join(dir, name), stat = lstatSync(file); - 读取本地文件runtime/completion-gate.mjs:20
else if (stat.isFile()) rows.push([key, 'file', hash(readFileSync(file))]); - 读取本地文件runtime/native-task.mjs:18
const visit=(file)=>{if(excluded.some(x=>file===x||file.startsWith(x+'/')))return;const st=lstatSync(file);if(st.isSymbolicLink())throw Error('impleme - 读取本地文件runtime/native-task.mjs:19
if(st.isDirectory()){for(const n of readdirSync(file).sort())if(!['__pycache__','.git','node_modules','.scratch','.pytest_cache','.mypy_cache','.ruff_ - 读取本地文件runtime/native-task.mjs:20
else if(st.isFile())rows.push([file.slice(p.cwd.length),hash(readFileSync(file))]);else throw Error('implementation_entry');}; - 读取本地文件runtime/preparation-host.mjs:20
if(existsSync(previousRoot))for(const id of readdirSync(previousRoot))if(/^prep-[a-f0-9-]{36}$/.test(id)){ - 读取本地文件runtime/preparation-host.mjs:20
if(existsSync(previousRoot))for(const id of readdirSync(previousRoot))if(/^prep-[a-f0-9-]{36}$/.test(id)){ - 读取本地文件runtime/preparation-host.mjs:62
if(exec.name==='skill'&&exec.arguments?.name==='to-spec'&&(!p.loadedSkills.includes('to-grill')||!existsSync(join(p.artifactRoot,'requirements.md')))) - 读取本地文件runtime/preparation-host.mjs:85
if(id){const p=get(id);return {...summary(p),error:p.error??null,...p.review?{reviewText:readFileSync(p.review,'utf8')}:{}};} - 读取本地文件runtime/preparation-host.mjs:86
const root=join(home,'preparations');if(existsSync(root))for(const id of readdirSync(root))if(/^prep-[a-f0-9-]{36}$/.test(id))get(id); - 读取本地文件runtime/preparation-host.mjs:86
const root=join(home,'preparations');if(existsSync(root))for(const id of readdirSync(root))if(/^prep-[a-f0-9-]{36}$/.test(id))get(id); - 读取本地文件vendor/pua/lib/source.js:9
const manifest = JSON.parse(readFileSync(new URL('upstream.json', root), 'utf8')); - 读取本地文件vendor/pua/lib/source.js:14
const bytes = readFileSync(new URL(entry.file, root)); - 读取本地文件vendor/guard-dist/index.js:2038
if (existsSync(manifestPath)) try { - 读取本地文件vendor/guard-dist/index.js:2039
if (JSON.parse(readFileSync(manifestPath, "utf8")).name === "dsh-completion-guard") { - 读取本地文件vendor/guard-dist/index.js:2299
return createHash("sha256").update(await readFile(path)).digest("hex"); - 读取本地文件vendor/guard-dist/index.js:2307
return record$1(JSON.parse(await readFile(path, "utf8"))); - 读取本地文件vendor/guard-dist/index.js:2314
const bytes = await readFile(path); - 读取本地文件vendor/guard-dist/index.js:2463
const lock = await readFile(resolve(profilePath, "pnpm-lock.yaml"), "utf8"); - 写入本地文件runtime/acceptance.mjs:13
await mkdir(dir,{recursive:true}); - 读取本地文件runtime/acceptance.mjs:17
try{if((await lstat(join(run.p.cwd,'node_modules'))).isDirectory())await symlink(join(run.p.cwd,'node_modules'),join(snapshot,'node_modules'),'dir');} - 写入本地文件runtime/acceptance.mjs:20
const scratch=join(dir,'scratch');await mkdir(scratch,{recursive:true}); - 执行外部命令固定命令runtime/acceptance.mjs:23
const child=spawn('/bin/sh',['-c',run.verify],{cwd:snapshot,detached:true,env:{...process.env,PYTHONDONTWRITEBYTECODE:'1',TMPDIR:scratch,DSH_TASK_WORK - 写入本地文件runtime/acceptance.mjs:37
await writeFile(join(dir,'result.json'),JSON.stringify(report,null,2)+'\n'); - 读取本地文件runtime/preparation.mjs:13
const visit=dir=>{for(const n of readdirSync(dir).sort()){ - 读取本地文件runtime/preparation.mjs:16
const st=lstatSync(p),key=relative(workspace,p); - 读取本地文件runtime/preparation.mjs:19
else if(st.isFile())rows.push([key,hash(readFileSync(p))]); - 读取本地文件runtime/preparation.mjs:26
for(const p of [join(input.workspace,'.spec-workflow'),artifactRoot])if(existsSync(p)&&lstatSync(p).isSymbolicLink())throw Error('preparation_symlink' - 读取本地文件runtime/preparation.mjs:26
for(const p of [join(input.workspace,'.spec-workflow'),artifactRoot])if(existsSync(p)&&lstatSync(p).isSymbolicLink())throw Error('preparation_symlink' - 写入本地文件runtime/preparation.mjs:27
mkdirSync(artifactRoot,{recursive:true});mkdirSync(dir,{recursive:true,mode:0o700}); - 写入本地文件runtime/preparation.mjs:31
export function savePreparation(p){writeFileSync(join(p.dir,'state.json'),JSON.stringify(p,null,2)+'\n',{mode:0o600});} - 读取本地文件runtime/preparation.mjs:41
let at=p.artifactRoot;for(const n of relative(p.artifactRoot,target).split('/')){at=join(at,n);if(existsSync(at)&&lstatSync(at).isSymbolicLink())throw - 写入本地文件runtime/preparation.mjs:43
mkdirSync(dirname(target),{recursive:true});writeFileSync(target,content); - 写入本地文件runtime/preparation.mjs:43
mkdirSync(dirname(target),{recursive:true});writeFileSync(target,content); - 执行外部命令固定命令runtime/preparation.mjs:57
const check=spawnSync('/bin/sh',['-n','-c',c.command],{timeout:1000,encoding:'utf8'});if(check.status!==0)throw Error('preparation_criterion_shell_syn - 写入本地文件runtime/preparation.mjs:69
const target=join(p.artifactRoot,'.task-runner');mkdirSync(target,{recursive:true}); - 写入本地文件runtime/preparation.mjs:71
writeFileSync(join(target,'check.py'),dispatcher(m.criteria)); - 读取本地文件vendor/guard-dist/domain-CRL0HSOC.js:19
while (!existsSync(ancestor)) { - 写入本地文件vendor/guard-dist/domain-CRL0HSOC.js:704
mkdirSync(root, { - 读取本地文件vendor/guard-dist/domain-CRL0HSOC.js:708
const stat = lstatSync(root); - 读取本地文件vendor/guard-dist/domain-CRL0HSOC.js:713
const entry = lstatSync(path$1); - 读取本地文件vendor/guard-dist/domain-CRL0HSOC.js:721
const entry = lstatSync(path$1); - 读取本地文件vendor/guard-dist/domain-CRL0HSOC.js:750
if (!existsSync(path$1)) return new Map(); - 读取本地文件vendor/guard-dist/domain-CRL0HSOC.js:754
raw = readFileSync(fd, "utf8"); - 删除本地文件vendor/guard-dist/domain-CRL0HSOC.js:900
unlinkSync(path$1); - 写入本地文件vendor/guard-dist/domain-CRL0HSOC.js:1134
renameSync(tmp, arbitrationPath(root)); - 写入本地文件vendor/guard-dist/domain-CRL0HSOC.js:1650
mkdirSync(root, { - 删除本地文件vendor/guard-dist/domain-CRL0HSOC.js:1714
unlinkSync(temporary); - 写入本地文件vendor/guard-dist/domain-CRL0HSOC.js:10473
mkdirSync(dirname(path$1), { recursive: true }); - 写入本地文件vendor/guard-dist/domain-CRL0HSOC.js:10474
writeFileSync(path$1, content); - 写入本地文件vendor/guard-dist/domain-CRL0HSOC.js:10476
writeFileSync(join(root, "probe.mjs"), DRIVER); - 执行外部命令来自配置/变量vendor/guard-dist/domain-CRL0HSOC.js:10490
const child = spawnSync(process.execPath, [ - 删除本地文件vendor/guard-dist/domain-CRL0HSOC.js:10514
rmSync(root, { - 执行外部命令固定命令vendor/guard-dist/domain-CRL0HSOC.js:10791
execFileSync("/usr/bin/codesign", [ - 执行外部命令固定命令vendor/guard-dist/domain-CRL0HSOC.js:10800
const integrity = JSON.parse(execFileSync("/usr/bin/plutil", [ - 执行外部命令固定命令vendor/guard-dist/domain-CRL0HSOC.js:10809
const executableName = execFileSync("/usr/bin/plutil", [ - 执行外部命令来自配置/变量vendor/guard-dist/domain-CRL0HSOC.js:10859
if (execFileSync(join(systemRoot, "System32", "WindowsPowerShell", "v1.0", "powershell.exe"), [ - 读取本地文件runtime/bundled-owner.mjs:12
const json=p=>JSON.parse(readFileSync(p,'utf8')); - 读取本地文件runtime/bundled-owner.mjs:17
for(const name of readdirSync(dir).sort()) { - 读取本地文件runtime/bundled-owner.mjs:18
const path=join(dir,name),stat=lstatSync(path),rel=relative(root,path).split(sep).join('/'); - 读取本地文件runtime/bundled-owner.mjs:34
const bytes=readFileSync(join(root,'vendor/bundle-integrity.json')); - 读取本地文件runtime/bundled-owner.mjs:40
for(const path of paths)if(hash(readFileSync(join(root,path)))!==inventory.files[path])fail('payload_changed:'+path); - 读取本地文件runtime/bundled-owner.mjs:56
const lockText=readFileSync(join(profileRoot,'pnpm-lock.yaml'),'utf8');
扫描于 2026/10/31(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/dsh-agent@deepseek-ai/dsh-commands@deepseek-ai/dsh-goal@deepseek-ai/dsh-jobs@deepseek-ai/dsh-llm@deepseek-ai/dsh-session@deepseek-ai/dsh-skill@deepseek-ai/dsh-skill-filesystem@deepseek-ai/dsh-tool-goal@deepseek-ai/dsh-tools@deepseek-ai/schemastery给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
DeepSeek Harness 任务启动器,把 PUA 和 Completion Guard 合在一起,带冻结验收、候选绑定证书,以及 8 轮 / 90 分钟上限。
README
由 DeepSeek 最新模型翻译生成DeepSeek Harness Task Runner
输入工作区和想做的事情,先用 SpecWorkflow 澄清需求、整理规格和生成验收脚本;确认具体版本后,自动创建受门禁保护的任务会话。
已有可信验收命令时,仍可直接执行。
默认最多 8 轮、90 分钟;验收失败继续修复,到限取消并记录未完成。
同一候选验收通过、当前 Goal 证书有效且 Goal 已完成,才允许 PUA 自动结束。
这是组合 PUA 与 Completion Guard 的本地集成,当前验证目标为 macOS / DeepSeek Harness 0.2.0-rc.2,PUA 0.3.27、Guard 0.9.0。其他宿主版本未声明兼容。
适合什么任务
适合给已有项目增加功能、修复缺陷或改造命令行工具。只有任务想法时,先澄清需求并准备验收;已有可信验收命令时,直接进入执行。
它新增 /task-run 与 dsh-task 启动器、任务契约生成、独立副本验收、候选与 Goal 版本绑定的证书门禁、预算取消及本地证据记录。
这些行为由本插件在宿主进程中协调;它不是仅安装一组插件的依赖清单。
安装
包内提交了可运行 JavaScript,无须安装时执行 build/prepare 脚本。
在 Harness 的“安装第三方插件”里选择本包的本地目录、本地 .tgz 文件或 GitHub 地址。
展开完整文档(README 剩余 1 节)
DeepSeek Harness Task Runner 输入工作区和想做的事情,先用 SpecWorkflow 澄清需求、整理规格和生成验收脚本;确认具体版本后,自动创建受门禁保护的任务会话。 已有可信验收命令时,仍可直接执行。 默认最多 8 轮、90 分钟;验收失败继续修复,到限取消并记录未完成。 同一候选验收通过、当前 Goal 证书有效且 Goal 已完成,才允许 PUA 自动结束。 这是组合 PUA 与 Completion Guard 的本地集成,当前验证目标为 macOS / DeepSeek Harness 0.2.0-rc.2,PUA 0.3.27、Guard 0.9.0。其他宿主版本未声明兼容。 适合什么任务 适合给已有项目增加功能、修复缺陷或改造命令行工具。只有任务想法时,先澄清需求并准备验收;已有可信验收命令时,直接进入执行。 它新增 /task-run 与 dsh-task 启动器、任务契约生成、独立副本验收、候选与 Goal 版本绑定的证书门禁、预算取消及本地证据记录。 这些行为由本插件在宿主进程中协调;它不是仅安装一组插件的依赖清单。 安装 包内提交了可运行 JavaScript,无须安装时执行 build/prepare 脚本。 在 Harness 的“安装第三方插件”里选择本包的本地目录、本地 .tgz 文件或 GitHub 地址。 本机没有 dsh CLI 时也可使用这个入口。先停止正在运行的任务,安装后重启 Harness。 当前验证范围为 macOS / DeepSeek Harness Desktop 0.2.0-rc.2;宿主须提供标准 Agent 预设、Goal 服务和两个原组件的安装记录。 其他客户端、Web/headless profile、Windows/Linux 和其他宿主版本尚未验证,不能据此宣称兼容。 在 Desktop 的「插件 → 添加插件」中,按顺序填入下表的安装来源。已有对应版本则保留,不必重复安装。 | 顺序 | 插件 | 安装来源 | | 1 | PUA(原作者) | @michengai/dsh-pua@0.3.27 | | 2 | Completion Guard(原作者) | dsh-completion-guard@0.9.0 | | 3 | Task Runner | github:bbskye5008/dsh-task-runner#v0.3.4 | 0.3.4 已内置 SpecWorkflow 的 to-grill(需求澄清)和 to-spec(规格整理),无需单独安装 SpecWorkflow。 这两个阶段只准备需求、规格和验收;确认后继续由现有 PUA + Guard 执行。 原始技能文件、MIT 许可和来源摘要保存在 vendor/specworkflow/;当前 SDK 的适配方式见 验证记录。 复制 Task Runner 安装来源,在 Desktop 的「插件 → 添加插件」输入框粘贴并安装: github:bbskye5008/dsh-task-runner#v0.3.4 已有 Task Runner 时,先取消活动任务,再通过同一入口安装这个版本并重启;启动后在插件详情核对版本为 0.3.4。 Task Runner 不会自行联网安装这两个前置插件,也不会修改账户或模型配置。 Desktop profile 由 Electron 应用管理;不要执行 dsh plugin --profile desktop add ...,CLI 会拒绝修改这个受管 profile。 GitHub 发布与市场目录更新相互独立,已安装插件也不会自动升级。 市场入口应以目录登记的版本为准;本版可直接使用上述固定标签安装来源。 离线安装可下载 v0.3.4 Release 的 .tgz,再在安装输入框填写下载文件的本地绝对路径。远程 Release 资产 URL 的直接安装方式尚未验证。 原 Guard 的 Desktop 宿主资格链需要 profile 保留它的正式安装记录;本包不绕过该检查。 原组件文件保持不变;组合层暂停两个原 server 行,加载包内固定版本的 server。 原 PUA 的客户端配置入口可继续使用。卸载组合包并重启后恢复原 server 行。 插件管理器可能要求确认插件来源;安装第三方代码属于用户自己的信任决定。 一个启动命令 安装 0.3.4 并重启 Harness,在已选择所需模型的普通会话中输入: /task-run --workspace "/绝对路径/工作区" --task "我想做的事情" 或在终端运行 dsh-task --workspace "/绝对路径/工作区" --task "我想做的事情"。 不提供 --verify 时创建独立准备会话,沿用来源会话的模型与推理设置: 1. to-grill 阅读项目、逐个澄清必要业务决策,保存 requirements.md。 2. to-spec 整理范围、非目标、边界与验收条件,保存 spec.md。这两个阶段不写代码。 3. 适配层进入验收准备阶段,在 .spec-workflow/prep-UUID/acceptance/ 生成独立验收脚本,用 acceptance.json 把每条条件映射到命令和脚本。宿主生成逐项执行的总验收器,任一条件失败则失败。 4. task_prepare_submit 生成含需求、规格、条件、命令和文件摘要的 review.md,进入等待确认状态。 用户在准备会话中回答问题,或使用 dsh-task reply PREP_ID "回答或修改意见"。 5. 阅读具体产物后输入返回的 /task-run approve PREP_ID DIGEST,或终端 dsh-task approve PREP_ID DIGEST,自动冻结整份规格与验收目录并启动现有 PUA + Guard 执行器。 /task-run review PREP_ID 或 dsh-task review PREP_ID 查看待确认版本; /task-run status PREP_ID 或 dsh-task status PREP_ID 查询状态; /task-run cancel PREP_ID 或 dsh-task cancel PREP_ID 取消准备。 修改任何已发布文档、脚本或辅助文件后,旧摘要确认失效,需重新提交并确认。 准备阶段若生产文件发生变化则拒绝交接,需要基于新的项目基线重新准备。 准备会话不能改生产代码、运行脚本、启动 Goal/PUA、调用后续 SpecWorkflow 实施技能或自行批准。 最多 8 轮、90 分钟继续约束正式执行阶段,从确认后创建执行运行时开始计时;需求讨论和等待用户确认不会启动或消耗 PUA 执行预算。重试、验收与 Goal 重签均不重置执行截止。 执行中不能降低或修改验收;需求变化要取消当前执行,回到准备阶段形成新版本并重新确认。 模型生成测试不等于测试充分:确认时仍需核对需求与用例覆盖,主观标准需要另行人工验收。 当前适配器要求每条完成条件都有可执行检查,无法自动检查的关键条件须在准备阶段解决。 准备会话的草稿与元数据会持久化;重启后可读取已提交版本并显式确认,但未提交的准备会话不会自动恢复模型执行。 取消后也不会自动启动。确认后使用准备时记录的模型选项,不重置旧执行预算。 已有验收命令:直接执行 如果已经有经过检查的验收命令,提供 --verify 即可跳过需求准备。在 Harness 中输入: /task-run --workspace "/绝对路径/工作区" --task "具体任务" --verify "npm test" 也可以在终端使用已安装插件的 CLI: node "$HOME/.dsh/profiles/desktop/node_modules/dsh-task-runner/cli.mjs" \ --workspace "/绝对路径/工作区" \ --task "完成具体功能,保留现有行为,并补充自测" \ --verify "python3 /绝对路径/独立验收目录/check.py" 通过 npm 全局链接或包的 bin 安装后,可把 node .../cli.mjs 换成 dsh-task。 本包不默认修改全局 PATH。若 ~/.local/bin 已在 PATH 中,可以一次性建立链接: mkdir -p "$HOME/.local/bin" ln -s "$HOME/.dsh/profiles/desktop/node_modules/dsh-task-runner/cli.mjs" "$HOME/.local/bin/dsh-task" 然后直接运行 dsh-task --workspace ... --task ... --verify ...。 任务较长时用 --task-file /绝对路径/任务.txt;与 --task 二选一。 可加 --rounds 4 或 --minutes 30 降低限制,任何值都不能提高到 8 轮 / 90 分钟以上。 先打开一个已配置模型的会话。模型沿用最近一个已加载根会话的设置; --session SESSION_ID 可指定来源会话。没有来源会话时直接报错。 CLI 返回新 sessionId 和证据目录;可用 status 查询,界面显示取决于宿主工作区列表。 该入口创建独立任务会话,沿用提交命令会话的模型配置。 支持等价 JSON 对象输入;无需再粘贴 PUA、Guard 和任务正文四段内容。 工作区路径必须绝对;描述和命令必须加引号。本机启动器使用标准 argv/JSON 编码,不模拟键盘输入,避免此前原生键入破坏 JSON 标点的问题。 node "$HOME/.dsh/profiles/desktop/node_modules/dsh-task-runner/cli.mjs" status node "$HOME/.dsh/profiles/desktop/node_modules/dsh-task-runner/cli.mjs" status task-UUID node "$HOME/.dsh/profiles/desktop/node_modules/dsh-task-runner/cli.mjs" cancel task-UUID node "$HOME/.dsh/profiles/desktop/node_modules/dsh-task-runner/cli.mjs" diagnose task-UUID Harness 对应命令是 /task-run status 和 /task-run cancel task-UUID。 自动做了什么 1. 保存任务原文、执行协议和生成的 profile,绑定具体工作区和会话。 2. 冻结已有 TASK/AGENTS、测试目录、识别出的验收脚本及 npm test 的 package/lock 定义。 外部脚本默认冻结它所在的独立目录,包含新增文件检测。可以重复使用 --freeze /额外依赖/路径 明确补充;目录过大或符号链接等不明确情况直接拒绝。 3. 创建真实 Goal,开启 PUA/Guard,将完整任务作为用户命令的原文中继注入模型。 4. 默认一个“实现、独立验收与交付”阶段;模型记录验证 ID、真实结果和剩余工作。 交付 TASK_GATE_FINAL.md 和 TASK_GATE_PROGRESS.md,宿主检查后签证。 5. Goal 完成导致 revision 变化,旧证书失效;再验收签证后,PUA 才能接受 LOOP_DONE。 验收命令在工作区的独立副本中运行,结果目录位于 ~/.dsh/task-runner/task-UUID/。 副本忽略 .git、node_modules、.scratch 和语言缓存;node_modules 复用现有依赖目录。 命令退出 0 才算通过,打印“pass”不算证据。模型不能用另一个命令替换验收。 命令及其子进程每次最多 120 秒,并受剩余总时间约束。命令应使用相对工作区路径或环境变量 DSH_TASK_WORKSPACE;写死原工作区绝对路径会破坏副本隔离,前后候选变化会被拒绝。 已有验收文件不能改;任务新增自测使用 self-tests/,避免覆盖被冻结的验收目录。 预算和状态 - 正式执行截止从批准后创建执行运行时开始记录;使用 --verify 时从直接启动执行开始记录。模型重试、验收和 Goal 重签不重置截止。 - 轮数按 PUA iteration 加额外物理 turn 保守计算;它与模型单次工具调用数不同。 - 到时取消当前模型活动、验收进程组、PUA 自动续轮,并解除 Goal 自动继续资格。 - 超时、到轮次、取消、需要输入、崩溃中断均不会记录成完成。 - 重启后旧运行标记为 interrupted,不恢复上一进程的 HMAC 证书,也不自动再给 90 分钟。 - 机器睡眠时无法调度取消,恢复运行时按原绝对截止拒绝后续模型步骤和完成放行。 status.json 保存状态、原截止和最终证书摘要;events.jsonl 保存真实验收与门禁决定; profile.json / user-message.txt 是冻结契约;checks/ 保存副本和实际进程结果。 控制器仅监听当前用户权限的 Unix socket,不开公网端口,不上传任务内容。 0.3.4 实测 2026-10-15,在 macOS / Harness Desktop 0.2.0-rc.2 使用 Flash / High 完成中文 CSV 工单工具联调: | 检查 | 结果 | | 需求澄清、规格与验收脚本生成 | 实际加载 to-grill / to-spec,确认前原型未改变 | | 具体版本确认 | 旧摘要被拒绝;新摘要批准后才启动 PUA + Guard | | 冻结生成验收 | 原型 3/39 → 交付 39/39;候选自测 34/34 | | 额外独立业务验收 | 测试前冻结,原型 3/29 → 交付 29/29,验收器未改动 | | 失败拦截 | 提前完成 Goal 被拒,失败候选不签证 | | Goal 变化与完成 | 同一候选在 rev1 → rev2 后重新签证,自动 complete | | 正式执行 | 1 轮、327.231 秒;首轮环境问题修复后重新从原型复测 | | 核心回归 | 57 项通过 | 本次单轮内从失败继续实施到通过;未声称验证了完整 8 轮稳定重试、连续跑满 90 分钟或跨平台兼容。 历史 0.2.2 的 JSONL 任务与预算/中断测试仍见 验证记录。 版本变化见 更新记录。 边界 三个输入减少的是配置工作,验收标准仍由用户负责。把全文绑定到一个验收命令,不等于自动理解每条中文要求,也不保证 npm test 已覆盖全部需求。 默认发现规则无法证明任意 shell 命令的传递依赖完整;重要的额外依赖请用 --freeze。 候选摘要包括源码、文档、测试和符号链接,排除上述依赖/缓存;不认证 node_modules 的每个字节。既有依赖与验收执行环境需要可信。 工具策略和同用户 Unix socket 均不是 OS 沙箱,不能防御任意同用户恶意代码。 证书由宿主进程私钥签发,只证明完成时的绑定和执行证据,不是离线公开签名。 常见问题与卸载 - open_a_model_configured_conversation_first:命令行找不到已加载的来源会话;先在 Harness 的正常会话中执行 /task-run ...,或加载一个已有会话后再运行命令行。 - host_qualification_unavailable:宿主版本、安装记录或实际依赖树未通过资格审计。先核对上述版本和来源;不要关闭 Guard、改写安装索引或更换验收命令来绕过。 - round_limit / deadline:预算到限,结果是未完成;检查证据目录后,由用户明确发起新的运行。重启不会自动续给预算。 - npm test 等验收命令需要的依赖应在开跑前准备好;验证时不会自动安装依赖。验收应使用相对路径或 DSH_TASK_WORKSPACE,额外外部依赖用 --freeze 登记。 - 卸载前先 dsh-task cancel task-UUID,再通过 Desktop 插件管理器卸载 Task Runner 并重启。保留原 PUA/Guard 插件即可恢复原服务器条目;旧任务证据仍保存在 ~/.dsh/task-runner/。 - 如果手工建立过 ~/.local/bin/dsh-task 链接,卸载后确认其仍指向本插件,再移除这个链接;不要删除其他同名命令。 上游与本插件的关系 感谢 MichengAI/dsh-pua 和 GreenLv/dsh-completion-guard。 正式前置安装来源均为原作者的 npm 包。本包还携带归属明确的 Apache-2.0 修改版服务器组件,以接入同候选验收和证书门禁;原始许可证、NOTICE、固定版本与文件哈希见 vendor/。这些修改不是上游官方版本,上游作者未背书。 本插件自身新增的协调逻辑位于 index.mjs、runtime/ 和 guard.mjs,组合差异可由 scripts/build-vendor.py 复现。 开发与发布 npm install --ignore-scripts --legacy-peer-deps npm test npm pack SDK peers 必须与宿主共享,不要把本地 SDK 副本打入包。包已含运行构建;GitHub 安装无须 prepare。 市场收录与 GitHub 发布不同:dsh-market 读取 awesome-dsh-plugin 精选目录,需另行提交条目。 任务目录、控制 token、机器配置和测试原始会话不进入发布包。 许可证 Apache-2.0;第三方来源及修改见 NOTICE、vendor/base-provenance.json。
预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
bbskye5008/dsh-task-runner
澄清需求并生成验收脚本,受门禁保护自动执行任务
相关插件 · 开发 / 工程
隐私简历生成器reactive-resume/reactive-resume
Reactive Resume 已迁至 GitHub 上的…
★ 45,125已汉化MCP
71.7
AI 架构文档生成器sopaco/deepwiki-rs
🚀 Litho 已进化为 Terrain —— 给你的 AI 智能体一张会呼吸的代码库地图。
★ 3,157已汉化DSH
70.8
长时任务执行闭环AMAP-ML/LongHorizon-Harness
面向 Computer-Use Agent 的 Loop Engineering
★ 1,764已汉化DSH
70.5
AI 编程纪律方法包GanyuanRan/Aegis
让 AI 编程 agent 变得可信:少返工、更安全、说“完成”前先给证据。
★ 1,384已汉化DSH
69.6
多代理编排运行时Enderfga/claw-orchestrator
面向编程智能体的运行时。把 Claude Code、Codex、Antigravity、Grok…
★ 586已汉化MCP
69.4
记忆进化插件csyangwen/dsh-memory-evolve
dsh-memory-evolve 使用场景指南
★ 461已汉化DSH
67.9