dsh-offhours 0.1.0 → 0.1.2
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 +21 -13
- package/bin/offhours.mjs +33 -16
- package/lib/client.js +29 -1
- package/package.json +6 -5
- package/panel/client.js +29 -1
- package/panel/index.js +18 -1
- package/panel/locale/en.json +5 -1
- package/panel/locale/zh.json +5 -1
- package/skills/offhours/SKILL.md +6 -5
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
DeepSeek Harness 社区插件:把看板里的待办,在**低谷/夜间**自动做掉。
|
|
4
4
|
|
|
5
5
|
- 只做一件事:`todo` 卡 → 每卡一个独立 git worktree → headless worker 干活并自证 → 证据写回卡 → 合并回收。
|
|
6
|
-
- 不需要 cron/systemd:插件进程内按 interval 自己扫;也可以手动 `offhours run --once`。
|
|
6
|
+
- 不需要 cron/systemd:插件进程内按 interval 自己扫;也可以手动 `npx dsh-offhours run --once`。
|
|
7
7
|
- 你的数据只在本地:看板是 `KANBAN.json`,状态/日志在 `stateDir`,不上传。
|
|
8
8
|
|
|
9
9
|
## 安装
|
|
@@ -14,26 +14,32 @@ dsh plugin --profile web add dsh-offhours
|
|
|
14
14
|
|
|
15
15
|
装完重启一次 `dsh web`(或让 HMR 生效),左侧出现「夜间跑批」面板。
|
|
16
16
|
|
|
17
|
+
> 为什么下面的命令写 `npx dsh-offhours`:安装插件不会把 CLI 加进全局 PATH;`npx` 会直接运行刚装好的同一个入口(首次会从 npm 取包)。如果你已经全局安装,可以简写成 `offhours`。
|
|
18
|
+
|
|
17
19
|
## 三步开始
|
|
18
20
|
|
|
19
21
|
```bash
|
|
20
22
|
# 1) 在你要跑批的 git 仓库里初始化(写配置 + 建/关联特性 + 生成看板)
|
|
21
23
|
cd ~/code/myapp
|
|
22
|
-
offhours init --repo . --name myapp
|
|
24
|
+
npx dsh-offhours init --repo . --name myapp
|
|
23
25
|
|
|
24
26
|
# 2) 体检(依赖、路径、worker 权限)
|
|
25
|
-
offhours doctor
|
|
27
|
+
npx dsh-offhours doctor
|
|
26
28
|
|
|
27
29
|
# 3) 建一张卡(自动盖当前会话;没有 session 的卡跑批不会捡)
|
|
28
|
-
offhours card add "给登录页补错误提示" \
|
|
30
|
+
npx dsh-offhours card add "给登录页补错误提示" \
|
|
29
31
|
--summary "目标:登录失败有提示。判据:npm test 通过。不做什么:不改后端。"
|
|
30
32
|
```
|
|
31
33
|
|
|
32
|
-
之后低谷时段自动跑;也可以用面板「立即跑」或 `offhours run --once`。
|
|
34
|
+
之后低谷时段自动跑;也可以用面板「立即跑」或 `npx dsh-offhours run --once`。
|
|
35
|
+
|
|
36
|
+
如果打开面板看到「先完成一次性初始化」,说明配置还没生成:在项目仓库执行上面的 `init`,刷新面板即可;不需要重装插件。
|
|
37
|
+
|
|
38
|
+
装完/升级插件后记得重启一次 `dsh web`,面板才会加载新代码。
|
|
33
39
|
|
|
34
40
|
## 配置
|
|
35
41
|
|
|
36
|
-
`~/.dsh/offhours/config.json`(`offhours init` 生成):
|
|
42
|
+
`~/.dsh/offhours/config.json`(`npx dsh-offhours init` 生成):
|
|
37
43
|
|
|
38
44
|
```json
|
|
39
45
|
{
|
|
@@ -62,13 +68,15 @@ offhours card add "给登录页补错误提示" \
|
|
|
62
68
|
|
|
63
69
|
| 命令 | 作用 |
|
|
64
70
|
|---|---|
|
|
65
|
-
| `offhours init --repo .` | 初始化配置/看板/特性 |
|
|
66
|
-
| `offhours doctor` | 依赖与权限体检(失败退出非 0) |
|
|
67
|
-
| `offhours card add "<标题>" --summary "<目标/判据/边界>"` | 建卡并盖章当前会话 |
|
|
68
|
-
| `offhours card list` | 列卡 |
|
|
69
|
-
| `offhours run --once` / `--dry-run` | 手动跑一轮 / 只看会挑哪张 |
|
|
70
|
-
| `offhours status` | 看板计数、心跳、最近状态(JSON) |
|
|
71
|
-
| `offhours boards` | 看板列表 |
|
|
71
|
+
| `npx dsh-offhours init --repo .` | 初始化配置/看板/特性 |
|
|
72
|
+
| `npx dsh-offhours doctor` | 依赖与权限体检(失败退出非 0) |
|
|
73
|
+
| `npx dsh-offhours card add "<标题>" --summary "<目标/判据/边界>"` | 建卡并盖章当前会话 |
|
|
74
|
+
| `npx dsh-offhours card list` | 列卡 |
|
|
75
|
+
| `npx dsh-offhours run --once` / `--dry-run` | 手动跑一轮 / 只看会挑哪张 |
|
|
76
|
+
| `npx dsh-offhours status` | 看板计数、心跳、最近状态(JSON) |
|
|
77
|
+
| `npx dsh-offhours boards` | 看板列表 |
|
|
78
|
+
|
|
79
|
+
> 不想走 npx:装完后 CLI 也在 profile 的 `node_modules/.bin/offhours`(例如 `~/.dsh/profiles/web/node_modules/.bin/offhours`),可以直接用绝对路径调用。
|
|
72
80
|
|
|
73
81
|
## 依赖
|
|
74
82
|
|
package/bin/offhours.mjs
CHANGED
|
@@ -20,15 +20,16 @@ import {
|
|
|
20
20
|
|
|
21
21
|
const HELP = `dsh-offhours —— 夜间/低谷自动跑批(配一个 git 仓库就能用)
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
offhours init --repo <git仓库路径> [--name 名称] [--board KANBAN.json] [--feature 特性名]
|
|
25
|
-
offhours doctor
|
|
26
|
-
offhours card add "<标题>" --summary "<目标/判据>" [--tags auto] [--board id]
|
|
27
|
-
offhours card list [--board id]
|
|
28
|
-
offhours run [--once] [--dry-run] [--force] [--board id]
|
|
29
|
-
offhours status [--board id]
|
|
30
|
-
offhours boards
|
|
23
|
+
装完插件后不需要全局安装 CLI,用 npx 调用即可:
|
|
24
|
+
npx dsh-offhours init --repo <git仓库路径> [--name 名称] [--board KANBAN.json] [--feature 特性名]
|
|
25
|
+
npx dsh-offhours doctor
|
|
26
|
+
npx dsh-offhours card add "<标题>" --summary "<目标/判据>" [--tags auto] [--board id]
|
|
27
|
+
npx dsh-offhours card list [--board id]
|
|
28
|
+
npx dsh-offhours run [--once] [--dry-run] [--force] [--board id]
|
|
29
|
+
npx dsh-offhours status [--board id]
|
|
30
|
+
npx dsh-offhours boards
|
|
31
31
|
|
|
32
|
+
如果你已经全局安装了本包,也可以把 npx dsh-offhours 换成 offhours。
|
|
32
33
|
全局:--config <path>(默认 ~/.dsh/offhours/config.json)
|
|
33
34
|
|
|
34
35
|
约束:worker 需要 dsh、python3、bash、git、jq、flock;zstd 可选(成本统计)。
|
|
@@ -53,14 +54,14 @@ function parse(argv) {
|
|
|
53
54
|
}
|
|
54
55
|
|
|
55
56
|
function die(msg, code = 1) {
|
|
56
|
-
console.error(`offhours: ${msg}`)
|
|
57
|
+
console.error(`dsh-offhours: ${msg}`)
|
|
57
58
|
process.exit(code)
|
|
58
59
|
}
|
|
59
60
|
|
|
60
61
|
function loadOrDie(flags) {
|
|
61
62
|
const { config, path, exists } = loadConfig(flags.config)
|
|
62
|
-
if (!exists) die(`没有配置:${path}\n先运行:offhours init --repo
|
|
63
|
-
if (!config.boards.length) die(`配置里没有看板:${path}\n先运行:offhours init --repo
|
|
63
|
+
if (!exists) die(`没有配置:${path}\n先运行:npx dsh-offhours init --repo <你的 git 仓库>`)
|
|
64
|
+
if (!config.boards.length) die(`配置里没有看板:${path}\n先运行:npx dsh-offhours init --repo <你的 git 仓库>`)
|
|
64
65
|
return { cfg: config, path }
|
|
65
66
|
}
|
|
66
67
|
|
|
@@ -104,8 +105,13 @@ function cmdInit(flags) {
|
|
|
104
105
|
writeFileSync(boardFile, '{\n "version": 1,\n "cards": []\n}\n', 'utf8')
|
|
105
106
|
}
|
|
106
107
|
mkdirSync(cfg.featuresRoot, { recursive: true })
|
|
108
|
+
// 合并已有登记表:init 一个新仓库不能把用户之前登记的仓库冲掉。
|
|
109
|
+
let registry = {}
|
|
110
|
+
try { registry = JSON.parse(readFileSync(join(cfg.featuresRoot, '.repos.json'), 'utf8')) || {} } catch { /* 首次初始化 */ }
|
|
111
|
+
if (!registry || typeof registry !== 'object' || Array.isArray(registry)) registry = {}
|
|
112
|
+
registry[name] = { path: repo, baseBranch: base }
|
|
107
113
|
writeFileSync(join(cfg.featuresRoot, '.repos.json'),
|
|
108
|
-
JSON.stringify(
|
|
114
|
+
JSON.stringify(registry, null, 2) + '\n', 'utf8')
|
|
109
115
|
saveConfig(cfgPath, cfg)
|
|
110
116
|
|
|
111
117
|
const env = {
|
|
@@ -118,6 +124,13 @@ function cmdInit(flags) {
|
|
|
118
124
|
let r = spawnSync(fb, args, { env, encoding: 'utf8' })
|
|
119
125
|
if (r.status !== 0) r = spawnSync(fb, ['ensure', feature, '--repos', name], { env, encoding: 'utf8' })
|
|
120
126
|
const featOut = String((r.stdout || r.stderr || '').trim()).split('\n').slice(-2).join('\n')
|
|
127
|
+
// feature CLI 可能把登记表改写成字符串;补回 baseBranch,且不丢已有仓库。
|
|
128
|
+
try {
|
|
129
|
+
let reg2 = JSON.parse(readFileSync(join(cfg.featuresRoot, '.repos.json'), 'utf8')) || {}
|
|
130
|
+
if (!reg2 || typeof reg2 !== 'object' || Array.isArray(reg2)) reg2 = {}
|
|
131
|
+
reg2[name] = { path: repo, baseBranch: base }
|
|
132
|
+
writeFileSync(join(cfg.featuresRoot, '.repos.json'), JSON.stringify(reg2, null, 2) + '\n', 'utf8')
|
|
133
|
+
} catch { /* 保留 feature 的写法 */ }
|
|
121
134
|
|
|
122
135
|
console.log(`✓ 配置:${cfgPath}`)
|
|
123
136
|
console.log(`✓ 仓库:${name} → ${repo}(基准分支 ${base})`)
|
|
@@ -126,13 +139,17 @@ function cmdInit(flags) {
|
|
|
126
139
|
if (featOut) console.log(featOut)
|
|
127
140
|
console.log('')
|
|
128
141
|
console.log('下一步:')
|
|
129
|
-
console.log(
|
|
130
|
-
console.log(
|
|
131
|
-
console.log(
|
|
142
|
+
console.log(' npx dsh-offhours doctor')
|
|
143
|
+
console.log(' npx dsh-offhours card add "第一张卡" --summary "目标/判据/不做什么"')
|
|
144
|
+
console.log(' npx dsh-offhours run --once')
|
|
132
145
|
}
|
|
133
146
|
|
|
134
147
|
function cmdDoctor(flags) {
|
|
135
|
-
const { config: cfg, path } = loadConfig(flags.config)
|
|
148
|
+
const { config: cfg, path, exists } = loadConfig(flags.config)
|
|
149
|
+
if (!exists) {
|
|
150
|
+
console.log(`未配置:${path}`)
|
|
151
|
+
console.log('先运行:npx dsh-offhours init --repo <你的 git 仓库>')
|
|
152
|
+
}
|
|
136
153
|
const rows = []
|
|
137
154
|
const fail = []
|
|
138
155
|
const hard = (name, ok, detail = '') => {
|
package/lib/client.js
CHANGED
|
@@ -1001,6 +1001,7 @@ window.__ModuleLoader__.load({
|
|
|
1001
1001
|
const reviews = Array.isArray(data.reviews) ? data.reviews : []
|
|
1002
1002
|
const running = Array.isArray(data.running) ? data.running : []
|
|
1003
1003
|
const recent = data.recent || {}
|
|
1004
|
+
const setup = data.setup || {}
|
|
1004
1005
|
const problems = (Array.isArray(data.problems) ? data.problems : []).filter(
|
|
1005
1006
|
// 「定时器当前是 active」是正常状态,不该显示成提示(旧版宿主会多带一个换行)
|
|
1006
1007
|
(p) => !/当前是\s*active\b/.test(String(p)),
|
|
@@ -1065,7 +1066,7 @@ window.__ModuleLoader__.load({
|
|
|
1065
1066
|
h('span', { style: { fontSize: 12, color: T.textSub } }, t('boardLabel')),
|
|
1066
1067
|
...(Array.isArray(snap.data && snap.data.boards) && snap.data.boards.length
|
|
1067
1068
|
? snap.data.boards
|
|
1068
|
-
: [
|
|
1069
|
+
: []
|
|
1069
1070
|
).map((b) =>
|
|
1070
1071
|
h(
|
|
1071
1072
|
Button,
|
|
@@ -1086,6 +1087,33 @@ window.__ModuleLoader__.load({
|
|
|
1086
1087
|
h('div', { style: { display: 'flex', gap: 6, flexWrap: 'wrap', marginTop: 4 } }, chips),
|
|
1087
1088
|
),
|
|
1088
1089
|
|
|
1090
|
+
setup.configured === false
|
|
1091
|
+
? h(
|
|
1092
|
+
'div',
|
|
1093
|
+
{
|
|
1094
|
+
style: {
|
|
1095
|
+
...cardStyle, borderColor: T.brand, fontSize: 12, lineHeight: 1.65,
|
|
1096
|
+
display: 'flex', flexDirection: 'column', gap: 6,
|
|
1097
|
+
},
|
|
1098
|
+
},
|
|
1099
|
+
h('div', { style: { fontWeight: 700, fontSize: 13, color: T.text } }, t('setupTitle')),
|
|
1100
|
+
h('div', { style: { color: T.textSub } }, t('setupBody')),
|
|
1101
|
+
h(
|
|
1102
|
+
'code',
|
|
1103
|
+
{
|
|
1104
|
+
style: {
|
|
1105
|
+
fontSize: 12, padding: '7px 9px', borderRadius: 8, background: T.fill,
|
|
1106
|
+
border: `1px solid ${T.borderStrong}`, wordBreak: 'break-all',
|
|
1107
|
+
},
|
|
1108
|
+
},
|
|
1109
|
+
setup.initCommand || 'npx dsh-offhours init --repo .',
|
|
1110
|
+
),
|
|
1111
|
+
h('div', { style: { color: T.textSub } }, t('setupAfter')),
|
|
1112
|
+
setup.configPath
|
|
1113
|
+
? h('div', { style: { color: T.textSub, wordBreak: 'break-all' } }, `${t('setupConfigPath')} ${setup.configPath}`)
|
|
1114
|
+
: null,
|
|
1115
|
+
)
|
|
1116
|
+
: null,
|
|
1089
1117
|
snap.error
|
|
1090
1118
|
? h('div', { style: { ...cardStyle, borderColor: T.danger, color: T.danger, fontSize: 12 } }, snap.error)
|
|
1091
1119
|
: null,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-offhours",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "DSH 社区插件:把看板待办在低谷/夜间自动做掉(挑卡 → 独占 worktree → worker → 证据 → 合并回收),只依赖配置里的 git 仓库。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
"./package.json": "./package.json"
|
|
12
12
|
},
|
|
13
13
|
"bin": {
|
|
14
|
-
"offhours": "./bin/offhours.mjs"
|
|
14
|
+
"offhours": "./bin/offhours.mjs",
|
|
15
|
+
"dsh-offhours": "./bin/offhours.mjs"
|
|
15
16
|
},
|
|
16
17
|
"files": [
|
|
17
18
|
"bin/offhours.mjs",
|
|
@@ -69,10 +70,10 @@
|
|
|
69
70
|
],
|
|
70
71
|
"repository": {
|
|
71
72
|
"type": "git",
|
|
72
|
-
"url": "git+https://github.com/
|
|
73
|
+
"url": "git+https://github.com/shuke52tt/dsh-offhours.git"
|
|
73
74
|
},
|
|
74
|
-
"homepage": "https://github.com/
|
|
75
|
+
"homepage": "https://github.com/shuke52tt/dsh-offhours#readme",
|
|
75
76
|
"bugs": {
|
|
76
|
-
"url": "https://github.com/
|
|
77
|
+
"url": "https://github.com/shuke52tt/dsh-offhours/issues"
|
|
77
78
|
}
|
|
78
79
|
}
|
package/panel/client.js
CHANGED
|
@@ -1001,6 +1001,7 @@ window.__ModuleLoader__.load({
|
|
|
1001
1001
|
const reviews = Array.isArray(data.reviews) ? data.reviews : []
|
|
1002
1002
|
const running = Array.isArray(data.running) ? data.running : []
|
|
1003
1003
|
const recent = data.recent || {}
|
|
1004
|
+
const setup = data.setup || {}
|
|
1004
1005
|
const problems = (Array.isArray(data.problems) ? data.problems : []).filter(
|
|
1005
1006
|
// 「定时器当前是 active」是正常状态,不该显示成提示(旧版宿主会多带一个换行)
|
|
1006
1007
|
(p) => !/当前是\s*active\b/.test(String(p)),
|
|
@@ -1065,7 +1066,7 @@ window.__ModuleLoader__.load({
|
|
|
1065
1066
|
h('span', { style: { fontSize: 12, color: T.textSub } }, t('boardLabel')),
|
|
1066
1067
|
...(Array.isArray(snap.data && snap.data.boards) && snap.data.boards.length
|
|
1067
1068
|
? snap.data.boards
|
|
1068
|
-
: [
|
|
1069
|
+
: []
|
|
1069
1070
|
).map((b) =>
|
|
1070
1071
|
h(
|
|
1071
1072
|
Button,
|
|
@@ -1086,6 +1087,33 @@ window.__ModuleLoader__.load({
|
|
|
1086
1087
|
h('div', { style: { display: 'flex', gap: 6, flexWrap: 'wrap', marginTop: 4 } }, chips),
|
|
1087
1088
|
),
|
|
1088
1089
|
|
|
1090
|
+
setup.configured === false
|
|
1091
|
+
? h(
|
|
1092
|
+
'div',
|
|
1093
|
+
{
|
|
1094
|
+
style: {
|
|
1095
|
+
...cardStyle, borderColor: T.brand, fontSize: 12, lineHeight: 1.65,
|
|
1096
|
+
display: 'flex', flexDirection: 'column', gap: 6,
|
|
1097
|
+
},
|
|
1098
|
+
},
|
|
1099
|
+
h('div', { style: { fontWeight: 700, fontSize: 13, color: T.text } }, t('setupTitle')),
|
|
1100
|
+
h('div', { style: { color: T.textSub } }, t('setupBody')),
|
|
1101
|
+
h(
|
|
1102
|
+
'code',
|
|
1103
|
+
{
|
|
1104
|
+
style: {
|
|
1105
|
+
fontSize: 12, padding: '7px 9px', borderRadius: 8, background: T.fill,
|
|
1106
|
+
border: `1px solid ${T.borderStrong}`, wordBreak: 'break-all',
|
|
1107
|
+
},
|
|
1108
|
+
},
|
|
1109
|
+
setup.initCommand || 'npx dsh-offhours init --repo .',
|
|
1110
|
+
),
|
|
1111
|
+
h('div', { style: { color: T.textSub } }, t('setupAfter')),
|
|
1112
|
+
setup.configPath
|
|
1113
|
+
? h('div', { style: { color: T.textSub, wordBreak: 'break-all' } }, `${t('setupConfigPath')} ${setup.configPath}`)
|
|
1114
|
+
: null,
|
|
1115
|
+
)
|
|
1116
|
+
: null,
|
|
1089
1117
|
snap.error
|
|
1090
1118
|
? h('div', { style: { ...cardStyle, borderColor: T.danger, color: T.danger, fontSize: 12 } }, snap.error)
|
|
1091
1119
|
: null,
|
package/panel/index.js
CHANGED
|
@@ -322,6 +322,7 @@ async function buildStatus(boardArg) {
|
|
|
322
322
|
if (Number.isFinite(n)) windowLeft = n
|
|
323
323
|
} catch { /* 忽略:面板降级为不显示余量 */ }
|
|
324
324
|
const COOLDOWN_MIN = cooldownMinFor(board)
|
|
325
|
+
const configured = !!(CFG._path && existsSync(CFG._path) && Array.isArray(CFG.boards) && CFG.boards.length > 0)
|
|
325
326
|
const out = {
|
|
326
327
|
ok: true,
|
|
327
328
|
now: fmtLocal(now),
|
|
@@ -341,6 +342,13 @@ async function buildStatus(boardArg) {
|
|
|
341
342
|
running: [],
|
|
342
343
|
recent: { log: [], receipt: null, runs: [] },
|
|
343
344
|
problems: [],
|
|
345
|
+
setup: {
|
|
346
|
+
configured,
|
|
347
|
+
configPath: CFG._path || '',
|
|
348
|
+
initCommand: 'npx dsh-offhours init --repo .',
|
|
349
|
+
doctorCommand: 'npx dsh-offhours doctor',
|
|
350
|
+
restartHint: '安装或更新插件后重启 dsh,面板才会加载新代码。',
|
|
351
|
+
},
|
|
344
352
|
}
|
|
345
353
|
|
|
346
354
|
// SCHEDULER-REPORT:按配置的调度方式如实报告(systemd / 插件内 interval)。
|
|
@@ -379,7 +387,7 @@ async function buildStatus(boardArg) {
|
|
|
379
387
|
}
|
|
380
388
|
} catch { out.problems.push('systemctl 查询失败(定时器状态未知)') }
|
|
381
389
|
}
|
|
382
|
-
if (CFG.scheduler === 'plugin' && out.timer.active === 'unknown') {
|
|
390
|
+
if (configured && CFG.scheduler === 'plugin' && out.timer.active === 'unknown') {
|
|
383
391
|
out.problems.push('插件内调度器没有心跳(确认 dsh 进程在跑,或 schedule.enabled=false)')
|
|
384
392
|
}
|
|
385
393
|
|
|
@@ -544,6 +552,15 @@ async function buildStatus(boardArg) {
|
|
|
544
552
|
out.recent.runs = []
|
|
545
553
|
}
|
|
546
554
|
|
|
555
|
+
if (!configured) {
|
|
556
|
+
// 未配置时只展示 setup 卡片;不要把空 path 触发的“看板读不到/冷却未知”当错误吓用户。
|
|
557
|
+
out.problems = []
|
|
558
|
+
out.todos = []
|
|
559
|
+
out.reviews = []
|
|
560
|
+
out.running = []
|
|
561
|
+
out.recent = { log: [], receipt: null, runs: [] }
|
|
562
|
+
out.timer.raw = 'unconfigured'
|
|
563
|
+
}
|
|
547
564
|
return out
|
|
548
565
|
}
|
|
549
566
|
|
package/panel/locale/en.json
CHANGED
|
@@ -77,6 +77,10 @@
|
|
|
77
77
|
"liveEmpty": "No output yet",
|
|
78
78
|
"liveFollow": "auto-follow",
|
|
79
79
|
"runningNowText": "Running now:",
|
|
80
|
-
"openWorkerSession": "Open worker session"
|
|
80
|
+
"openWorkerSession": "Open worker session",
|
|
81
|
+
"setupTitle": "One-time setup",
|
|
82
|
+
"setupBody": "Run this inside the git repository you want to batch:",
|
|
83
|
+
"setupAfter": "Then reload or restart dsh. The board appears here; work only starts off-peak while the machine is idle.",
|
|
84
|
+
"setupConfigPath": "Config file:"
|
|
81
85
|
}
|
|
82
86
|
}
|
package/panel/locale/zh.json
CHANGED
|
@@ -77,6 +77,10 @@
|
|
|
77
77
|
"liveEmpty": "还没有输出(等它开始吐字)",
|
|
78
78
|
"liveFollow": "自动跟随最新",
|
|
79
79
|
"runningNowText": "正在跑批:",
|
|
80
|
-
"openWorkerSession": "打开处理会话(对话/轨迹)"
|
|
80
|
+
"openWorkerSession": "打开处理会话(对话/轨迹)",
|
|
81
|
+
"setupTitle": "先完成一次性初始化",
|
|
82
|
+
"setupBody": "在要跑批的 git 仓库里运行:",
|
|
83
|
+
"setupAfter": "然后刷新或重启 dsh;左侧会出现看板,只有低谷且机器空闲时才会自动跑。",
|
|
84
|
+
"setupConfigPath": "配置文件:"
|
|
81
85
|
}
|
|
82
86
|
}
|
package/skills/offhours/SKILL.md
CHANGED
|
@@ -17,10 +17,11 @@ description: "夜间/低谷自动跑批(dsh-offhours):把看板待办在
|
|
|
17
17
|
## 建卡(唯一正确入口)
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
|
-
offhours card add "<标题>" --summary "<目标 + 判据(命令) + 涉及面 + 不做什么>"
|
|
20
|
+
npx dsh-offhours card add "<标题>" --summary "<目标 + 判据(命令) + 涉及面 + 不做什么>"
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
- 必须在 dsh 会话里执行:它会用 `DSH_SESSION_ID` 盖章 `sourceSessionId`;
|
|
24
|
+
- CLI 没进全局 PATH:统一用 `npx dsh-offhours ...`(或 profile 里的 `node_modules/.bin/offhours`)。
|
|
24
25
|
**没有 sourceSessionId 的卡跑批永远不会捡**(不是 bug,是隔离要求)。
|
|
25
26
|
- 用 dsh-kanban 的 `board_add` 建的卡不带 session,只适合人工看板,不适合跑批。
|
|
26
27
|
- 判据必须是命令,不是形容词;一张卡 = 一个可独立合并的成果。
|
|
@@ -28,10 +29,10 @@ offhours card add "<标题>" --summary "<目标 + 判据(命令) + 涉及面 +
|
|
|
28
29
|
## 查状态 / 手动跑
|
|
29
30
|
|
|
30
31
|
```bash
|
|
31
|
-
offhours doctor # 依赖、配置、权限体检(先跑这个)
|
|
32
|
-
offhours status # 看板计数 + 心跳 + 最近状态(JSON)
|
|
33
|
-
offhours run --once # 手动跑一轮(生产调度器之外)
|
|
34
|
-
offhours run --dry-run # 只看会挑哪张,不启动 worker
|
|
32
|
+
npx dsh-offhours doctor # 依赖、配置、权限体检(先跑这个)
|
|
33
|
+
npx dsh-offhours status # 看板计数 + 心跳 + 最近状态(JSON)
|
|
34
|
+
npx dsh-offhours run --once # 手动跑一轮(生产调度器之外)
|
|
35
|
+
npx dsh-offhours run --dry-run # 只看会挑哪张,不启动 worker
|
|
35
36
|
```
|
|
36
37
|
|
|
37
38
|
面板:dsh Web 左侧「夜间跑批」;`/offhours` 命令也可查状态。
|