🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

目标看板 miuzel/dsh-graph

DeepSeek Harnessv0.22.0
miuzel0 天前有提交已提供中文文档扫描:含敏感能力

把工作组织成目标看板的 DeepSeek HarnessDSH插件 —— 基于图的目标管理Graph-based…

46.5/100
综合分
26
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/11/4 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

自动兼容检查未通过:缺少 main/exports/bin 入口声明;仓库 package.json 标记 private,未发布到 npm,需从源码安装。以下命令仍可尝试,但可能失败。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add miuzel/dsh-graph
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:需留意
是什么
dsh 原生插件 · tool
装得上吗
实装验证未通过(unknown),装前请到仓库确认最近更新与 issue
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 0 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
⚠︎ 实装验证未通过(unknown · 2026/10/21) ——可能是验证环境差异,装前建议到 GitHub 仓库确认最近更新与 issue。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查需源码安装

缺少 main/exports/bin 入口声明;仓库 package.json 标记 private,未发布到 npm,需从源码安装

展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✓npm 包dsh-graph @ 0.22.0
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✗入口文件缺少入口声明

源码安装时若 pnpm 拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑。

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/31 22:56:48

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件
查看扫描证据(共 476 处,展示前 106 条)
  • 读取本地文件
    core/cache.ts:17
    for (const name of ["events.jsonl", "project.yaml", "order.json", "rules.md"]) { try { const s=statSync(join(key,name)); h.update(name+":"+s.mtimeMs+"
  • 写入本地文件
    core/events.ts:52
    appendFileSync(
  • 读取本地文件
    core/events.ts:67
    if (!existsSync(file)) return [];
  • 读取本地文件
    core/events.ts:69
    const lines = readFileSync(file, "utf8").split("\n");
  • 写入本地文件
    core/events.ts:222
    mkdirSync(memDir, { recursive: true });
  • 读取本地文件
    core/events.ts:233
    const lease = JSON.parse(readFileSync(lock, "utf8"));
  • 删除本地文件
    core/events.ts:240
    if (!alive && Number(lease.expires) < Date.now()) { unlinkSync(lock); continue; }
  • 删除本地文件
    core/events.ts:247
    try { return fn(); } finally { closeSync(fd); try { unlinkSync(lock); } catch {} }
  • 写入本地文件
    core/events.ts:256
    mkdirSync(memDir, { recursive: true });
  • 读取本地文件
    core/events.ts:267
    if (!existsSync(file)) return [];
  • 读取本地文件
    core/events.ts:269
    const lines = readFileSync(file, "utf8").split("\n");
  • 读取本地文件
    core/events.ts:289
    const file = join(root, "memory", "memory.jsonl"); if (!existsSync(file)) return [];
  • 读取本地文件
    core/ops.ts:244
    const actual = realpathSync(forWrite && !existsSync(resolved) ? dirname(resolved) : resolved);
  • 读取本地文件
    core/ops.ts:245
    const expected = forWrite && !existsSync(resolved) ? dirname(resolved) : resolved;
  • 读取本地文件
    core/ops.ts:443
    if (existsSync(backlog)) {
  • 读取本地文件
    core/ops.ts:444
    for (const f of readdirSync(backlog)) {
  • 读取本地文件
    core/ops.ts:448
    for (const af of readdirSync(backlogArchived)) {
  • 读取本地文件
    core/ops.ts:451
    if (existsSync(nested)) out.push(nested);
  • 写入本地文件
    core/ops.ts:548
    mkdirSync(join(root, d), { recursive: true });
  • 写入本地文件
    core/ops.ts:550
    if (fresh) writeFileSync(events, "", "utf8");
  • 写入本地文件
    core/ops.ts:552
    if (!existsSync(index)) writeFileSync(index, "{}\n", "utf8");
  • 写入本地文件
    core/ops.ts:555
    writeFileSync(
  • 写入本地文件
    core/ops.ts:798
    mkdirSync(dir, { recursive: true });
  • 写入本地文件
    core/ops.ts:800
    copyFileSync(target, join(dir, `HANDOFF-${ts}.md`));
  • 删除本地文件
    core/ops.ts:4714
    try { rmSync(join(sharedCardsDir(root), `${sharedId}.md`), { force: true }); } catch { }
  • 删除本地文件
    core/ops.ts:4986
    try { rmSync(newFile, { force: true }); } catch (re) { restoreErr = re; }
  • 删除本地文件
    core/ops.ts:5010
    rmSync(file, { force: true });
  • 删除本地文件
    core/ops.ts:5018
    rmSync(newFile, { force: true });
  • 删除本地文件
    core/ops.ts:5125
    try { rmSync(newFile, { force: true }); } catch (re) { restoreErr = re; }
  • 删除本地文件
    core/ops.ts:5149
    rmSync(file, { force: true });
  • 执行外部命令固定命令
    core/ops.ts:8471
    head = execFileSync("git", ["rev-parse", "HEAD"], { cwd: workspace, encoding: "utf8", timeout: 3000, stdio: ["ignore", "pipe", "ignore"] }).trim();
  • 读取本地文件
    core/platform.ts:156
    entries = readdirSync(parentDir);
  • 读取本地文件
    core/platform.ts:165
    lstatSync(join(parentDir, requested));
  • 写入本地文件
    core/platform.ts:234
    renameSync(src, dest);
  • 写入本地文件
    core/platform.ts:239
    renameSync(src, dest);
  • 读取本地文件
    core/platform.ts:245
    if (existsSync(dest)) {
  • 写入本地文件
    core/platform.ts:246
    renameSync(dest, backup);
  • 写入本地文件
    core/platform.ts:249
    renameSync(src, dest);
  • 删除本地文件
    core/platform.ts:251
    try { unlinkSync(backup); } catch { }
  • 读取本地文件
    core/platform.ts:254
    if (backedUp && existsSync(backup)) {
  • 写入本地文件
    core/platform.ts:255
    try { renameSync(backup, dest); } catch { }
  • 写入本地文件
    core/platform.ts:295
    chmodSync(fdOrPath, mode);
  • 读取本地文件
    core/platform.ts:322
    const st = lstatSync(filePath);
  • 读取本地文件
    core/platform.ts:323
    const text = content ?? readFileSync(filePath, "utf8");
  • 读取本地文件
    core/root.ts:54
    if (existsSync(gitPath)) {
  • 读取本地文件
    core/root.ts:55
    return statSync(gitPath).mtimeMs;
  • 读取本地文件
    core/root.ts:83
    while (!existsSync(probe)) { const parent = resolve(probe, ".."); if (parent === probe) break; probe = parent; }
  • 执行外部命令来自配置/变量
    core/root.ts:136
    execSync: (cmd: string, options: any) => execSync(cmd, options),
  • 执行外部命令来自配置/变量
    core/root.ts:137
    execFileSync: (file: string, args: string[], options: any) => execFileSync(file, args, options),
  • 读取本地文件
    core/root.ts:421
    if (existsSync(localRoot) && existsSync(resolve(localRoot, "events.jsonl"))) {
  • 读取本地文件
    core/transaction.ts:132
    return Date.now() - lstatSync(lockPath).mtimeMs;
  • 读取本地文件
    core/transaction.ts:169
    before = lstatSync(lockPath);
  • 写入本地文件
    core/transaction.ts:174
    try { chmodSync(lockPath, 0o600); } catch { }
  • 读取本地文件
    core/transaction.ts:176
    try { holder = readFileSync(lockPath, "utf8").trim(); } catch { holder = null; }
  • 写入本地文件
    core/transaction.ts:194
    renameSync(lockPath, quarantine);
  • 读取本地文件
    core/transaction.ts:199
    try { moved = lstatSync(quarantine); } catch { moved = null; }
  • 写入本地文件
    core/transaction.ts:202
    try { renameSync(quarantine, lockPath); } catch { }
  • 删除本地文件递归
    core/transaction.ts:206
    rmSync(quarantine, { recursive: true, force: true });
  • 写入本地文件
    core/transaction.ts:225
    writeFileSync(lockPath, String(pid), { flag: "wx" });
  • 读取本地文件
    core/transaction.ts:230
    if (existsSync(lockPath)) {
  • 读取本地文件
    core/transaction.ts:232
    const holder = readFileSync(lockPath, "utf8").trim();
  • 写入本地文件
    core/transaction.ts:244
    writeFileSync(lockPath, String(pid), { flag: "w" });
  • 删除本地文件
    core/transaction.ts:316
    rmSync(lockPath, { force: true });
  • 写入本地文件
    core/transaction.ts:460
    writeFileSync(tmp, content, "utf8");
  • 删除本地文件
    core/transaction.ts:463
    try { if (existsSync(tmp)) rmSync(tmp, { force: true }); } catch { }
  • 读取本地文件
    core/version-lane.ts:43
    if (!existsSync(vfile)) throw new GraphError(`版本 ${slug} 不存在`);
  • 读取本地文件
    core/version-lane.ts:44
    const doc = parseDoc(readFileSync(vfile, "utf8"));
  • 读取本地文件
    core/version-lane.ts:51
    const doc = parseDoc(readFileSync(vfile, "utf8"));
  • 写入本地文件
    core/version-lane.ts:53
    writeFileSync(vfile, serializeDoc(doc), "utf8");
  • 读取本地文件
    core/version-lane.ts:63
    if (existsSync(goalsDir)) {
  • 读取本地文件
    core/version-lane.ts:64
    const entries = readdirSync(goalsDir).filter((d) => !d.startsWith("."));
  • 读取本地文件
    core/version-lane.ts:68
    if (existsSync(goalFile)) return true;
  • 写入本地文件
    core/version-lane.ts:117
    writeFileSync(gf, serializeDoc(doc), "utf8");
  • 写入本地文件
    core/version-lane.ts:135
    writeFileSync(gf, serializeDoc(doc), "utf8");
  • 写入本地文件
    core/version-lane.ts:153
    writeFileSync(gf, serializeDoc(doc), "utf8");
  • 写入本地文件
    core/version-lane.ts:208
    mkdirSync(join(vdir, "goals"), { recursive: true });
  • 写入本地文件
    core/version-lane.ts:219
    writeFileSync(join(vdir, "version.md"), serializeDoc(doc), "utf8");
  • 删除本地文件
    core/version-lane.ts:399
    if (existsSync(cardsDir)) rmdirSync(cardsDir);
  • 删除本地文件
    core/version-lane.ts:402
    if (existsSync(goalFile)) rmSync(goalFile);
  • 删除本地文件
    core/version-lane.ts:404
    rmdirSync(entryPath);
  • 删除本地文件
    core/version-lane.ts:406
    rmdirSync(goalsDir);
  • 删除本地文件
    core/version-lane.ts:414
    if (existsSync(cardsDir)) rmdirSync(cardsDir);
  • 删除本地文件
    core/version-lane.ts:416
    if (existsSync(goalFile)) rmSync(goalFile);
  • 执行外部命令固定命令
    core/worktree.ts:26
    return execFileSync("git", args, { cwd, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] }).trim();
  • 读取本地文件
    core/worktree.ts:64
    if (!existsSync(file)) return true;
  • 读取本地文件
    core/worktree.ts:161
    if (!existsSync(file)) return null;
  • 读取本地文件
    core/worktree.ts:163
    const parsed = JSON.parse(readFileSync(file, "utf8")) as Partial<BoardOwnerMarker>;
  • 读取本地文件
    core/worktree.ts:261
    try { const gf = findGoalFile(root, assoc.goal); const af = join(dirname(gf), "attempts", assoc.attempt, "attempt.md"); if (existsSync(af)) attemptMet
  • 读取本地文件
    core/worktree.ts:517
    if (existsSync(join(dirname(gf), "attempts", c.attempt, "attempt.md"))) return true;
  • 执行外部命令固定命令
    core/worktree.ts:664
    return execFileSync("git", args, {
  • 读取本地文件
    core/worktree.ts:1164
    if (existsSync(targetPath2)) {
  • 写入本地文件
    core/worktree.ts:1194
    mkdirSync(resolve(mainWorktree, ".worktrees"), { recursive: true });
  • 读取本地文件
    dsh-graph-host/index.js:822
    manifest = JSON.parse(readFileSync(manifestUrl, "utf8"));
  • 读取本地文件
    dsh-graph-host/index.js:880
    return readFileSync(new URL(rel, import.meta.url), "utf8");
  • 执行外部命令固定命令
    dsh-graph-host/index.js:1835
    const text = execFileSync("git", ["worktree", "list", "--porcelain"], {
  • 执行外部命令固定命令
    dsh-graph-host/index.js:1927
    execFileSync("git", ["merge-base", "--is-ancestor", compareHead, entry.head], {
  • 读取本地文件
    dsh-graph-host/index.js:2101
    try { if (existsSync(join(dir, GRAPH_LEGACY_SETTINGS_MARKER))) return null; } catch { }
  • 读取本地文件
    dsh-graph-host/index.js:2107
    if (!existsSync(file)) continue;
  • 读取本地文件
    dsh-graph-host/index.js:2108
    const got = coerceLegacyGraphSettings(parseYaml(readFileSync(file, "utf8"))?.[GRAPH_LEGACY_SETTINGS_SECTION]);
  • 写入本地文件
    dsh-graph-host/index.js:2140
    writeFileSync(join(legacy.dir, GRAPH_LEGACY_SETTINGS_MARKER), `${new Date().toISOString()} ${trace}\n`);
  • 读取本地文件
    dsh-graph-host/index.js:2801
    attemptEntries = readdirSync(attemptsDir);
  • 写入本地文件
    dsh-graph-host/index.js:2819
    mkdirSync(attemptsDir, { recursive: true });
  • 执行外部命令固定命令
    dsh-graph-host/index.js:3078
    return execFileSync("git", ["rev-parse", "--verify", `${raw}^{commit}`], {
  • 执行外部命令固定命令
    dsh-graph-host/index.js:3089
    return execFileSync("git", ["diff", "--name-only", baseline, candidate], {
  • 写入本地文件
    dsh-graph-host/index.js:5042
    writeFileSync(orderFile, JSON.stringify(order, null, 2), "utf8");
  • 写入本地文件
    dsh-graph-host/index.js:6681
    writeFileSync(
扫描于 2026/11/4(0 天前) · 范围 全包扫描 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

界面预览

3 张 · 点击查看大图

功能亮点

  • 目标看板组织工作
  • 二维泳道看板
  • 文件与事件流存储
展开完整介绍(139 字)↓

把工作组织成目标看板的 DeepSeek Harness (dsh) 插件:目标 / 判据 / 上下文卡片 / 执行 attempt 的二维泳道看板,数据以文件+事件流落在 .dsh-graph · Goal-kanban plugin for DeepSeek Harness

README

由 DeepSeek 最新模型翻译生成
dsh-graph 把工作组织成目标看板的 DeepSeek Harness(DSH)插件 —— 基于图的目标管理(Graph-based Goal Management)。 当前版本 v0.23.0 —— npm 包名 dsh-graph,一个包同时提供面向智能体的 53 个 graph_ 工具(含 /api/dsh-graph REST 端点)与内嵌 DSH Web 的二维泳道看板。 最新亮点(v0.23.0) - 长任务智能关照与僵局干预:主管空闲期间,对进行中的子代理长任务按生效间隔自动发起巡检与状态把关;连续未回复或进展停滞时自动升级等待人工,到期只触发巡检,不武断中断执行;支持整组关照的暂停、继续与重置。 - 子代理时间预算调度与动态基准重算:支持在目标中显式配置预计任务时间预算(未配置则继承项目/全局默认阈值);首次派发、运行中调整预算,或主管向运行中子代理发送新消息时,立即依据最新时间基准重新计算关照截止,并保持至少 5 分钟无答有效冷却,防止频繁唤醒。 - 运行轮次精确隔离与历史保真追溯:子代理运行按起止时点划定独立轮次,停止即停表,重新运行自起新轮;精确记录每轮起始预算与变更时间线,禁止以停止时刻预算冒充整轮预算;正常宿主重建遇到同一运行中任务时不拆分轮次,并如实标注观察空窗。
展开完整文档(README 剩余 1 节)
dsh-graph

把工作组织成目标看板的 DeepSeek Harness(DSH)插件 —— 基于图的目标管理(Graph-based Goal Management)。

当前版本 v0.23.0 —— npm 包名 dsh-graph,一个包同时提供面向智能体的 53 个 graph_ 工具(含 /api/dsh-graph REST 端点)与内嵌 DSH Web 的二维泳道看板。

最新亮点(v0.23.0)

- 长任务智能关照与僵局干预:主管空闲期间,对进行中的子代理长任务按生效间隔自动发起巡检与状态把关;连续未回复或进展停滞时自动升级等待人工,到期只触发巡检,不武断中断执行;支持整组关照的暂停、继续与重置。
- 子代理时间预算调度与动态基准重算:支持在目标中显式配置预计任务时间预算(未配置则继承项目/全局默认阈值);首次派发、运行中调整预算,或主管向运行中子代理发送新消息时,立即依据最新时间基准重新计算关照截止,并保持至少 5 分钟无答有效冷却,防止频繁唤醒。
- 运行轮次精确隔离与历史保真追溯:子代理运行按起止时点划定独立轮次,停止即停表,重新运行自起新轮;精确记录每轮起始预算与变更时间线,禁止以停止时刻预算冒充整轮预算;正常宿主重建遇到同一运行中任务时不拆分轮次,并如实标注观察空窗。
- 主管会话智能保活机制:名下有子代理在运行且主管处于空闲时,自动在适当时机进行有界续期与单次防离线保活,避免长时间未交互导致上下文失效。
- 插件 HTTP 接口安全加固与派发去重:全面封闭无凭证访问风险,对齐宿主统一鉴权与身份白名单校验;强化派发准入门禁,严格防止同一目标并发派发重复执行尝试,杜绝状态冲突与资源争用。

变更史见 CHANGELOG.md。

平台状态

| 平台 | 本版状态 |
| Linux / WSL2 | ✅ 已实测通过(本版全量测试 fail 0;H 系列共享探针在本版全绿) |
| 原生 Windows | ✅ 本版已实测通过(2026-11-02,win32/x64 + Node v24.21.0,宿主 0.2.1-rc.5,通过 22 / 失败 0 / 告警 0):详见 platform-gate §7.13 回填表 —— T1 静态/台账(67 项 268 处命中未登记 0)/ 派发可用(零硬编码 shell 名)/ H 组合探针(H1–H6 除 H3 外全绿)全部通过;T3 看板文件系统生命周期 32 步盘面断言全通过;T4/T5 实例启动就绪与 REST 鉴权换票冒烟通过。 |
| macOS | ⏳ 本版未验证:v0.23.0 未在原生 macOS 上执行真机门禁 ⇒ 不得读出「已通过」;结论同样以平台门禁 §7 回填表(不随包发布)为准。历史记录见 §7.4 / §7.7,只覆盖各自版本的产品代码。 |

三平台共用同一安装包。已知限制:① macOS 默认文件系统 APFS 大小写不敏感——仅大小写不同的目标编号 / 版本泳道会落到同一实体,请勿只用大小写区分;② macOS 上经显式传入且含符号链接的工作区路径(如位于 /tmp、/var 之下)会被拒绝并报 graph root symlink is not allowed,由 process.cwd() 推导的路径不受影响。

HTTP 鉴权(Web 入口)

Web 宿主里的 /api/dsh-graph/ 走单一受保护入口:只注册一条 prefix 路由。每个请求先由宿主公开的 connection.admit 鉴权,再判定 owner,之后才分发业务。未通过 ⇒ 401(匿名或凭证无效)、403(信任边界或非 owner)、503(宿主没有 admit 等能力,无法判定,fail-closed)。该入口只影响 HTTP*:graph_ 工具面不经过它。

鉴权行为只在 DSH 0.2.1-rc.2 实测;engines.dsh 声明的其它宿主版本未逐版验证。完整口径见 dsh-graph-host/README.md。

安装

dsh plugin --profile <name> add dsh-graph

需要 Node ≥ 22。依赖说明、宿主兼容范围(engines.dsh 声明与实测宿主)、侧边栏用法、数据目录等完整内容,见 dsh-graph-host/README.md(即 npm 包内 README)。升级宿主后若 Web 看板半边不激活(web boot: … did not activate),见该 README 的「升级残留自检与清理」。

核心概念

- 基于图的目标管理:目标是自足实体 —— 自然语言任务 + 动态生成的取证计划与质量判据;任务类型不预先模板化,结构化的是生命周期与求值语义。
- 四阶段生命周期:描述 → 收集 → 执行 → 确认,由引擎强制的状态机:draft → planning → collecting → ready → in_progress → review → delivered(任意阶段可进入 blocked)。
- 判据先于执行:进入执行前先登记质量判据,评审按逐条判据核验产出物。
- 上下文卡片:目标 Runner 的种子上下文,生命周期 empty → collecting → filled → reviewed;形态分文本 / 文件 / 图片 / 数据。
- 排期:Backlog(暂存池)↔ Version(批量质量管理)↔ 独立目标(standalone);看板泳道顺序是展示态,可拖拽调整。
- 分级评审与策略配置:支持配置项目专属模块区域 review.regions、冻结契约 review.contract_paths 与排除前缀 review.non_product_prefixes,未登记区域自动安全升级 strict,空契约默认 M1 不触发。
- 换会话交接:graph_handoff 生成交接文档(board 投影 + 长期记忆 + 环境事实),graph_claim_supervisor 由新会话幂等接管。
- 目标间关系:目标之间可标记「取代 / 调整 / 补充 / 相关」四类关系(graph_set_relation,可增可删);关系只记在目标 frontmatter 这一处真源,看板卡片与目标弹窗直接可见。
- Profile 全局设置:子代理默认 provider / model、推理档位、执行模式、提示词语言与补充提示词,可在「设置 → 看板设置」「右侧栏 → 插件 → dsh-graph」两处任一打开,两处读写同一份 profile 配置(workspace project.yaml 明确配置优先)。

提供的工具

53 个 graph_ 工具,按功能分组(逐个说明见 dsh-graph-host/README.md 或 graph_help):

| 分组 | 工具 |
| 目标生命周期 | graph_create_goal · graph_rename_goal · graph_set_description · graph_set_goal_type · graph_set_goal_tags · graph_set_goal_budget · graph_amend_goal · graph_transition · graph_postpone_goal · graph_archive_goal · graph_unarchive_goal · graph_delete_goal · graph_clean_worktree · graph_list_worktrees |
| 目标关系 | graph_set_relation |
| 质量判据 | graph_set_criteria |
| 上下文卡片 | graph_add_card · graph_fill_card · graph_review_card · graph_bind_collect_card · graph_delete_card · graph_convert_card_to_shared · graph_convert_card_to_owned · graph_attach_shared_card · graph_detach_shared_card · graph_list_shared_cards |
| 附件 | graph_store_attachment · graph_delete_attachment |
| 排期 | graph_move_goal |
| 执行派发 | graph_start_attempt · graph_start_review · graph_set_directive · graph_record_attempt_handoff · graph_unbind_goal_child · graph_abandon_attempt |
| 记忆 | graph_memory_add · graph_memory_recall · graph_memory_remove · graph_memory_replace |
| 配置管理 | graph_get_settings · graph_update_settings |
| 校验 / 对账 | graph_validate · graph_rebuild |
| 状态汇报 | graph_report_status · graph_report_supervisor_status · graph_care_outcome |
| 评审裁决 | graph_resolve_accept |
| 历史讨论 | graph_add_comment |
| 完成摘要 | graph_write_results · graph_refresh_results |
| 换会话 | graph_handoff · graph_claim_supervisor |
| 帮助 | graph_help |

看板(浏览器客户端)

浏览器二维泳道看板:横向是生命周期阶段列(描述 / 收集 / 执行 / 确认 / 交付 / 阻塞),每个版本一条泳道,另有 Backlog 与独立目标区;支持拖拽排期、判据 / 上下文卡片抽屉、实时状态显示、阻塞折叠等。以下为虚构演示数据(nebula-notes)截图:

看板总览目标详情弹窗侧边栏看板(窄档:阶段列纵向堆叠、工具条折叠为 ⋯ 工具)

侧边栏与数据目录

侧边栏入口、窄档(<480px)分档行为与「怎么把看板放进窄档」的实测说明,以及数据目录 <workspace>/.dsh-graph(纯文本 + 只追加 events.jsonl,git 友好、可 graph_rebuild 对账)的完整说明,均见 dsh-graph-host/README.md。

仓库结构(monorepo)

- core/ —— 核心层源码(唯一事实源),经 scripts/sync-core.sh 编译成 dist/core/.js 进发布包;核心层不依赖 DSH。
- dsh-graph-host/ —— 单包发布物源码:index.js(工具 + REST 端点)、lib/client/.js(看板源模块,构建产物为 dist/lib/client.js)、cordis.patch.yml、supervisor-guide.{zh,en}.md、README.md、LICENSE。
- schema/、docs/、scripts/ —— 数据 / 设计文档 / 构建脚本;一切构建产物落在 dist/(gitignored)。

开发

bash scripts/build.sh # 同步 core + 客户端产物 + 复制发布资产到 dist/
node --test core/tests/.test.ts # 全量测试
./node_modules/.bin/tsc --noEmit -p tsconfig.json
隔离测试实例(不碰主 GUI):DSH_HOME 与 workspace 均在 ./tmp/dsh-test/ 下 bash scripts/dsh-test-web.sh <DSH版本> [--port PORT]

构建与实验一律在隔离 worktree(.worktrees/<goal>-att-<NN>)内进行;约定见 AGENTS.md,隔离实例参数与开发回路见 docs/dev-instance-guide.md。README 截图用 scripts/dsh-graph-mock-seed.mjs 生成虚构演示数据后复现。

License

MIT(Copyright © 2026 miuzel)—— 见 dsh-graph-host/LICENSE。
预览分享卡片长什么样 ↓miuzel/dsh-graph
分享 · DeepSeek Harness Hub
miuzel/dsh-graph

把工作组织成目标看板的 DeepSeek HarnessDSH插件 —— 基于图的目标管理Graph-based…

这是你的仓库?认领条目

回到顶部