superlab 0.1.43 → 0.1.44

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.
@@ -134,6 +134,11 @@ function validateAutoMode(mode, status = null, evalProtocol = null) {
134
134
  ["terminal goal type", mode.terminalGoalType],
135
135
  ["terminal goal target", mode.terminalGoalTarget],
136
136
  ["required terminal artifact", mode.requiredTerminalArtifact],
137
+ ["primary gate", mode.primaryGate],
138
+ ["secondary guard", mode.secondaryGuard],
139
+ ["promotion condition", mode.promotionCondition],
140
+ ["stop reason", mode.stopReason],
141
+ ["escalation reason", mode.escalationReason],
137
142
  ["max iterations", mode.maxIterations],
138
143
  ["max wall-clock time", mode.maxWallClockTime],
139
144
  ["max failures", mode.maxFailures],
@@ -21,6 +21,7 @@ const {
21
21
  verifyStageContract,
22
22
  } = require("./auto_contracts.cjs");
23
23
  const {
24
+ listMissingCurrentAutoModeFields,
24
25
  parseAutoLedger,
25
26
  parseAutoMode,
26
27
  parseAutoStatus,
@@ -337,6 +338,12 @@ async function startAutoMode({ targetDir, now = new Date() }) {
337
338
  const existingStatus = parseAutoStatus(targetDir);
338
339
  const existingLedger = parseAutoLedger(targetDir);
339
340
  const evalProtocol = parseEvalProtocol(targetDir);
341
+ const missingSchemaFields = listMissingCurrentAutoModeFields(mode);
342
+ if (missingSchemaFields.length > 0) {
343
+ throw new Error(
344
+ `auto-mode.md is missing current contract fields: ${missingSchemaFields.join(", ")}; run \`superlab update --target ${targetDir}\` to apply the managed schema migration, then fill the new fields before starting auto mode`
345
+ );
346
+ }
340
347
  const issues = validateAutoMode(mode, null, evalProtocol);
341
348
  if (issues.length > 0) {
342
349
  throw new Error(issues.join(" | "));
@@ -24,6 +24,11 @@ function parseAutoMode(targetDir) {
24
24
  terminalGoalType: normalizeScalar(extractValue(text, ["Terminal goal type", "终止目标类型"])),
25
25
  terminalGoalTarget: extractValue(text, ["Terminal goal target", "终止目标目标值"]),
26
26
  requiredTerminalArtifact: extractValue(text, ["Required terminal artifact", "终止目标工件"]),
27
+ primaryGate: extractValue(text, ["Primary gate", "主 gate"]),
28
+ secondaryGuard: extractValue(text, ["Secondary guard", "次级 guard"]),
29
+ promotionCondition: extractValue(text, ["Promotion condition", "升格条件"]),
30
+ stopReason: extractValue(text, ["Stop reason", "停止原因"]),
31
+ escalationReason: extractValue(text, ["Escalation reason", "升级原因"]),
27
32
  maxIterations: extractValue(text, ["Max iterations", "最大迭代轮次"]),
28
33
  maxWallClockTime: extractValue(text, ["Max wall-clock time", "最大运行时长"]),
29
34
  maxFailures: extractValue(text, ["Max failures", "最大失败次数"]),
@@ -47,6 +52,25 @@ function parseAutoMode(targetDir) {
47
52
  };
48
53
  }
49
54
 
55
+ const CURRENT_AUTO_MODE_SCHEMA_FIELDS = [
56
+ ["Autonomy level", "autonomyLevel"],
57
+ ["Approval status", "approvalStatus"],
58
+ ["Terminal goal type", "terminalGoalType"],
59
+ ["Terminal goal target", "terminalGoalTarget"],
60
+ ["Required terminal artifact", "requiredTerminalArtifact"],
61
+ ["Primary gate", "primaryGate"],
62
+ ["Secondary guard", "secondaryGuard"],
63
+ ["Promotion condition", "promotionCondition"],
64
+ ["Stop reason", "stopReason"],
65
+ ["Escalation reason", "escalationReason"],
66
+ ];
67
+
68
+ function listMissingCurrentAutoModeFields(mode) {
69
+ return CURRENT_AUTO_MODE_SCHEMA_FIELDS
70
+ .filter(([, key]) => !isMeaningful(mode[key]))
71
+ .map(([label]) => label);
72
+ }
73
+
50
74
  function parseAutoStatus(targetDir) {
51
75
  const text = readFileIfExists(contextFile(targetDir, "auto-status.md"));
52
76
  return {
@@ -369,6 +393,8 @@ function resolveRequiredArtifact(targetDir, configuredPath) {
369
393
  }
370
394
 
371
395
  module.exports = {
396
+ CURRENT_AUTO_MODE_SCHEMA_FIELDS,
397
+ listMissingCurrentAutoModeFields,
372
398
  parseAutoLedger,
373
399
  parseAutoMode,
374
400
  parseAutoStatus,
package/lib/i18n.cjs CHANGED
@@ -2210,15 +2210,27 @@ const zhRecipeQuickPathLine =
2210
2210
  ZH_CONTENT[path.join(".codex", "prompts", "lab.md")] = ZH_CONTENT[
2211
2211
  path.join(".codex", "prompts", "lab.md")
2212
2212
  ].replace(
2213
+ "\n\n## 子命令\n\n",
2214
+ "\n\n## 可接受的阶段写法\n\n- `/lab:idea ...`、`/lab: idea ...`、`/lab idea ...`、`/lab-idea`、`/lab:idea ...`\n- `/lab:data ...`、`/lab: data ...`、`/lab data ...`、`/lab-data`、`/lab:data ...`\n- `/lab:auto ...`、`/lab: auto ...`、`/lab auto ...`、`/lab-auto`、`/lab:auto ...`\n- `/lab:framing ...`、`/lab: framing ...`、`/lab framing ...`、`/lab-framing`、`/lab:framing ...`\n- `/lab:spec ...`、`/lab: spec ...`、`/lab spec ...`、`/lab-spec`、`/lab:spec ...`\n- `/lab:run ...`、`/lab: run ...`、`/lab run ...`、`/lab-run`、`/lab:run ...`\n- `/lab:iterate ...`、`/lab: iterate ...`、`/lab iterate ...`、`/lab-iterate`、`/lab:iterate ...`\n- `/lab:review ...`、`/lab: review ...`、`/lab review ...`、`/lab-review`、`/lab:review ...`\n- `/lab:report ...`、`/lab: report ...`、`/lab report ...`、`/lab-report`、`/lab:report ...`\n- `/lab:write ...`、`/lab: write ...`、`/lab write ...`、`/lab-write`、`/lab:write ...`\n\n## 子命令\n\n"
2215
+ ).replace(
2213
2216
  "- 始终使用 `skills/lab/SKILL.md` 作为工作流合同。\n",
2214
2217
  `- 始终使用 \`skills/lab/SKILL.md\` 作为工作流合同。\n${zhRecipeQuickPathLine}`
2218
+ ).replace(
2219
+ "- 用户显式调用 `/lab:<stage>` 时,要立刻执行该 stage,而不是只推荐别的 `/lab` stage。\n",
2220
+ "- 用户只要显式调用某个 stage,无论写成 `/lab:<stage>`、`/lab: <stage>`、`/lab <stage>`、`/lab-<stage>` 还是 `/lab:<stage>`,都要立刻执行该 stage,而不是只推荐别的 `/lab` stage。\n"
2215
2221
  );
2216
2222
 
2217
2223
  ZH_CONTENT[path.join(".claude", "commands", "lab.md")] = ZH_CONTENT[
2218
2224
  path.join(".claude", "commands", "lab.md")
2219
2225
  ].replace(
2226
+ "\n\n## 阶段别名\n\n",
2227
+ "\n\n## 可接受的阶段写法\n\n- `/lab:idea ...`、`/lab: idea ...`、`/lab idea ...`、`/lab-idea`、`/lab:idea ...`\n- `/lab:data ...`、`/lab: data ...`、`/lab data ...`、`/lab-data`、`/lab:data ...`\n- `/lab:auto ...`、`/lab: auto ...`、`/lab auto ...`、`/lab-auto`、`/lab:auto ...`\n- `/lab:framing ...`、`/lab: framing ...`、`/lab framing ...`、`/lab-framing`、`/lab:framing ...`\n- `/lab:spec ...`、`/lab: spec ...`、`/lab spec ...`、`/lab-spec`、`/lab:spec ...`\n- `/lab:run ...`、`/lab: run ...`、`/lab run ...`、`/lab-run`、`/lab:run ...`\n- `/lab:iterate ...`、`/lab: iterate ...`、`/lab iterate ...`、`/lab-iterate`、`/lab:iterate ...`\n- `/lab:review ...`、`/lab: review ...`、`/lab review ...`、`/lab-review`、`/lab:review ...`\n- `/lab:report ...`、`/lab: report ...`、`/lab report ...`、`/lab-report`、`/lab:report ...`\n- `/lab:write ...`、`/lab: write ...`、`/lab write ...`、`/lab-write`、`/lab:write ...`\n\n## 阶段别名\n\n"
2228
+ ).replace(
2220
2229
  "- 始终使用 `skills/lab/SKILL.md` 作为工作流合同。\n",
2221
2230
  `- 始终使用 \`skills/lab/SKILL.md\` 作为工作流合同。\n${zhRecipeQuickPathLine}`
2231
+ ).replace(
2232
+ "- 用户显式调用 `/lab <stage> ...` 或 `/lab-<stage>` 时,要立刻执行该 stage,而不是只推荐别的阶段。\n",
2233
+ "- 用户只要显式调用某个 stage,无论写成 `/lab:<stage>`、`/lab: <stage>`、`/lab <stage>`、`/lab-<stage>` 还是 `/lab:<stage>`,都要立刻执行该 stage,而不是只推荐别的阶段。\n"
2222
2234
  );
2223
2235
 
2224
2236
  ZH_CONTENT[path.join(".codex", "skills", "lab", "SKILL.md")] = `---
package/lib/install.cjs CHANGED
@@ -1,6 +1,7 @@
1
1
  const fs = require("node:fs");
2
2
  const os = require("node:os");
3
3
  const path = require("node:path");
4
+ const { CURRENT_AUTO_MODE_SCHEMA_FIELDS } = require("./auto_state.cjs");
4
5
  const { getLocalizedContent } = require("./i18n.cjs");
5
6
 
6
7
  const REPO_ROOT = path.resolve(__dirname, "..");
@@ -132,6 +133,68 @@ function installLabAssets(targetDir, force) {
132
133
  );
133
134
  }
134
135
 
136
+ function autoModeSchemaFieldLine(label, lang) {
137
+ if (lang === "zh") {
138
+ const zhDefaults = {
139
+ "Autonomy level": "- 自治级别: L2",
140
+ "Approval status": "- 批准状态: draft",
141
+ "Terminal goal type": "- 终止目标类型: ",
142
+ "Terminal goal target": "- 终止目标目标值: ",
143
+ "Required terminal artifact": "- 终止目标工件: ",
144
+ "Primary gate": "- 主 gate: ",
145
+ "Secondary guard": "- 次级 guard: ",
146
+ "Promotion condition": "- 升格条件: ",
147
+ "Stop reason": "- 停止原因: ",
148
+ "Escalation reason": "- 升级原因: ",
149
+ };
150
+ return zhDefaults[label] || "";
151
+ }
152
+
153
+ const defaults = {
154
+ "Autonomy level": "- Autonomy level: L2",
155
+ "Approval status": "- Approval status: draft",
156
+ "Terminal goal type": "- Terminal goal type: ",
157
+ "Terminal goal target": "- Terminal goal target: ",
158
+ "Required terminal artifact": "- Required terminal artifact: ",
159
+ "Primary gate": "- Primary gate: ",
160
+ "Secondary guard": "- Secondary guard: ",
161
+ "Promotion condition": "- Promotion condition: ",
162
+ "Stop reason": "- Stop reason: ",
163
+ "Escalation reason": "- Escalation reason: ",
164
+ };
165
+ return defaults[label] || "";
166
+ }
167
+
168
+ function migrateAutoModeContext(targetDir, lang) {
169
+ const filePath = path.join(targetDir, ".lab", "context", "auto-mode.md");
170
+ if (!fs.existsSync(filePath)) {
171
+ return;
172
+ }
173
+
174
+ const existing = fs.readFileSync(filePath, "utf8");
175
+ const missing = CURRENT_AUTO_MODE_SCHEMA_FIELDS
176
+ .map(([label]) => label)
177
+ .filter((label) => {
178
+ const localizedLabel = autoModeSchemaFieldLine(label, lang).replace(/^- /, "").split(":")[0];
179
+ return !existing.includes(`${label}:`) && !existing.includes(`${localizedLabel}:`);
180
+ });
181
+ if (missing.length === 0) {
182
+ return;
183
+ }
184
+
185
+ const trimmed = existing.trimEnd();
186
+ const header =
187
+ lang === "zh"
188
+ ? "## Managed schema migration\n\n- 这段由 `superlab update` 补齐,用于把旧版 auto 契约升级到当前 schema。保留现有内容,只补缺失字段。\n"
189
+ : "## Managed schema migration\n\n- This block was added by `superlab update` to bring a legacy auto contract up to the current schema without overwriting your existing content.\n";
190
+ const body = missing
191
+ .map((label) => autoModeSchemaFieldLine(label, lang))
192
+ .filter(Boolean)
193
+ .join("\n");
194
+
195
+ fs.writeFileSync(filePath, `${trimmed}\n\n${header}${body}\n`);
196
+ }
197
+
135
198
  function ensureConfiguredProjectDirs(targetDir) {
136
199
  const workflowConfigPath = path.join(targetDir, ".lab", "config", "workflow.json");
137
200
  if (!fs.existsSync(workflowConfigPath)) {
@@ -605,6 +668,7 @@ function installSuperlab({
605
668
  writePlatformShims(targetDir, resolvedLang, force);
606
669
  writeManagedCoreFile(targetDir, resolvedLang, { force });
607
670
  localizeInstalledAssets(targetDir, resolvedLang, { newlyCreatedProjectOwnedPaths });
671
+ migrateAutoModeContext(targetDir, resolvedLang);
608
672
  ensureConfiguredProjectDirs(targetDir);
609
673
  chmodScripts(targetDir);
610
674
  const metadata = {
@@ -13,6 +13,21 @@ argument-hint: [stage] [target]
13
13
 
14
14
  Use the same repository artifacts and stage boundaries every time.
15
15
 
16
+ ## Accepted Stage Spellings
17
+
18
+ Treat all of these as equivalent stage requests:
19
+
20
+ - `/lab:idea ...`, `/lab: idea ...`, `/lab idea ...`, `/lab-idea`, `/lab:idea ...`
21
+ - `/lab:data ...`, `/lab: data ...`, `/lab data ...`, `/lab-data`, `/lab:data ...`
22
+ - `/lab:auto ...`, `/lab: auto ...`, `/lab auto ...`, `/lab-auto`, `/lab:auto ...`
23
+ - `/lab:framing ...`, `/lab: framing ...`, `/lab framing ...`, `/lab-framing`, `/lab:framing ...`
24
+ - `/lab:spec ...`, `/lab: spec ...`, `/lab spec ...`, `/lab-spec`, `/lab:spec ...`
25
+ - `/lab:run ...`, `/lab: run ...`, `/lab run ...`, `/lab-run`, `/lab:run ...`
26
+ - `/lab:iterate ...`, `/lab: iterate ...`, `/lab iterate ...`, `/lab-iterate`, `/lab:iterate ...`
27
+ - `/lab:review ...`, `/lab: review ...`, `/lab review ...`, `/lab-review`, `/lab:review ...`
28
+ - `/lab:report ...`, `/lab: report ...`, `/lab report ...`, `/lab-report`, `/lab:report ...`
29
+ - `/lab:write ...`, `/lab: write ...`, `/lab write ...`, `/lab-write`, `/lab:write ...`
30
+
16
31
  ## Stage Aliases
17
32
 
18
33
  - `/lab idea ...` or `/lab-idea`
@@ -50,7 +65,7 @@ Use the same repository artifacts and stage boundaries every time.
50
65
 
51
66
  - Always use `skills/lab/SKILL.md` as the workflow contract.
52
67
  - Use `skills/lab/references/recipes.md` as the quick path for common stage chains; do not invent new slash commands or aliases from it.
53
- - When the user explicitly invokes `/lab <stage> ...` or a direct `/lab-<stage>` alias, execute that stage now against the provided argument instead of only recommending another lab stage.
68
+ - When the user explicitly invokes a stage through `/lab:<stage>`, `/lab: <stage>`, `/lab <stage>`, `/lab-<stage>`, or `/lab:<stage>`, execute that stage now against the provided argument instead of only recommending another lab stage.
54
69
  - Start by giving the user a concise stage summary. Materialize managed artifacts immediately when the stage contract requires them, then report the output path and next step.
55
70
  - When ambiguity matters, ask one clarifying question at a time; when multiple paths are viable, present 2-3 approaches before converging.
56
71
  - `spec` is not complete until the approved change is frozen under `.lab/changes/<change-id>/`.
@@ -7,7 +7,22 @@ argument-hint: workflow question or stage choice
7
7
 
8
8
  `/lab` is a strict research workflow command family. Use the same repository artifacts and stage boundaries every time.
9
9
 
10
- ## Subcommands
10
+ ## Accepted Stage Spellings
11
+
12
+ Treat all of these as equivalent stage requests:
13
+
14
+ - `/lab:idea ...`, `/lab: idea ...`, `/lab idea ...`, `/lab-idea`, `/lab:idea ...`
15
+ - `/lab:data ...`, `/lab: data ...`, `/lab data ...`, `/lab-data`, `/lab:data ...`
16
+ - `/lab:auto ...`, `/lab: auto ...`, `/lab auto ...`, `/lab-auto`, `/lab:auto ...`
17
+ - `/lab:framing ...`, `/lab: framing ...`, `/lab framing ...`, `/lab-framing`, `/lab:framing ...`
18
+ - `/lab:spec ...`, `/lab: spec ...`, `/lab spec ...`, `/lab-spec`, `/lab:spec ...`
19
+ - `/lab:run ...`, `/lab: run ...`, `/lab run ...`, `/lab-run`, `/lab:run ...`
20
+ - `/lab:iterate ...`, `/lab: iterate ...`, `/lab iterate ...`, `/lab-iterate`, `/lab:iterate ...`
21
+ - `/lab:review ...`, `/lab: review ...`, `/lab review ...`, `/lab-review`, `/lab:review ...`
22
+ - `/lab:report ...`, `/lab: report ...`, `/lab report ...`, `/lab-report`, `/lab:report ...`
23
+ - `/lab:write ...`, `/lab: write ...`, `/lab write ...`, `/lab-write`, `/lab:write ...`
24
+
25
+ ## Stage Aliases
11
26
 
12
27
  - `/lab:idea`
13
28
  Research the idea through two brainstorm passes and two literature sweeps, define the problem and failure case, compare against closest prior work, then end with a source-backed recommendation and an explicit approval gate before any implementation.
@@ -44,7 +59,7 @@ argument-hint: workflow question or stage choice
44
59
 
45
60
  - Always use `skills/lab/SKILL.md` as the workflow contract.
46
61
  - Use `skills/lab/references/recipes.md` as the quick path for common stage chains; do not invent new slash commands or aliases from it.
47
- - When the user explicitly invokes `/lab:<stage>`, execute that stage now against the provided argument instead of only recommending another `/lab` stage.
62
+ - When the user explicitly invokes a stage through `/lab:<stage>`, `/lab: <stage>`, `/lab <stage>`, `/lab-<stage>`, or `/lab:<stage>`, execute that stage now against the provided argument instead of only recommending another `/lab` stage.
48
63
  - Start by giving the user a concise stage summary. Materialize managed artifacts immediately when the stage contract requires them, then report the output path and next step.
49
64
  - When ambiguity matters, ask one clarifying question at a time; when multiple paths are viable, present 2-3 approaches before converging.
50
65
  - `/lab:spec` is not complete until the approved change is frozen under `.lab/changes/<change-id>/`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "superlab",
3
- "version": "0.1.43",
3
+ "version": "0.1.44",
4
4
  "description": "Strict /lab research workflow installer for Codex and Claude",
5
5
  "keywords": [
6
6
  "codex",