superlab 0.1.45 → 0.1.47
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/bin/superlab.cjs +40 -4
- package/lib/auto_contracts.cjs +147 -0
- package/lib/auto_runner.cjs +181 -18
- package/lib/auto_state.cjs +146 -1
- package/lib/i18n.cjs +2 -2
- package/lib/install.cjs +8 -2
- package/package-assets/claude/commands/lab/auto.md +4 -0
- package/package-assets/claude/commands/lab-auto.md +4 -0
- package/package-assets/claude/commands/lab:auto.md +4 -0
- package/package-assets/claude/commands/lab/357/274/232auto.md +4 -0
- package/package-assets/codex/prompts/lab/auto.md +4 -0
- package/package-assets/codex/prompts/lab-auto.md +4 -0
- package/package-assets/codex/prompts/lab:auto.md +4 -0
- package/package-assets/codex/prompts/lab/357/274/232auto.md +4 -0
- package/package-assets/shared/lab/context/auto-mode.md +3 -0
- package/package.json +1 -1
package/bin/superlab.cjs
CHANGED
|
@@ -39,7 +39,7 @@ Usage:
|
|
|
39
39
|
superlab init [--target <dir>] [--platform codex|claude|both|all] [--lang en|zh] [--force]
|
|
40
40
|
superlab install [--target <dir>] [--platform codex|claude|both|all] [--lang en|zh] [--force]
|
|
41
41
|
superlab paper attach-template --path <dir> [--target <dir>]
|
|
42
|
-
superlab auto start [--target <dir>]
|
|
42
|
+
superlab auto start [--target <dir>] [--objective <text>] [--campaign-kind <kind>] [--allowed-stages <csv>] [--autonomy-level <L1|L2|L3>]
|
|
43
43
|
superlab auto status [--target <dir>]
|
|
44
44
|
superlab auto stop [--target <dir>]
|
|
45
45
|
superlab update [--target <dir>]
|
|
@@ -222,10 +222,38 @@ function parseAutoArgs(argv) {
|
|
|
222
222
|
if (!["start", "status", "stop"].includes(action || "")) {
|
|
223
223
|
throw new Error(`Unknown auto action: ${action || "(missing)"}`);
|
|
224
224
|
}
|
|
225
|
-
|
|
225
|
+
const options = {
|
|
226
226
|
action,
|
|
227
|
-
|
|
227
|
+
targetDir: process.cwd(),
|
|
228
|
+
requestedObjective: "",
|
|
229
|
+
requestedCampaignKind: "",
|
|
230
|
+
requestedAllowedStages: "",
|
|
231
|
+
requestedAutonomyLevel: "",
|
|
228
232
|
};
|
|
233
|
+
|
|
234
|
+
for (let index = 0; index < rest.length; index += 1) {
|
|
235
|
+
const value = rest[index];
|
|
236
|
+
if (value === "--target") {
|
|
237
|
+
options.targetDir = path.resolve(rest[index + 1]);
|
|
238
|
+
index += 1;
|
|
239
|
+
} else if (action === "start" && value === "--objective") {
|
|
240
|
+
options.requestedObjective = rest[index + 1] || "";
|
|
241
|
+
index += 1;
|
|
242
|
+
} else if (action === "start" && value === "--campaign-kind") {
|
|
243
|
+
options.requestedCampaignKind = rest[index + 1] || "";
|
|
244
|
+
index += 1;
|
|
245
|
+
} else if (action === "start" && value === "--allowed-stages") {
|
|
246
|
+
options.requestedAllowedStages = rest[index + 1] || "";
|
|
247
|
+
index += 1;
|
|
248
|
+
} else if (action === "start" && value === "--autonomy-level") {
|
|
249
|
+
options.requestedAutonomyLevel = (rest[index + 1] || "").trim();
|
|
250
|
+
index += 1;
|
|
251
|
+
} else {
|
|
252
|
+
throw new Error(`Unknown option: ${value}`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return options;
|
|
229
257
|
}
|
|
230
258
|
|
|
231
259
|
function printVersion(options) {
|
|
@@ -963,7 +991,15 @@ async function main() {
|
|
|
963
991
|
return;
|
|
964
992
|
}
|
|
965
993
|
if (options.action === "start") {
|
|
966
|
-
const result = await startAutoMode({
|
|
994
|
+
const result = await startAutoMode({
|
|
995
|
+
targetDir: options.targetDir,
|
|
996
|
+
requestedContract: {
|
|
997
|
+
objective: options.requestedObjective,
|
|
998
|
+
campaignKind: options.requestedCampaignKind,
|
|
999
|
+
allowedStages: options.requestedAllowedStages,
|
|
1000
|
+
autonomyLevel: options.requestedAutonomyLevel,
|
|
1001
|
+
},
|
|
1002
|
+
});
|
|
967
1003
|
const verb = result.status.status === "stopped" ? "stopped" : "completed";
|
|
968
1004
|
console.log(`auto mode ${verb} in ${options.targetDir}`);
|
|
969
1005
|
console.log(`objective: ${result.mode.objective}`);
|
package/lib/auto_contracts.cjs
CHANGED
|
@@ -6,6 +6,7 @@ const {
|
|
|
6
6
|
extractValue,
|
|
7
7
|
isMeaningful,
|
|
8
8
|
normalizeList,
|
|
9
|
+
normalizeScalar,
|
|
9
10
|
parseInteger,
|
|
10
11
|
readFileIfExists,
|
|
11
12
|
readWorkflowConfig,
|
|
@@ -43,6 +44,147 @@ const PROMOTION_CANONICAL_FILES = [
|
|
|
43
44
|
path.join(".lab", "context", "workflow-state.md"),
|
|
44
45
|
];
|
|
45
46
|
|
|
47
|
+
function isLocalProcessAlive(ownerId) {
|
|
48
|
+
const pid = parseInteger(ownerId, null);
|
|
49
|
+
if (!Number.isInteger(pid) || pid <= 0) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
process.kill(pid, 0);
|
|
54
|
+
return true;
|
|
55
|
+
} catch (error) {
|
|
56
|
+
if (error && error.code === "EPERM") {
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function inferCampaignKind({ campaignKind = "", allowedStages = [] }) {
|
|
64
|
+
if (isMeaningful(campaignKind)) {
|
|
65
|
+
return campaignKind.trim().toLowerCase();
|
|
66
|
+
}
|
|
67
|
+
const stageSet = new Set((allowedStages || []).map((stage) => stage.trim().toLowerCase()).filter(Boolean));
|
|
68
|
+
const hasPlanning = ["idea", "data", "framing", "spec"].some((stage) => stageSet.has(stage));
|
|
69
|
+
const hasExecution = ["run", "iterate"].some((stage) => stageSet.has(stage));
|
|
70
|
+
const hasWriteOnly = stageSet.has("write") && !hasExecution;
|
|
71
|
+
|
|
72
|
+
if (hasPlanning && !hasExecution) {
|
|
73
|
+
return "spec";
|
|
74
|
+
}
|
|
75
|
+
if (hasExecution) {
|
|
76
|
+
return "experiment-loop";
|
|
77
|
+
}
|
|
78
|
+
if (hasWriteOnly || stageSet.has("report")) {
|
|
79
|
+
return "report-polish";
|
|
80
|
+
}
|
|
81
|
+
return "generic";
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function normalizeRequestedAutoContract(requested = {}) {
|
|
85
|
+
const allowedStages = Array.isArray(requested.allowedStages)
|
|
86
|
+
? requested.allowedStages.map((stage) => String(stage).trim().toLowerCase()).filter(Boolean)
|
|
87
|
+
: normalizeList(requested.allowedStages || "").map((stage) => stage.toLowerCase());
|
|
88
|
+
return {
|
|
89
|
+
objective: (requested.objective || "").trim(),
|
|
90
|
+
autonomyLevel: normalizeScalar(requested.autonomyLevel || ""),
|
|
91
|
+
campaignKind:
|
|
92
|
+
isMeaningful(requested.campaignKind || "") || allowedStages.length > 0
|
|
93
|
+
? inferCampaignKind({
|
|
94
|
+
campaignKind: requested.campaignKind || "",
|
|
95
|
+
allowedStages,
|
|
96
|
+
})
|
|
97
|
+
: "",
|
|
98
|
+
allowedStages,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function sameStageSet(left, right) {
|
|
103
|
+
if (left.length !== right.length) {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
const leftSet = new Set(left);
|
|
107
|
+
return right.every((value) => leftSet.has(value));
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function hasLiveOwner(status, ledger) {
|
|
111
|
+
const normalizedStatus = (status.status || "").trim().toLowerCase();
|
|
112
|
+
const observedState = (ledger.observedState || "").trim().toLowerCase();
|
|
113
|
+
if ((ledger.ownerType || "").trim().toLowerCase() === "local-process" && isLocalProcessAlive(ledger.ownerId)) {
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
if (["local-runner", "remote-runner"].includes((ledger.ownerType || "").trim().toLowerCase())) {
|
|
117
|
+
return ["running", "retrying", "resuming", "checkpointed"].includes(observedState);
|
|
118
|
+
}
|
|
119
|
+
return normalizedStatus === "running" || ["running", "retrying", "resuming"].includes(observedState);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function classifyAutoContractFit({ mode, status, ledger, requested }) {
|
|
123
|
+
const normalizedRequest = normalizeRequestedAutoContract(requested);
|
|
124
|
+
const requestIsEmpty =
|
|
125
|
+
!isMeaningful(normalizedRequest.objective) &&
|
|
126
|
+
!isMeaningful(normalizedRequest.campaignKind) &&
|
|
127
|
+
normalizedRequest.allowedStages.length === 0;
|
|
128
|
+
const currentCampaignKind = inferCampaignKind(mode);
|
|
129
|
+
if (requestIsEmpty) {
|
|
130
|
+
return {
|
|
131
|
+
classification: "fit",
|
|
132
|
+
reason: "no requested contract override",
|
|
133
|
+
currentCampaignKind,
|
|
134
|
+
requestedCampaignKind: "",
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const requestedCampaignKind = normalizedRequest.campaignKind || currentCampaignKind;
|
|
139
|
+
const requestedStages = normalizedRequest.allowedStages.length > 0
|
|
140
|
+
? normalizedRequest.allowedStages
|
|
141
|
+
: mode.allowedStages;
|
|
142
|
+
const stageOutsideCurrentEnvelope = requestedStages.some((stage) => !mode.allowedStages.includes(stage));
|
|
143
|
+
const objectiveDiffers =
|
|
144
|
+
isMeaningful(normalizedRequest.objective) &&
|
|
145
|
+
isMeaningful(mode.objective) &&
|
|
146
|
+
normalizedRequest.objective.trim() !== mode.objective.trim();
|
|
147
|
+
const kindDiffers = requestedCampaignKind !== currentCampaignKind;
|
|
148
|
+
|
|
149
|
+
if (hasLiveOwner(status, ledger) && (kindDiffers || stageOutsideCurrentEnvelope || objectiveDiffers)) {
|
|
150
|
+
return {
|
|
151
|
+
classification: "live-conflict",
|
|
152
|
+
reason: "requested campaign conflicts with a live auto campaign",
|
|
153
|
+
currentCampaignKind,
|
|
154
|
+
requestedCampaignKind,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (kindDiffers || stageOutsideCurrentEnvelope) {
|
|
159
|
+
return {
|
|
160
|
+
classification: "hard-mismatch",
|
|
161
|
+
reason: stageOutsideCurrentEnvelope
|
|
162
|
+
? "requested stages fall outside the current auto-stage envelope"
|
|
163
|
+
: "requested campaign kind differs from the current auto campaign",
|
|
164
|
+
currentCampaignKind,
|
|
165
|
+
requestedCampaignKind,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (!sameStageSet(requestedStages, mode.allowedStages) || objectiveDiffers) {
|
|
170
|
+
return {
|
|
171
|
+
classification: "soft-mismatch",
|
|
172
|
+
reason: !sameStageSet(requestedStages, mode.allowedStages)
|
|
173
|
+
? "requested stages differ but stay inside the current envelope"
|
|
174
|
+
: "requested objective differs inside the same campaign family",
|
|
175
|
+
currentCampaignKind,
|
|
176
|
+
requestedCampaignKind,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return {
|
|
181
|
+
classification: "fit",
|
|
182
|
+
reason: "requested campaign matches current auto contract",
|
|
183
|
+
currentCampaignKind,
|
|
184
|
+
requestedCampaignKind,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
46
188
|
function resolveFrozenCoreEntries(rawValue) {
|
|
47
189
|
const normalized = normalizeList(rawValue);
|
|
48
190
|
const paths = new Set();
|
|
@@ -380,9 +522,14 @@ module.exports = {
|
|
|
380
522
|
REVIEW_CONTEXT_FILES,
|
|
381
523
|
VALID_APPROVAL_STATUSES,
|
|
382
524
|
VALID_TERMINAL_GOAL_TYPES,
|
|
525
|
+
classifyAutoContractFit,
|
|
383
526
|
changedSnapshotPaths,
|
|
384
527
|
detectFrozenCoreChanges,
|
|
528
|
+
hasLiveOwner,
|
|
385
529
|
hashPathState,
|
|
530
|
+
inferCampaignKind,
|
|
531
|
+
isLocalProcessAlive,
|
|
532
|
+
normalizeRequestedAutoContract,
|
|
386
533
|
resolveFrozenCoreEntries,
|
|
387
534
|
resolveStageCommand,
|
|
388
535
|
snapshotFrozenCore,
|
package/lib/auto_runner.cjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const fs = require("node:fs");
|
|
2
|
+
const path = require("node:path");
|
|
2
3
|
const { spawn } = require("node:child_process");
|
|
3
4
|
const { refreshContext } = require("./context.cjs");
|
|
4
5
|
const { parseEvalProtocol, validateEvalProtocol } = require("./eval_protocol.cjs");
|
|
@@ -9,7 +10,11 @@ const {
|
|
|
9
10
|
sleep,
|
|
10
11
|
} = require("./auto_common.cjs");
|
|
11
12
|
const {
|
|
13
|
+
classifyAutoContractFit,
|
|
12
14
|
detectFrozenCoreChanges,
|
|
15
|
+
inferCampaignKind,
|
|
16
|
+
isLocalProcessAlive,
|
|
17
|
+
normalizeRequestedAutoContract,
|
|
13
18
|
resolveStageCommand,
|
|
14
19
|
snapshotFrozenCore,
|
|
15
20
|
snapshotPaths,
|
|
@@ -28,6 +33,7 @@ const {
|
|
|
28
33
|
readWorkflowLanguage,
|
|
29
34
|
resolveRequiredArtifact,
|
|
30
35
|
writeAutoLedger,
|
|
36
|
+
writeAutoMode,
|
|
31
37
|
writeAutoOutcome,
|
|
32
38
|
writeAutoStatus,
|
|
33
39
|
} = require("./auto_state.cjs");
|
|
@@ -48,22 +54,6 @@ function isStopTransition(value) {
|
|
|
48
54
|
return ["stop", "campaign-stop", "terminal-stop"].includes((value || "").trim().toLowerCase());
|
|
49
55
|
}
|
|
50
56
|
|
|
51
|
-
function isLocalProcessAlive(ownerId) {
|
|
52
|
-
const pid = parseInteger(ownerId, null);
|
|
53
|
-
if (!Number.isInteger(pid) || pid <= 0) {
|
|
54
|
-
return false;
|
|
55
|
-
}
|
|
56
|
-
try {
|
|
57
|
-
process.kill(pid, 0);
|
|
58
|
-
return true;
|
|
59
|
-
} catch (error) {
|
|
60
|
-
if (error && error.code === "EPERM") {
|
|
61
|
-
return true;
|
|
62
|
-
}
|
|
63
|
-
return false;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
57
|
function resolveResumePlan({ mode, evalProtocol, status, ledger, now }) {
|
|
68
58
|
const hasLedgerState = [
|
|
69
59
|
ledger.campaignId,
|
|
@@ -143,6 +133,146 @@ function resolveResumePlan({ mode, evalProtocol, status, ledger, now }) {
|
|
|
143
133
|
return { blockingIssue: "", resumePlan: null };
|
|
144
134
|
}
|
|
145
135
|
|
|
136
|
+
function makeCampaignId({ requested, now }) {
|
|
137
|
+
const raw = isMeaningful(requested.campaignKind)
|
|
138
|
+
? `${requested.campaignKind}-${now.toISOString()}`
|
|
139
|
+
: `auto-${now.toISOString()}`;
|
|
140
|
+
return raw.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function archiveAutoArtifact(targetDir, relativePath, campaignId, now) {
|
|
144
|
+
const absolutePath = path.join(targetDir, relativePath);
|
|
145
|
+
if (!fs.existsSync(absolutePath)) {
|
|
146
|
+
return "";
|
|
147
|
+
}
|
|
148
|
+
const archiveDir = path.join(targetDir, ".lab", "context", "archive");
|
|
149
|
+
fs.mkdirSync(archiveDir, { recursive: true });
|
|
150
|
+
const baseName = path.basename(relativePath);
|
|
151
|
+
const archivePath = path.join(
|
|
152
|
+
archiveDir,
|
|
153
|
+
`${now.toISOString().slice(0, 10)}-${campaignId}-${baseName}`
|
|
154
|
+
);
|
|
155
|
+
fs.copyFileSync(absolutePath, archivePath);
|
|
156
|
+
return archivePath;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function buildRolledOverAutoMode(mode, requested, now) {
|
|
160
|
+
const allowedStages = requested.allowedStages.length > 0 ? requested.allowedStages : mode.allowedStages;
|
|
161
|
+
const campaignKind = requested.campaignKind || inferCampaignKind({ allowedStages });
|
|
162
|
+
return {
|
|
163
|
+
campaignId: makeCampaignId({ requested: { ...requested, campaignKind }, now }),
|
|
164
|
+
campaignKind,
|
|
165
|
+
campaignStartedAt: now.toISOString(),
|
|
166
|
+
objective: requested.objective || mode.objective,
|
|
167
|
+
autonomyLevel: requested.autonomyLevel || mode.autonomyLevel || "l2",
|
|
168
|
+
approvalStatus: "draft",
|
|
169
|
+
allowedStages,
|
|
170
|
+
successCriteria: "",
|
|
171
|
+
terminalGoalType: "",
|
|
172
|
+
terminalGoalTarget: "",
|
|
173
|
+
requiredTerminalArtifact: "",
|
|
174
|
+
primaryGate: "",
|
|
175
|
+
secondaryGuard: "",
|
|
176
|
+
promotionCondition: "",
|
|
177
|
+
stopReason: "",
|
|
178
|
+
escalationReason: "",
|
|
179
|
+
maxIterations: mode.maxIterations,
|
|
180
|
+
maxWallClockTime: mode.maxWallClockTime,
|
|
181
|
+
maxFailures: mode.maxFailures,
|
|
182
|
+
pollInterval: mode.pollInterval,
|
|
183
|
+
stageCommands: {
|
|
184
|
+
run: "",
|
|
185
|
+
iterate: "",
|
|
186
|
+
review: "",
|
|
187
|
+
report: "",
|
|
188
|
+
write: "",
|
|
189
|
+
},
|
|
190
|
+
successCheckCommand: "",
|
|
191
|
+
stopCheckCommand: mode.stopCheckCommand,
|
|
192
|
+
promotionCheckCommand: "",
|
|
193
|
+
promotionCommand: "",
|
|
194
|
+
promotionPolicy: "",
|
|
195
|
+
frozenCore: mode.frozenCore,
|
|
196
|
+
explorationEnvelope: "",
|
|
197
|
+
stopConditions: "",
|
|
198
|
+
escalationConditions: "",
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function rolloverAutoCampaign({ targetDir, mode, status, ledger, requested, lang, now }) {
|
|
203
|
+
const newMode = buildRolledOverAutoMode(mode, requested, now);
|
|
204
|
+
const archivedPaths = [
|
|
205
|
+
archiveAutoArtifact(targetDir, path.join(".lab", "context", "auto-mode.md"), mode.campaignId || "auto-campaign", now),
|
|
206
|
+
archiveAutoArtifact(targetDir, path.join(".lab", "context", "auto-status.md"), mode.campaignId || "auto-campaign", now),
|
|
207
|
+
].filter(Boolean);
|
|
208
|
+
|
|
209
|
+
const hasMeaningfulLedger = [
|
|
210
|
+
ledger.campaignId,
|
|
211
|
+
ledger.ownerType,
|
|
212
|
+
ledger.ownerId,
|
|
213
|
+
ledger.observedState,
|
|
214
|
+
ledger.activeRung,
|
|
215
|
+
].some((value) => isMeaningful(value));
|
|
216
|
+
if (hasMeaningfulLedger) {
|
|
217
|
+
const archivedLedger = archiveAutoArtifact(
|
|
218
|
+
targetDir,
|
|
219
|
+
path.join(".lab", "context", "auto-ledger.md"),
|
|
220
|
+
mode.campaignId || "auto-campaign",
|
|
221
|
+
now
|
|
222
|
+
);
|
|
223
|
+
if (archivedLedger) {
|
|
224
|
+
archivedPaths.push(archivedLedger);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
writeAutoMode(targetDir, newMode, { lang });
|
|
229
|
+
writeAutoStatus(
|
|
230
|
+
targetDir,
|
|
231
|
+
{
|
|
232
|
+
status: "idle",
|
|
233
|
+
currentStage: "",
|
|
234
|
+
currentCommand: "",
|
|
235
|
+
activeRunId: "",
|
|
236
|
+
iterationCount: "0",
|
|
237
|
+
currentRung: "",
|
|
238
|
+
watchTarget: "",
|
|
239
|
+
nextRung: "",
|
|
240
|
+
startedAt: "",
|
|
241
|
+
lastHeartbeat: now.toISOString(),
|
|
242
|
+
lastCheckpoint: "",
|
|
243
|
+
lastSummary: `rolled over from previous auto campaign${archivedPaths.length > 0 ? `; archived: ${archivedPaths.join(", ")}` : ""}`,
|
|
244
|
+
decision: "fill the new auto-mode contract and approve it before starting the next campaign",
|
|
245
|
+
},
|
|
246
|
+
{ lang }
|
|
247
|
+
);
|
|
248
|
+
writeAutoLedger(
|
|
249
|
+
targetDir,
|
|
250
|
+
{
|
|
251
|
+
campaignId: newMode.campaignId,
|
|
252
|
+
objective: newMode.objective,
|
|
253
|
+
activeStage: "",
|
|
254
|
+
activeRung: "",
|
|
255
|
+
ownerType: "",
|
|
256
|
+
ownerId: "",
|
|
257
|
+
command: "",
|
|
258
|
+
watchTarget: "",
|
|
259
|
+
startedAt: "",
|
|
260
|
+
lastObservedAt: now.toISOString(),
|
|
261
|
+
observedState: "draft",
|
|
262
|
+
lastCheckpoint: "",
|
|
263
|
+
checkpointSummary: "new campaign draft created by controlled rollover",
|
|
264
|
+
nextTransition: "",
|
|
265
|
+
continueBoundary: "Fill and approve the new contract before starting the campaign.",
|
|
266
|
+
stopBoundary: "",
|
|
267
|
+
escalationBoundary: "",
|
|
268
|
+
requiredReadSet: ".lab/context/eval-protocol.md, .lab/context/auto-mode.md, .lab/context/auto-status.md, .lab/context/auto-ledger.md, .lab/context/auto-outcome.md",
|
|
269
|
+
resumeCommand: "",
|
|
270
|
+
},
|
|
271
|
+
{ lang }
|
|
272
|
+
);
|
|
273
|
+
return { newMode, archivedPaths };
|
|
274
|
+
}
|
|
275
|
+
|
|
146
276
|
async function runCommandWithPolling({
|
|
147
277
|
targetDir,
|
|
148
278
|
stage,
|
|
@@ -333,17 +463,51 @@ async function evaluateTerminalGoal({ mode, iteration, targetDir, deadlineMs })
|
|
|
333
463
|
};
|
|
334
464
|
}
|
|
335
465
|
|
|
336
|
-
async function startAutoMode({ targetDir, now = new Date() }) {
|
|
466
|
+
async function startAutoMode({ targetDir, now = new Date(), requestedContract = null }) {
|
|
337
467
|
const mode = parseAutoMode(targetDir);
|
|
338
468
|
const existingStatus = parseAutoStatus(targetDir);
|
|
339
469
|
const existingLedger = parseAutoLedger(targetDir);
|
|
340
470
|
const evalProtocol = parseEvalProtocol(targetDir);
|
|
471
|
+
const lang = readWorkflowLanguage(targetDir);
|
|
341
472
|
const missingSchemaFields = listMissingCurrentAutoModeFields(mode);
|
|
342
473
|
if (missingSchemaFields.length > 0) {
|
|
343
474
|
throw new Error(
|
|
344
475
|
`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
476
|
);
|
|
346
477
|
}
|
|
478
|
+
if (requestedContract) {
|
|
479
|
+
const fit = classifyAutoContractFit({
|
|
480
|
+
mode,
|
|
481
|
+
status: existingStatus,
|
|
482
|
+
ledger: existingLedger,
|
|
483
|
+
requested: requestedContract,
|
|
484
|
+
});
|
|
485
|
+
if (fit.classification === "live-conflict") {
|
|
486
|
+
throw new Error(
|
|
487
|
+
`requested auto campaign conflicts with the current live campaign; stop the live campaign before rolling over (current: ${fit.currentCampaignKind}, requested: ${fit.requestedCampaignKind})`
|
|
488
|
+
);
|
|
489
|
+
}
|
|
490
|
+
if (fit.classification === "hard-mismatch") {
|
|
491
|
+
const normalizedRequest = normalizeRequestedAutoContract(requestedContract);
|
|
492
|
+
const { newMode, archivedPaths } = rolloverAutoCampaign({
|
|
493
|
+
targetDir,
|
|
494
|
+
mode,
|
|
495
|
+
status: existingStatus,
|
|
496
|
+
ledger: existingLedger,
|
|
497
|
+
requested: normalizedRequest,
|
|
498
|
+
lang,
|
|
499
|
+
now,
|
|
500
|
+
});
|
|
501
|
+
throw new Error(
|
|
502
|
+
`current auto contract does not fit the requested campaign and was rolled over to a new draft (${newMode.campaignId}); archived old campaign files: ${archivedPaths.join(", ")}; fill the new contract fields and approve it before starting auto mode`
|
|
503
|
+
);
|
|
504
|
+
}
|
|
505
|
+
if (fit.classification === "soft-mismatch") {
|
|
506
|
+
throw new Error(
|
|
507
|
+
`current auto contract only partially fits the requested campaign: ${fit.reason}; update auto-mode.md or narrow the request before starting auto mode`
|
|
508
|
+
);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
347
511
|
const issues = validateAutoMode(mode, null, evalProtocol);
|
|
348
512
|
if (issues.length > 0) {
|
|
349
513
|
throw new Error(issues.join(" | "));
|
|
@@ -366,7 +530,6 @@ async function startAutoMode({ targetDir, now = new Date() }) {
|
|
|
366
530
|
throw new Error(blockingIssue);
|
|
367
531
|
}
|
|
368
532
|
|
|
369
|
-
const lang = readWorkflowLanguage(targetDir);
|
|
370
533
|
const timestamp = now.toISOString();
|
|
371
534
|
const status = {
|
|
372
535
|
status: "running",
|
package/lib/auto_state.cjs
CHANGED
|
@@ -16,6 +16,9 @@ function parseAutoMode(targetDir) {
|
|
|
16
16
|
return {
|
|
17
17
|
path: contextFile(targetDir, "auto-mode.md"),
|
|
18
18
|
text,
|
|
19
|
+
campaignId: extractValue(text, ["Campaign id", "Campaign ID", "活动 id"]),
|
|
20
|
+
campaignKind: normalizeScalar(extractValue(text, ["Campaign kind", "活动类型"])),
|
|
21
|
+
campaignStartedAt: extractValue(text, ["Campaign started at", "活动开始时间"]),
|
|
19
22
|
objective: extractValue(text, ["Objective", "目标"]),
|
|
20
23
|
autonomyLevel: normalizeScalar(extractValue(text, ["Autonomy level", "自治级别"])),
|
|
21
24
|
approvalStatus: normalizeScalar(extractValue(text, ["Approval status", "批准状态"])),
|
|
@@ -52,7 +55,10 @@ function parseAutoMode(targetDir) {
|
|
|
52
55
|
};
|
|
53
56
|
}
|
|
54
57
|
|
|
55
|
-
const
|
|
58
|
+
const CURRENT_AUTO_MODE_MIGRATION_FIELDS = [
|
|
59
|
+
["Campaign id", "campaignId"],
|
|
60
|
+
["Campaign kind", "campaignKind"],
|
|
61
|
+
["Campaign started at", "campaignStartedAt"],
|
|
56
62
|
["Autonomy level", "autonomyLevel"],
|
|
57
63
|
["Approval status", "approvalStatus"],
|
|
58
64
|
["Terminal goal type", "terminalGoalType"],
|
|
@@ -65,12 +71,22 @@ const CURRENT_AUTO_MODE_SCHEMA_FIELDS = [
|
|
|
65
71
|
["Escalation reason", "escalationReason"],
|
|
66
72
|
];
|
|
67
73
|
|
|
74
|
+
const CURRENT_AUTO_MODE_SCHEMA_FIELDS = CURRENT_AUTO_MODE_MIGRATION_FIELDS.filter(
|
|
75
|
+
([label]) => !["Campaign id", "Campaign kind", "Campaign started at"].includes(label)
|
|
76
|
+
);
|
|
77
|
+
|
|
68
78
|
function listMissingCurrentAutoModeFields(mode) {
|
|
69
79
|
return CURRENT_AUTO_MODE_SCHEMA_FIELDS
|
|
70
80
|
.filter(([, key]) => !isMeaningful(mode[key]))
|
|
71
81
|
.map(([label]) => label);
|
|
72
82
|
}
|
|
73
83
|
|
|
84
|
+
function listMissingMigratedAutoModeFields(mode) {
|
|
85
|
+
return CURRENT_AUTO_MODE_MIGRATION_FIELDS
|
|
86
|
+
.filter(([, key]) => !isMeaningful(mode[key]))
|
|
87
|
+
.map(([label]) => label);
|
|
88
|
+
}
|
|
89
|
+
|
|
74
90
|
function parseAutoStatus(targetDir) {
|
|
75
91
|
const text = readFileIfExists(contextFile(targetDir, "auto-status.md"));
|
|
76
92
|
return {
|
|
@@ -392,18 +408,147 @@ function resolveRequiredArtifact(targetDir, configuredPath) {
|
|
|
392
408
|
};
|
|
393
409
|
}
|
|
394
410
|
|
|
411
|
+
function renderAutoModeContract(mode, { lang = "en" } = {}) {
|
|
412
|
+
const allowedStages = Array.isArray(mode.allowedStages) ? mode.allowedStages.join(", ") : (mode.allowedStages || "");
|
|
413
|
+
if (lang === "zh") {
|
|
414
|
+
return `# 自动模式契约
|
|
415
|
+
|
|
416
|
+
用这个文件定义 \`/lab:auto\` 的有边界自治执行范围。
|
|
417
|
+
|
|
418
|
+
## 目标
|
|
419
|
+
|
|
420
|
+
- Campaign id: ${mode.campaignId || ""}
|
|
421
|
+
- 活动类型: ${mode.campaignKind || ""}
|
|
422
|
+
- 活动开始时间: ${mode.campaignStartedAt || ""}
|
|
423
|
+
- Objective: ${mode.objective || ""}
|
|
424
|
+
- 自治级别: ${mode.autonomyLevel || "L2"}
|
|
425
|
+
- 批准状态: ${mode.approvalStatus || "draft"}
|
|
426
|
+
- 允许阶段: ${allowedStages}
|
|
427
|
+
- 成功标准: ${mode.successCriteria || ""}
|
|
428
|
+
- 终止目标类型: ${mode.terminalGoalType || ""}
|
|
429
|
+
- 终止目标目标值: ${mode.terminalGoalTarget || ""}
|
|
430
|
+
- 终止目标工件: ${mode.requiredTerminalArtifact || ""}
|
|
431
|
+
- 主 gate: ${mode.primaryGate || ""}
|
|
432
|
+
- 次级 guard: ${mode.secondaryGuard || ""}
|
|
433
|
+
- 升格条件: ${mode.promotionCondition || ""}
|
|
434
|
+
- 停止原因: ${mode.stopReason || ""}
|
|
435
|
+
- 升级原因: ${mode.escalationReason || ""}
|
|
436
|
+
|
|
437
|
+
## 循环预算
|
|
438
|
+
|
|
439
|
+
- Max iterations: ${mode.maxIterations || ""}
|
|
440
|
+
- Max wall-clock time: ${mode.maxWallClockTime || ""}
|
|
441
|
+
- Max failures: ${mode.maxFailures || ""}
|
|
442
|
+
- Poll interval: ${mode.pollInterval || ""}
|
|
443
|
+
|
|
444
|
+
## 阶段命令
|
|
445
|
+
|
|
446
|
+
- Run command: ${mode.stageCommands?.run || ""}
|
|
447
|
+
- Iterate command: ${mode.stageCommands?.iterate || ""}
|
|
448
|
+
- Review command: ${mode.stageCommands?.review || ""}
|
|
449
|
+
- Report command: ${mode.stageCommands?.report || ""}
|
|
450
|
+
- Write command: ${mode.stageCommands?.write || ""}
|
|
451
|
+
- Success check command: ${mode.successCheckCommand || ""}
|
|
452
|
+
- Stop check command: ${mode.stopCheckCommand || ""}
|
|
453
|
+
- Promotion check command: ${mode.promotionCheckCommand || ""}
|
|
454
|
+
- Promotion command: ${mode.promotionCommand || ""}
|
|
455
|
+
|
|
456
|
+
## 升格策略
|
|
457
|
+
|
|
458
|
+
- Promotion policy: ${mode.promotionPolicy || ""}
|
|
459
|
+
|
|
460
|
+
## 边界
|
|
461
|
+
|
|
462
|
+
- Frozen core: ${mode.frozenCore || ""}
|
|
463
|
+
- Exploration envelope: ${mode.explorationEnvelope || ""}
|
|
464
|
+
|
|
465
|
+
## 停止条件
|
|
466
|
+
|
|
467
|
+
- Stop conditions: ${mode.stopConditions || ""}
|
|
468
|
+
- Escalation conditions: ${mode.escalationConditions || ""}
|
|
469
|
+
`;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
return `# Auto Mode Contract
|
|
473
|
+
|
|
474
|
+
Use this file to define the bounded autonomous execution envelope for \`/lab:auto\`.
|
|
475
|
+
|
|
476
|
+
## Objective
|
|
477
|
+
|
|
478
|
+
- Campaign id: ${mode.campaignId || ""}
|
|
479
|
+
- Campaign kind: ${mode.campaignKind || ""}
|
|
480
|
+
- Campaign started at: ${mode.campaignStartedAt || ""}
|
|
481
|
+
- Objective: ${mode.objective || ""}
|
|
482
|
+
- Autonomy level: ${mode.autonomyLevel || "L2"}
|
|
483
|
+
- Approval status: ${mode.approvalStatus || "draft"}
|
|
484
|
+
- Allowed stages: ${allowedStages}
|
|
485
|
+
- Success criteria: ${mode.successCriteria || ""}
|
|
486
|
+
- Terminal goal type: ${mode.terminalGoalType || ""}
|
|
487
|
+
- Terminal goal target: ${mode.terminalGoalTarget || ""}
|
|
488
|
+
- Required terminal artifact: ${mode.requiredTerminalArtifact || ""}
|
|
489
|
+
- Primary gate: ${mode.primaryGate || ""}
|
|
490
|
+
- Secondary guard: ${mode.secondaryGuard || ""}
|
|
491
|
+
- Promotion condition: ${mode.promotionCondition || ""}
|
|
492
|
+
- Stop reason: ${mode.stopReason || ""}
|
|
493
|
+
- Escalation reason: ${mode.escalationReason || ""}
|
|
494
|
+
|
|
495
|
+
## Loop Budget
|
|
496
|
+
|
|
497
|
+
- Max iterations: ${mode.maxIterations || ""}
|
|
498
|
+
- Max wall-clock time: ${mode.maxWallClockTime || ""}
|
|
499
|
+
- Max failures: ${mode.maxFailures || ""}
|
|
500
|
+
- Poll interval: ${mode.pollInterval || ""}
|
|
501
|
+
|
|
502
|
+
## Stage Commands
|
|
503
|
+
|
|
504
|
+
- Run command: ${mode.stageCommands?.run || ""}
|
|
505
|
+
- Iterate command: ${mode.stageCommands?.iterate || ""}
|
|
506
|
+
- Review command: ${mode.stageCommands?.review || ""}
|
|
507
|
+
- Report command: ${mode.stageCommands?.report || ""}
|
|
508
|
+
- Write command: ${mode.stageCommands?.write || ""}
|
|
509
|
+
- Success check command: ${mode.successCheckCommand || ""}
|
|
510
|
+
- Stop check command: ${mode.stopCheckCommand || ""}
|
|
511
|
+
- Promotion check command: ${mode.promotionCheckCommand || ""}
|
|
512
|
+
- Promotion command: ${mode.promotionCommand || ""}
|
|
513
|
+
|
|
514
|
+
## Promotion Policy
|
|
515
|
+
|
|
516
|
+
- Promotion policy: ${mode.promotionPolicy || ""}
|
|
517
|
+
|
|
518
|
+
## Boundaries
|
|
519
|
+
|
|
520
|
+
- Frozen core: ${mode.frozenCore || ""}
|
|
521
|
+
- Exploration envelope: ${mode.explorationEnvelope || ""}
|
|
522
|
+
|
|
523
|
+
## Stop Conditions
|
|
524
|
+
|
|
525
|
+
- Stop conditions: ${mode.stopConditions || ""}
|
|
526
|
+
- Escalation conditions: ${mode.escalationConditions || ""}
|
|
527
|
+
`;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
function writeAutoMode(targetDir, mode, { lang = "en" } = {}) {
|
|
531
|
+
const filePath = contextFile(targetDir, "auto-mode.md");
|
|
532
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
533
|
+
fs.writeFileSync(filePath, renderAutoModeContract(mode, { lang }).trimEnd() + "\n");
|
|
534
|
+
}
|
|
535
|
+
|
|
395
536
|
module.exports = {
|
|
537
|
+
CURRENT_AUTO_MODE_MIGRATION_FIELDS,
|
|
396
538
|
CURRENT_AUTO_MODE_SCHEMA_FIELDS,
|
|
397
539
|
listMissingCurrentAutoModeFields,
|
|
540
|
+
listMissingMigratedAutoModeFields,
|
|
398
541
|
parseAutoLedger,
|
|
399
542
|
parseAutoMode,
|
|
400
543
|
parseAutoStatus,
|
|
401
544
|
readWorkflowLanguage,
|
|
402
545
|
renderAutoLedger,
|
|
546
|
+
renderAutoModeContract,
|
|
403
547
|
renderAutoOutcome,
|
|
404
548
|
renderAutoStatus,
|
|
405
549
|
resolveRequiredArtifact,
|
|
406
550
|
writeAutoLedger,
|
|
551
|
+
writeAutoMode,
|
|
407
552
|
writeAutoOutcome,
|
|
408
553
|
writeAutoStatus,
|
|
409
554
|
};
|
package/lib/i18n.cjs
CHANGED
|
@@ -2180,7 +2180,7 @@ ZH_CONTENT[path.join(".codex", "prompts", "lab-data.md")] = codexPrompt(
|
|
|
2180
2180
|
ZH_CONTENT[path.join(".codex", "prompts", "lab-auto.md")] = codexPrompt(
|
|
2181
2181
|
"在已批准边界内编排自动实验循环",
|
|
2182
2182
|
"auto mode objective",
|
|
2183
|
-
"使用已安装的 `lab` 技能:`.codex/skills/lab/SKILL.md`。\n\n立刻针对用户当前给出的参数执行 `/lab:auto`,不要只推荐别的 `/lab` 阶段。只有在缺少阻塞性前提时,才明确指出缺什么,并且一次最多追问一个问题。\n\n本命令运行 `/lab:auto` 阶段。它必须读取 `.lab/context/eval-protocol.md`、`.lab/context/auto-mode.md`、`.lab/context/auto-status.md`、`.lab/context/auto-ledger.md` 与 `.lab/context/auto-outcome.md`,先确认 autonomy level、approval status、terminal goal schema,以及 primary gate、secondary guard、promotion condition、stop reason、escalation reason,再把 eval-protocol 里的指标释义、主表计划、来源约束与结构化实验阶梯当作执行依据,在不修改 mission、framing 和核心 claims 的前提下编排已批准的 `run`、`iterate`、`review`、`report`,轮询长任务完成情况;如果声明了 rung,就保持会话活着并按 rung 转移继续推进。\n首个可见输出块必须是 `Auto preflight`。这个块必须列出已读取文件,并回显 `Autonomy level`、`Approval status`、`Allowed stages`、`Terminal goal`、`Primary gate` 和 `Secondary guard`,然后才能进入执行摘要或动作计划。\n如果 preflight 所需字段缺失、过期或彼此冲突,就必须在执行前停下,并明确指出到底是哪一个字段阻止了 loop 启动。\n当 loop 活着时,必须把当前 owner、观察状态、checkpoint 摘要、继续边界、停止边界和恢复读取集合写进 `.lab/context/auto-ledger.md`。\n如果仓库的 workflow language 是中文,摘要、清单条目、任务标签和进度更新都必须使用中文,除非某个文件路径、代码标识符或字面指标名必须保持原样。\n把 `Layer 3`、`Phase 1`、`Table 2` 这类表达视为论文范围目标;只有显式写成 `Autonomy level L3` 或 `自治级别 L3` 时,才把它当成执行权限级别。\n不要用 `sleep 30`、单次 `pgrep` 或一次性的 `metrics.json` 探针来代替真实长任务命令;当真实实验进程还活着时,只允许发进度更新并继续等待。"
|
|
2183
|
+
"使用已安装的 `lab` 技能:`.codex/skills/lab/SKILL.md`。\n\n立刻针对用户当前给出的参数执行 `/lab:auto`,不要只推荐别的 `/lab` 阶段。只有在缺少阻塞性前提时,才明确指出缺什么,并且一次最多追问一个问题。\n\n先把用户请求规范化成可交给 CLI 的 auto contract 字段:objective、autonomy level、campaign kind、allowed stages,以及任何不改变范围就能明确的 terminal-goal 提示。\n你的第一步执行动作必须是对当前项目运行 `superlab auto start`,而不是自己直接改写 `.lab/context/auto-mode.md`、`.lab/context/auto-status.md`、`.lab/context/auto-ledger.md` 或 `.lab/context/auto-outcome.md`。\n把规范化后的字段通过 CLI 参数传下去,包括 `--objective`、`--campaign-kind`、`--allowed-stages`,以及在用户已明确或已隐含时传 `--autonomy-level`。\nCLI 返回后的 runtime 结果才是事实来源。如果 CLI 报 rollover、conflict、缺字段,或已经成功启动 campaign,就如实回报,不要绕过 CLI 自己做 prompt 侧写回。\n\n本命令运行 `/lab:auto` 阶段。它必须读取 `.lab/context/eval-protocol.md`、`.lab/context/auto-mode.md`、`.lab/context/auto-status.md`、`.lab/context/auto-ledger.md` 与 `.lab/context/auto-outcome.md`,先确认 autonomy level、approval status、terminal goal schema,以及 primary gate、secondary guard、promotion condition、stop reason、escalation reason,再把 eval-protocol 里的指标释义、主表计划、来源约束与结构化实验阶梯当作执行依据,在不修改 mission、framing 和核心 claims 的前提下编排已批准的 `run`、`iterate`、`review`、`report`,轮询长任务完成情况;如果声明了 rung,就保持会话活着并按 rung 转移继续推进。\n首个可见输出块必须是 `Auto preflight`。这个块必须列出已读取文件,并回显 `Autonomy level`、`Approval status`、`Allowed stages`、`Terminal goal`、`Primary gate` 和 `Secondary guard`,然后才能进入执行摘要或动作计划。\n如果 preflight 所需字段缺失、过期或彼此冲突,就必须在执行前停下,并明确指出到底是哪一个字段阻止了 loop 启动。\n当 loop 活着时,必须把当前 owner、观察状态、checkpoint 摘要、继续边界、停止边界和恢复读取集合写进 `.lab/context/auto-ledger.md`。\n如果仓库的 workflow language 是中文,摘要、清单条目、任务标签和进度更新都必须使用中文,除非某个文件路径、代码标识符或字面指标名必须保持原样。\n把 `Layer 3`、`Phase 1`、`Table 2` 这类表达视为论文范围目标;只有显式写成 `Autonomy level L3` 或 `自治级别 L3` 时,才把它当成执行权限级别。\n不要用 `sleep 30`、单次 `pgrep` 或一次性的 `metrics.json` 探针来代替真实长任务命令;当真实实验进程还活着时,只允许发进度更新并继续等待。"
|
|
2184
2184
|
);
|
|
2185
2185
|
|
|
2186
2186
|
ZH_CONTENT[path.join(".claude", "commands", "lab.md")] = claudeCommand(
|
|
@@ -2201,7 +2201,7 @@ ZH_CONTENT[path.join(".claude", "commands", "lab-auto.md")] = claudeCommand(
|
|
|
2201
2201
|
"lab-auto",
|
|
2202
2202
|
"在已批准边界内编排自动实验循环",
|
|
2203
2203
|
"auto mode objective",
|
|
2204
|
-
"使用已安装的 `lab` 技能:`.claude/skills/lab/SKILL.md`。\n\n立刻针对用户当前给出的参数执行 `auto` 阶段,不要只推荐别的 lab 阶段。只有在缺少阻塞性前提时,才明确指出缺什么,并且一次最多追问一个问题。\n\n本命令运行 lab workflow 的 `auto` 阶段。它必须读取 `.lab/context/eval-protocol.md`、`.lab/context/auto-mode.md`、`.lab/context/auto-status.md`、`.lab/context/auto-ledger.md` 与 `.lab/context/auto-outcome.md`,先确认 autonomy level、approval status、terminal goal schema,以及 primary gate、secondary guard、promotion condition、stop reason、escalation reason,再把 eval-protocol 里的指标释义、主表计划、来源约束与结构化实验阶梯当作执行依据,在不修改 mission、framing 和核心 claims 的前提下编排已批准的 `run`、`iterate`、`review`、`report`,轮询长任务完成情况;如果声明了 rung,就保持会话活着并按 rung 转移继续推进。\n首个可见输出块必须是 `Auto preflight`。这个块必须列出已读取文件,并回显 `Autonomy level`、`Approval status`、`Allowed stages`、`Terminal goal`、`Primary gate` 和 `Secondary guard`,然后才能进入执行摘要或动作计划。\n如果 preflight 所需字段缺失、过期或彼此冲突,就必须在执行前停下,并明确指出到底是哪一个字段阻止了 loop 启动。\n当 loop 活着时,必须把当前 owner、观察状态、checkpoint 摘要、继续边界、停止边界和恢复读取集合写进 `.lab/context/auto-ledger.md`。\n如果仓库的 workflow language 是中文,摘要、清单条目、任务标签和进度更新都必须使用中文,除非某个文件路径、代码标识符或字面指标名必须保持原样。\n把 `Layer 3`、`Phase 1`、`Table 2` 这类表达视为论文范围目标;只有显式写成 `Autonomy level L3` 或 `自治级别 L3` 时,才把它当成执行权限级别。\n不要用 `sleep 30`、单次 `pgrep` 或一次性的 `metrics.json` 探针来代替真实长任务命令;当真实实验进程还活着时,只允许发进度更新并继续等待。"
|
|
2204
|
+
"使用已安装的 `lab` 技能:`.claude/skills/lab/SKILL.md`。\n\n立刻针对用户当前给出的参数执行 `auto` 阶段,不要只推荐别的 lab 阶段。只有在缺少阻塞性前提时,才明确指出缺什么,并且一次最多追问一个问题。\n\n先把用户请求规范化成可交给 CLI 的 auto contract 字段:objective、autonomy level、campaign kind、allowed stages,以及任何不改变范围就能明确的 terminal-goal 提示。\n你的第一步执行动作必须是对当前项目运行 `superlab auto start`,而不是自己直接改写 `.lab/context/auto-mode.md`、`.lab/context/auto-status.md`、`.lab/context/auto-ledger.md` 或 `.lab/context/auto-outcome.md`。\n把规范化后的字段通过 CLI 参数传下去,包括 `--objective`、`--campaign-kind`、`--allowed-stages`,以及在用户已明确或已隐含时传 `--autonomy-level`。\nCLI 返回后的 runtime 结果才是事实来源。如果 CLI 报 rollover、conflict、缺字段,或已经成功启动 campaign,就如实回报,不要绕过 CLI 自己做 prompt 侧写回。\n\n本命令运行 lab workflow 的 `auto` 阶段。它必须读取 `.lab/context/eval-protocol.md`、`.lab/context/auto-mode.md`、`.lab/context/auto-status.md`、`.lab/context/auto-ledger.md` 与 `.lab/context/auto-outcome.md`,先确认 autonomy level、approval status、terminal goal schema,以及 primary gate、secondary guard、promotion condition、stop reason、escalation reason,再把 eval-protocol 里的指标释义、主表计划、来源约束与结构化实验阶梯当作执行依据,在不修改 mission、framing 和核心 claims 的前提下编排已批准的 `run`、`iterate`、`review`、`report`,轮询长任务完成情况;如果声明了 rung,就保持会话活着并按 rung 转移继续推进。\n首个可见输出块必须是 `Auto preflight`。这个块必须列出已读取文件,并回显 `Autonomy level`、`Approval status`、`Allowed stages`、`Terminal goal`、`Primary gate` 和 `Secondary guard`,然后才能进入执行摘要或动作计划。\n如果 preflight 所需字段缺失、过期或彼此冲突,就必须在执行前停下,并明确指出到底是哪一个字段阻止了 loop 启动。\n当 loop 活着时,必须把当前 owner、观察状态、checkpoint 摘要、继续边界、停止边界和恢复读取集合写进 `.lab/context/auto-ledger.md`。\n如果仓库的 workflow language 是中文,摘要、清单条目、任务标签和进度更新都必须使用中文,除非某个文件路径、代码标识符或字面指标名必须保持原样。\n把 `Layer 3`、`Phase 1`、`Table 2` 这类表达视为论文范围目标;只有显式写成 `Autonomy level L3` 或 `自治级别 L3` 时,才把它当成执行权限级别。\n不要用 `sleep 30`、单次 `pgrep` 或一次性的 `metrics.json` 探针来代替真实长任务命令;当真实实验进程还活着时,只允许发进度更新并继续等待。"
|
|
2205
2205
|
);
|
|
2206
2206
|
|
|
2207
2207
|
const zhRecipeQuickPathLine =
|
package/lib/install.cjs
CHANGED
|
@@ -1,7 +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 {
|
|
4
|
+
const { CURRENT_AUTO_MODE_MIGRATION_FIELDS } = require("./auto_state.cjs");
|
|
5
5
|
const { getLocalizedContent } = require("./i18n.cjs");
|
|
6
6
|
|
|
7
7
|
const REPO_ROOT = path.resolve(__dirname, "..");
|
|
@@ -156,6 +156,9 @@ function installLabAssets(targetDir, force) {
|
|
|
156
156
|
function autoModeSchemaFieldLine(label, lang) {
|
|
157
157
|
if (lang === "zh") {
|
|
158
158
|
const zhDefaults = {
|
|
159
|
+
"Campaign id": "- Campaign id: ",
|
|
160
|
+
"Campaign kind": "- 活动类型: ",
|
|
161
|
+
"Campaign started at": "- 活动开始时间: ",
|
|
159
162
|
"Autonomy level": "- 自治级别: L2",
|
|
160
163
|
"Approval status": "- 批准状态: draft",
|
|
161
164
|
"Terminal goal type": "- 终止目标类型: ",
|
|
@@ -171,6 +174,9 @@ function autoModeSchemaFieldLine(label, lang) {
|
|
|
171
174
|
}
|
|
172
175
|
|
|
173
176
|
const defaults = {
|
|
177
|
+
"Campaign id": "- Campaign id: ",
|
|
178
|
+
"Campaign kind": "- Campaign kind: ",
|
|
179
|
+
"Campaign started at": "- Campaign started at: ",
|
|
174
180
|
"Autonomy level": "- Autonomy level: L2",
|
|
175
181
|
"Approval status": "- Approval status: draft",
|
|
176
182
|
"Terminal goal type": "- Terminal goal type: ",
|
|
@@ -192,7 +198,7 @@ function migrateAutoModeContext(targetDir, lang) {
|
|
|
192
198
|
}
|
|
193
199
|
|
|
194
200
|
const existing = fs.readFileSync(filePath, "utf8");
|
|
195
|
-
const missing =
|
|
201
|
+
const missing = CURRENT_AUTO_MODE_MIGRATION_FIELDS
|
|
196
202
|
.map(([label]) => label)
|
|
197
203
|
.filter((label) => {
|
|
198
204
|
const localizedLabel = autoModeSchemaFieldLine(label, lang).replace(/^- /, "").split(":")[0];
|
|
@@ -7,6 +7,10 @@ argument-hint: autonomous campaign target
|
|
|
7
7
|
Use the installed `lab` skill at `.claude/skills/lab/SKILL.md`.
|
|
8
8
|
|
|
9
9
|
Execute the requested `/lab-auto` command against the user's argument now. Do not only recommend another lab stage. If a blocking prerequisite is missing, say exactly what is missing and ask at most one clarifying question.
|
|
10
|
+
First normalize the user's request into CLI-ready auto contract fields: objective, autonomy level, campaign kind, allowed stages, and any explicit terminal-goal hints that can be inferred without changing scope.
|
|
11
|
+
Your first execution action must be to run `superlab auto start` against the current project instead of directly rewriting `.lab/context/auto-mode.md`, `.lab/context/auto-status.md`, `.lab/context/auto-ledger.md`, or `.lab/context/auto-outcome.md` yourself.
|
|
12
|
+
Pass the normalized fields through CLI flags, including `--objective`, `--campaign-kind`, `--allowed-stages`, and `--autonomy-level` when the user specified or implied them.
|
|
13
|
+
After that CLI handoff, treat the CLI/runtime result as the source of truth. If it reports rollover, conflict, missing contract fields, or a started campaign, reflect that result back to the user instead of bypassing it with prompt-side edits.
|
|
10
14
|
This command runs the `auto` stage of the lab workflow. It must read `.lab/context/eval-protocol.md`, `.lab/context/auto-mode.md`, `.lab/context/auto-status.md`, `.lab/context/auto-ledger.md`, and `.lab/context/auto-outcome.md`, enforce the declared terminal goal schema, make the primary gate, secondary guard, promotion condition, stop reason, and escalation reason explicit, orchestrate approved run, iterate, review, and report stages inside that contract, poll long-running work until completion or stop conditions, and write live owner state plus progress and the final outcome back into `.lab/context/auto-status.md`, `.lab/context/auto-ledger.md`, and `.lab/context/auto-outcome.md`.
|
|
11
15
|
The first visible block must be `Auto preflight`. That first visible block must list the files read and echo `Autonomy level`, `Approval status`, `Allowed stages`, `Terminal goal`, `Primary gate`, and `Secondary guard` before any execution summary or action plan.
|
|
12
16
|
If the preflight block cannot be completed because any required field is missing, stale, or inconsistent, stop before execution and say exactly which field blocked arming the loop.
|
|
@@ -7,6 +7,10 @@ argument-hint: autonomous campaign target
|
|
|
7
7
|
Use the installed `lab` skill at `.claude/skills/lab/SKILL.md`.
|
|
8
8
|
|
|
9
9
|
Execute the requested `/lab-auto` command against the user's argument now. Do not only recommend another lab stage. If a blocking prerequisite is missing, say exactly what is missing and ask at most one clarifying question.
|
|
10
|
+
First normalize the user's request into CLI-ready auto contract fields: objective, autonomy level, campaign kind, allowed stages, and any explicit terminal-goal hints that can be inferred without changing scope.
|
|
11
|
+
Your first execution action must be to run `superlab auto start` against the current project instead of directly rewriting `.lab/context/auto-mode.md`, `.lab/context/auto-status.md`, `.lab/context/auto-ledger.md`, or `.lab/context/auto-outcome.md` yourself.
|
|
12
|
+
Pass the normalized fields through CLI flags, including `--objective`, `--campaign-kind`, `--allowed-stages`, and `--autonomy-level` when the user specified or implied them.
|
|
13
|
+
After that CLI handoff, treat the CLI/runtime result as the source of truth. If it reports rollover, conflict, missing contract fields, or a started campaign, reflect that result back to the user instead of bypassing it with prompt-side edits.
|
|
10
14
|
This command runs the `auto` stage of the lab workflow. It must read `.lab/context/eval-protocol.md`, `.lab/context/auto-mode.md`, `.lab/context/auto-status.md`, `.lab/context/auto-ledger.md`, and `.lab/context/auto-outcome.md`, enforce the declared terminal goal schema, make the primary gate, secondary guard, promotion condition, stop reason, and escalation reason explicit, orchestrate approved run, iterate, review, and report stages inside that contract, poll long-running work until completion or stop conditions, and write live owner state plus progress and the final outcome back into `.lab/context/auto-status.md`, `.lab/context/auto-ledger.md`, and `.lab/context/auto-outcome.md`.
|
|
11
15
|
The first visible block must be `Auto preflight`. That first visible block must list the files read and echo `Autonomy level`, `Approval status`, `Allowed stages`, `Terminal goal`, `Primary gate`, and `Secondary guard` before any execution summary or action plan.
|
|
12
16
|
If the preflight block cannot be completed because any required field is missing, stale, or inconsistent, stop before execution and say exactly which field blocked arming the loop.
|
|
@@ -7,6 +7,10 @@ argument-hint: autonomous campaign target
|
|
|
7
7
|
Use the installed `lab` skill at `.claude/skills/lab/SKILL.md`.
|
|
8
8
|
|
|
9
9
|
Execute the requested `/lab-auto` command against the user's argument now. Do not only recommend another lab stage. If a blocking prerequisite is missing, say exactly what is missing and ask at most one clarifying question.
|
|
10
|
+
First normalize the user's request into CLI-ready auto contract fields: objective, autonomy level, campaign kind, allowed stages, and any explicit terminal-goal hints that can be inferred without changing scope.
|
|
11
|
+
Your first execution action must be to run `superlab auto start` against the current project instead of directly rewriting `.lab/context/auto-mode.md`, `.lab/context/auto-status.md`, `.lab/context/auto-ledger.md`, or `.lab/context/auto-outcome.md` yourself.
|
|
12
|
+
Pass the normalized fields through CLI flags, including `--objective`, `--campaign-kind`, `--allowed-stages`, and `--autonomy-level` when the user specified or implied them.
|
|
13
|
+
After that CLI handoff, treat the CLI/runtime result as the source of truth. If it reports rollover, conflict, missing contract fields, or a started campaign, reflect that result back to the user instead of bypassing it with prompt-side edits.
|
|
10
14
|
This command runs the `auto` stage of the lab workflow. It must read `.lab/context/eval-protocol.md`, `.lab/context/auto-mode.md`, `.lab/context/auto-status.md`, `.lab/context/auto-ledger.md`, and `.lab/context/auto-outcome.md`, enforce the declared terminal goal schema, make the primary gate, secondary guard, promotion condition, stop reason, and escalation reason explicit, orchestrate approved run, iterate, review, and report stages inside that contract, poll long-running work until completion or stop conditions, and write live owner state plus progress and the final outcome back into `.lab/context/auto-status.md`, `.lab/context/auto-ledger.md`, and `.lab/context/auto-outcome.md`.
|
|
11
15
|
The first visible block must be `Auto preflight`. That first visible block must list the files read and echo `Autonomy level`, `Approval status`, `Allowed stages`, `Terminal goal`, `Primary gate`, and `Secondary guard` before any execution summary or action plan.
|
|
12
16
|
If the preflight block cannot be completed because any required field is missing, stale, or inconsistent, stop before execution and say exactly which field blocked arming the loop.
|
|
@@ -7,6 +7,10 @@ argument-hint: autonomous campaign target
|
|
|
7
7
|
Use the installed `lab` skill at `.claude/skills/lab/SKILL.md`.
|
|
8
8
|
|
|
9
9
|
Execute the requested `/lab-auto` command against the user's argument now. Do not only recommend another lab stage. If a blocking prerequisite is missing, say exactly what is missing and ask at most one clarifying question.
|
|
10
|
+
First normalize the user's request into CLI-ready auto contract fields: objective, autonomy level, campaign kind, allowed stages, and any explicit terminal-goal hints that can be inferred without changing scope.
|
|
11
|
+
Your first execution action must be to run `superlab auto start` against the current project instead of directly rewriting `.lab/context/auto-mode.md`, `.lab/context/auto-status.md`, `.lab/context/auto-ledger.md`, or `.lab/context/auto-outcome.md` yourself.
|
|
12
|
+
Pass the normalized fields through CLI flags, including `--objective`, `--campaign-kind`, `--allowed-stages`, and `--autonomy-level` when the user specified or implied them.
|
|
13
|
+
After that CLI handoff, treat the CLI/runtime result as the source of truth. If it reports rollover, conflict, missing contract fields, or a started campaign, reflect that result back to the user instead of bypassing it with prompt-side edits.
|
|
10
14
|
This command runs the `auto` stage of the lab workflow. It must read `.lab/context/eval-protocol.md`, `.lab/context/auto-mode.md`, `.lab/context/auto-status.md`, `.lab/context/auto-ledger.md`, and `.lab/context/auto-outcome.md`, enforce the declared terminal goal schema, make the primary gate, secondary guard, promotion condition, stop reason, and escalation reason explicit, orchestrate approved run, iterate, review, and report stages inside that contract, poll long-running work until completion or stop conditions, and write live owner state plus progress and the final outcome back into `.lab/context/auto-status.md`, `.lab/context/auto-ledger.md`, and `.lab/context/auto-outcome.md`.
|
|
11
15
|
The first visible block must be `Auto preflight`. That first visible block must list the files read and echo `Autonomy level`, `Approval status`, `Allowed stages`, `Terminal goal`, `Primary gate`, and `Secondary guard` before any execution summary or action plan.
|
|
12
16
|
If the preflight block cannot be completed because any required field is missing, stale, or inconsistent, stop before execution and say exactly which field blocked arming the loop.
|
|
@@ -6,6 +6,10 @@ argument-hint: autonomous campaign target
|
|
|
6
6
|
Use the installed `lab` skill at `.codex/skills/lab/SKILL.md`.
|
|
7
7
|
|
|
8
8
|
Execute the requested `/lab:auto` stage against the user's argument now. Do not only recommend another lab stage. If a blocking prerequisite is missing, say exactly what is missing and ask at most one clarifying question.
|
|
9
|
+
First normalize the user's request into CLI-ready auto contract fields: objective, autonomy level, campaign kind, allowed stages, and any explicit terminal-goal hints that can be inferred without changing scope.
|
|
10
|
+
Your first execution action must be to run `superlab auto start` against the current project instead of directly rewriting `.lab/context/auto-mode.md`, `.lab/context/auto-status.md`, `.lab/context/auto-ledger.md`, or `.lab/context/auto-outcome.md` yourself.
|
|
11
|
+
Pass the normalized fields through CLI flags, including `--objective`, `--campaign-kind`, `--allowed-stages`, and `--autonomy-level` when the user specified or implied them.
|
|
12
|
+
After that CLI handoff, treat the CLI/runtime result as the source of truth. If it reports rollover, conflict, missing contract fields, or a started campaign, reflect that result back to the user instead of bypassing it with prompt-side edits.
|
|
9
13
|
This command runs the `/lab:auto` stage. It must read `.lab/context/eval-protocol.md`, `.lab/context/auto-mode.md`, `.lab/context/auto-status.md`, `.lab/context/auto-ledger.md`, and `.lab/context/auto-outcome.md`, enforce the declared terminal goal schema, make the primary gate, secondary guard, promotion condition, stop reason, and escalation reason explicit, orchestrate approved run, iterate, review, and report stages inside that contract, poll long-running work until completion or stop conditions, and write live owner state plus progress and the final outcome back into `.lab/context/auto-status.md`, `.lab/context/auto-ledger.md`, and `.lab/context/auto-outcome.md`.
|
|
10
14
|
The first visible block must be `Auto preflight`. That first visible block must list the files read and echo `Autonomy level`, `Approval status`, `Allowed stages`, `Terminal goal`, `Primary gate`, and `Secondary guard` before any execution summary or action plan.
|
|
11
15
|
If the preflight block cannot be completed because any required field is missing, stale, or inconsistent, stop before execution and say exactly which field blocked arming the loop.
|
|
@@ -6,6 +6,10 @@ argument-hint: autonomous campaign target
|
|
|
6
6
|
Use the installed `lab` skill at `.codex/skills/lab/SKILL.md`.
|
|
7
7
|
|
|
8
8
|
Execute the requested `/lab:auto` stage against the user's argument now. Do not only recommend another lab stage. If a blocking prerequisite is missing, say exactly what is missing and ask at most one clarifying question.
|
|
9
|
+
First normalize the user's request into CLI-ready auto contract fields: objective, autonomy level, campaign kind, allowed stages, and any explicit terminal-goal hints that can be inferred without changing scope.
|
|
10
|
+
Your first execution action must be to run `superlab auto start` against the current project instead of directly rewriting `.lab/context/auto-mode.md`, `.lab/context/auto-status.md`, `.lab/context/auto-ledger.md`, or `.lab/context/auto-outcome.md` yourself.
|
|
11
|
+
Pass the normalized fields through CLI flags, including `--objective`, `--campaign-kind`, `--allowed-stages`, and `--autonomy-level` when the user specified or implied them.
|
|
12
|
+
After that CLI handoff, treat the CLI/runtime result as the source of truth. If it reports rollover, conflict, missing contract fields, or a started campaign, reflect that result back to the user instead of bypassing it with prompt-side edits.
|
|
9
13
|
This command runs the `/lab:auto` stage. It must read `.lab/context/eval-protocol.md`, `.lab/context/auto-mode.md`, `.lab/context/auto-status.md`, `.lab/context/auto-ledger.md`, and `.lab/context/auto-outcome.md`, enforce the declared terminal goal schema, make the primary gate, secondary guard, promotion condition, stop reason, and escalation reason explicit, orchestrate approved run, iterate, review, and report stages inside that contract, poll long-running work until completion or stop conditions, and write live owner state plus progress and the final outcome back into `.lab/context/auto-status.md`, `.lab/context/auto-ledger.md`, and `.lab/context/auto-outcome.md`.
|
|
10
14
|
The first visible block must be `Auto preflight`. That first visible block must list the files read and echo `Autonomy level`, `Approval status`, `Allowed stages`, `Terminal goal`, `Primary gate`, and `Secondary guard` before any execution summary or action plan.
|
|
11
15
|
If the preflight block cannot be completed because any required field is missing, stale, or inconsistent, stop before execution and say exactly which field blocked arming the loop.
|
|
@@ -6,6 +6,10 @@ argument-hint: autonomous campaign target
|
|
|
6
6
|
Use the installed `lab` skill at `.codex/skills/lab/SKILL.md`.
|
|
7
7
|
|
|
8
8
|
Execute the requested `/lab:auto` stage against the user's argument now. Do not only recommend another lab stage. If a blocking prerequisite is missing, say exactly what is missing and ask at most one clarifying question.
|
|
9
|
+
First normalize the user's request into CLI-ready auto contract fields: objective, autonomy level, campaign kind, allowed stages, and any explicit terminal-goal hints that can be inferred without changing scope.
|
|
10
|
+
Your first execution action must be to run `superlab auto start` against the current project instead of directly rewriting `.lab/context/auto-mode.md`, `.lab/context/auto-status.md`, `.lab/context/auto-ledger.md`, or `.lab/context/auto-outcome.md` yourself.
|
|
11
|
+
Pass the normalized fields through CLI flags, including `--objective`, `--campaign-kind`, `--allowed-stages`, and `--autonomy-level` when the user specified or implied them.
|
|
12
|
+
After that CLI handoff, treat the CLI/runtime result as the source of truth. If it reports rollover, conflict, missing contract fields, or a started campaign, reflect that result back to the user instead of bypassing it with prompt-side edits.
|
|
9
13
|
This command runs the `/lab:auto` stage. It must read `.lab/context/eval-protocol.md`, `.lab/context/auto-mode.md`, `.lab/context/auto-status.md`, `.lab/context/auto-ledger.md`, and `.lab/context/auto-outcome.md`, enforce the declared terminal goal schema, make the primary gate, secondary guard, promotion condition, stop reason, and escalation reason explicit, orchestrate approved run, iterate, review, and report stages inside that contract, poll long-running work until completion or stop conditions, and write live owner state plus progress and the final outcome back into `.lab/context/auto-status.md`, `.lab/context/auto-ledger.md`, and `.lab/context/auto-outcome.md`.
|
|
10
14
|
The first visible block must be `Auto preflight`. That first visible block must list the files read and echo `Autonomy level`, `Approval status`, `Allowed stages`, `Terminal goal`, `Primary gate`, and `Secondary guard` before any execution summary or action plan.
|
|
11
15
|
If the preflight block cannot be completed because any required field is missing, stale, or inconsistent, stop before execution and say exactly which field blocked arming the loop.
|
|
@@ -6,6 +6,10 @@ argument-hint: autonomous campaign target
|
|
|
6
6
|
Use the installed `lab` skill at `.codex/skills/lab/SKILL.md`.
|
|
7
7
|
|
|
8
8
|
Execute the requested `/lab:auto` stage against the user's argument now. Do not only recommend another lab stage. If a blocking prerequisite is missing, say exactly what is missing and ask at most one clarifying question.
|
|
9
|
+
First normalize the user's request into CLI-ready auto contract fields: objective, autonomy level, campaign kind, allowed stages, and any explicit terminal-goal hints that can be inferred without changing scope.
|
|
10
|
+
Your first execution action must be to run `superlab auto start` against the current project instead of directly rewriting `.lab/context/auto-mode.md`, `.lab/context/auto-status.md`, `.lab/context/auto-ledger.md`, or `.lab/context/auto-outcome.md` yourself.
|
|
11
|
+
Pass the normalized fields through CLI flags, including `--objective`, `--campaign-kind`, `--allowed-stages`, and `--autonomy-level` when the user specified or implied them.
|
|
12
|
+
After that CLI handoff, treat the CLI/runtime result as the source of truth. If it reports rollover, conflict, missing contract fields, or a started campaign, reflect that result back to the user instead of bypassing it with prompt-side edits.
|
|
9
13
|
This command runs the `/lab:auto` stage. It must read `.lab/context/eval-protocol.md`, `.lab/context/auto-mode.md`, `.lab/context/auto-status.md`, `.lab/context/auto-ledger.md`, and `.lab/context/auto-outcome.md`, enforce the declared terminal goal schema, make the primary gate, secondary guard, promotion condition, stop reason, and escalation reason explicit, orchestrate approved run, iterate, review, and report stages inside that contract, poll long-running work until completion or stop conditions, and write live owner state plus progress and the final outcome back into `.lab/context/auto-status.md`, `.lab/context/auto-ledger.md`, and `.lab/context/auto-outcome.md`.
|
|
10
14
|
The first visible block must be `Auto preflight`. That first visible block must list the files read and echo `Autonomy level`, `Approval status`, `Allowed stages`, `Terminal goal`, `Primary gate`, and `Secondary guard` before any execution summary or action plan.
|
|
11
15
|
If the preflight block cannot be completed because any required field is missing, stale, or inconsistent, stop before execution and say exactly which field blocked arming the loop.
|
|
@@ -7,6 +7,9 @@ Use `.lab/context/auto-ledger.md` as the live runtime ledger for ownership, chec
|
|
|
7
7
|
|
|
8
8
|
## Objective
|
|
9
9
|
|
|
10
|
+
- Campaign id:
|
|
11
|
+
- Campaign kind:
|
|
12
|
+
- Campaign started at:
|
|
10
13
|
- Objective:
|
|
11
14
|
- Autonomy level: L2
|
|
12
15
|
- Autonomy level controls execution privilege, not paper layer or table number.
|