superlab 0.1.41 → 0.1.43
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/lib/auto_runner.cjs +264 -8
- package/lib/auto_state.cjs +114 -0
- package/lib/i18n.cjs +43 -4
- package/lib/install.cjs +1 -0
- package/package-assets/claude/commands/lab-auto.md +3 -1
- package/package-assets/claude/commands/lab.md +4 -0
- package/package-assets/codex/prompts/lab-auto.md +3 -1
- package/package-assets/codex/prompts/lab.md +4 -0
- package/package-assets/shared/lab/context/auto-ledger.md +35 -0
- package/package-assets/shared/lab/context/auto-mode.md +2 -0
- package/package-assets/shared/skills/lab/SKILL.md +5 -2
- package/package-assets/shared/skills/lab/stages/auto.md +30 -9
- package/package.json +1 -1
package/lib/auto_runner.cjs
CHANGED
|
@@ -21,10 +21,12 @@ const {
|
|
|
21
21
|
verifyStageContract,
|
|
22
22
|
} = require("./auto_contracts.cjs");
|
|
23
23
|
const {
|
|
24
|
+
parseAutoLedger,
|
|
24
25
|
parseAutoMode,
|
|
25
26
|
parseAutoStatus,
|
|
26
27
|
readWorkflowLanguage,
|
|
27
28
|
resolveRequiredArtifact,
|
|
29
|
+
writeAutoLedger,
|
|
28
30
|
writeAutoOutcome,
|
|
29
31
|
writeAutoStatus,
|
|
30
32
|
} = require("./auto_state.cjs");
|
|
@@ -33,6 +35,10 @@ function normalizeTransition(value) {
|
|
|
33
35
|
return (value || "").trim();
|
|
34
36
|
}
|
|
35
37
|
|
|
38
|
+
function normalizeObservedState(value) {
|
|
39
|
+
return (value || "").trim().toLowerCase();
|
|
40
|
+
}
|
|
41
|
+
|
|
36
42
|
function isSuccessTransition(value) {
|
|
37
43
|
return ["success", "terminal-success", "campaign-success"].includes((value || "").trim().toLowerCase());
|
|
38
44
|
}
|
|
@@ -41,6 +47,101 @@ function isStopTransition(value) {
|
|
|
41
47
|
return ["stop", "campaign-stop", "terminal-stop"].includes((value || "").trim().toLowerCase());
|
|
42
48
|
}
|
|
43
49
|
|
|
50
|
+
function isLocalProcessAlive(ownerId) {
|
|
51
|
+
const pid = parseInteger(ownerId, null);
|
|
52
|
+
if (!Number.isInteger(pid) || pid <= 0) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
try {
|
|
56
|
+
process.kill(pid, 0);
|
|
57
|
+
return true;
|
|
58
|
+
} catch (error) {
|
|
59
|
+
if (error && error.code === "EPERM") {
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function resolveResumePlan({ mode, evalProtocol, status, ledger, now }) {
|
|
67
|
+
const hasLedgerState = [
|
|
68
|
+
ledger.campaignId,
|
|
69
|
+
ledger.observedState,
|
|
70
|
+
ledger.activeRung,
|
|
71
|
+
ledger.nextTransition,
|
|
72
|
+
ledger.ownerId,
|
|
73
|
+
].some((value) => isMeaningful(value));
|
|
74
|
+
if (!hasLedgerState) {
|
|
75
|
+
return { blockingIssue: "", resumePlan: null };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if ((ledger.ownerType || "").trim().toLowerCase() === "local-process" && isLocalProcessAlive(ledger.ownerId)) {
|
|
79
|
+
return {
|
|
80
|
+
blockingIssue: `auto campaign already has a live local owner: ${ledger.ownerId}`,
|
|
81
|
+
resumePlan: null,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const startedAt = isMeaningful(status.startedAt) ? status.startedAt : now.toISOString();
|
|
86
|
+
const campaignId = isMeaningful(ledger.campaignId)
|
|
87
|
+
? ledger.campaignId
|
|
88
|
+
: `auto-${startedAt.replace(/[:.]/g, "-")}`;
|
|
89
|
+
const iterationCount = parseInteger(status.iterationCount, 0);
|
|
90
|
+
const observedState = normalizeObservedState(ledger.observedState);
|
|
91
|
+
|
|
92
|
+
if (evalProtocol.experimentRungs.length > 0) {
|
|
93
|
+
const rungMap = new Map(evalProtocol.experimentRungs.map((rung) => [rung.id, rung]));
|
|
94
|
+
const nextTransition = normalizeTransition(ledger.nextTransition || status.nextRung);
|
|
95
|
+
if (
|
|
96
|
+
isMeaningful(nextTransition) &&
|
|
97
|
+
!isSuccessTransition(nextTransition) &&
|
|
98
|
+
!isStopTransition(nextTransition) &&
|
|
99
|
+
rungMap.has(nextTransition)
|
|
100
|
+
) {
|
|
101
|
+
const rung = rungMap.get(nextTransition);
|
|
102
|
+
return {
|
|
103
|
+
blockingIssue: "",
|
|
104
|
+
resumePlan: {
|
|
105
|
+
kind: "ladder",
|
|
106
|
+
rungId: nextTransition,
|
|
107
|
+
stage: rung.stage,
|
|
108
|
+
watchTarget: rung.watch,
|
|
109
|
+
campaignId,
|
|
110
|
+
startedAt,
|
|
111
|
+
iterationsCompleted: iterationCount,
|
|
112
|
+
lastCheckpoint: ledger.lastCheckpoint || status.lastCheckpoint || "",
|
|
113
|
+
reason: `resuming at next rung ${nextTransition}`,
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const activeRung = normalizeTransition(ledger.activeRung || status.currentRung);
|
|
119
|
+
if (
|
|
120
|
+
["running", "retrying"].includes(observedState) &&
|
|
121
|
+
isMeaningful(activeRung) &&
|
|
122
|
+
rungMap.has(activeRung)
|
|
123
|
+
) {
|
|
124
|
+
const rung = rungMap.get(activeRung);
|
|
125
|
+
return {
|
|
126
|
+
blockingIssue: "",
|
|
127
|
+
resumePlan: {
|
|
128
|
+
kind: "ladder",
|
|
129
|
+
rungId: activeRung,
|
|
130
|
+
stage: rung.stage,
|
|
131
|
+
watchTarget: rung.watch,
|
|
132
|
+
campaignId,
|
|
133
|
+
startedAt,
|
|
134
|
+
iterationsCompleted: Math.max(0, iterationCount - 1),
|
|
135
|
+
lastCheckpoint: ledger.lastCheckpoint || status.lastCheckpoint || "",
|
|
136
|
+
reason: `restarting active rung ${activeRung} after owner exit`,
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return { blockingIssue: "", resumePlan: null };
|
|
143
|
+
}
|
|
144
|
+
|
|
44
145
|
async function runCommandWithPolling({
|
|
45
146
|
targetDir,
|
|
46
147
|
stage,
|
|
@@ -53,6 +154,8 @@ async function runCommandWithPolling({
|
|
|
53
154
|
rungId = "",
|
|
54
155
|
watchTarget = "",
|
|
55
156
|
nextRung = "",
|
|
157
|
+
ownerInfo = null,
|
|
158
|
+
updateLedger = null,
|
|
56
159
|
}) {
|
|
57
160
|
const child = spawn(command, {
|
|
58
161
|
cwd: targetDir,
|
|
@@ -106,6 +209,20 @@ async function runCommandWithPolling({
|
|
|
106
209
|
},
|
|
107
210
|
{ lang }
|
|
108
211
|
);
|
|
212
|
+
if (typeof updateLedger === "function") {
|
|
213
|
+
updateLedger({
|
|
214
|
+
ownerType: ownerInfo?.ownerType || "local-process",
|
|
215
|
+
ownerId: String(child.pid || ownerInfo?.ownerId || ""),
|
|
216
|
+
command,
|
|
217
|
+
watchTarget,
|
|
218
|
+
activeStage: stage,
|
|
219
|
+
activeRung: rungId,
|
|
220
|
+
startedAt,
|
|
221
|
+
lastObservedAt: new Date().toISOString(),
|
|
222
|
+
observedState: "running",
|
|
223
|
+
nextTransition: nextRung || "",
|
|
224
|
+
});
|
|
225
|
+
}
|
|
109
226
|
await sleep(pollIntervalMs);
|
|
110
227
|
}
|
|
111
228
|
|
|
@@ -217,6 +334,8 @@ async function evaluateTerminalGoal({ mode, iteration, targetDir, deadlineMs })
|
|
|
217
334
|
|
|
218
335
|
async function startAutoMode({ targetDir, now = new Date() }) {
|
|
219
336
|
const mode = parseAutoMode(targetDir);
|
|
337
|
+
const existingStatus = parseAutoStatus(targetDir);
|
|
338
|
+
const existingLedger = parseAutoLedger(targetDir);
|
|
220
339
|
const evalProtocol = parseEvalProtocol(targetDir);
|
|
221
340
|
const issues = validateAutoMode(mode, null, evalProtocol);
|
|
222
341
|
if (issues.length > 0) {
|
|
@@ -229,20 +348,30 @@ async function startAutoMode({ targetDir, now = new Date() }) {
|
|
|
229
348
|
if (mode.approvalStatus !== "approved") {
|
|
230
349
|
throw new Error(`approval status must be approved before auto mode can start (current: ${mode.approvalStatus || "missing"})`);
|
|
231
350
|
}
|
|
351
|
+
const { blockingIssue, resumePlan } = resolveResumePlan({
|
|
352
|
+
mode,
|
|
353
|
+
evalProtocol,
|
|
354
|
+
status: existingStatus,
|
|
355
|
+
ledger: existingLedger,
|
|
356
|
+
now,
|
|
357
|
+
});
|
|
358
|
+
if (blockingIssue) {
|
|
359
|
+
throw new Error(blockingIssue);
|
|
360
|
+
}
|
|
232
361
|
|
|
233
362
|
const lang = readWorkflowLanguage(targetDir);
|
|
234
363
|
const timestamp = now.toISOString();
|
|
235
364
|
const status = {
|
|
236
365
|
status: "running",
|
|
237
|
-
currentStage: mode.allowedStages[0] || "run",
|
|
366
|
+
currentStage: resumePlan?.stage || mode.allowedStages[0] || "run",
|
|
238
367
|
currentCommand: "",
|
|
239
368
|
activeRunId: "",
|
|
240
|
-
iterationCount:
|
|
241
|
-
startedAt: timestamp,
|
|
369
|
+
iterationCount: String(resumePlan?.iterationsCompleted || 0),
|
|
370
|
+
startedAt: resumePlan?.startedAt || timestamp,
|
|
242
371
|
lastHeartbeat: timestamp,
|
|
243
|
-
lastCheckpoint: "",
|
|
244
|
-
lastSummary: "",
|
|
245
|
-
decision: "armed for bounded auto orchestration",
|
|
372
|
+
lastCheckpoint: resumePlan?.lastCheckpoint || "",
|
|
373
|
+
lastSummary: resumePlan?.reason || "",
|
|
374
|
+
decision: resumePlan?.reason || "armed for bounded auto orchestration",
|
|
246
375
|
};
|
|
247
376
|
writeAutoStatus(targetDir, status, { lang });
|
|
248
377
|
|
|
@@ -257,13 +386,36 @@ async function startAutoMode({ targetDir, now = new Date() }) {
|
|
|
257
386
|
const { loopStages, finalStages } = splitAutoStages(mode.allowedStages);
|
|
258
387
|
const executedStages = [];
|
|
259
388
|
let failureCount = 0;
|
|
260
|
-
let iterationsCompleted = 0;
|
|
389
|
+
let iterationsCompleted = resumePlan?.iterationsCompleted || 0;
|
|
261
390
|
let currentStatus = { ...status };
|
|
262
391
|
let successReached = false;
|
|
263
392
|
let stopMatched = false;
|
|
264
393
|
let promotionApplied = false;
|
|
265
394
|
let stopReason = "";
|
|
266
395
|
let finalRung = "";
|
|
396
|
+
const campaignId = resumePlan?.campaignId || `auto-${startedAt.replace(/[:.]/g, "-")}`;
|
|
397
|
+
let currentLedger = {
|
|
398
|
+
campaignId,
|
|
399
|
+
objective: mode.objective,
|
|
400
|
+
activeStage: status.currentStage,
|
|
401
|
+
activeRung: resumePlan?.rungId || "",
|
|
402
|
+
ownerType: "",
|
|
403
|
+
ownerId: "",
|
|
404
|
+
command: "",
|
|
405
|
+
watchTarget: resumePlan?.watchTarget || "",
|
|
406
|
+
startedAt,
|
|
407
|
+
lastObservedAt: timestamp,
|
|
408
|
+
observedState: resumePlan ? "resuming" : "armed",
|
|
409
|
+
lastCheckpoint: resumePlan?.lastCheckpoint || "",
|
|
410
|
+
checkpointSummary: resumePlan?.reason || "auto loop armed and waiting for the first owned command",
|
|
411
|
+
nextTransition: resumePlan?.rungId || "",
|
|
412
|
+
continueBoundary: "Continue while the active owner is still running and no stop condition has matched.",
|
|
413
|
+
stopBoundary: mode.stopConditions,
|
|
414
|
+
escalationBoundary: mode.escalationConditions,
|
|
415
|
+
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",
|
|
416
|
+
resumeCommand: "",
|
|
417
|
+
};
|
|
418
|
+
writeAutoLedger(targetDir, currentLedger, { lang });
|
|
267
419
|
const outcomeProtocolFields = {
|
|
268
420
|
primaryMetrics: evalProtocol.primaryMetrics,
|
|
269
421
|
secondaryMetrics: evalProtocol.secondaryMetrics,
|
|
@@ -305,6 +457,22 @@ async function startAutoMode({ targetDir, now = new Date() }) {
|
|
|
305
457
|
writeAutoStatus(targetDir, currentStatus, { lang });
|
|
306
458
|
};
|
|
307
459
|
|
|
460
|
+
const writeLedger = (overrides = {}) => {
|
|
461
|
+
currentLedger = {
|
|
462
|
+
...currentLedger,
|
|
463
|
+
activeStage: currentStatus.currentStage || currentLedger.activeStage,
|
|
464
|
+
activeRung: currentStatus.currentRung || currentLedger.activeRung,
|
|
465
|
+
watchTarget: currentStatus.watchTarget || currentLedger.watchTarget,
|
|
466
|
+
lastCheckpoint: currentStatus.lastCheckpoint || currentLedger.lastCheckpoint,
|
|
467
|
+
checkpointSummary: currentStatus.lastSummary || currentLedger.checkpointSummary,
|
|
468
|
+
lastObservedAt: new Date().toISOString(),
|
|
469
|
+
stopBoundary: mode.stopConditions,
|
|
470
|
+
escalationBoundary: mode.escalationConditions,
|
|
471
|
+
...overrides,
|
|
472
|
+
};
|
|
473
|
+
writeAutoLedger(targetDir, currentLedger, { lang });
|
|
474
|
+
};
|
|
475
|
+
|
|
308
476
|
const failAutoMode = (message) => {
|
|
309
477
|
currentStatus = {
|
|
310
478
|
...currentStatus,
|
|
@@ -313,6 +481,13 @@ async function startAutoMode({ targetDir, now = new Date() }) {
|
|
|
313
481
|
decision: message,
|
|
314
482
|
};
|
|
315
483
|
writeAutoStatus(targetDir, currentStatus, { lang });
|
|
484
|
+
writeLedger({
|
|
485
|
+
observedState: "failed",
|
|
486
|
+
ownerType: currentLedger.ownerType || "local-process",
|
|
487
|
+
checkpointSummary: message,
|
|
488
|
+
nextTransition: "terminal-failure",
|
|
489
|
+
resumeCommand: "",
|
|
490
|
+
});
|
|
316
491
|
writeAutoOutcome(
|
|
317
492
|
targetDir,
|
|
318
493
|
{
|
|
@@ -366,6 +541,8 @@ async function startAutoMode({ targetDir, now = new Date() }) {
|
|
|
366
541
|
rungId,
|
|
367
542
|
watchTarget,
|
|
368
543
|
nextRung,
|
|
544
|
+
ownerInfo: { ownerType: "local-process" },
|
|
545
|
+
updateLedger: writeLedger,
|
|
369
546
|
});
|
|
370
547
|
verifyStageContract({ stage, snapshot: contract.snapshot });
|
|
371
548
|
executedStages.push(stage);
|
|
@@ -378,6 +555,18 @@ async function startAutoMode({ targetDir, now = new Date() }) {
|
|
|
378
555
|
nextRung,
|
|
379
556
|
decision: rungId ? `completed rung ${rungId}` : `completed stage ${stage}`,
|
|
380
557
|
});
|
|
558
|
+
writeLedger({
|
|
559
|
+
ownerType: "local-process",
|
|
560
|
+
observedState: "checkpointed",
|
|
561
|
+
command,
|
|
562
|
+
watchTarget,
|
|
563
|
+
activeStage: stage,
|
|
564
|
+
activeRung: rungId || currentStatus.currentRung,
|
|
565
|
+
ownerId: currentLedger.ownerId,
|
|
566
|
+
checkpointSummary: rungId ? `completed rung ${rungId}` : `completed stage ${stage}`,
|
|
567
|
+
nextTransition: nextRung || "",
|
|
568
|
+
resumeCommand: command,
|
|
569
|
+
});
|
|
381
570
|
const frozenCoreChanges = detectFrozenCoreChanges(frozenCoreSnapshot);
|
|
382
571
|
if (frozenCoreChanges.length > 0) {
|
|
383
572
|
failAutoMode(`frozen core changed: ${frozenCoreChanges.join(", ")}`);
|
|
@@ -412,6 +601,17 @@ async function startAutoMode({ targetDir, now = new Date() }) {
|
|
|
412
601
|
nextRung,
|
|
413
602
|
decision: `retrying ${rungId || stage} after failure ${failureCount}`,
|
|
414
603
|
});
|
|
604
|
+
writeLedger({
|
|
605
|
+
ownerType: "local-process",
|
|
606
|
+
observedState: "retrying",
|
|
607
|
+
command,
|
|
608
|
+
watchTarget,
|
|
609
|
+
activeStage: stage,
|
|
610
|
+
activeRung: rungId || currentStatus.currentRung,
|
|
611
|
+
checkpointSummary: `retrying ${rungId || stage} after failure ${failureCount}`,
|
|
612
|
+
nextTransition: rungId || stage,
|
|
613
|
+
resumeCommand: command,
|
|
614
|
+
});
|
|
415
615
|
}
|
|
416
616
|
}
|
|
417
617
|
};
|
|
@@ -451,6 +651,14 @@ async function startAutoMode({ targetDir, now = new Date() }) {
|
|
|
451
651
|
currentCommand: mode.promotionCommand,
|
|
452
652
|
decision: `promotion policy matched after ${label}`,
|
|
453
653
|
});
|
|
654
|
+
writeLedger({
|
|
655
|
+
ownerType: "local-process",
|
|
656
|
+
command: mode.promotionCommand,
|
|
657
|
+
observedState: "checkpointed",
|
|
658
|
+
checkpointSummary: `promotion policy matched after ${label}`,
|
|
659
|
+
nextTransition: "post-promotion refresh",
|
|
660
|
+
resumeCommand: mode.promotionCommand,
|
|
661
|
+
});
|
|
454
662
|
promotionApplied = true;
|
|
455
663
|
const frozenCoreChangesAfterPromotion = detectFrozenCoreChanges(frozenCoreSnapshot);
|
|
456
664
|
if (frozenCoreChangesAfterPromotion.length > 0) {
|
|
@@ -463,7 +671,12 @@ async function startAutoMode({ targetDir, now = new Date() }) {
|
|
|
463
671
|
|
|
464
672
|
if (evalProtocol.experimentRungs.length > 0) {
|
|
465
673
|
const rungMap = new Map(evalProtocol.experimentRungs.map((rung) => [rung.id, rung]));
|
|
466
|
-
let currentRung =
|
|
674
|
+
let currentRung = resumePlan?.kind === "ladder"
|
|
675
|
+
? rungMap.get(resumePlan.rungId)
|
|
676
|
+
: evalProtocol.experimentRungs[0];
|
|
677
|
+
if (!currentRung) {
|
|
678
|
+
failAutoMode(`resume rung is missing from the current experiment ladder: ${resumePlan?.rungId || ""}`);
|
|
679
|
+
}
|
|
467
680
|
|
|
468
681
|
while (currentRung && iterationsCompleted < Math.max(1, maxIterations)) {
|
|
469
682
|
if (!mode.allowedStages.includes(currentRung.stage)) {
|
|
@@ -618,6 +831,12 @@ async function startAutoMode({ targetDir, now = new Date() }) {
|
|
|
618
831
|
decision: stopReason || "stopped by stop condition",
|
|
619
832
|
};
|
|
620
833
|
writeAutoStatus(targetDir, currentStatus, { lang });
|
|
834
|
+
writeLedger({
|
|
835
|
+
observedState: "stopped",
|
|
836
|
+
checkpointSummary: stopReason || "stopped by stop condition",
|
|
837
|
+
nextTransition: "terminal-stop",
|
|
838
|
+
resumeCommand: "",
|
|
839
|
+
});
|
|
621
840
|
writeAutoOutcome(
|
|
622
841
|
targetDir,
|
|
623
842
|
{
|
|
@@ -670,6 +889,12 @@ async function startAutoMode({ targetDir, now = new Date() }) {
|
|
|
670
889
|
decision: stopReason || "stopped by stop condition",
|
|
671
890
|
};
|
|
672
891
|
writeAutoStatus(targetDir, currentStatus, { lang });
|
|
892
|
+
writeLedger({
|
|
893
|
+
observedState: "stopped",
|
|
894
|
+
checkpointSummary: stopReason || "stopped by stop condition",
|
|
895
|
+
nextTransition: "terminal-stop",
|
|
896
|
+
resumeCommand: "",
|
|
897
|
+
});
|
|
673
898
|
writeAutoOutcome(
|
|
674
899
|
targetDir,
|
|
675
900
|
{
|
|
@@ -724,6 +949,12 @@ async function startAutoMode({ targetDir, now = new Date() }) {
|
|
|
724
949
|
decision: successReached ? "completed configured auto goal" : "completed configured stages",
|
|
725
950
|
};
|
|
726
951
|
writeAutoStatus(targetDir, currentStatus, { lang });
|
|
952
|
+
writeLedger({
|
|
953
|
+
observedState: "completed",
|
|
954
|
+
checkpointSummary: successReached ? "completed configured auto goal" : "completed configured stages",
|
|
955
|
+
nextTransition: "terminal-success",
|
|
956
|
+
resumeCommand: "",
|
|
957
|
+
});
|
|
727
958
|
writeAutoOutcome(
|
|
728
959
|
targetDir,
|
|
729
960
|
{
|
|
@@ -805,6 +1036,31 @@ function stopAutoMode({ targetDir, now = new Date() }) {
|
|
|
805
1036
|
decision: "stopped by operator",
|
|
806
1037
|
};
|
|
807
1038
|
writeAutoStatus(targetDir, status, { lang });
|
|
1039
|
+
writeAutoLedger(
|
|
1040
|
+
targetDir,
|
|
1041
|
+
{
|
|
1042
|
+
campaignId: existing.startedAt ? `auto-${existing.startedAt.replace(/[:.]/g, "-")}` : `auto-${now.toISOString().replace(/[:.]/g, "-")}`,
|
|
1043
|
+
objective: mode.objective,
|
|
1044
|
+
activeStage: existing.currentStage || "",
|
|
1045
|
+
activeRung: existing.currentRung || "",
|
|
1046
|
+
ownerType: "local-process",
|
|
1047
|
+
ownerId: "",
|
|
1048
|
+
command: existing.currentCommand || "",
|
|
1049
|
+
watchTarget: existing.watchTarget || "",
|
|
1050
|
+
startedAt: existing.startedAt || now.toISOString(),
|
|
1051
|
+
lastObservedAt: now.toISOString(),
|
|
1052
|
+
observedState: "stopped",
|
|
1053
|
+
lastCheckpoint: existing.lastCheckpoint || "",
|
|
1054
|
+
checkpointSummary: "stopped by operator",
|
|
1055
|
+
nextTransition: "terminal-stop",
|
|
1056
|
+
continueBoundary: "No further automatic progress is allowed until a new approved auto run starts.",
|
|
1057
|
+
stopBoundary: mode.stopConditions,
|
|
1058
|
+
escalationBoundary: mode.escalationConditions,
|
|
1059
|
+
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",
|
|
1060
|
+
resumeCommand: "",
|
|
1061
|
+
},
|
|
1062
|
+
{ lang }
|
|
1063
|
+
);
|
|
808
1064
|
writeAutoOutcome(
|
|
809
1065
|
targetDir,
|
|
810
1066
|
{
|
package/lib/auto_state.cjs
CHANGED
|
@@ -68,6 +68,33 @@ function parseAutoStatus(targetDir) {
|
|
|
68
68
|
};
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
+
function parseAutoLedger(targetDir) {
|
|
72
|
+
const text = readFileIfExists(contextFile(targetDir, "auto-ledger.md"));
|
|
73
|
+
return {
|
|
74
|
+
path: contextFile(targetDir, "auto-ledger.md"),
|
|
75
|
+
text,
|
|
76
|
+
campaignId: extractValue(text, ["Campaign id", "Campaign ID", "活动 id"]),
|
|
77
|
+
objective: extractValue(text, ["Objective", "目标"]),
|
|
78
|
+
activeStage: extractValue(text, ["Active stage", "当前阶段"]),
|
|
79
|
+
activeRung: extractValue(text, ["Active rung", "当前 rung"]),
|
|
80
|
+
ownerType: extractValue(text, ["Owner type", "Owner 类型"]),
|
|
81
|
+
ownerId: extractValue(text, ["Owner id", "Owner ID"]),
|
|
82
|
+
command: extractValue(text, ["Command", "命令"]),
|
|
83
|
+
watchTarget: extractValue(text, ["Watch target", "监视目标"]),
|
|
84
|
+
startedAt: extractValue(text, ["Started at", "开始时间"]),
|
|
85
|
+
lastObservedAt: extractValue(text, ["Last observed at", "最近观察时间"]),
|
|
86
|
+
observedState: extractValue(text, ["Observed state", "观察状态"]),
|
|
87
|
+
lastCheckpoint: extractValue(text, ["Last checkpoint", "最近 checkpoint"]),
|
|
88
|
+
checkpointSummary: extractValue(text, ["Checkpoint summary", "Checkpoint 摘要"]),
|
|
89
|
+
nextTransition: extractValue(text, ["Next transition", "下一转换"]),
|
|
90
|
+
continueBoundary: extractValue(text, ["Continue boundary", "继续边界"]),
|
|
91
|
+
stopBoundary: extractValue(text, ["Stop boundary", "停止边界"]),
|
|
92
|
+
escalationBoundary: extractValue(text, ["Escalation boundary", "升级边界"]),
|
|
93
|
+
requiredReadSet: extractValue(text, ["Required read set", "必要读取集合"]),
|
|
94
|
+
resumeCommand: extractValue(text, ["Resume command", "恢复命令"]),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
71
98
|
function renderAutoStatus(status, { lang = "en" } = {}) {
|
|
72
99
|
if (lang === "zh") {
|
|
73
100
|
return `# 自动模式状态
|
|
@@ -240,12 +267,96 @@ function renderAutoOutcome(outcome, { lang = "en" } = {}) {
|
|
|
240
267
|
`;
|
|
241
268
|
}
|
|
242
269
|
|
|
270
|
+
function renderAutoLedger(ledger, { lang = "en" } = {}) {
|
|
271
|
+
if (lang === "zh") {
|
|
272
|
+
return `# 自动运行账本
|
|
273
|
+
|
|
274
|
+
## Campaign
|
|
275
|
+
|
|
276
|
+
- Campaign id: ${ledger.campaignId || ""}
|
|
277
|
+
- Objective: ${ledger.objective || ""}
|
|
278
|
+
- Active stage: ${ledger.activeStage || ""}
|
|
279
|
+
- Active rung: ${ledger.activeRung || ""}
|
|
280
|
+
|
|
281
|
+
## Owner
|
|
282
|
+
|
|
283
|
+
- Owner type: ${ledger.ownerType || ""}
|
|
284
|
+
- Owner id: ${ledger.ownerId || ""}
|
|
285
|
+
- Command: ${ledger.command || ""}
|
|
286
|
+
- Watch target: ${ledger.watchTarget || ""}
|
|
287
|
+
- Started at: ${ledger.startedAt || ""}
|
|
288
|
+
- Last observed at: ${ledger.lastObservedAt || ""}
|
|
289
|
+
- Observed state: ${ledger.observedState || ""}
|
|
290
|
+
|
|
291
|
+
## Checkpoints
|
|
292
|
+
|
|
293
|
+
- Last checkpoint: ${ledger.lastCheckpoint || ""}
|
|
294
|
+
- Checkpoint summary: ${ledger.checkpointSummary || ""}
|
|
295
|
+
- Next transition: ${ledger.nextTransition || ""}
|
|
296
|
+
|
|
297
|
+
## Boundaries
|
|
298
|
+
|
|
299
|
+
- Continue boundary: ${ledger.continueBoundary || ""}
|
|
300
|
+
- Stop boundary: ${ledger.stopBoundary || ""}
|
|
301
|
+
- Escalation boundary: ${ledger.escalationBoundary || ""}
|
|
302
|
+
|
|
303
|
+
## Resume
|
|
304
|
+
|
|
305
|
+
- Required read set: ${ledger.requiredReadSet || ""}
|
|
306
|
+
- Resume command: ${ledger.resumeCommand || ""}
|
|
307
|
+
`;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
return `# Auto Runtime Ledger
|
|
311
|
+
|
|
312
|
+
## Campaign
|
|
313
|
+
|
|
314
|
+
- Campaign id: ${ledger.campaignId || ""}
|
|
315
|
+
- Objective: ${ledger.objective || ""}
|
|
316
|
+
- Active stage: ${ledger.activeStage || ""}
|
|
317
|
+
- Active rung: ${ledger.activeRung || ""}
|
|
318
|
+
|
|
319
|
+
## Owner
|
|
320
|
+
|
|
321
|
+
- Owner type: ${ledger.ownerType || ""}
|
|
322
|
+
- Owner id: ${ledger.ownerId || ""}
|
|
323
|
+
- Command: ${ledger.command || ""}
|
|
324
|
+
- Watch target: ${ledger.watchTarget || ""}
|
|
325
|
+
- Started at: ${ledger.startedAt || ""}
|
|
326
|
+
- Last observed at: ${ledger.lastObservedAt || ""}
|
|
327
|
+
- Observed state: ${ledger.observedState || ""}
|
|
328
|
+
|
|
329
|
+
## Checkpoints
|
|
330
|
+
|
|
331
|
+
- Last checkpoint: ${ledger.lastCheckpoint || ""}
|
|
332
|
+
- Checkpoint summary: ${ledger.checkpointSummary || ""}
|
|
333
|
+
- Next transition: ${ledger.nextTransition || ""}
|
|
334
|
+
|
|
335
|
+
## Boundaries
|
|
336
|
+
|
|
337
|
+
- Continue boundary: ${ledger.continueBoundary || ""}
|
|
338
|
+
- Stop boundary: ${ledger.stopBoundary || ""}
|
|
339
|
+
- Escalation boundary: ${ledger.escalationBoundary || ""}
|
|
340
|
+
|
|
341
|
+
## Resume
|
|
342
|
+
|
|
343
|
+
- Required read set: ${ledger.requiredReadSet || ""}
|
|
344
|
+
- Resume command: ${ledger.resumeCommand || ""}
|
|
345
|
+
`;
|
|
346
|
+
}
|
|
347
|
+
|
|
243
348
|
function writeAutoOutcome(targetDir, outcome, { lang = "en" } = {}) {
|
|
244
349
|
const filePath = contextFile(targetDir, "auto-outcome.md");
|
|
245
350
|
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
246
351
|
fs.writeFileSync(filePath, renderAutoOutcome(outcome, { lang }).trimEnd() + "\n");
|
|
247
352
|
}
|
|
248
353
|
|
|
354
|
+
function writeAutoLedger(targetDir, ledger, { lang = "en" } = {}) {
|
|
355
|
+
const filePath = contextFile(targetDir, "auto-ledger.md");
|
|
356
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
357
|
+
fs.writeFileSync(filePath, renderAutoLedger(ledger, { lang }).trimEnd() + "\n");
|
|
358
|
+
}
|
|
359
|
+
|
|
249
360
|
function resolveRequiredArtifact(targetDir, configuredPath) {
|
|
250
361
|
if (!isMeaningful(configuredPath)) {
|
|
251
362
|
return { relativePath: "", absolutePath: "" };
|
|
@@ -258,12 +369,15 @@ function resolveRequiredArtifact(targetDir, configuredPath) {
|
|
|
258
369
|
}
|
|
259
370
|
|
|
260
371
|
module.exports = {
|
|
372
|
+
parseAutoLedger,
|
|
261
373
|
parseAutoMode,
|
|
262
374
|
parseAutoStatus,
|
|
263
375
|
readWorkflowLanguage,
|
|
376
|
+
renderAutoLedger,
|
|
264
377
|
renderAutoOutcome,
|
|
265
378
|
renderAutoStatus,
|
|
266
379
|
resolveRequiredArtifact,
|
|
380
|
+
writeAutoLedger,
|
|
267
381
|
writeAutoOutcome,
|
|
268
382
|
writeAutoStatus,
|
|
269
383
|
};
|
package/lib/i18n.cjs
CHANGED
|
@@ -1563,6 +1563,7 @@ const ZH_SKILL_FILES = {
|
|
|
1563
1563
|
`# 自动模式契约
|
|
1564
1564
|
|
|
1565
1565
|
用这个文件定义 \`/lab:auto\` 的有边界自治执行范围。
|
|
1566
|
+
把 \`.lab/context/auto-ledger.md\` 当成运行时账本,记录 owner、checkpoint、resume 和 stop 边界。
|
|
1566
1567
|
|
|
1567
1568
|
## 目标
|
|
1568
1569
|
|
|
@@ -1602,6 +1603,7 @@ const ZH_SKILL_FILES = {
|
|
|
1602
1603
|
- Rung 的 \`Command\` 应该绑定真实的长任务命令,由它产出最终实验结果。
|
|
1603
1604
|
- 短 watcher 只用于查看进度;当真实实验还在运行时,不要把短 watcher 当成 stage 或 rung 的主命令。
|
|
1604
1605
|
- 当真实实验进程还活着时,只记录进度更新并继续等待。
|
|
1606
|
+
- 当 loop 处于运行态时,把当前 owner、命令和 watch target 写进 \`.lab/context/auto-ledger.md\`。
|
|
1605
1607
|
- Run command:
|
|
1606
1608
|
- Iterate command:
|
|
1607
1609
|
- Review command:
|
|
@@ -1634,6 +1636,43 @@ const ZH_SKILL_FILES = {
|
|
|
1634
1636
|
- Stop conditions:
|
|
1635
1637
|
- Escalation conditions:
|
|
1636
1638
|
- Canonical promotion writeback: update \`.lab/context/data-decisions.md\`、\`.lab/context/decisions.md\` 和 \`.lab/context/workflow-state.md\`,然后刷新 \`state.md\` 等派生视图。
|
|
1639
|
+
`,
|
|
1640
|
+
[path.join(".lab", "context", "auto-ledger.md")]:
|
|
1641
|
+
`# 自动运行账本
|
|
1642
|
+
|
|
1643
|
+
## Campaign
|
|
1644
|
+
|
|
1645
|
+
- Campaign id:
|
|
1646
|
+
- Objective:
|
|
1647
|
+
- Active stage:
|
|
1648
|
+
- Active rung:
|
|
1649
|
+
|
|
1650
|
+
## Owner
|
|
1651
|
+
|
|
1652
|
+
- Owner type:
|
|
1653
|
+
- Owner id:
|
|
1654
|
+
- Command:
|
|
1655
|
+
- Watch target:
|
|
1656
|
+
- Started at:
|
|
1657
|
+
- Last observed at:
|
|
1658
|
+
- Observed state:
|
|
1659
|
+
|
|
1660
|
+
## Checkpoints
|
|
1661
|
+
|
|
1662
|
+
- Last checkpoint:
|
|
1663
|
+
- Checkpoint summary:
|
|
1664
|
+
- Next transition:
|
|
1665
|
+
|
|
1666
|
+
## Boundaries
|
|
1667
|
+
|
|
1668
|
+
- Continue boundary:
|
|
1669
|
+
- Stop boundary:
|
|
1670
|
+
- Escalation boundary:
|
|
1671
|
+
|
|
1672
|
+
## Resume
|
|
1673
|
+
|
|
1674
|
+
- Required read set:
|
|
1675
|
+
- Resume command:
|
|
1637
1676
|
`,
|
|
1638
1677
|
[path.join(".lab", "context", "auto-outcome.md")]:
|
|
1639
1678
|
`# 自动结果
|
|
@@ -2129,7 +2168,7 @@ ZH_CONTENT[path.join(".lab", ".managed", "templates", "framing.md")] = `# 论文
|
|
|
2129
2168
|
ZH_CONTENT[path.join(".codex", "prompts", "lab.md")] = codexPrompt(
|
|
2130
2169
|
"查看 /lab 研究工作流总览并选择合适阶段",
|
|
2131
2170
|
"workflow question 或 stage choice",
|
|
2132
|
-
"# `/lab` for Codex\n\n`/lab` 是严格的研究工作流命令族。每次都使用同一套仓库工件和阶段边界。\n\n## 子命令\n\n- `/lab:idea`\n 先做两轮脑暴和两轮文献检索,再定义问题与 failure case、对比最接近前作,并输出带 approval gate 的 source-backed recommendation。\n\n- `/lab:data`\n 把已批准的 idea 转成数据集与 benchmark 方案,记录数据集年份、使用过该数据集的论文、下载来源、许可或访问限制,以及 classic-public、recent-strong-public、claim-specific 三类 benchmark 的纳入理由,和 canonical baselines、strong historical baselines、recent strong public methods、closest prior work 四类对比方法的纳入理由。\n\n- `/lab:auto`\n 在不改变 mission、framing 和核心 claims 的前提下,读取 eval-protocol 与 auto-mode 契约并自动编排 `run`、`iterate`、`review`、`report`,必要时扩展数据集、benchmark 和 comparison methods,并在满足升格策略时自动升级 primary package。启动前必须选定 autonomy level、声明 terminal goal,并显式写清 primary gate、secondary guard、promotion condition、stop reason 和 escalation reason,再批准契约。\n\n- `/lab:framing`\n 通过审计当前领域与相邻领域的术语,锁定 paper-facing 的方法名、模块名、论文题目和 contribution bullets,并在 section 起草前保留 approval gate。\n\n- `/lab:spec`\n 把已批准的 idea 转成 `.lab/changes/<change-id>/` 下的一个 lab change 目录,并在其中写出 `proposal`、`design`、`spec`、`tasks`。\n\n- `/lab:run`\n 执行最小有意义验证运行,登记 run,并生成第一版标准化评估摘要。\n\n- `/lab:iterate`\n 在冻结 mission、阈值、verification commands 与 `completion_promise` 的前提下执行有边界的实验迭代。\n\n- `/lab:review`\n 以 reviewer mode 审查文档或结果,先给短摘要,再输出 findings、fatal flaws、fix priority 和 residual risks。\n\n- `/lab:report`\n 从 runs 和 iterations 工件生成最终研究报告。\n\n- `/lab:write`\n 使用已安装 `lab` skill 下 vendored 的 paper-writing references,把稳定 report 工件转成论文 section。\n\n## 调度规则\n\n- 始终使用 `skills/lab/SKILL.md` 作为工作流合同。\n- 用户显式调用 `/lab:<stage>` 时,要立刻执行该 stage,而不是只推荐别的 `/lab` stage。\n- 先给简洁的阶段摘要;只要 stage 合同要求受管工件,就应立刻落盘,再回报输出路径和下一步。\n- 如果歧义会影响结论,一次只问一个问题;如果有多条可行路径,先给 2-3 个方案再收敛。\n- `/lab:spec` 前应已有经批准的数据集与 benchmark 方案。\n- `/lab:run`、`/lab:iterate`、`/lab:auto`、`/lab:report` 都应遵循 `.lab/context/eval-protocol.md`。\n- `.lab/context/eval-protocol.md` 不只定义主指标和主表,也应定义指标释义、实验阶梯,以及指标和对比实现的来源。\n- `/lab:auto` 只编排已批准边界内的执行阶段,不替代手动的 idea/data/framing/spec 决策。\n- `/lab:write` 前必须已有经批准的 `/lab:framing` 工件。\n\n## 如何输入 `/lab:auto`\n\n## `/lab:auto` 层级指南\n\n- `L1`:适合安全验证、一轮 bounded 真实运行,或简单 report 刷新。\n- `L2`:默认推荐级别,适合冻结核心边界内的常规实验迭代。\n- `L3`:激进 campaign 级别,只在你明确想做更大范围探索和可选写作时使用。\n- 如果不确定,默认推荐 `L2`。\n- 如果用户输入没写级别,或者把级别和 `paper layer`、`phase`、`table` 混用了,就应先停下来,要求用户明确选 `L1/L2/L3`。\n\n- 把 `Autonomy level L1/L2/L3` 视为执行权限级别,不要和论文里的 layer、phase、table 编号混用。\n- 把 `paper layer`、`phase`、`table` 视为实验目标。例如 `paper layer 3` 或 `Phase 1` 不是 `Autonomy level L3`。\n- 一条好的 `/lab:auto` 输入应至少说清:objective、自治级别、terminal goal、scope、allowed modifications。\n- 如果 workflow language 是中文,摘要、清单条目、任务标签和进度更新都应使用中文,除非文件路径、代码标识符或字面指标名必须保持原样。\n- 示例:`/lab:auto 自治级别 L2。目标:推进 paper layer 3。终止条件:完成 bounded protocol、测试、最小实现和一轮小规模结果。允许修改:配置、数据接入、评估脚本。`\n"
|
|
2171
|
+
"# `/lab` for Codex\n\n`/lab` 是严格的研究工作流命令族。每次都使用同一套仓库工件和阶段边界。\n\n## 子命令\n\n- `/lab:idea`\n 先做两轮脑暴和两轮文献检索,再定义问题与 failure case、对比最接近前作,并输出带 approval gate 的 source-backed recommendation。\n\n- `/lab:data`\n 把已批准的 idea 转成数据集与 benchmark 方案,记录数据集年份、使用过该数据集的论文、下载来源、许可或访问限制,以及 classic-public、recent-strong-public、claim-specific 三类 benchmark 的纳入理由,和 canonical baselines、strong historical baselines、recent strong public methods、closest prior work 四类对比方法的纳入理由。\n\n- `/lab:auto`\n 在不改变 mission、framing 和核心 claims 的前提下,读取 eval-protocol 与 auto-mode 契约并自动编排 `run`、`iterate`、`review`、`report`,必要时扩展数据集、benchmark 和 comparison methods,并在满足升格策略时自动升级 primary package。启动前必须选定 autonomy level、声明 terminal goal,并显式写清 primary gate、secondary guard、promotion condition、stop reason 和 escalation reason,再批准契约。\n\n- `/lab:framing`\n 通过审计当前领域与相邻领域的术语,锁定 paper-facing 的方法名、模块名、论文题目和 contribution bullets,并在 section 起草前保留 approval gate。\n\n- `/lab:spec`\n 把已批准的 idea 转成 `.lab/changes/<change-id>/` 下的一个 lab change 目录,并在其中写出 `proposal`、`design`、`spec`、`tasks`。\n\n- `/lab:run`\n 执行最小有意义验证运行,登记 run,并生成第一版标准化评估摘要。\n\n- `/lab:iterate`\n 在冻结 mission、阈值、verification commands 与 `completion_promise` 的前提下执行有边界的实验迭代。\n\n- `/lab:review`\n 以 reviewer mode 审查文档或结果,先给短摘要,再输出 findings、fatal flaws、fix priority 和 residual risks。\n\n- `/lab:report`\n 从 runs 和 iterations 工件生成最终研究报告。\n\n- `/lab:write`\n 使用已安装 `lab` skill 下 vendored 的 paper-writing references,把稳定 report 工件转成论文 section。\n\n## 调度规则\n\n- 始终使用 `skills/lab/SKILL.md` 作为工作流合同。\n- 用户显式调用 `/lab:<stage>` 时,要立刻执行该 stage,而不是只推荐别的 `/lab` stage。\n- 先给简洁的阶段摘要;只要 stage 合同要求受管工件,就应立刻落盘,再回报输出路径和下一步。\n- 如果歧义会影响结论,一次只问一个问题;如果有多条可行路径,先给 2-3 个方案再收敛。\n- `/lab:spec` 前应已有经批准的数据集与 benchmark 方案。\n- `/lab:run`、`/lab:iterate`、`/lab:auto`、`/lab:report` 都应遵循 `.lab/context/eval-protocol.md`。\n- `.lab/context/eval-protocol.md` 不只定义主指标和主表,也应定义指标释义、实验阶梯,以及指标和对比实现的来源。\n- `/lab:auto` 只编排已批准边界内的执行阶段,不替代手动的 idea/data/framing/spec 决策。\n- `/lab:write` 前必须已有经批准的 `/lab:framing` 工件。\n\n## 如何输入 `/lab:auto`\n\n## `/lab:auto` 层级指南\n\n- `L1`:适合安全验证、一轮 bounded 真实运行,或简单 report 刷新。\n- `L2`:默认推荐级别,适合冻结核心边界内的常规实验迭代。\n- `L3`:激进 campaign 级别,只在你明确想做更大范围探索和可选写作时使用。\n- 如果不确定,默认推荐 `L2`。\n- 如果用户输入没写级别,或者把级别和 `paper layer`、`phase`、`table` 混用了,就应先停下来,要求用户明确选 `L1/L2/L3`。\n- 真正的 `/lab:auto` 首个可见输出必须是 `Auto preflight`。\n- 这个首个可见输出必须展示已读取文件,以及 `Autonomy level`、`Allowed stages`、`Terminal goal`、`Primary gate`、`Secondary guard`。\n- 如果无法从 `.lab/context/eval-protocol.md`、`.lab/context/auto-mode.md`、`.lab/context/auto-status.md` 和 `.lab/context/auto-outcome.md` 完成 preflight,就必须停下,而不是假装 loop 已经 armed。\n\n- 把 `Autonomy level L1/L2/L3` 视为执行权限级别,不要和论文里的 layer、phase、table 编号混用。\n- 把 `paper layer`、`phase`、`table` 视为实验目标。例如 `paper layer 3` 或 `Phase 1` 不是 `Autonomy level L3`。\n- 一条好的 `/lab:auto` 输入应至少说清:objective、自治级别、terminal goal、scope、allowed modifications。\n- 如果 workflow language 是中文,摘要、清单条目、任务标签和进度更新都应使用中文,除非文件路径、代码标识符或字面指标名必须保持原样。\n- 示例:`/lab:auto 自治级别 L2。目标:推进 paper layer 3。终止条件:完成 bounded protocol、测试、最小实现和一轮小规模结果。允许修改:配置、数据接入、评估脚本。`\n"
|
|
2133
2172
|
);
|
|
2134
2173
|
|
|
2135
2174
|
ZH_CONTENT[path.join(".codex", "prompts", "lab-data.md")] = codexPrompt(
|
|
@@ -2141,14 +2180,14 @@ ZH_CONTENT[path.join(".codex", "prompts", "lab-data.md")] = codexPrompt(
|
|
|
2141
2180
|
ZH_CONTENT[path.join(".codex", "prompts", "lab-auto.md")] = codexPrompt(
|
|
2142
2181
|
"在已批准边界内编排自动实验循环",
|
|
2143
2182
|
"auto mode objective",
|
|
2144
|
-
"使用已安装的 `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-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如果仓库的 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本命令运行 `/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` 探针来代替真实长任务命令;当真实实验进程还活着时,只允许发进度更新并继续等待。"
|
|
2145
2184
|
);
|
|
2146
2185
|
|
|
2147
2186
|
ZH_CONTENT[path.join(".claude", "commands", "lab.md")] = claudeCommand(
|
|
2148
2187
|
"lab",
|
|
2149
2188
|
"查看 /lab 研究工作流总览并选择合适阶段",
|
|
2150
2189
|
"[stage] [target]",
|
|
2151
|
-
"# `/lab` for Claude\n\n`/lab` 是 Claude Code 里的 lab 工作流分发入口。调用方式有两种:\n\n- `/lab <stage> ...`\n- `/lab-idea`、`/lab-data`、`/lab-auto`、`/lab-framing`、`/lab-spec`、`/lab-run`、`/lab-iterate`、`/lab-review`、`/lab-report`、`/lab-write`\n\n## 阶段别名\n\n- `/lab idea ...` 或 `/lab-idea`\n- `/lab data ...` 或 `/lab-data`\n- `/lab auto ...` 或 `/lab-auto`\n- `/lab framing ...` 或 `/lab-framing`\n- `/lab spec ...` 或 `/lab-spec`\n- `/lab run ...` 或 `/lab-run`\n- `/lab iterate ...` 或 `/lab-iterate`\n- `/lab review ...` 或 `/lab-review`\n- `/lab report ...` 或 `/lab-report`\n- `/lab write ...` 或 `/lab-write`\n\n## 调度规则\n\n- 始终使用 `skills/lab/SKILL.md` 作为工作流合同。\n- 用户显式调用 `/lab <stage> ...` 或 `/lab-<stage>` 时,要立刻执行该 stage,而不是只推荐别的阶段。\n- 先给简洁的阶段摘要;只要 stage 合同要求受管工件,就应立刻落盘,再回报输出路径和下一步。\n- 如果歧义会影响结论,一次只问一个问题;如果有多条可行路径,先给 2-3 个方案再收敛。\n- `spec` 前应已有经批准的数据集与 benchmark 方案。\n- `run`、`iterate`、`auto`、`report` 都应遵循 `.lab/context/eval-protocol.md`。\n- `auto` 只编排已批准边界内的执行阶段,不替代手动的 idea/data/framing/spec 决策。\n- `write` 前必须已有经批准的 `framing` 工件。\n\n## 如何输入 `/lab auto`\n\n## `/lab auto` 层级指南\n\n- `L1`:适合安全验证、一轮 bounded 真实运行,或简单 report 刷新。\n- `L2`:默认推荐级别,适合冻结核心边界内的常规实验迭代。\n- `L3`:激进 campaign 级别,只在你明确想做更大范围探索和可选写作时使用。\n- 如果不确定,默认推荐 `L2`。\n- 如果用户输入没写级别,或者把级别和 `paper layer`、`phase`、`table` 混用了,就应先停下来,要求用户明确选 `L1/L2/L3`。\n\n- 把 `Autonomy level L1/L2/L3` 视为执行权限级别,不要和论文里的 layer、phase、table 编号混用。\n- 把 `paper layer`、`phase`、`table` 视为实验目标。例如 `paper layer 3` 或 `Phase 1` 不是 `Autonomy level L3`。\n- 一条好的 `/lab auto` 输入应至少说清:objective、自治级别、terminal goal、scope、allowed modifications。\n- 如果 workflow language 是中文,摘要、清单条目、任务标签和进度更新都应使用中文,除非文件路径、代码标识符或字面指标名必须保持原样。\n- 示例:`/lab auto 自治级别 L2。目标:推进 paper layer 3。终止条件:完成 bounded protocol、测试、最小实现和一轮小规模结果。允许修改:配置、数据接入、评估脚本。`\n"
|
|
2190
|
+
"# `/lab` for Claude\n\n`/lab` 是 Claude Code 里的 lab 工作流分发入口。调用方式有两种:\n\n- `/lab <stage> ...`\n- `/lab-idea`、`/lab-data`、`/lab-auto`、`/lab-framing`、`/lab-spec`、`/lab-run`、`/lab-iterate`、`/lab-review`、`/lab-report`、`/lab-write`\n\n## 阶段别名\n\n- `/lab idea ...` 或 `/lab-idea`\n- `/lab data ...` 或 `/lab-data`\n- `/lab auto ...` 或 `/lab-auto`\n- `/lab framing ...` 或 `/lab-framing`\n- `/lab spec ...` 或 `/lab-spec`\n- `/lab run ...` 或 `/lab-run`\n- `/lab iterate ...` 或 `/lab-iterate`\n- `/lab review ...` 或 `/lab-review`\n- `/lab report ...` 或 `/lab-report`\n- `/lab write ...` 或 `/lab-write`\n\n## 调度规则\n\n- 始终使用 `skills/lab/SKILL.md` 作为工作流合同。\n- 用户显式调用 `/lab <stage> ...` 或 `/lab-<stage>` 时,要立刻执行该 stage,而不是只推荐别的阶段。\n- 先给简洁的阶段摘要;只要 stage 合同要求受管工件,就应立刻落盘,再回报输出路径和下一步。\n- 如果歧义会影响结论,一次只问一个问题;如果有多条可行路径,先给 2-3 个方案再收敛。\n- `spec` 前应已有经批准的数据集与 benchmark 方案。\n- `run`、`iterate`、`auto`、`report` 都应遵循 `.lab/context/eval-protocol.md`。\n- `auto` 只编排已批准边界内的执行阶段,不替代手动的 idea/data/framing/spec 决策。\n- `write` 前必须已有经批准的 `framing` 工件。\n\n## 如何输入 `/lab auto`\n\n## `/lab auto` 层级指南\n\n- `L1`:适合安全验证、一轮 bounded 真实运行,或简单 report 刷新。\n- `L2`:默认推荐级别,适合冻结核心边界内的常规实验迭代。\n- `L3`:激进 campaign 级别,只在你明确想做更大范围探索和可选写作时使用。\n- 如果不确定,默认推荐 `L2`。\n- 如果用户输入没写级别,或者把级别和 `paper layer`、`phase`、`table` 混用了,就应先停下来,要求用户明确选 `L1/L2/L3`。\n- 真正的 `/lab auto` 首个可见输出必须是 `Auto preflight`。\n- 这个首个可见输出必须展示已读取文件,以及 `Autonomy level`、`Allowed stages`、`Terminal goal`、`Primary gate`、`Secondary guard`。\n- 如果无法从 `.lab/context/eval-protocol.md`、`.lab/context/auto-mode.md`、`.lab/context/auto-status.md` 和 `.lab/context/auto-outcome.md` 完成 preflight,就必须停下,而不是假装 loop 已经 armed。\n\n- 把 `Autonomy level L1/L2/L3` 视为执行权限级别,不要和论文里的 layer、phase、table 编号混用。\n- 把 `paper layer`、`phase`、`table` 视为实验目标。例如 `paper layer 3` 或 `Phase 1` 不是 `Autonomy level L3`。\n- 一条好的 `/lab auto` 输入应至少说清:objective、自治级别、terminal goal、scope、allowed modifications。\n- 如果 workflow language 是中文,摘要、清单条目、任务标签和进度更新都应使用中文,除非文件路径、代码标识符或字面指标名必须保持原样。\n- 示例:`/lab auto 自治级别 L2。目标:推进 paper layer 3。终止条件:完成 bounded protocol、测试、最小实现和一轮小规模结果。允许修改:配置、数据接入、评估脚本。`\n"
|
|
2152
2191
|
);
|
|
2153
2192
|
|
|
2154
2193
|
ZH_CONTENT[path.join(".claude", "commands", "lab-data.md")] = claudeCommand(
|
|
@@ -2162,7 +2201,7 @@ ZH_CONTENT[path.join(".claude", "commands", "lab-auto.md")] = claudeCommand(
|
|
|
2162
2201
|
"lab-auto",
|
|
2163
2202
|
"在已批准边界内编排自动实验循环",
|
|
2164
2203
|
"auto mode objective",
|
|
2165
|
-
"使用已安装的 `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-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如果仓库的 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本命令运行 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` 探针来代替真实长任务命令;当真实实验进程还活着时,只允许发进度更新并继续等待。"
|
|
2166
2205
|
);
|
|
2167
2206
|
|
|
2168
2207
|
const zhRecipeQuickPathLine =
|
package/lib/install.cjs
CHANGED
|
@@ -44,6 +44,7 @@ const PROJECT_OWNED_LOCALIZED_PATHS = [
|
|
|
44
44
|
path.join(".lab", "context", "eval-protocol.md"),
|
|
45
45
|
path.join(".lab", "context", "auto-mode.md"),
|
|
46
46
|
path.join(".lab", "context", "auto-status.md"),
|
|
47
|
+
path.join(".lab", "context", "auto-ledger.md"),
|
|
47
48
|
path.join(".lab", "context", "auto-outcome.md"),
|
|
48
49
|
path.join(".lab", "context", "terminology-lock.md"),
|
|
49
50
|
path.join(".lab", "context", "summary.md"),
|
|
@@ -7,7 +7,9 @@ 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
|
-
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`, 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
|
|
10
|
+
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
|
+
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
|
+
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.
|
|
11
13
|
When the repository workflow language is Chinese, summaries, checklist items, task labels, and progress updates should be written in Chinese unless a literal identifier must stay unchanged.
|
|
12
14
|
Treat `Layer 3`, `Phase 1`, or `Table 2` as paper-scope targets. Treat `Autonomy level L3` as the execution permission level.
|
|
13
15
|
Do not replace the real long-running experiment command with a short watcher such as `sleep 30`, `pgrep`, or a one-shot `metrics.json` probe. While the real experiment process is still alive, emit only a progress update and keep waiting.
|
|
@@ -70,6 +70,10 @@ Use the same repository artifacts and stage boundaries every time.
|
|
|
70
70
|
- `L3` is the aggressive campaign level. Use it only when you explicitly want broad exploration, larger search space changes, and optional manuscript-writing work.
|
|
71
71
|
- If you are unsure, choose `L2`.
|
|
72
72
|
- If the request omits the level or mixes it with a paper layer, phase, or table target, `/lab auto` should stop and ask for an explicit autonomy level before arming the loop.
|
|
73
|
+
- The first visible output of a real `/lab auto` run must be `Auto preflight`.
|
|
74
|
+
- That first visible output must show files read plus `Autonomy level`, `Allowed stages`, `Terminal goal`, `Primary gate`, and `Secondary guard`.
|
|
75
|
+
- If the preflight block cannot be completed from `.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`, `/lab auto` should stop instead of acting like the loop is armed.
|
|
76
|
+
- While the loop is alive, `/lab auto` should keep `.lab/context/auto-ledger.md` updated with the active owner, observed state, and resume boundary.
|
|
73
77
|
|
|
74
78
|
- Treat `Autonomy level L1/L2/L3` as the execution privilege level, not as a paper layer, phase, or table number.
|
|
75
79
|
- Treat `paper layer`, `phase`, and `table` as experiment targets. For example, `paper layer 3` or `Phase 1` should not be interpreted as `Autonomy level L3`.
|
|
@@ -6,7 +6,9 @@ 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
|
-
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`, 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
|
|
9
|
+
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
|
+
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
|
+
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.
|
|
10
12
|
When the repository workflow language is Chinese, summaries, checklist items, task labels, and progress updates should be written in Chinese unless a literal identifier must stay unchanged.
|
|
11
13
|
Treat `Layer 3`, `Phase 1`, or `Table 2` as paper-scope targets. Treat `Autonomy level L3` as the execution permission level.
|
|
12
14
|
Do not replace the real long-running experiment command with a short watcher such as `sleep 30`, `pgrep`, or a one-shot `metrics.json` probe. While the real experiment process is still alive, emit only a progress update and keep waiting.
|
|
@@ -64,6 +64,10 @@ argument-hint: workflow question or stage choice
|
|
|
64
64
|
- `L3` is the aggressive campaign level. Use it only when you explicitly want broad exploration, larger search space changes, and optional manuscript-writing work.
|
|
65
65
|
- If you are unsure, choose `L2`.
|
|
66
66
|
- If the request omits the level or mixes it with a paper layer, phase, or table target, `/lab:auto` should stop and ask for an explicit autonomy level before arming the loop.
|
|
67
|
+
- The first visible output of a real `/lab:auto` run must be `Auto preflight`.
|
|
68
|
+
- That first visible output must show files read plus `Autonomy level`, `Allowed stages`, `Terminal goal`, `Primary gate`, and `Secondary guard`.
|
|
69
|
+
- If the preflight block cannot be completed from `.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`, `/lab:auto` should stop instead of acting like the loop is armed.
|
|
70
|
+
- While the loop is alive, `/lab:auto` should keep `.lab/context/auto-ledger.md` updated with the active owner, observed state, and resume boundary.
|
|
67
71
|
|
|
68
72
|
- Treat `Autonomy level L1/L2/L3` as the execution privilege level, not as a paper layer, phase, or table number.
|
|
69
73
|
- Treat `paper layer`, `phase`, and `table` as experiment targets. For example, `paper layer 3` or `Phase 1` should not be interpreted as `Autonomy level L3`.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Auto Runtime Ledger
|
|
2
|
+
|
|
3
|
+
## Campaign
|
|
4
|
+
|
|
5
|
+
- Campaign id:
|
|
6
|
+
- Objective:
|
|
7
|
+
- Active stage:
|
|
8
|
+
- Active rung:
|
|
9
|
+
|
|
10
|
+
## Owner
|
|
11
|
+
|
|
12
|
+
- Owner type:
|
|
13
|
+
- Owner id:
|
|
14
|
+
- Command:
|
|
15
|
+
- Watch target:
|
|
16
|
+
- Started at:
|
|
17
|
+
- Last observed at:
|
|
18
|
+
- Observed state:
|
|
19
|
+
|
|
20
|
+
## Checkpoints
|
|
21
|
+
|
|
22
|
+
- Last checkpoint:
|
|
23
|
+
- Checkpoint summary:
|
|
24
|
+
- Next transition:
|
|
25
|
+
|
|
26
|
+
## Boundaries
|
|
27
|
+
|
|
28
|
+
- Continue boundary:
|
|
29
|
+
- Stop boundary:
|
|
30
|
+
- Escalation boundary:
|
|
31
|
+
|
|
32
|
+
## Resume
|
|
33
|
+
|
|
34
|
+
- Required read set:
|
|
35
|
+
- Resume command:
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
Use this file to define the bounded autonomous execution envelope for `/lab:auto`.
|
|
4
4
|
Pair it with `.lab/context/eval-protocol.md`, which defines the paper-facing metrics, tables, gates, and benchmark ladder that auto mode should optimize against.
|
|
5
5
|
If `eval-protocol.md` declares structured rung entries, auto mode follows those rung transitions first and uses the stage commands here as per-stage fallbacks.
|
|
6
|
+
Use `.lab/context/auto-ledger.md` as the live runtime ledger for ownership, checkpoints, resume, and stop boundaries.
|
|
6
7
|
|
|
7
8
|
## Objective
|
|
8
9
|
|
|
@@ -42,6 +43,7 @@ If `eval-protocol.md` declares structured rung entries, auto mode follows those
|
|
|
42
43
|
- Rung `Command` should be the real long-running command that owns the experiment result.
|
|
43
44
|
- A short watcher is only a progress probe. Do not use a short watcher as the stage or rung command when the real experiment is still running.
|
|
44
45
|
- While the real experiment process is still alive, only record a progress update and keep waiting.
|
|
46
|
+
- Record the active owner, command, and watch target in `.lab/context/auto-ledger.md` while the loop is alive.
|
|
45
47
|
- Run command:
|
|
46
48
|
- Iterate command:
|
|
47
49
|
- Review command:
|
|
@@ -108,10 +108,13 @@ Use this skill when the user invokes `/lab:*` or asks for the structured researc
|
|
|
108
108
|
### `/lab:auto`
|
|
109
109
|
|
|
110
110
|
- Use this stage to orchestrate approved execution stages with bounded autonomy.
|
|
111
|
-
- Read `.lab/config/workflow.json`, `.lab/context/mission.md`, `.lab/context/state.md`, `.lab/context/workflow-state.md`, `.lab/context/decisions.md`, `.lab/context/data-decisions.md`, `.lab/context/evidence-index.md`, `.lab/context/terminology-lock.md`, `.lab/context/auto-mode.md`, and `.lab/context/auto-
|
|
112
|
-
- Treat `.lab/context/auto-mode.md` as the control contract
|
|
111
|
+
- Read `.lab/config/workflow.json`, `.lab/context/mission.md`, `.lab/context/state.md`, `.lab/context/workflow-state.md`, `.lab/context/decisions.md`, `.lab/context/data-decisions.md`, `.lab/context/evidence-index.md`, `.lab/context/terminology-lock.md`, `.lab/context/auto-mode.md`, `.lab/context/auto-status.md`, and `.lab/context/auto-ledger.md` before acting.
|
|
112
|
+
- Treat `.lab/context/auto-mode.md` as the control contract, `.lab/context/auto-status.md` as the live summary, and `.lab/context/auto-ledger.md` as the runtime ledger.
|
|
113
113
|
- Require `.lab/context/auto-mode.md` to expose `Primary gate`, `Secondary guard`, `Promotion condition`, `Stop reason`, and `Escalation reason` before execution.
|
|
114
114
|
- Require `Autonomy level` and `Approval status` in `.lab/context/auto-mode.md` before execution.
|
|
115
|
+
- Start every `/lab:auto` run with a visible `Auto preflight` summary that reports files read plus `Autonomy level`, `Approval status`, `Allowed stages`, `Terminal goal`, `Primary gate`, and `Secondary guard`.
|
|
116
|
+
- If any required preflight field is missing or inconsistent, stop before any loop action. Do not present a fake auto summary as if the loop were armed.
|
|
117
|
+
- Keep `.lab/context/auto-ledger.md` updated with the active owner, observed state, and resume boundary while the loop is live.
|
|
115
118
|
- Treat `L1` as safe-run validation, `L2` as bounded iteration, and `L3` as aggressive campaign mode.
|
|
116
119
|
- Surface the level guide every time `/lab:auto` starts, and make the detailed guide mandatory when the user omits the level or mixes it with a paper layer, phase, or table target.
|
|
117
120
|
- Reuse `/lab:run`, `/lab:iterate`, `/lab:review`, `/lab:report`, and optional `/lab:write` instead of inventing a second workflow.
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Required Output
|
|
4
4
|
|
|
5
|
+
- visible `Auto preflight` summary
|
|
5
6
|
- Auto Mode Contract
|
|
6
7
|
- approved auto-mode contract
|
|
7
8
|
- live auto-status state
|
|
@@ -21,6 +22,7 @@
|
|
|
21
22
|
- `.lab/context/terminology-lock.md`
|
|
22
23
|
- `.lab/context/auto-mode.md`
|
|
23
24
|
- `.lab/context/auto-status.md`
|
|
25
|
+
- `.lab/context/auto-ledger.md`
|
|
24
26
|
- `.lab/context/auto-outcome.md`
|
|
25
27
|
|
|
26
28
|
## Context Write Set
|
|
@@ -35,6 +37,7 @@
|
|
|
35
37
|
- `.lab/context/summary.md`
|
|
36
38
|
- `.lab/context/session-brief.md`
|
|
37
39
|
- `.lab/context/auto-status.md`
|
|
40
|
+
- `.lab/context/auto-ledger.md`
|
|
38
41
|
- `.lab/context/auto-outcome.md`
|
|
39
42
|
|
|
40
43
|
## Boundary Rules
|
|
@@ -47,6 +50,7 @@
|
|
|
47
50
|
- Treat `Sanity and Alternative-Explanation Checks` as the anomaly gate for automation. When a rung yields all-null outputs, suspiciously identical runs, no-op deltas, or impl/result mismatches, pause promotion logic until implementation reality checks, alternative explanations, and at least one cross-check are recorded.
|
|
48
51
|
- Treat paper-template selection as an explicit write-time gate, not as a silent fallback, when the loop is about to create `.tex` deliverables for the first time.
|
|
49
52
|
- Treat `.lab/context/auto-mode.md` as a visible control plane. The contract should make the primary gate, secondary guard, promotion condition, stop reason, and escalation reason explicit before execution starts.
|
|
53
|
+
- Treat `.lab/context/auto-ledger.md` as the live runtime ledger for owner identity, observed state, checkpoint progress, continue boundary, stop boundary, escalation boundary, and resume read set.
|
|
50
54
|
- The contract must declare `Autonomy level` and `Approval status`, and execution starts only when approval is explicitly set to `approved`.
|
|
51
55
|
- The contract must also declare a concrete terminal goal:
|
|
52
56
|
- `rounds`
|
|
@@ -71,7 +75,22 @@
|
|
|
71
75
|
- Keep a poll-based waiting loop instead of sleeping blindly.
|
|
72
76
|
- Do not treat a short watcher such as `sleep 30`, a one-shot `pgrep`, or a single `metrics.json` probe as the rung command when the real experiment is still running.
|
|
73
77
|
- Bind each rung to the real long-running command or process that owns the experiment result.
|
|
78
|
+
- Record the active owner as one of:
|
|
79
|
+
- `local-process`
|
|
80
|
+
- `local-runner`
|
|
81
|
+
- `remote-runner`
|
|
82
|
+
- Every nonterminal `/lab:auto` state must remain resumable from `.lab/context/auto-ledger.md` plus `.lab/context/auto-status.md`.
|
|
83
|
+
- Start every real `/lab:auto` run with a visible `Auto preflight` block before any execution summary or action plan. That first visible output should list:
|
|
84
|
+
- files read
|
|
85
|
+
- `Autonomy level`
|
|
86
|
+
- `Approval status`
|
|
87
|
+
- `Allowed stages`
|
|
88
|
+
- `Terminal goal`
|
|
89
|
+
- `Primary gate`
|
|
90
|
+
- `Secondary guard`
|
|
91
|
+
- If any of those preflight fields are missing, stale, or inconsistent, stop before execution and report the blocking field directly.
|
|
74
92
|
- Always write a canonical `.lab/context/auto-outcome.md` when the run completes, stops, or fails.
|
|
93
|
+
- Always keep `.lab/context/auto-ledger.md` in sync with the current active owner while the loop is live.
|
|
75
94
|
- Keep handoff wording stable across auto outcomes and downstream report or write handoffs: record completed work, frozen scope, allowed next action, required read set for the next owner, and the accept or revise or reject boundary.
|
|
76
95
|
- When the evaluation protocol declares structured ladder rungs, execute them as a foreground rung state machine:
|
|
77
96
|
- each rung must declare `Stage`, `Goal`, `Command`, `Watch`, `Gate`, `On pass`, `On fail`, and `On stop`
|
|
@@ -93,15 +112,16 @@
|
|
|
93
112
|
## Minimum Procedure
|
|
94
113
|
|
|
95
114
|
1. Validate the auto-mode contract
|
|
96
|
-
2.
|
|
97
|
-
3.
|
|
98
|
-
4.
|
|
99
|
-
5.
|
|
100
|
-
6.
|
|
101
|
-
7.
|
|
102
|
-
8. Evaluate the declared
|
|
103
|
-
9. Evaluate the
|
|
104
|
-
10.
|
|
115
|
+
2. Emit the visible `Auto preflight` summary
|
|
116
|
+
3. Confirm the approved autonomy level matches the requested stage envelope
|
|
117
|
+
4. Set or refresh auto-status
|
|
118
|
+
5. Choose the next allowed `/lab` stage or structured ladder rung
|
|
119
|
+
6. Launch the bounded action
|
|
120
|
+
7. Poll for process completion, checkpoint movement, or summary generation while keeping the session alive
|
|
121
|
+
8. Evaluate the declared rung gate and transition to the next rung when structured ladder mode is active
|
|
122
|
+
9. Evaluate the declared terminal goal semantics at the correct boundary
|
|
123
|
+
10. Evaluate the primary gate, secondary guard, promotion condition, stop reason, and escalation reason at the correct boundary
|
|
124
|
+
11. Write auto-outcome and decide continue, promote, stop, or escalate
|
|
105
125
|
|
|
106
126
|
## Interaction Contract
|
|
107
127
|
|
|
@@ -113,6 +133,7 @@
|
|
|
113
133
|
- If you are unsure, choose `L2`.
|
|
114
134
|
|
|
115
135
|
- Start with a concise summary of the objective, the frozen core, and the next automatic stage.
|
|
136
|
+
- The first visible output must be `Auto preflight`, not a result summary or stage recommendation.
|
|
116
137
|
- Always surface the level guide before execution.
|
|
117
138
|
- If the contract is incomplete, ask one clarifying question at a time.
|
|
118
139
|
- If multiple next actions are credible, present 2-3 bounded options with trade-offs before arming a long run.
|