superlab 0.1.6 → 0.1.8
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 +90 -16
- package/README.zh-CN.md +89 -14
- package/bin/superlab.cjs +242 -1
- package/lib/context.cjs +337 -0
- package/lib/i18n.cjs +673 -41
- package/lib/install.cjs +249 -51
- package/package-assets/claude/commands/lab/framing.md +11 -0
- package/package-assets/claude/commands/lab/idea.md +2 -1
- package/package-assets/claude/commands/lab/iterate.md +2 -1
- package/package-assets/claude/commands/lab/report.md +2 -1
- package/package-assets/claude/commands/lab/review.md +2 -1
- package/package-assets/claude/commands/lab/run.md +2 -1
- package/package-assets/claude/commands/lab/spec.md +2 -1
- package/package-assets/claude/commands/lab/write.md +2 -1
- package/package-assets/codex/prompts/lab-framing.md +9 -0
- package/package-assets/codex/prompts/lab-idea.md +2 -1
- package/package-assets/codex/prompts/lab-iterate.md +2 -1
- package/package-assets/codex/prompts/lab-report.md +2 -1
- package/package-assets/codex/prompts/lab-review.md +2 -1
- package/package-assets/codex/prompts/lab-run.md +2 -1
- package/package-assets/codex/prompts/lab-spec.md +2 -1
- package/package-assets/codex/prompts/lab-write.md +2 -1
- package/package-assets/shared/{templates → lab/.managed/templates}/design.md +3 -3
- package/package-assets/shared/lab/.managed/templates/framing.md +66 -0
- package/package-assets/shared/{templates → lab/.managed/templates}/paper-plan.md +1 -0
- package/package-assets/shared/{templates → lab/.managed/templates}/proposal.md +1 -1
- package/package-assets/shared/{templates → lab/.managed/templates}/spec.md +2 -2
- package/package-assets/shared/{templates → lab/.managed/templates}/tasks.md +2 -2
- package/package-assets/shared/{templates → lab/.managed/templates}/write-iteration.md +1 -0
- package/package-assets/shared/lab/changes/README.md +10 -0
- package/package-assets/shared/lab/config/workflow.json +6 -0
- package/package-assets/shared/lab/context/next-action.md +19 -0
- package/package-assets/shared/lab/context/session-brief.md +30 -0
- package/package-assets/shared/lab/context/summary.md +21 -0
- package/package-assets/shared/lab/context/terminology-lock.md +27 -0
- package/package-assets/shared/lab/system/core.md +41 -0
- package/package-assets/shared/skills/lab/SKILL.md +54 -37
- package/package-assets/shared/skills/lab/references/paper-writing/abstract.md +2 -17
- package/package-assets/shared/skills/lab/references/paper-writing/introduction.md +3 -63
- package/package-assets/shared/skills/lab/references/paper-writing/method.md +4 -34
- package/package-assets/shared/skills/lab/references/workflow.md +4 -4
- package/package-assets/shared/skills/lab/stages/framing.md +70 -0
- package/package-assets/shared/skills/lab/stages/idea.md +5 -5
- package/package-assets/shared/skills/lab/stages/iterate.md +8 -8
- package/package-assets/shared/skills/lab/stages/report.md +7 -6
- package/package-assets/shared/skills/lab/stages/review.md +6 -5
- package/package-assets/shared/skills/lab/stages/run.md +4 -4
- package/package-assets/shared/skills/lab/stages/spec.md +11 -11
- package/package-assets/shared/skills/lab/stages/write.md +14 -10
- package/package.json +1 -1
- package/package-assets/shared/changes/README.md +0 -10
- package/package-assets/shared/config/workflow.json +0 -5
- package/package-assets/shared/examples/minimal-uplift-workflow.md +0 -73
- /package/package-assets/shared/{scripts → lab/.managed/scripts}/eval_report.py +0 -0
- /package/package-assets/shared/{scripts → lab/.managed/scripts}/register_run.py +0 -0
- /package/package-assets/shared/{scripts → lab/.managed/scripts}/summarize_iterations.py +0 -0
- /package/package-assets/shared/{scripts → lab/.managed/scripts}/validate_results.py +0 -0
- /package/package-assets/shared/{templates → lab/.managed/templates}/final-report.md +0 -0
- /package/package-assets/shared/{templates → lab/.managed/templates}/idea.md +0 -0
- /package/package-assets/shared/{templates → lab/.managed/templates}/iteration-report.md +0 -0
- /package/package-assets/shared/{templates → lab/.managed/templates}/paper-section.md +0 -0
- /package/package-assets/shared/{templates → lab/.managed/templates}/paper-section.tex +0 -0
- /package/package-assets/shared/{templates → lab/.managed/templates}/paper.tex +0 -0
- /package/package-assets/shared/{templates → lab/.managed/templates}/review-checklist.md +0 -0
- /package/package-assets/shared/{context → lab/context}/decisions.md +0 -0
- /package/package-assets/shared/{context → lab/context}/evidence-index.md +0 -0
- /package/package-assets/shared/{context → lab/context}/mission.md +0 -0
- /package/package-assets/shared/{context → lab/context}/open-questions.md +0 -0
- /package/package-assets/shared/{context → lab/context}/state.md +0 -0
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ It combines:
|
|
|
8
8
|
|
|
9
9
|
- command adapters for Codex and Claude
|
|
10
10
|
- a shared `/lab` skill with stage-specific rules
|
|
11
|
-
- lab-native change artifacts under `.
|
|
11
|
+
- lab-native change artifacts under `.lab/changes/`
|
|
12
12
|
- bounded Ralph Wiggum style iteration for experiments
|
|
13
13
|
- helper scripts for run registration and evaluation summaries
|
|
14
14
|
|
|
@@ -22,6 +22,8 @@ cd your-project
|
|
|
22
22
|
superlab init
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
+
After `init` or `update`, start a new Codex or Claude session. If the new `/lab:*` commands still do not show up, restart the app.
|
|
26
|
+
|
|
25
27
|
If the package has not been published yet, install from GitHub instead:
|
|
26
28
|
|
|
27
29
|
```bash
|
|
@@ -45,11 +47,14 @@ This writes:
|
|
|
45
47
|
- `.codex/skills/lab/`
|
|
46
48
|
- `.claude/commands/lab/*.md`
|
|
47
49
|
- `.claude/skills/lab/`
|
|
48
|
-
-
|
|
49
|
-
-
|
|
50
|
-
- `.
|
|
51
|
-
- `.
|
|
52
|
-
- `.
|
|
50
|
+
- `AGENTS.md`
|
|
51
|
+
- `CLAUDE.md`
|
|
52
|
+
- `.lab/system/core.md`
|
|
53
|
+
- `.lab/config/workflow.json`
|
|
54
|
+
- `.lab/context/`
|
|
55
|
+
- `.lab/changes/`
|
|
56
|
+
- `.lab/.managed/templates/`
|
|
57
|
+
- `.lab/.managed/scripts/`
|
|
53
58
|
|
|
54
59
|
If you prefer non-interactive use:
|
|
55
60
|
|
|
@@ -88,7 +93,70 @@ Refresh every registered project initialized from this user account:
|
|
|
88
93
|
superlab update --all-projects
|
|
89
94
|
```
|
|
90
95
|
|
|
91
|
-
`superlab init` writes `.
|
|
96
|
+
`superlab init` writes `.lab/.managed/install.json` inside each project and registers the project in the user-level registry so `update --all-projects` knows what to refresh.
|
|
97
|
+
|
|
98
|
+
Legacy projects from older `superlab` versions may already contain `.codex/`, `.claude/`, or `.superlab/` assets without `.lab/.managed/install.json`. `superlab update` now reconstructs that metadata and upgrades the project in place.
|
|
99
|
+
|
|
100
|
+
## Context Tools
|
|
101
|
+
|
|
102
|
+
Refresh the compressed handoff layer from live project context:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
superlab context refresh
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Prune resolved or stale active-context entries:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
superlab context prune
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Archive cold iteration and writing history:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
superlab context archive
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Print the minimal handoff bundle for a new AI session:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
superlab handoff
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Check that the managed `.lab` layout is healthy:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
superlab doctor
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
`doctor` validates:
|
|
133
|
+
|
|
134
|
+
- required `.lab` files
|
|
135
|
+
- `workflow.json` schema
|
|
136
|
+
- `deliverables_root` placement
|
|
137
|
+
- LaTeX-first paper output layout under `<deliverables_root>/paper/`
|
|
138
|
+
|
|
139
|
+
## Version
|
|
140
|
+
|
|
141
|
+
Show the CLI version and the current project asset version:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
superlab version
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Show only the current project asset version:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
superlab version --project
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Show a specific project:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
superlab version --target /path/to/project
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
If a project still uses an older pre-metadata installation, `superlab version` reports `project: legacy` until you run `superlab update`.
|
|
92
160
|
|
|
93
161
|
## Language
|
|
94
162
|
|
|
@@ -101,11 +169,12 @@ superlab init --lang zh
|
|
|
101
169
|
superlab init --lang en
|
|
102
170
|
```
|
|
103
171
|
|
|
104
|
-
This installer also writes `.
|
|
172
|
+
This installer also writes `.lab/config/workflow.json`, which is the global contract for:
|
|
105
173
|
|
|
106
174
|
- `workflow_language`
|
|
107
175
|
- `paper_language`
|
|
108
176
|
- `paper_format`
|
|
177
|
+
- `deliverables_root`
|
|
109
178
|
|
|
110
179
|
Stages should follow that file rather than guess language locally.
|
|
111
180
|
|
|
@@ -120,12 +189,14 @@ Stages should follow that file rather than guess language locally.
|
|
|
120
189
|
## Command Set
|
|
121
190
|
|
|
122
191
|
- `/lab:idea` researches an idea, critiques it, and writes the initial research framing.
|
|
123
|
-
- `/lab:
|
|
192
|
+
- `/lab:framing` locks paper-facing method names, module names, titles, and contribution wording before drafting.
|
|
193
|
+
- `/lab:spec` converts the approved idea into one `.lab/changes/<change-id>/` directory.
|
|
124
194
|
- `/lab:run` executes a small-scale validation run and establishes the evaluation pipeline.
|
|
125
195
|
- `/lab:iterate` runs bounded experiment loops with fixed mission, explicit thresholds, and per-round reports.
|
|
126
196
|
- `/lab:review` audits documents and results in reviewer mode.
|
|
127
197
|
- `/lab:report` produces the final report from accumulated artifacts.
|
|
128
198
|
- `/lab:write` converts stable report artifacts into paper sections through small writing rounds.
|
|
199
|
+
It requires an approved `/lab:framing` artifact before drafting.
|
|
129
200
|
It reads vendored section references derived from `Research-Paper-Writing-Skills`.
|
|
130
201
|
|
|
131
202
|
See the source command docs in [commands/codex/lab.md](/Users/zhouhao119/coding/write/commands/codex/lab.md) and [commands/claude/lab.md](/Users/zhouhao119/coding/write/commands/claude/lab.md). The npm package installs real command assets from `package-assets/`.
|
|
@@ -139,7 +210,7 @@ See the source command docs in [commands/codex/lab.md](/Users/zhouhao119/coding/
|
|
|
139
210
|
- `scripts/` contains reproducibility helpers.
|
|
140
211
|
- `tests/` contains minimal regression coverage for the helper scripts.
|
|
141
212
|
- `examples/` contains a minimal end-to-end usage example.
|
|
142
|
-
- `docs/` contains the design spec and
|
|
213
|
+
- `docs/` contains the design spec and release notes.
|
|
143
214
|
|
|
144
215
|
## Typical Flow
|
|
145
216
|
|
|
@@ -149,17 +220,20 @@ See the source command docs in [commands/codex/lab.md](/Users/zhouhao119/coding/
|
|
|
149
220
|
4. Run `/lab:iterate` to improve against fixed targets using bounded iterations.
|
|
150
221
|
5. Run `/lab:review` whenever you need reviewer-grade critique.
|
|
151
222
|
6. Run `/lab:report` to synthesize the final report.
|
|
152
|
-
7. Run `/lab:
|
|
223
|
+
7. Run `/lab:framing` to lock naming, title, and contribution wording.
|
|
224
|
+
8. Run `/lab:write` to draft paper sections from stable report evidence.
|
|
153
225
|
|
|
154
|
-
`/lab:write` writes final manuscript output
|
|
226
|
+
`/lab:write` writes final manuscript output under the configured `deliverables_root` (default: `docs/research`):
|
|
155
227
|
|
|
156
|
-
- `docs/
|
|
157
|
-
- `docs/paper/
|
|
228
|
+
- `docs/research/report.md`
|
|
229
|
+
- `docs/research/paper/main.tex`
|
|
230
|
+
- `docs/research/paper/sections/*.tex`
|
|
158
231
|
|
|
159
232
|
Internal writing-control artifacts stay under:
|
|
160
233
|
|
|
161
|
-
- `.
|
|
162
|
-
- `.
|
|
234
|
+
- `.lab/writing/framing.md`
|
|
235
|
+
- `.lab/writing/plan.md`
|
|
236
|
+
- `.lab/writing/iterations/*.md`
|
|
163
237
|
|
|
164
238
|
## Helper Scripts
|
|
165
239
|
|
package/README.zh-CN.md
CHANGED
|
@@ -20,6 +20,8 @@ cd your-project
|
|
|
20
20
|
superlab init
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
+
执行完 `init` 或 `update` 后,请新开一个 Codex 或 Claude 会话;如果新的 `/lab:*` 命令仍未生效,再重启应用。
|
|
24
|
+
|
|
23
25
|
如果 npm 还没发布,也可以直接从 GitHub 安装:
|
|
24
26
|
|
|
25
27
|
```bash
|
|
@@ -43,11 +45,14 @@ npx github:zhouhaoUCAS/superlab init
|
|
|
43
45
|
- `.codex/skills/lab/`
|
|
44
46
|
- `.claude/commands/lab/*.md`
|
|
45
47
|
- `.claude/skills/lab/`
|
|
46
|
-
-
|
|
47
|
-
-
|
|
48
|
-
- `.
|
|
49
|
-
- `.
|
|
50
|
-
- `.
|
|
48
|
+
- `AGENTS.md`
|
|
49
|
+
- `CLAUDE.md`
|
|
50
|
+
- `.lab/system/core.md`
|
|
51
|
+
- `.lab/config/workflow.json`
|
|
52
|
+
- `.lab/context/`
|
|
53
|
+
- `.lab/changes/`
|
|
54
|
+
- `.lab/.managed/templates/`
|
|
55
|
+
- `.lab/.managed/scripts/`
|
|
51
56
|
|
|
52
57
|
如果你更喜欢非交互方式,也可以直接传参:
|
|
53
58
|
|
|
@@ -86,7 +91,70 @@ superlab update --target /path/to/project
|
|
|
86
91
|
superlab update --all-projects
|
|
87
92
|
```
|
|
88
93
|
|
|
89
|
-
`superlab init` 会在项目内写入 `.
|
|
94
|
+
`superlab init` 会在项目内写入 `.lab/.managed/install.json`,并在用户级 registry 里登记项目路径,所以 `update --all-projects` 才知道要刷新哪些项目。
|
|
95
|
+
|
|
96
|
+
较老版本的 `superlab` 项目可能已经有 `.codex/`、`.claude/` 或 `.superlab/` 资产,但还没有 `.lab/.managed/install.json`。现在 `superlab update` 会自动重建这份 metadata,然后原地升级该项目。
|
|
97
|
+
|
|
98
|
+
## 上下文工具
|
|
99
|
+
|
|
100
|
+
根据当前项目上下文重建压缩后的 handoff 层:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
superlab context refresh
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
清理已解决或已过期的 active-context 内容:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
superlab context prune
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
把冷历史迭代和写作轮次归档出去:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
superlab context archive
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
输出新 AI 会话最小接手包:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
superlab handoff
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
检查当前 `.lab` 受管布局是否健康:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
superlab doctor
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
`doctor` 目前会校验:
|
|
131
|
+
|
|
132
|
+
- 必需的 `.lab` 文件是否存在
|
|
133
|
+
- `workflow.json` 结构是否合法
|
|
134
|
+
- `deliverables_root` 是否放在合理位置
|
|
135
|
+
- `<deliverables_root>/paper/` 下是否仍然满足 LaTeX-first 输出约束
|
|
136
|
+
|
|
137
|
+
## 版本查询
|
|
138
|
+
|
|
139
|
+
查看当前 CLI 版本和当前目录项目的资产版本:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
superlab version
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
只看当前项目资产版本:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
superlab version --project
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
查看指定项目:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
superlab version --target /path/to/project
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
如果项目还是旧的 pre-metadata 安装,`superlab version` 会显示 `project: legacy`;执行一次 `superlab update` 后就会切换到正式版本号。
|
|
90
158
|
|
|
91
159
|
## 语言
|
|
92
160
|
|
|
@@ -99,11 +167,12 @@ superlab init --lang zh
|
|
|
99
167
|
superlab init --lang en
|
|
100
168
|
```
|
|
101
169
|
|
|
102
|
-
安装器还会写入 `.
|
|
170
|
+
安装器还会写入 `.lab/config/workflow.json`。这个文件是全局约束,至少控制:
|
|
103
171
|
|
|
104
172
|
- `workflow_language`
|
|
105
173
|
- `paper_language`
|
|
106
174
|
- `paper_format`
|
|
175
|
+
- `deliverables_root`
|
|
107
176
|
|
|
108
177
|
后续 stage 应该按这个配置决定语言和论文格式,而不是各模板自己猜。
|
|
109
178
|
|
|
@@ -118,12 +187,14 @@ superlab init --lang en
|
|
|
118
187
|
## 命令集合
|
|
119
188
|
|
|
120
189
|
- `/lab:idea` 调研 idea、文献、数据集、指标和 baseline,并输出初始方案。
|
|
121
|
-
- `/lab:
|
|
190
|
+
- `/lab:framing` 在正式写作前收紧方法名、模块名、论文题目和 contribution wording。
|
|
191
|
+
- `/lab:spec` 把批准后的方案转换成一个统一的 `.lab/changes/<change-id>/` 目录。
|
|
122
192
|
- `/lab:run` 执行最小可运行实验,并建立首版评估链路。
|
|
123
193
|
- `/lab:iterate` 以固定 mission、固定阈值和最大轮次做有边界的实验迭代。
|
|
124
194
|
- `/lab:review` 以审稿人模式检查方法、对照、公平性、泄漏和统计问题。
|
|
125
195
|
- `/lab:report` 根据累积工件生成最终实验报告。
|
|
126
196
|
- `/lab:write` 把稳定的 report 工件转成论文 section,并按小步方式逐轮修改。
|
|
197
|
+
它要求先有一个经批准的 `/lab:framing` 工件。
|
|
127
198
|
它会读取随 `lab` 一起安装的 vendored 章节参考,这些参考来源于 `Research-Paper-Writing-Skills`。
|
|
128
199
|
|
|
129
200
|
## 使用流程
|
|
@@ -135,17 +206,20 @@ superlab init --lang en
|
|
|
135
206
|
5. 用 `/lab:iterate` 进行多轮迭代。
|
|
136
207
|
6. 在关键节点运行 `/lab:review`。
|
|
137
208
|
7. 最后用 `/lab:report` 产出总报告。
|
|
138
|
-
8. 用 `/lab:
|
|
209
|
+
8. 用 `/lab:framing` 收紧题目、命名和 contribution wording。
|
|
210
|
+
9. 用 `/lab:write` 把稳定结果写成论文各 section。
|
|
139
211
|
|
|
140
|
-
`/lab:write`
|
|
212
|
+
`/lab:write` 会把最终可交付物写到 `deliverables_root` 指定的目录,默认是 `docs/research`:
|
|
141
213
|
|
|
142
|
-
- `docs/
|
|
143
|
-
- `docs/paper/
|
|
214
|
+
- `docs/research/report.md`
|
|
215
|
+
- `docs/research/paper/main.tex`
|
|
216
|
+
- `docs/research/paper/sections/*.tex`
|
|
144
217
|
|
|
145
218
|
内部写作控制工件放在:
|
|
146
219
|
|
|
147
|
-
- `.
|
|
148
|
-
- `.
|
|
220
|
+
- `.lab/writing/framing.md`
|
|
221
|
+
- `.lab/writing/plan.md`
|
|
222
|
+
- `.lab/writing/iterations/*.md`
|
|
149
223
|
|
|
150
224
|
## 仓库内容
|
|
151
225
|
|
|
@@ -156,6 +230,7 @@ superlab init --lang en
|
|
|
156
230
|
- `scripts/` 是运行登记、评估汇总和结果校验脚本。
|
|
157
231
|
- `tests/` 是脚本与安装器测试。
|
|
158
232
|
- `examples/` 是最小端到端示例。
|
|
233
|
+
- `docs/` 存放设计文档和发布说明。
|
|
159
234
|
- `docs/release.md` 是发布到 npm 的操作说明。
|
|
160
235
|
- `.github/workflows/ci.yml` 会在 `main` 和 PR 上自动执行 `npm run release:check`。
|
|
161
236
|
- `.github/workflows/publish.yml` 支持在配置好 `NPM_TOKEN` 后手动从 GitHub Actions 发布到 npm。
|
package/bin/superlab.cjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
const fs = require("node:fs");
|
|
3
4
|
const path = require("node:path");
|
|
4
5
|
const {
|
|
5
6
|
PACKAGE_VERSION,
|
|
@@ -9,8 +10,20 @@ const {
|
|
|
9
10
|
updateAllProjects,
|
|
10
11
|
updateSuperlabProject,
|
|
11
12
|
} = require("../lib/install.cjs");
|
|
13
|
+
const {
|
|
14
|
+
archiveContext,
|
|
15
|
+
pruneContext,
|
|
16
|
+
refreshContext,
|
|
17
|
+
} = require("../lib/context.cjs");
|
|
12
18
|
const { promptSelect } = require("../lib/init_tui.cjs");
|
|
13
19
|
|
|
20
|
+
function restartReminder(lang) {
|
|
21
|
+
if (lang === "zh") {
|
|
22
|
+
return "项目资产已更新。请新开一个 Codex/Claude 会话;如果仍未生效,再重启应用。";
|
|
23
|
+
}
|
|
24
|
+
return "Project assets updated. Start a new Codex/Claude session; if changes still do not appear, restart the app.";
|
|
25
|
+
}
|
|
26
|
+
|
|
14
27
|
function printHelp() {
|
|
15
28
|
console.log(`superlab
|
|
16
29
|
|
|
@@ -20,12 +33,20 @@ Usage:
|
|
|
20
33
|
superlab update [--target <dir>]
|
|
21
34
|
superlab update --all-projects
|
|
22
35
|
superlab version [--target <dir>] [--global|--project]
|
|
36
|
+
superlab handoff [--target <dir>]
|
|
37
|
+
superlab doctor [--target <dir>]
|
|
38
|
+
superlab context refresh [--target <dir>]
|
|
39
|
+
superlab context prune [--target <dir>]
|
|
40
|
+
superlab context archive [--target <dir>]
|
|
23
41
|
|
|
24
42
|
Commands:
|
|
25
43
|
init Initialize /lab commands, skills, templates, and scripts in a target
|
|
26
44
|
install Backward-compatible alias for init
|
|
27
45
|
update Refresh an initialized project or all registered projects
|
|
28
46
|
version Show installed CLI version and project asset version
|
|
47
|
+
handoff Print the minimal context handoff bundle for a project
|
|
48
|
+
doctor Check project health for the managed .lab layout
|
|
49
|
+
context Maintain project context summaries and archives
|
|
29
50
|
help Show this help message
|
|
30
51
|
`);
|
|
31
52
|
}
|
|
@@ -121,6 +142,35 @@ function parseVersionArgs(argv) {
|
|
|
121
142
|
return options;
|
|
122
143
|
}
|
|
123
144
|
|
|
145
|
+
function parseTargetOnlyArgs(argv) {
|
|
146
|
+
const options = {
|
|
147
|
+
targetDir: process.cwd(),
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
151
|
+
const value = argv[index];
|
|
152
|
+
if (value === "--target") {
|
|
153
|
+
options.targetDir = path.resolve(argv[index + 1]);
|
|
154
|
+
index += 1;
|
|
155
|
+
} else {
|
|
156
|
+
throw new Error(`Unknown option: ${value}`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return options;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function parseContextArgs(argv) {
|
|
164
|
+
const [action, ...rest] = argv;
|
|
165
|
+
if (!["refresh", "prune", "archive"].includes(action || "")) {
|
|
166
|
+
throw new Error(`Unknown context action: ${action || "(missing)"}`);
|
|
167
|
+
}
|
|
168
|
+
return {
|
|
169
|
+
action,
|
|
170
|
+
...parseTargetOnlyArgs(rest),
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
|
|
124
174
|
function printVersion(options) {
|
|
125
175
|
const lines = [];
|
|
126
176
|
if (!options.projectOnly) {
|
|
@@ -143,6 +193,167 @@ function printVersion(options) {
|
|
|
143
193
|
console.log(lines.join("\n"));
|
|
144
194
|
}
|
|
145
195
|
|
|
196
|
+
function printHandoff(options) {
|
|
197
|
+
const handoffFiles = [
|
|
198
|
+
".lab/context/session-brief.md",
|
|
199
|
+
".lab/context/mission.md",
|
|
200
|
+
".lab/context/state.md",
|
|
201
|
+
".lab/context/evidence-index.md",
|
|
202
|
+
];
|
|
203
|
+
const sessionBriefPath = path.join(options.targetDir, handoffFiles[0]);
|
|
204
|
+
if (!fs.existsSync(sessionBriefPath)) {
|
|
205
|
+
throw new Error(`No handoff brief found in ${options.targetDir}. Run 'superlab init' first.`);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const sessionBrief = fs.readFileSync(sessionBriefPath, "utf8").trimEnd();
|
|
209
|
+
console.log(`target: ${options.targetDir}`);
|
|
210
|
+
console.log("read-order:");
|
|
211
|
+
for (const filePath of handoffFiles) {
|
|
212
|
+
console.log(`- ${filePath}`);
|
|
213
|
+
}
|
|
214
|
+
console.log("");
|
|
215
|
+
console.log(sessionBrief);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function listFilesRecursive(dir) {
|
|
219
|
+
if (!fs.existsSync(dir)) {
|
|
220
|
+
return [];
|
|
221
|
+
}
|
|
222
|
+
const files = [];
|
|
223
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
224
|
+
const fullPath = path.join(dir, entry.name);
|
|
225
|
+
if (entry.isDirectory()) {
|
|
226
|
+
files.push(...listFilesRecursive(fullPath));
|
|
227
|
+
} else {
|
|
228
|
+
files.push(fullPath);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return files;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function readWorkflowConfig(targetDir) {
|
|
235
|
+
const configPath = path.join(targetDir, ".lab", "config", "workflow.json");
|
|
236
|
+
try {
|
|
237
|
+
return {
|
|
238
|
+
config: JSON.parse(fs.readFileSync(configPath, "utf8")),
|
|
239
|
+
issues: [],
|
|
240
|
+
};
|
|
241
|
+
} catch (error) {
|
|
242
|
+
return {
|
|
243
|
+
config: null,
|
|
244
|
+
issues: [`invalid workflow.json: ${error.message}`],
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function validateWorkflowConfig(config) {
|
|
250
|
+
const issues = [];
|
|
251
|
+
if (!config || typeof config !== "object") {
|
|
252
|
+
return issues;
|
|
253
|
+
}
|
|
254
|
+
if (!["en", "zh"].includes(config.workflow_language)) {
|
|
255
|
+
issues.push("invalid workflow_language");
|
|
256
|
+
}
|
|
257
|
+
if (!["en", "zh"].includes(config.paper_language)) {
|
|
258
|
+
issues.push("invalid paper_language");
|
|
259
|
+
}
|
|
260
|
+
if (config.paper_format !== "latex") {
|
|
261
|
+
issues.push("unsupported paper_format");
|
|
262
|
+
}
|
|
263
|
+
if (typeof config.deliverables_root !== "string" || config.deliverables_root.trim() === "") {
|
|
264
|
+
issues.push("invalid deliverables_root");
|
|
265
|
+
} else {
|
|
266
|
+
const normalized = config.deliverables_root.replace(/\\/g, "/");
|
|
267
|
+
if (normalized === ".lab" || normalized.startsWith(".lab/")) {
|
|
268
|
+
issues.push("deliverables_root must not point inside .lab");
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
return issues;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
function validateDeliverables(targetDir, config) {
|
|
275
|
+
const issues = [];
|
|
276
|
+
if (!config || typeof config.deliverables_root !== "string" || config.deliverables_root.trim() === "") {
|
|
277
|
+
return issues;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
const deliverablesRoot = path.join(targetDir, config.deliverables_root);
|
|
281
|
+
const paperDir = path.join(deliverablesRoot, "paper");
|
|
282
|
+
const mainTexPath = path.join(paperDir, "main.tex");
|
|
283
|
+
const mainMdPath = path.join(paperDir, "main.md");
|
|
284
|
+
const sectionsDir = path.join(paperDir, "sections");
|
|
285
|
+
|
|
286
|
+
if (fs.existsSync(mainMdPath)) {
|
|
287
|
+
issues.push("paper main manuscript must be main.tex");
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
if (fs.existsSync(paperDir) && !fs.existsSync(mainTexPath)) {
|
|
291
|
+
issues.push("paper output is missing paper/main.tex");
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
if (fs.existsSync(sectionsDir)) {
|
|
295
|
+
const nonTexFiles = listFilesRecursive(sectionsDir)
|
|
296
|
+
.filter((filePath) => path.extname(filePath) !== ".tex")
|
|
297
|
+
.map((filePath) => path.relative(targetDir, filePath));
|
|
298
|
+
if (nonTexFiles.length > 0) {
|
|
299
|
+
issues.push(`paper sections must be .tex files: ${nonTexFiles.join(", ")}`);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
return issues;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function printDoctor(options) {
|
|
307
|
+
const projectInfo = getProjectVersionInfo({ targetDir: options.targetDir });
|
|
308
|
+
const requiredPaths = [
|
|
309
|
+
".lab/system/core.md",
|
|
310
|
+
".lab/config/workflow.json",
|
|
311
|
+
".lab/context/mission.md",
|
|
312
|
+
".lab/context/state.md",
|
|
313
|
+
".lab/context/decisions.md",
|
|
314
|
+
".lab/context/evidence-index.md",
|
|
315
|
+
".lab/context/open-questions.md",
|
|
316
|
+
".lab/context/terminology-lock.md",
|
|
317
|
+
".lab/context/summary.md",
|
|
318
|
+
".lab/context/next-action.md",
|
|
319
|
+
".lab/context/session-brief.md",
|
|
320
|
+
".lab/.managed/install.json",
|
|
321
|
+
];
|
|
322
|
+
const missing = requiredPaths.filter((relativePath) => !fs.existsSync(path.join(options.targetDir, relativePath)));
|
|
323
|
+
const { config, issues: configReadIssues } = readWorkflowConfig(options.targetDir);
|
|
324
|
+
const configIssues = configReadIssues.concat(validateWorkflowConfig(config));
|
|
325
|
+
const deliverableIssues = validateDeliverables(options.targetDir, config);
|
|
326
|
+
|
|
327
|
+
if (projectInfo.status === "missing") {
|
|
328
|
+
console.log("status: missing");
|
|
329
|
+
console.log(`target: ${options.targetDir}`);
|
|
330
|
+
console.log("project: not initialized");
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
if (missing.length > 0 || configIssues.length > 0 || deliverableIssues.length > 0) {
|
|
335
|
+
console.log("status: degraded");
|
|
336
|
+
console.log(`target: ${options.targetDir}`);
|
|
337
|
+
console.log(`project: ${projectInfo.package_version}`);
|
|
338
|
+
console.log(`platform: ${projectInfo.platform}`);
|
|
339
|
+
console.log(`language: ${projectInfo.lang}`);
|
|
340
|
+
console.log(`missing: ${missing.length > 0 ? missing.join(", ") : "none"}`);
|
|
341
|
+
console.log(`config: ${configIssues.length > 0 ? configIssues.join(" | ") : "none"}`);
|
|
342
|
+
console.log(`outputs: ${deliverableIssues.length > 0 ? deliverableIssues.join(" | ") : "none"}`);
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
console.log("status: ok");
|
|
347
|
+
console.log(`target: ${options.targetDir}`);
|
|
348
|
+
console.log(`cli: ${PACKAGE_VERSION}`);
|
|
349
|
+
console.log(`project: ${projectInfo.package_version}`);
|
|
350
|
+
console.log(`platform: ${projectInfo.platform}`);
|
|
351
|
+
console.log(`language: ${projectInfo.lang}`);
|
|
352
|
+
console.log("missing: none");
|
|
353
|
+
console.log("config: none");
|
|
354
|
+
console.log("outputs: none");
|
|
355
|
+
}
|
|
356
|
+
|
|
146
357
|
function shouldUseInteractiveInit(options) {
|
|
147
358
|
if (options.lang && options.platform) {
|
|
148
359
|
return false;
|
|
@@ -194,7 +405,7 @@ async function main() {
|
|
|
194
405
|
return;
|
|
195
406
|
}
|
|
196
407
|
|
|
197
|
-
if (!["init", "install", "update", "version"].includes(command)) {
|
|
408
|
+
if (!["init", "install", "update", "version", "handoff", "doctor", "context"].includes(command)) {
|
|
198
409
|
throw new Error(`Unknown command: ${command}`);
|
|
199
410
|
}
|
|
200
411
|
|
|
@@ -203,6 +414,33 @@ async function main() {
|
|
|
203
414
|
return;
|
|
204
415
|
}
|
|
205
416
|
|
|
417
|
+
if (command === "handoff") {
|
|
418
|
+
printHandoff(parseTargetOnlyArgs(rest));
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
if (command === "doctor") {
|
|
423
|
+
printDoctor(parseTargetOnlyArgs(rest));
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
if (command === "context") {
|
|
428
|
+
const options = parseContextArgs(rest);
|
|
429
|
+
if (options.action === "refresh") {
|
|
430
|
+
refreshContext({ targetDir: options.targetDir });
|
|
431
|
+
console.log(`context refreshed in ${options.targetDir}`);
|
|
432
|
+
return;
|
|
433
|
+
}
|
|
434
|
+
if (options.action === "prune") {
|
|
435
|
+
pruneContext({ targetDir: options.targetDir });
|
|
436
|
+
console.log(`context pruned in ${options.targetDir}`);
|
|
437
|
+
return;
|
|
438
|
+
}
|
|
439
|
+
const result = archiveContext({ targetDir: options.targetDir });
|
|
440
|
+
console.log(`context archived in ${result.archivePath}`);
|
|
441
|
+
return;
|
|
442
|
+
}
|
|
443
|
+
|
|
206
444
|
if (command === "update") {
|
|
207
445
|
const options = parseUpdateArgs(rest);
|
|
208
446
|
if (options.allProjects) {
|
|
@@ -214,6 +452,7 @@ async function main() {
|
|
|
214
452
|
for (const project of result.skipped) {
|
|
215
453
|
console.log(`skipped: ${project.path} (${project.reason})`);
|
|
216
454
|
}
|
|
455
|
+
console.log(restartReminder(detectLanguage()));
|
|
217
456
|
return;
|
|
218
457
|
}
|
|
219
458
|
|
|
@@ -224,6 +463,7 @@ async function main() {
|
|
|
224
463
|
if (metadata.migration) {
|
|
225
464
|
console.log(`migration: ${metadata.migration}`);
|
|
226
465
|
}
|
|
466
|
+
console.log(restartReminder(metadata.lang));
|
|
227
467
|
return;
|
|
228
468
|
}
|
|
229
469
|
|
|
@@ -236,6 +476,7 @@ async function main() {
|
|
|
236
476
|
console.log(`superlab installed into ${options.targetDir}`);
|
|
237
477
|
console.log(`platform: ${options.platform}`);
|
|
238
478
|
console.log(`language: ${options.lang}`);
|
|
479
|
+
console.log(restartReminder(options.lang));
|
|
239
480
|
}
|
|
240
481
|
|
|
241
482
|
main().catch((error) => {
|