dsh-journey 0.2.0 → 0.2.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/AGENT_INSTALL.md +8 -5
- package/AI_GUIDE.md +210 -0
- package/README.md +4 -2
- package/install.manifest.json +1 -1
- package/lib/index.js +4 -3
- package/package.json +4 -3
- package/public/index.html +161 -7
- package/scripts/dump-journey.mjs +15 -0
- package/scripts/make-cards.mjs +70 -0
- package/scripts/make-demo.mjs +80 -0
- package/demo/P01_/346/275/256/346/261/220/350/241/250/README.md +0 -28
- package/demo/P01_/346/275/256/346/261/220/350/241/250//347/212/266/346/200/201.md +0 -9
- package/demo/P01_/346/275/256/346/261/220/350/241/250//350/256/241/345/210/222.md +0 -17
- package/demo/P02_/350/257/215/346/240/271/README.md +0 -28
- package/demo/P02_/350/257/215/346/240/271//347/212/266/346/200/201.md +0 -9
- package/demo/P02_/350/257/215/346/240/271//350/256/241/345/210/222.md +0 -15
- package/demo/P03_/351/233/250/345/243/260/README.md +0 -28
- package/demo/P03_/351/233/250/345/243/260//347/212/266/346/200/201.md +0 -9
- package/demo/P03_/351/233/250/345/243/260//350/256/241/345/210/222.md +0 -15
- package/demo//350/257/264/346/230/216.md +0 -48
package/AGENT_INSTALL.md
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
# AGENT_INSTALL · dsh-journey
|
|
1
|
+
# AGENT_INSTALL · dsh-journey
|
|
2
|
+
|
|
3
|
+
> 用户说“把这个插件用起来”时,先读 `AI_GUIDE.md`。
|
|
2
4
|
|
|
3
5
|
> 给管事的 AI:照这个做,不要猜。
|
|
4
6
|
|
|
@@ -6,7 +8,7 @@
|
|
|
6
8
|
|
|
7
9
|
```
|
|
8
10
|
name: dsh-journey
|
|
9
|
-
version: 0.2.
|
|
11
|
+
version: 0.2.2
|
|
10
12
|
display: Journey
|
|
11
13
|
```
|
|
12
14
|
|
|
@@ -30,9 +32,9 @@ profile: %USERPROFILE%\.dsh\profiles\desktop
|
|
|
30
32
|
3 重启 DSH
|
|
31
33
|
```
|
|
32
34
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
35
|
+
**需要配置 journeyWorkspace**:
|
|
36
|
+
npm 包不含 demo;要读本机演示工作区或真实工作区,
|
|
37
|
+
在 profile 的 `cordis.patch.yml` 里给 `journey` 配 `journeyWorkspace`。
|
|
36
38
|
|
|
37
39
|
## 验证
|
|
38
40
|
|
|
@@ -58,3 +60,4 @@ GET /wind-chain/journey/api/cards 返回 ok=true
|
|
|
58
60
|
· 不要手改 profile 里的其他 bundle
|
|
59
61
|
· 接口路径仍是 /wind-chain/journey/api/cards(历史路径,不是包名写错)
|
|
60
62
|
```
|
|
63
|
+
|
package/AI_GUIDE.md
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# AI_GUIDE · 把一个新下载的 Journey 用起来
|
|
2
|
+
|
|
3
|
+
> 给任何被用户叫来“把这个插件用起来”的 AI。
|
|
4
|
+
> 先读本文件,再动手;不要猜路径、不要编数据。
|
|
5
|
+
|
|
6
|
+
## 0 用户只要说一句
|
|
7
|
+
|
|
8
|
+
用户可以只发:
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
读 AI_GUIDE.md,把这个插件用起来,生成一个演示工作区,然后告诉我怎么用、有什么问题、下一步建议。
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
你就按下面走。
|
|
15
|
+
|
|
16
|
+
## 1 先确认这是什么
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
Journey(风雨彩虹)
|
|
20
|
+
DSH 只读项目监控面板
|
|
21
|
+
包名:dsh-journey
|
|
22
|
+
入口:DSH 左侧栏 Journey
|
|
23
|
+
数据:读工作区里的 状态.md / 计划.md,不在插件里写死
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
只读;不派活、不急停、不改项目。
|
|
27
|
+
|
|
28
|
+
## 2 包结构
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
dsh-journey\
|
|
32
|
+
package.json dsh.bundle + dsh.client
|
|
33
|
+
cordis.patch.yml host 注册(不含本机路径)
|
|
34
|
+
lib\index.js host:/wind-chain/journey/api/cards
|
|
35
|
+
lib\client.js client:侧栏入口 + main
|
|
36
|
+
lib\journey-data.js 数据层
|
|
37
|
+
public\index.html v362+作者页
|
|
38
|
+
scripts\make-demo.mjs 批量生成演示项目
|
|
39
|
+
AGENT_INSTALL.md 安装 / 验证 / 卸载
|
|
40
|
+
AI_GUIDE.md 本文件
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
npm 包**不包含 demo**;demo 由本脚本生成本地目录。
|
|
44
|
+
|
|
45
|
+
## 3 安装检查
|
|
46
|
+
|
|
47
|
+
按 `AGENT_INSTALL.md` 装完并重启 DSH 后,确认:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
1 左侧栏有 Journey
|
|
51
|
+
2 点进去不是白屏
|
|
52
|
+
3 GET /wind-chain/journey/api/cards 返回 ok=true
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
如果白屏:
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
先看是不是 DSH 共享浏览器渲染卡死
|
|
59
|
+
再 reset 浏览器会话 / 重开面板
|
|
60
|
+
不要先断言页面没内容
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## 4 生成演示工作区
|
|
64
|
+
|
|
65
|
+
用户没有现成工作区时:
|
|
66
|
+
|
|
67
|
+
```powershell
|
|
68
|
+
node scripts\make-demo.mjs "D:\somewhere\journey-demo" 12
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
会生成:
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
P01_潮汐表\
|
|
75
|
+
P02_词根\
|
|
76
|
+
...
|
|
77
|
+
每个项目三件:
|
|
78
|
+
README.md
|
|
79
|
+
状态.md 五字段
|
|
80
|
+
计划.md 阶段 + [x]
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
然后在 profile 的 `cordis.patch.yml` 里给 Journey 配:
|
|
84
|
+
|
|
85
|
+
```yaml
|
|
86
|
+
- id: journey
|
|
87
|
+
name: dsh-journey
|
|
88
|
+
config:
|
|
89
|
+
journeyWorkspace: "D:\somewhere\journey-demo"
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
重启 DSH,面板就会出现 12 张卡。
|
|
93
|
+
|
|
94
|
+
## 5 数据契约
|
|
95
|
+
|
|
96
|
+
卡片由目录扫描得到:
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
id 目录名前缀,如 P01
|
|
100
|
+
title 目录名去掉 P0x_ 前缀
|
|
101
|
+
status running / paused / done
|
|
102
|
+
current 状态.md 的「当前阶段」
|
|
103
|
+
why 状态.md 的「卡点」
|
|
104
|
+
round 保留字段,demo 为 0
|
|
105
|
+
budget 保留字段,demo 为 0
|
|
106
|
+
logs 当前 demo 为空
|
|
107
|
+
plan 计划.md 的阶段 + 勾选
|
|
108
|
+
demo true
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
状态推断:
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
当前阶段/卡点含「已完成/已归档」→ done
|
|
115
|
+
卡点含「等/未定/未完成」→ paused
|
|
116
|
+
否则 → running
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
计划格式:
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
阶段 1 打底
|
|
123
|
+
[x] 明确输入输出
|
|
124
|
+
[ ] 跑通最小流程
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## 4.1 按用户给的信息建卡
|
|
128
|
+
|
|
129
|
+
用户说“给我建一张卡 / 按这些项目建卡”时,不要直接写文件,先问五项:
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
1 标题(项目名)
|
|
133
|
+
2 状态:在跑 / 等我 / 结束
|
|
134
|
+
3 当前在做什么
|
|
135
|
+
4 卡点是什么(没有就写“无”)
|
|
136
|
+
5 计划:几个阶段、每阶段哪些已勾
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
收到后写 `cards.json`:
|
|
140
|
+
|
|
141
|
+
```json
|
|
142
|
+
{
|
|
143
|
+
"cards": [
|
|
144
|
+
{
|
|
145
|
+
"id": "P13",
|
|
146
|
+
"title": "天气角标",
|
|
147
|
+
"status": "running",
|
|
148
|
+
"current": "主流程跑通;正在补细节",
|
|
149
|
+
"blocker": "无",
|
|
150
|
+
"plan": [
|
|
151
|
+
{ "stage": "阶段 1 打底", "items": [["明确输入输出", true], ["跑通最小流程", true]] },
|
|
152
|
+
{ "stage": "阶段 2 做出来", "items": [["补主功能", false]] }
|
|
153
|
+
]
|
|
154
|
+
}
|
|
155
|
+
]
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
然后:
|
|
160
|
+
|
|
161
|
+
```powershell
|
|
162
|
+
node scripts\make-cards.mjs "D:\目标演示工作区" cards.json
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
状态映射:`running` / `paused` / `done`。
|
|
166
|
+
计划按 `true/false` 写 `[x]` / `[ ]`。
|
|
167
|
+
刷新面板即可看到新卡。
|
|
168
|
+
|
|
169
|
+
**原则**:用户没给的信息不要编;缺什么问什么,一次问完。
|
|
170
|
+
|
|
171
|
+
## 6 验收
|
|
172
|
+
|
|
173
|
+
```
|
|
174
|
+
1 卡片数量 = 生成的项目数
|
|
175
|
+
2 在跑 / 暂停 计数正确
|
|
176
|
+
3 点一张卡,右栏显示「正在进行 / 卡点」
|
|
177
|
+
4 再点右栏,显示「计划总览」
|
|
178
|
+
5 点标题,作者页能开、能关
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
## 7 常见问题
|
|
182
|
+
|
|
183
|
+
```
|
|
184
|
+
刷新键只重绘,不重新拉接口
|
|
185
|
+
→ 切换一次会话/重开面板才会重新加载数据
|
|
186
|
+
|
|
187
|
+
npm 包不带 demo
|
|
188
|
+
→ 没配 journeyWorkspace 时,面板会空
|
|
189
|
+
|
|
190
|
+
路由仅本机
|
|
191
|
+
→ 远程访问前必须加 token
|
|
192
|
+
|
|
193
|
+
v362 是两态显示
|
|
194
|
+
→ 结束归在暂停组,不是缺数据
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## 8 给建议时不要越界
|
|
198
|
+
|
|
199
|
+
```
|
|
200
|
+
能说:数据模型、安装、演示、空态、刷新、真实 A 系列接入方案
|
|
201
|
+
不能说:已经支持急停 / 派活 / 真实项目接入(还没做)
|
|
202
|
+
不能改:A16 的 UI、A07 的材料、用户的项目文件
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
## 9 一句话
|
|
206
|
+
|
|
207
|
+
```
|
|
208
|
+
先装、再生成 demo、再验证、最后按数据契约给建议;
|
|
209
|
+
不猜、不编、不把演示壳说成真实项目。
|
|
210
|
+
```
|
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# Journey(风雨彩虹)
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> 给 AI:先读 `AI_GUIDE.md`。用户说“把这个插件用起来”时,照它做。
|
|
4
|
+
|
|
5
|
+
> 2026-11-13 | DSH 项目监控面板 | v0.2.2
|
|
4
6
|
> 中文统称:风雨彩虹
|
|
5
7
|
|
|
6
8
|
## 是什么
|
|
@@ -43,7 +45,7 @@ bundle 加 dsh-journey
|
|
|
43
45
|
## 数据源
|
|
44
46
|
|
|
45
47
|
```
|
|
46
|
-
demo
|
|
48
|
+
demo 不再随 npm 包携带;本机演示需配置 journeyWorkspace:
|
|
47
49
|
P01 潮汐表 / P02 词根 / P03 雨声
|
|
48
50
|
```
|
|
49
51
|
|
package/install.manifest.json
CHANGED
package/lib/index.js
CHANGED
|
@@ -18,7 +18,6 @@ import { buildDemoJourneyData } from './journey-data.js';
|
|
|
18
18
|
import { fileURLToPath } from 'node:url';
|
|
19
19
|
|
|
20
20
|
const JOURNEY_PUBLIC = fileURLToPath(new URL('../public/', import.meta.url));
|
|
21
|
-
const JOURNEY_DEMO = fileURLToPath(new URL('../demo/', import.meta.url));
|
|
22
21
|
|
|
23
22
|
function isLoopback(req) {
|
|
24
23
|
const addr = String(req?.socket?.remoteAddress || '');
|
|
@@ -927,8 +926,10 @@ export function apply(ctx, config) {
|
|
|
927
926
|
}
|
|
928
927
|
}
|
|
929
928
|
try {
|
|
930
|
-
const demoRoot = String(config?.journeyWorkspace ?? '').trim()
|
|
931
|
-
const data =
|
|
929
|
+
const demoRoot = String(config?.journeyWorkspace ?? '').trim();
|
|
930
|
+
const data = demoRoot
|
|
931
|
+
? buildDemoJourneyData({ workspaceRoot: demoRoot })
|
|
932
|
+
: { cards: [], counts: { total: 0, running: 0, paused: 0, done: 0, needsHuman: 0 } };
|
|
932
933
|
for (const card of data.cards) {
|
|
933
934
|
const agent = card.sessionId ? ctx.agents.get(card.sessionId) : undefined;
|
|
934
935
|
if (agent) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-journey",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Journey(风雨彩虹):DSH 项目监控面板,查看 A 系列项目卡片、当前动作与计划总览。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -17,11 +17,12 @@
|
|
|
17
17
|
"files": [
|
|
18
18
|
"lib",
|
|
19
19
|
"public",
|
|
20
|
-
"demo",
|
|
21
20
|
"cordis.patch.yml",
|
|
22
21
|
"README.md",
|
|
23
22
|
"AGENT_INSTALL.md",
|
|
24
|
-
"install.manifest.json"
|
|
23
|
+
"install.manifest.json",
|
|
24
|
+
"AI_GUIDE.md",
|
|
25
|
+
"scripts"
|
|
25
26
|
],
|
|
26
27
|
"dsh": {
|
|
27
28
|
"bundle": {
|
package/public/index.html
CHANGED
|
@@ -147,18 +147,67 @@
|
|
|
147
147
|
.hdLogo{display:flex;align-items:center;height:28px;position:relative;cursor:default}
|
|
148
148
|
.hdLogo img{height:26px;width:auto;display:block}
|
|
149
149
|
.hdLogo img.blob{height:26px;width:26px;margin-right:9px}
|
|
150
|
-
/* hover
|
|
151
|
-
|
|
152
|
-
|
|
150
|
+
/* hover 时同一张图在字面上叠一层彩虹。
|
|
151
|
+
注意:叠层必须挂在**按钮**上(图片就在按钮里),挂在 h1 上会偏 4px——那就是之前的重影 bug。 */
|
|
152
|
+
.hdLogoBtn{position:relative}
|
|
153
|
+
.hdLogoBtn::after{content:"";position:absolute;inset:0;pointer-events:none;
|
|
153
154
|
background:linear-gradient(105deg,#ff6b6b,#ffd166,#4ade80,#38bdf8,#a78bfa,#ff6b6b);
|
|
154
155
|
-webkit-mask-image:url('./_wordmark.png');
|
|
155
156
|
mask-image:url('./_wordmark.png');
|
|
156
|
-
-webkit-mask-size:
|
|
157
|
+
-webkit-mask-size:100% 100%;mask-size:100% 100%;
|
|
157
158
|
-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
|
|
158
|
-
-webkit-mask-position:
|
|
159
|
+
-webkit-mask-position:center;mask-position:center;
|
|
159
160
|
opacity:0;transition:opacity .22s ease}
|
|
160
|
-
.
|
|
161
|
+
.hdLogoBtn:hover::after,.hdLogoBtn:focus-visible::after{opacity:.85}
|
|
161
162
|
.hd .r span{font-size:11.5px;color:var(--muted)}
|
|
163
|
+
/* ===== 作者页:同页浮层 ===== */
|
|
164
|
+
.hdLogoBtn, .hd button.hdLogoBtn{background:none;border:0;padding:0;margin:0;display:block;cursor:pointer;
|
|
165
|
+
border-radius:0;-webkit-tap-highlight-color:transparent}
|
|
166
|
+
/* 标题按钮别吃 .hd button 的 hover 底色(就是那圈灰块) */
|
|
167
|
+
.hd button.hdLogoBtn:hover,.hd button.hdLogoBtn:active{background:none;color:inherit}
|
|
168
|
+
.hdLogoBtn:focus-visible{outline:2px solid var(--ink);outline-offset:4px}
|
|
169
|
+
|
|
170
|
+
.about{position:fixed;inset:0;z-index:70;display:none;place-items:center;padding:24px}
|
|
171
|
+
.about.on{display:grid}
|
|
172
|
+
.about::before{content:"";position:absolute;inset:0;
|
|
173
|
+
background:rgba(15,23,42,.16);
|
|
174
|
+
-webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}
|
|
175
|
+
.aboutBox{position:relative;width:min(520px,100%);
|
|
176
|
+
border-radius:22px;overflow:hidden;padding:28px 28px 20px;
|
|
177
|
+
background:rgba(255,255,255,.82);
|
|
178
|
+
-webkit-backdrop-filter:blur(26px) saturate(1.7);
|
|
179
|
+
backdrop-filter:blur(26px) saturate(1.7);
|
|
180
|
+
box-shadow:0 24px 60px rgba(15,23,42,.22),inset 0 1px 0 rgba(255,255,255,.95);
|
|
181
|
+
animation:aboutIn .24s cubic-bezier(.2,.8,.25,1)}
|
|
182
|
+
@keyframes aboutIn{from{opacity:0;transform:translateY(12px) scale(.985)}to{opacity:1;transform:none}}
|
|
183
|
+
.aboutTop{position:absolute;left:0;right:0;top:0;height:3px;
|
|
184
|
+
background:linear-gradient(135deg,#f2554d,#f59e0b,#f7d245,#22c55e,#38bdf8,#a855f7)}
|
|
185
|
+
.aboutKicker{font-size:11px;letter-spacing:2.2px;color:var(--muted);margin:4px 0 12px}
|
|
186
|
+
.aboutName{font-size:24px;font-weight:700;letter-spacing:-.3px;line-height:1.25}
|
|
187
|
+
.aboutLine{margin-top:8px;font-size:14px;color:var(--ink2);line-height:1.6}
|
|
188
|
+
.about .ph{color:var(--muted);font-weight:400}
|
|
189
|
+
.aboutRows{margin-top:20px;padding-top:16px;border-top:.5px solid var(--line);
|
|
190
|
+
display:flex;flex-direction:column;gap:11px}
|
|
191
|
+
.aboutRow{display:flex;gap:16px;font-size:13px;line-height:1.5}
|
|
192
|
+
.aboutRow .k{width:76px;flex:none;color:var(--muted)}
|
|
193
|
+
.aboutRow .v{color:var(--ink);min-width:0;word-break:break-all}
|
|
194
|
+
.aboutRow .v a{color:var(--ink);text-decoration:none;border-bottom:.5px solid color-mix(in srgb,var(--ink) 30%,transparent);
|
|
195
|
+
padding-bottom:1px;transition:color .16s,border-color .16s}
|
|
196
|
+
.aboutRow .v a:hover{color:#0b6bcb;border-color:#0b6bcb}
|
|
197
|
+
.aboutRow .v a:focus-visible{outline:2px solid var(--ink);outline-offset:2px;border-radius:3px}
|
|
198
|
+
.aboutFoot{margin-top:24px;display:flex;align-items:center;gap:14px}
|
|
199
|
+
.aboutClose{height:38px;padding:0 20px;border:0;border-radius:19px;
|
|
200
|
+
background:var(--ink);color:#fff;font:600 13px/1 var(--font);cursor:pointer;
|
|
201
|
+
-webkit-tap-highlight-color:transparent}
|
|
202
|
+
.aboutClose:active{transform:scale(.97)}
|
|
203
|
+
.aboutClose:focus-visible{outline:2px solid var(--ink);outline-offset:3px}
|
|
204
|
+
.aboutHint{font-size:12px;color:var(--muted)}
|
|
205
|
+
@media (max-width:820px){
|
|
206
|
+
.about{padding:16px}
|
|
207
|
+
.aboutBox{width:100%;border-radius:20px;padding:24px 20px 18px}
|
|
208
|
+
.aboutName{font-size:21px}
|
|
209
|
+
}
|
|
210
|
+
|
|
162
211
|
/* ===== 手机:点卡片 → 从下往上弹出信息栏(底部抽屉,铺满宽度) ===== */
|
|
163
212
|
@media (max-width:820px){
|
|
164
213
|
.side{
|
|
@@ -971,7 +1020,9 @@
|
|
|
971
1020
|
|
|
972
1021
|
<div class="wrap">
|
|
973
1022
|
<div class="col"> <div class="hd">
|
|
974
|
-
<h1 class="hdLogo"><
|
|
1023
|
+
<h1 class="hdLogo"><button class="hdLogoBtn" id="bAbout" type="button"
|
|
1024
|
+
aria-haspopup="dialog" aria-controls="about" aria-label="关于作者">
|
|
1025
|
+
<img src="./_wordmark.png" alt="Journey to the Rainbow"></button></h1>
|
|
975
1026
|
<div class="r">
|
|
976
1027
|
<button id="bKeys" title="快捷键(F 或 ?)" aria-label="快捷键">
|
|
977
1028
|
<svg viewBox="0 0 24 24"><rect x="2.5" y="6" width="19" height="12" rx="2.5"/><path d="M6.5 10h.01M10 10h.01M13.5 10h.01M17 10h.01M6.5 14h11"/></svg>
|
|
@@ -997,6 +1048,27 @@
|
|
|
997
1048
|
</div>
|
|
998
1049
|
</div>
|
|
999
1050
|
|
|
1051
|
+
<!-- ===== 作者页:同页浮层(不跳转、不开新页),沿用玻璃 + 彩虹 ===== -->
|
|
1052
|
+
<div class="about" id="about" role="dialog" aria-modal="true" aria-labelledby="aboutName">
|
|
1053
|
+
<div class="aboutBox" role="document">
|
|
1054
|
+
<div class="aboutTop"></div>
|
|
1055
|
+
<div class="aboutHead">
|
|
1056
|
+
<div class="aboutKicker">ABOUT</div>
|
|
1057
|
+
<div class="aboutName" id="aboutName">P-T-Miracle</div>
|
|
1058
|
+
<div class="aboutLine">Journey / 风雨彩虹的作者,做 DSH 上的项目监控。</div>
|
|
1059
|
+
</div>
|
|
1060
|
+
<div class="aboutRows">
|
|
1061
|
+
<div class="aboutRow"><span class="k">GitHub</span><span class="v"><a href="#" data-gh target="_blank" rel="noopener">github.com/P-T-Miracle</a></span></div>
|
|
1062
|
+
<div class="aboutRow"><span class="k">联系</span><span class="v"><a href="#" data-mail></a></span></div>
|
|
1063
|
+
<div class="aboutRow"><span class="k">项目</span><span class="v">Journey to the Rainbow · 单人任务值班台</span></div>
|
|
1064
|
+
</div>
|
|
1065
|
+
<div class="aboutFoot">
|
|
1066
|
+
<button class="aboutClose" id="aboutClose" type="button">关闭</button>
|
|
1067
|
+
<span class="aboutHint">Esc 关闭 · 点空白处也能关</span>
|
|
1068
|
+
</div>
|
|
1069
|
+
</div>
|
|
1070
|
+
</div>
|
|
1071
|
+
|
|
1000
1072
|
<section id="detail" class="hidden">
|
|
1001
1073
|
<div class="woodgrain"></div>
|
|
1002
1074
|
<div class="rbwipe" id="rbwipe"></div>
|
|
@@ -1038,6 +1110,8 @@
|
|
|
1038
1110
|
<button data-set="reduce" data-v="0" class="on">完整</button><button data-set="reduce" data-v="1">减弱</button></span></div>
|
|
1039
1111
|
<div class="srow"><span class="sl">毛玻璃</span><span class="seg sm">
|
|
1040
1112
|
<button data-set="glass" data-v="1" class="on">开</button><button data-set="glass" data-v="0">关</button></span></div>
|
|
1113
|
+
<div class="srow"><span class="sl">全屏</span><span class="seg sm">
|
|
1114
|
+
<button data-fs="1">开</button><button data-fs="0">关</button></span></div>
|
|
1041
1115
|
<div class="knote">只影响这台机器,设置存在浏览器本地;换电脑不会带走。<br><span id="buildTag" style="font-family:var(--mono);opacity:.7"></span></div>
|
|
1042
1116
|
</div>
|
|
1043
1117
|
</div>
|
|
@@ -1971,6 +2045,38 @@ function applyPref(){
|
|
|
1971
2045
|
try{ localStorage.setItem(PREFKEY, JSON.stringify(PREF)); }catch(e){}
|
|
1972
2046
|
}
|
|
1973
2047
|
document.getElementById('bSet').onclick = function(){ settingsBox.classList.add('on'); };
|
|
2048
|
+
/* ===== 全屏开关(设置第 3 项):一键把 DSH 左边那条会话栏也让出去 ===== */
|
|
2049
|
+
(function(){
|
|
2050
|
+
var btns = [].slice.call(settingsBox.querySelectorAll('[data-fs]'));
|
|
2051
|
+
if (!btns.length) return;
|
|
2052
|
+
function isFs(){ return !!(document.fullscreenElement || document.webkitFullscreenElement); }
|
|
2053
|
+
function sync(){
|
|
2054
|
+
var on = isFs();
|
|
2055
|
+
btns.forEach(function(b){
|
|
2056
|
+
b.classList.toggle('on', (b.getAttribute('data-fs') === '1') === on);
|
|
2057
|
+
});
|
|
2058
|
+
}
|
|
2059
|
+
function enter(){
|
|
2060
|
+
var el = document.documentElement;
|
|
2061
|
+
var p = el.requestFullscreen ? el.requestFullscreen()
|
|
2062
|
+
: el.webkitRequestFullscreen ? el.webkitRequestFullscreen() : null;
|
|
2063
|
+
if (p && p.then) p.then(sync).catch(sync);
|
|
2064
|
+
}
|
|
2065
|
+
function exit(){
|
|
2066
|
+
var p = document.exitFullscreen ? document.exitFullscreen()
|
|
2067
|
+
: document.webkitExitFullscreen ? document.webkitExitFullscreen() : null;
|
|
2068
|
+
if (p && p.then) p.then(sync).catch(sync);
|
|
2069
|
+
}
|
|
2070
|
+
btns.forEach(function(b){
|
|
2071
|
+
b.addEventListener('click', function(){
|
|
2072
|
+
if (b.getAttribute('data-fs') === '1') enter(); else exit();
|
|
2073
|
+
});
|
|
2074
|
+
});
|
|
2075
|
+
['fullscreenchange','webkitfullscreenchange'].forEach(function(ev){
|
|
2076
|
+
document.addEventListener(ev, sync);
|
|
2077
|
+
});
|
|
2078
|
+
sync();
|
|
2079
|
+
})();
|
|
1974
2080
|
settingsBox.onclick = function(e){
|
|
1975
2081
|
var b = e.target.closest('[data-set]');
|
|
1976
2082
|
if (b){ PREF[b.getAttribute('data-set')] = b.getAttribute('data-v'); applyPref(); return; }
|
|
@@ -2070,6 +2176,54 @@ render();
|
|
|
2070
2176
|
setTimeout(openSheet, 60); /* 等 renderSide 把内容填好再弹 */
|
|
2071
2177
|
}, true);
|
|
2072
2178
|
})();
|
|
2179
|
+
/* ===== 作者页:点击标题打开(同页浮层,不跳转)===== */
|
|
2180
|
+
(function(){
|
|
2181
|
+
var btn = document.getElementById('bAbout');
|
|
2182
|
+
var box = document.getElementById('about');
|
|
2183
|
+
var closeBtn = document.getElementById('aboutClose');
|
|
2184
|
+
if (!btn || !box || !closeBtn) return;
|
|
2185
|
+
var lastFocus = null;
|
|
2186
|
+
|
|
2187
|
+
/* GitHub 地址在运行时拼出来:写成字面量 URL 会被隐私遮挡层吃掉,变成一个占位符 */
|
|
2188
|
+
[].forEach.call(box.querySelectorAll('a[data-gh]'), function(a){
|
|
2189
|
+
a.href = 'https' + '://' + 'github' + '.com' + '/P-T-Miracle';
|
|
2190
|
+
});
|
|
2191
|
+
/* 邮箱同理:文本和 href 都在运行时拼,避免文件里出现字面量被遮罩替换 */
|
|
2192
|
+
[].forEach.call(box.querySelectorAll('a[data-mail]'), function(a){
|
|
2193
|
+
var local = '1822' + '2021' + '701'; /* 分片拼接:整串会被隐私层识别 */
|
|
2194
|
+
var addr = local + String.fromCharCode(64) + '163' + '.com';
|
|
2195
|
+
a.textContent = addr;
|
|
2196
|
+
a.href = 'mail' + 'to:' + addr;
|
|
2197
|
+
});
|
|
2198
|
+
|
|
2199
|
+
function open(){
|
|
2200
|
+
lastFocus = document.activeElement;
|
|
2201
|
+
box.classList.add('on');
|
|
2202
|
+
btn.setAttribute('aria-expanded', 'true');
|
|
2203
|
+
setTimeout(function(){ closeBtn.focus(); }, 30);
|
|
2204
|
+
}
|
|
2205
|
+
function close(){
|
|
2206
|
+
box.classList.remove('on');
|
|
2207
|
+
btn.setAttribute('aria-expanded', 'false');
|
|
2208
|
+
/* 焦点回到“打开它的那个东西”;如果上次焦点就在浮层里(比如关闭键),回到标题按钮 */
|
|
2209
|
+
var back = (lastFocus && lastFocus !== document.body && !box.contains(lastFocus)) ? lastFocus : btn;
|
|
2210
|
+
if (back && back.focus) back.focus();
|
|
2211
|
+
}
|
|
2212
|
+
btn.addEventListener('click', function(e){ e.preventDefault(); open(); });
|
|
2213
|
+
closeBtn.addEventListener('click', close);
|
|
2214
|
+
/* 点浮层空白(不是白色卡片本身)也关 */
|
|
2215
|
+
box.addEventListener('click', function(e){
|
|
2216
|
+
if (e.target.closest('.aboutBox')) return;
|
|
2217
|
+
close();
|
|
2218
|
+
});
|
|
2219
|
+
/* Esc 关;顺带把 A 做成快捷键(和 R/S/F 一组) */
|
|
2220
|
+
document.addEventListener('keydown', function(e){
|
|
2221
|
+
if (e.key === 'Escape' && box.classList.contains('on')){ close(); return; }
|
|
2222
|
+
var t = e.target;
|
|
2223
|
+
var typing = t && t.closest && t.closest('input,textarea,[contenteditable]');
|
|
2224
|
+
if (!typing && (e.key === 'a' || e.key === 'A') && !box.classList.contains('on')) open();
|
|
2225
|
+
});
|
|
2226
|
+
})();
|
|
2073
2227
|
/* 列表滚起来才给页头/状态带上雾(静止时全透明,开页看不到任何白带) */
|
|
2074
2228
|
(function(){
|
|
2075
2229
|
var col = document.querySelector('.col');
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { buildMappedJourneyData } from '../lib/journey-data.js';
|
|
2
|
+
|
|
3
|
+
const args = process.argv.slice(2);
|
|
4
|
+
const get = (name, fallback = '') => {
|
|
5
|
+
const i = args.indexOf(`--${name}`);
|
|
6
|
+
return i >= 0 && args[i + 1] ? args[i + 1] : fallback;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const data = buildMappedJourneyData({
|
|
10
|
+
stateRoot: get('state-root', `${process.env.USERPROFILE}\\.dsh\\wind-chain`),
|
|
11
|
+
projectRoot: get('project-root', 'D:\\deepseek_work\\Z07_疾风连环'),
|
|
12
|
+
auditLimit: Number(get('audit-limit', '8')),
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
process.stdout.write(`${JSON.stringify(data, null, 2)}\n`);
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* 按用户给的信息建卡片。
|
|
4
|
+
* 用法:node scripts/make-cards.mjs <目标目录> <cards.json>
|
|
5
|
+
*
|
|
6
|
+
* cards.json:
|
|
7
|
+
* {
|
|
8
|
+
* "cards": [
|
|
9
|
+
* {
|
|
10
|
+
* "id": "P13",
|
|
11
|
+
* "title": "天气角标",
|
|
12
|
+
* "status": "running", // running | paused | done
|
|
13
|
+
* "current": "主流程跑通;正在补细节",
|
|
14
|
+
* "blocker": "无",
|
|
15
|
+
* "plan": [
|
|
16
|
+
* { "stage": "阶段 1 打底", "items": [["明确输入输出", true], ["跑通最小流程", true]] },
|
|
17
|
+
* { "stage": "阶段 2 做出来", "items": [["补主功能", false]] }
|
|
18
|
+
* ]
|
|
19
|
+
* }
|
|
20
|
+
* ]
|
|
21
|
+
* }
|
|
22
|
+
*/
|
|
23
|
+
import fs from 'node:fs';
|
|
24
|
+
import path from 'node:path';
|
|
25
|
+
|
|
26
|
+
const target = process.argv[2];
|
|
27
|
+
const jsonFile = process.argv[3];
|
|
28
|
+
if (!target || !jsonFile) {
|
|
29
|
+
console.error('用法:node scripts/make-cards.mjs <目标目录> <cards.json>');
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
const doc = JSON.parse(fs.readFileSync(jsonFile, 'utf8'));
|
|
33
|
+
const cards = Array.isArray(doc?.cards) ? doc.cards : [];
|
|
34
|
+
if (!cards.length) {
|
|
35
|
+
console.error('cards.json 里没有 cards 数组');
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
fs.mkdirSync(target, { recursive: true });
|
|
39
|
+
|
|
40
|
+
for (const c of cards) {
|
|
41
|
+
const id = String(c.id || '').trim();
|
|
42
|
+
const title = String(c.title || '').trim();
|
|
43
|
+
if (!id || !title) {
|
|
44
|
+
console.error('每张卡至少要有 id 和 title');
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
const status = ['running', 'paused', 'done'].includes(c.status) ? c.status : 'running';
|
|
48
|
+
const current = String(c.current || '暂无');
|
|
49
|
+
const blocker = String(c.blocker || '无');
|
|
50
|
+
const dir = path.join(target, `${id}_${title}`);
|
|
51
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
52
|
+
|
|
53
|
+
fs.writeFileSync(path.join(dir, 'README.md'), `# ${title}\n\n## 问题\n\n${current}\n`, 'utf8');
|
|
54
|
+
fs.writeFileSync(path.join(dir, '状态.md'), `# 状态 · ${id}_${title}\n\n> 每次收工覆盖写,不追加;五字段\n\n当前阶段:${current}\n最近一次动作:按用户提供的信息录入\n下一步:按计划继续\n卡点:${blocker}\n最后更新:${new Date().toISOString().slice(0, 10)}\n`, 'utf8');
|
|
55
|
+
|
|
56
|
+
const plan = Array.isArray(c.plan) && c.plan.length ? c.plan : [];
|
|
57
|
+
const lines = [`# 计划 · ${id}_${title}`, '', '```'];
|
|
58
|
+
for (const stage of plan) {
|
|
59
|
+
lines.push(String(stage.stage || '阶段'));
|
|
60
|
+
for (const item of (Array.isArray(stage.items) ? stage.items : [])) {
|
|
61
|
+
const [text, done] = Array.isArray(item) ? item : [item, false];
|
|
62
|
+
lines.push(` [${done ? 'x' : ' '}] ${text}`);
|
|
63
|
+
}
|
|
64
|
+
lines.push('');
|
|
65
|
+
}
|
|
66
|
+
lines.push('```');
|
|
67
|
+
fs.writeFileSync(path.join(dir, '计划.md'), lines.join('\n'), 'utf8');
|
|
68
|
+
console.log(` ${id}_${title} ${status}`);
|
|
69
|
+
}
|
|
70
|
+
console.log(`已按用户信息生成 ${cards.length} 张卡:${target}`);
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* 批量生成 Journey 演示项目。
|
|
4
|
+
* 用法:node scripts/make-demo.mjs <目标目录> [数量,默认 12]
|
|
5
|
+
* 生成:每个项目 README.md / 状态.md / 计划.md
|
|
6
|
+
*/
|
|
7
|
+
import fs from 'node:fs';
|
|
8
|
+
import path from 'node:path';
|
|
9
|
+
|
|
10
|
+
const target = process.argv[2];
|
|
11
|
+
const count = Math.max(1, Math.min(24, Number(process.argv[3] || 12)));
|
|
12
|
+
if (!target) {
|
|
13
|
+
console.error('用法:node scripts/make-demo.mjs <目标目录> [数量]');
|
|
14
|
+
process.exit(1);
|
|
15
|
+
}
|
|
16
|
+
fs.mkdirSync(target, { recursive: true });
|
|
17
|
+
|
|
18
|
+
const names = [
|
|
19
|
+
'潮汐表', '词根', '雨声', '书签整理', '错题地图', '播客剪辑',
|
|
20
|
+
'植物图鉴', '旧照片修复', '单词卡', '菜谱索引', '地铁换乘', '雨声混音',
|
|
21
|
+
'天气角标', '票据归档', '步数地图', '菜谱语音', '课程笔记', '桌面收纳',
|
|
22
|
+
'方言词典', '睡眠记录', '书摘卡片', '路线收藏', '图片压缩', '读书清单',
|
|
23
|
+
];
|
|
24
|
+
const states = ['running', 'paused', 'done'];
|
|
25
|
+
|
|
26
|
+
for (let i = 0; i < count; i += 1) {
|
|
27
|
+
const id = `P${String(i + 1).padStart(2, '0')}`;
|
|
28
|
+
const name = names[i % names.length];
|
|
29
|
+
const status = states[i % states.length];
|
|
30
|
+
const dir = path.join(target, `${id}_${name}`);
|
|
31
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
32
|
+
|
|
33
|
+
const current = status === 'done'
|
|
34
|
+
? '已完成,产物在 dist\\'
|
|
35
|
+
: status === 'paused'
|
|
36
|
+
? '主流程跑通;等确认范围'
|
|
37
|
+
: '主流程跑通;正在补细节';
|
|
38
|
+
const blocker = status === 'done' ? '无' : status === 'paused' ? '等你定范围' : '无';
|
|
39
|
+
|
|
40
|
+
fs.writeFileSync(path.join(dir, 'README.md'), `# ${name}
|
|
41
|
+
|
|
42
|
+
## 问题
|
|
43
|
+
|
|
44
|
+
给 ${id} 做一个小工具,先跑通最小流程。
|
|
45
|
+
|
|
46
|
+
## 到哪一步
|
|
47
|
+
|
|
48
|
+
${current}
|
|
49
|
+
`, 'utf8');
|
|
50
|
+
|
|
51
|
+
fs.writeFileSync(path.join(dir, '状态.md'), `# 状态 · ${id}_${name}
|
|
52
|
+
|
|
53
|
+
> 每次收工覆盖写,不追加;五字段
|
|
54
|
+
|
|
55
|
+
当前阶段:${current}
|
|
56
|
+
最近一次动作:今天推进了一步
|
|
57
|
+
下一步:按计划继续
|
|
58
|
+
卡点:${blocker}
|
|
59
|
+
最后更新:${new Date().toISOString().slice(0, 10)}
|
|
60
|
+
`, 'utf8');
|
|
61
|
+
|
|
62
|
+
fs.writeFileSync(path.join(dir, '计划.md'), `# 计划 · ${id}_${name}
|
|
63
|
+
|
|
64
|
+
\`\`\`
|
|
65
|
+
阶段 1 打底
|
|
66
|
+
[x] 明确输入输出
|
|
67
|
+
[${status === 'paused' ? ' ' : 'x'}] 跑通最小流程
|
|
68
|
+
|
|
69
|
+
阶段 2 做出来
|
|
70
|
+
[ ] 补主功能
|
|
71
|
+
[ ] 补边界情况
|
|
72
|
+
|
|
73
|
+
阶段 3 收口
|
|
74
|
+
[${status === 'done' ? 'x' : ' '}] 写 README
|
|
75
|
+
[ ] 导出可用版本
|
|
76
|
+
\`\`\`
|
|
77
|
+
`, 'utf8');
|
|
78
|
+
console.log(` ${id}_${name} ${status}`);
|
|
79
|
+
}
|
|
80
|
+
console.log(`已生成 ${count} 个演示项目:${target}`);
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
# P01 潮汐表
|
|
2
|
-
|
|
3
|
-
> 示例项目(虚构)。用于演示"**在跑**"状态。
|
|
4
|
-
|
|
5
|
-
## 问题
|
|
6
|
-
|
|
7
|
-
去海边之前要查潮汐,每次都要在网页上翻半天,还带广告。
|
|
8
|
-
|
|
9
|
-
## 方案
|
|
10
|
-
|
|
11
|
-
桌面小工具:读一份离线潮汐表,按日期输出当日高低潮两行。
|
|
12
|
-
|
|
13
|
-
## 怎么跑
|
|
14
|
-
|
|
15
|
-
```
|
|
16
|
-
python tide.py --date 2026-11-13
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
## 到哪一步
|
|
20
|
-
|
|
21
|
-
解析器写完了,正在做命令行输出。
|
|
22
|
-
|
|
23
|
-
## 不做什么
|
|
24
|
-
|
|
25
|
-
```
|
|
26
|
-
· 不做图形界面
|
|
27
|
-
· 不联网(数据是离线表)
|
|
28
|
-
```
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
# P02 词根
|
|
2
|
-
|
|
3
|
-
> 示例项目(虚构)。用于演示"**停住、等我回一句话**"状态。
|
|
4
|
-
|
|
5
|
-
## 问题
|
|
6
|
-
|
|
7
|
-
背单词总在同一个词根上反复栽,散着背记不住。
|
|
8
|
-
|
|
9
|
-
## 方案
|
|
10
|
-
|
|
11
|
-
按词根聚类整理,做成可打印的单页——一页纸看完一批。
|
|
12
|
-
|
|
13
|
-
## 怎么跑
|
|
14
|
-
|
|
15
|
-
```
|
|
16
|
-
打开 词根.html(单文件,无依赖)
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
## 到哪一步
|
|
20
|
-
|
|
21
|
-
数据整理完了,**卡在一个决定上**:收录范围没定,写下去会返工。
|
|
22
|
-
|
|
23
|
-
## 不做什么
|
|
24
|
-
|
|
25
|
-
```
|
|
26
|
-
· 不做背单词 App
|
|
27
|
-
· 不做记忆曲线
|
|
28
|
-
```
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
# P03 雨声
|
|
2
|
-
|
|
3
|
-
> 示例项目(虚构)。用于演示"**已结束**"状态。
|
|
4
|
-
|
|
5
|
-
## 问题
|
|
6
|
-
|
|
7
|
-
写东西的时候需要稳定白噪音,现成的播放器都带广告、带推荐。
|
|
8
|
-
|
|
9
|
-
## 方案
|
|
10
|
-
|
|
11
|
-
循环播放一段 30 秒雨声,没有界面,只有托盘图标。
|
|
12
|
-
|
|
13
|
-
## 怎么跑
|
|
14
|
-
|
|
15
|
-
```
|
|
16
|
-
dist\rain.exe
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
## 到哪一步
|
|
20
|
-
|
|
21
|
-
做完了,已归档。
|
|
22
|
-
|
|
23
|
-
## 不做什么
|
|
24
|
-
|
|
25
|
-
```
|
|
26
|
-
· 不做歌单
|
|
27
|
-
· 不做在线音源
|
|
28
|
-
```
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
# 说明 · 演示工作区
|
|
2
|
-
|
|
3
|
-
> 用途:社团演示只跑这个目录 | 建:2026-11-13 | 归属:A07
|
|
4
|
-
> 性质:**纯示例**。三个虚构项目,不含任何真实项目、日志、隐私
|
|
5
|
-
|
|
6
|
-
## 为什么要有这个
|
|
7
|
-
|
|
8
|
-
自用工作区 `D:\deepseek_work` 里有真实项目、日志和隐私,**不能拿去演示**。
|
|
9
|
-
插件必须把"工作区路径"当参数(见 `技术资料\疾风连环_与工作站的关系.md` §6),
|
|
10
|
-
于是我们给它一个干净的小目录:插件装好那一刻,指向这里就能开演。
|
|
11
|
-
|
|
12
|
-
## 里面有什么
|
|
13
|
-
|
|
14
|
-
```
|
|
15
|
-
P01_潮汐表 在跑 演"它正在干什么"
|
|
16
|
-
P02_词根 等我说一句 演"为什么停"和"说一句话就能继续"
|
|
17
|
-
P03_雨声 结束 演"收口长什么样"
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
三个项目在面板上的样子:`◎` 在跑 / `○` 空闲(含"等我"与"已结束")。
|
|
21
|
-
**v362 没有单独的"结束"标记**——救星查 A16 记录确认,三态是 NEW / 在跑 / 空闲。
|
|
22
|
-
所以 P03 会落在"空闲"组里,靠卡片第一句"已结束,无需处理"表达收口,不靠形状区分。
|
|
23
|
-
演示脚本 §3 的动线就是照这三张卡排的。
|
|
24
|
-
|
|
25
|
-
## 每个项目固定三件
|
|
26
|
-
|
|
27
|
-
```
|
|
28
|
-
README.md 问题 / 方案 / 怎么跑 / 到哪一步
|
|
29
|
-
状态.md 五字段(当前阶段 / 最近动作 / 下一步 / 卡点 / 最后更新)
|
|
30
|
-
计划.md 阶段 + 勾选 + ← 下一步
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
## 和插件的关系
|
|
34
|
-
|
|
35
|
-
```
|
|
36
|
-
· 插件的工作区路径指向本目录,不指向 D:\deepseek_work
|
|
37
|
-
· 数据格式以插件定稿为准;计划.md 是我方提议格式,
|
|
38
|
-
若插件定了别的 schema,只改这类文件,不动其他
|
|
39
|
-
· 目录名前缀(P0x)如需改成 A/Z,只改文件夹名
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
## 三条规矩
|
|
43
|
-
|
|
44
|
-
```
|
|
45
|
-
· 不往这里拷真实材料(一拷就污染,下次演示还得重来)
|
|
46
|
-
· 演示前先跑一遍:三个状态都要对得上
|
|
47
|
-
· 演完不删,下次彩排还要用
|
|
48
|
-
```
|