@tea-agent/loop-agent 0.31.1 → 0.32.1
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/AGENTS.md +1 -1
- package/CHANGELOG.md +46 -0
- package/README.md +1 -1
- package/dist/shared/operator/capabilities.js +22 -1
- package/dist/shared/operator/command-lifecycle.js +94 -0
- package/dist/shared/operator/index.js +1 -0
- package/dist/worker/cli.js +10 -24
- package/dist/worker/console/doctor.js +11 -4
- package/dist/worker/console/observe-health-match.js +18 -15
- package/dist/worker/console/operator-actions.js +2 -1
- package/dist/worker/console/static/assets/index-Bpa2qrc-.js +29 -0
- package/dist/worker/console/static/assets/index-BqfFDdnG.css +1 -0
- package/dist/worker/console/static/index.html +2 -2
- package/dist/worker/console/static-src/app/console-types.js +140 -0
- package/dist/worker/console/static-src/app/useConsoleShell.js +101 -0
- package/dist/worker/console/static-src/app/useOperatorActions.js +304 -0
- package/dist/worker/console/static-src/app/usePrdImport.js +171 -0
- package/dist/worker/console/static-src/app/useRecoveryActions.js +257 -0
- package/dist/worker/console/static-src/app/useRecoveryConsole.js +334 -0
- package/dist/worker/console/static-src/app/useTaskWizard.js +229 -0
- package/dist/worker/console/static-src/chat-view-types.js +2 -0
- package/dist/worker/console/static-src/night/night-types.js +24 -0
- package/dist/worker/console/static-src/night/useNightBoard.js +125 -0
- package/dist/worker/console/static-src/night/useNightWizard.js +171 -0
- package/dist/worker/console/static-src/operator-chat/chat-sse-events.js +253 -0
- package/dist/worker/console/static-src/operator-chat/format.js +71 -0
- package/dist/worker/console/static-src/operator-chat/refs.js +47 -0
- package/dist/worker/console/static-src/operator-chat/tools-catalog.js +77 -0
- package/dist/worker/console/static-src/operator-chat/types.js +1 -0
- package/dist/worker/console/static-src/operator-chat/useChatSessions.js +320 -0
- package/dist/worker/console/static-src/operator-chat/useChatStream.js +209 -0
- package/dist/worker/console/static-src/operator-chat/useChatThread.js +218 -0
- package/dist/worker/console/static-src/operator-chat/useComposer.js +125 -0
- package/dist/worker/console/static-src/operator-chat/useInterview.js +108 -0
- package/dist/worker/console/static-src/operator-chat/useRepoBrowser.js +123 -0
- package/dist/worker/console/static-src/operator-chat/useRuntimeControls.js +207 -0
- package/dist/worker/feature/acceptance-policy.js +227 -0
- package/dist/worker/feature/decision-loader.js +1 -1
- package/dist/worker/feature/next-action.js +56 -6
- package/dist/worker/feature/profile-schema.js +3 -0
- package/dist/worker/feature/reducer.js +1 -0
- package/dist/worker/feature/review.js +72 -8
- package/dist/worker/feature/scaffold.js +14 -0
- package/dist/worker/loop-agent/controller-protocol.js +143 -0
- package/dist/worker/materialize/harness-task-lifecycle-probe.js +126 -0
- package/dist/worker/materialize/harness-task-lineage.js +220 -0
- package/dist/worker/materialize/harness-task-materializer.js +350 -80
- package/dist/worker/observability/progress-composite.js +1 -0
- package/dist/worker/observability/read-model.js +66 -19
- package/dist/worker/pool/attempt-identity.js +41 -0
- package/dist/worker/pool/attempt-lease.js +184 -0
- package/dist/worker/pool/attempt-transition.js +210 -0
- package/dist/worker/pool/begin-attempt-with-lease.js +26 -0
- package/dist/worker/pool/begin-attempt.js +35 -0
- package/dist/worker/pool/failure-routing.js +49 -0
- package/dist/worker/pool/recovery-decision.js +163 -0
- package/dist/worker/pool/run-owner-store.js +126 -0
- package/dist/worker/pool/run-store.js +32 -46
- package/dist/worker/pool/runtime-reconcile-inventory.js +127 -0
- package/dist/worker/pool/state-projection.js +57 -0
- package/dist/worker/run-task/run-task.js +31 -4
- package/dist/worker/runner/run-ready.js +64 -14
- package/dist/worker/runner/single-task-attempt.js +42 -13
- package/dist/worker/task-graph/acceptance-schema.js +3 -0
- package/docs/README.md +3 -1
- package/docs/architecture/evolution.md +1 -1
- package/docs/operations/README.md +1 -0
- package/docs/templates/README.md +1 -0
- package/docs/templates/agent-worker-production-readiness-checklist.md +47 -0
- package/docs/templates/evaluation/agents-map-slim-v1.md +1 -1
- package/docs/templates/evaluation/agents-map-verbose-v0.md +1 -1
- package/docs/templates/init-managed-agents.md +1 -1
- package/docs/templates/product-line/scaffold-samples/backend-only/acceptance.yaml +3 -0
- package/docs/templates/product-line/scaffold-samples/backend-only/feature.yaml +11 -0
- package/docs/templates/product-line/scaffold-samples/fe-with-api/acceptance.yaml +3 -0
- package/docs/templates/product-line/scaffold-samples/fe-with-api/feature.yaml +11 -0
- package/docs/templates/product-line/scaffold-samples/frontend-only/acceptance.yaml +3 -0
- package/docs/templates/product-line/scaffold-samples/frontend-only/feature.yaml +11 -0
- package/package.json +5 -4
- package/skills/agent-worker/SKILL.md +1 -1
- package/skills/agent-worker/references/agent-worker-operator.md +1 -1
- package/skills/loop-agent/references/command-reference.md +2 -2
- package/skills/loop-agent/references/harness-policy.md +1 -1
- package/dist/worker/console/static/assets/index-D9gnJn_l.js +0 -29
- package/dist/worker/console/static/assets/index-rajoXwkM.css +0 -1
|
@@ -6,7 +6,7 @@ import { getTaskPaths } from "../../task/runtime.js";
|
|
|
6
6
|
import { formatDuration, noopProgressReporter, } from "../progress-reporter.js";
|
|
7
7
|
import { redactForPreview, truncatePreview } from "../observability/events.js";
|
|
8
8
|
import { controllerIdentityExpectationFailure, resolveControllerIdentity, } from "../loop-agent/loop-agent-client.js";
|
|
9
|
-
import {
|
|
9
|
+
import { materializeTaskSpecV2, } from "../materialize/harness-task-materializer.js";
|
|
10
10
|
import { preflightTargetRepo } from "../preflight.js";
|
|
11
11
|
import { getTaskPoolRoot } from "../pool/run-store.js";
|
|
12
12
|
import { checkRequiredOutputs } from "../outcomes/gate.js";
|
|
@@ -26,7 +26,12 @@ export async function runTaskSpec(options) {
|
|
|
26
26
|
const commands = [];
|
|
27
27
|
const progress = options.progress ?? noopProgressReporter;
|
|
28
28
|
const taskId = options.taskSpec.id;
|
|
29
|
-
const eventCtx = {
|
|
29
|
+
const eventCtx = {
|
|
30
|
+
progress,
|
|
31
|
+
workerRunId,
|
|
32
|
+
taskId,
|
|
33
|
+
featureId: options.taskSpec.feature_id,
|
|
34
|
+
};
|
|
30
35
|
const recordingClient = new RecordingRunTaskClient(options.client, commands);
|
|
31
36
|
const client = new ObservedRunTaskClient(recordingClient, eventCtx);
|
|
32
37
|
if (options.preflight !== false) {
|
|
@@ -57,9 +62,9 @@ export async function runTaskSpec(options) {
|
|
|
57
62
|
}
|
|
58
63
|
const materializeStep = "materialize";
|
|
59
64
|
const materializeStartedAt = Date.now();
|
|
60
|
-
const
|
|
65
|
+
const materializeResult = await runObservedStep(eventCtx, materializeStep, async () => {
|
|
61
66
|
progress.step("materialize harness task");
|
|
62
|
-
return
|
|
67
|
+
return materializeTaskSpecV2({
|
|
63
68
|
repoRoot: options.repoRoot,
|
|
64
69
|
taskSpec: options.taskSpec,
|
|
65
70
|
taskSpecPath: options.taskSpecPath,
|
|
@@ -67,6 +72,14 @@ export async function runTaskSpec(options) {
|
|
|
67
72
|
now,
|
|
68
73
|
});
|
|
69
74
|
});
|
|
75
|
+
const materializeManifest = materializeResult.manifest;
|
|
76
|
+
const materializeOutcome = materializeResult.outcome;
|
|
77
|
+
if (materializeOutcome.type === "recovery-required") {
|
|
78
|
+
throw new Error(`materialize recovery required (${materializeOutcome.recovery.recommendedAction}): ${materializeOutcome.recovery.reason}`);
|
|
79
|
+
}
|
|
80
|
+
if (materializeOutcome.type === "resume-existing") {
|
|
81
|
+
progress.note(`materialize resume-existing: revision ${materializeOutcome.revisionId}, run ${materializeOutcome.runId}`);
|
|
82
|
+
}
|
|
70
83
|
progress.step(`materialized ${materializeManifest.harnessTaskId} in ${formatDuration(Date.now() - materializeStartedAt)}`);
|
|
71
84
|
const taskArtifactsDir = path.join(options.repoRoot, ".harness", "tasks", materializeManifest.harnessTaskId, "artifacts");
|
|
72
85
|
await mkdir(taskArtifactsDir, { recursive: true });
|
|
@@ -230,6 +243,9 @@ export async function runTaskSpec(options) {
|
|
|
230
243
|
dagPath,
|
|
231
244
|
runRecordPath,
|
|
232
245
|
materializeManifest,
|
|
246
|
+
materializeOutcome,
|
|
247
|
+
lineageId: materializeManifest.lineageId,
|
|
248
|
+
revisionId: materializeManifest.revisionId,
|
|
233
249
|
reportDecision,
|
|
234
250
|
commands,
|
|
235
251
|
...(declaredArtifacts ? { declaredArtifacts } : {}),
|
|
@@ -317,6 +333,9 @@ export async function runTaskSpec(options) {
|
|
|
317
333
|
dagPath,
|
|
318
334
|
runRecordPath,
|
|
319
335
|
materializeManifest,
|
|
336
|
+
materializeOutcome,
|
|
337
|
+
lineageId: materializeManifest.lineageId,
|
|
338
|
+
revisionId: materializeManifest.revisionId,
|
|
320
339
|
reportDecision,
|
|
321
340
|
commands,
|
|
322
341
|
...(declaredArtifacts ? { declaredArtifacts } : {}),
|
|
@@ -329,6 +348,7 @@ export async function runTaskSpec(options) {
|
|
|
329
348
|
source: "artifact",
|
|
330
349
|
label: "worker-run-record",
|
|
331
350
|
workerRunId,
|
|
351
|
+
featureId: options.taskSpec.feature_id,
|
|
332
352
|
taskId,
|
|
333
353
|
artifactRefs: {
|
|
334
354
|
runRecordPath,
|
|
@@ -496,6 +516,7 @@ function emitStepStarted(ctx, stepName) {
|
|
|
496
516
|
spanId: `step:${ctx.workerRunId}:${stepName}`,
|
|
497
517
|
parentSpanId: ctx.workerRunId,
|
|
498
518
|
workerRunId: ctx.workerRunId,
|
|
519
|
+
featureId: ctx.featureId,
|
|
499
520
|
taskId: ctx.taskId,
|
|
500
521
|
status: "running",
|
|
501
522
|
});
|
|
@@ -508,6 +529,7 @@ function emitStepFinished(ctx, stepName, status, durationMs) {
|
|
|
508
529
|
spanId: `step:${ctx.workerRunId}:${stepName}`,
|
|
509
530
|
parentSpanId: ctx.workerRunId,
|
|
510
531
|
workerRunId: ctx.workerRunId,
|
|
532
|
+
featureId: ctx.featureId,
|
|
511
533
|
taskId: ctx.taskId,
|
|
512
534
|
status,
|
|
513
535
|
durationMs,
|
|
@@ -760,6 +782,7 @@ class ObservedRunTaskClient {
|
|
|
760
782
|
source: "loop-agent-command",
|
|
761
783
|
label: options.artifactName,
|
|
762
784
|
workerRunId: this.eventCtx.workerRunId,
|
|
785
|
+
featureId: this.eventCtx.featureId,
|
|
763
786
|
taskId: this.eventCtx.taskId,
|
|
764
787
|
pid: info.pid,
|
|
765
788
|
timeoutMs: options.timeoutMs,
|
|
@@ -783,6 +806,7 @@ class ObservedRunTaskClient {
|
|
|
783
806
|
source: "loop-agent-command",
|
|
784
807
|
label: options.artifactName,
|
|
785
808
|
workerRunId: this.eventCtx.workerRunId,
|
|
809
|
+
featureId: this.eventCtx.featureId,
|
|
786
810
|
taskId: this.eventCtx.taskId,
|
|
787
811
|
message: `elapsed ${info.elapsedMs}ms`,
|
|
788
812
|
});
|
|
@@ -795,6 +819,7 @@ class ObservedRunTaskClient {
|
|
|
795
819
|
source: "loop-agent-command",
|
|
796
820
|
label: options.artifactName,
|
|
797
821
|
workerRunId: this.eventCtx.workerRunId,
|
|
822
|
+
featureId: this.eventCtx.featureId,
|
|
798
823
|
taskId: this.eventCtx.taskId,
|
|
799
824
|
exitCode: result.exitCode,
|
|
800
825
|
timedOut: result.timedOut,
|
|
@@ -810,6 +835,7 @@ class ObservedRunTaskClient {
|
|
|
810
835
|
source: "loop-agent-command",
|
|
811
836
|
label: options.artifactName,
|
|
812
837
|
workerRunId: this.eventCtx.workerRunId,
|
|
838
|
+
featureId: this.eventCtx.featureId,
|
|
813
839
|
taskId: this.eventCtx.taskId,
|
|
814
840
|
status: "failed",
|
|
815
841
|
message: errorMessage(error),
|
|
@@ -823,6 +849,7 @@ class ObservedRunTaskClient {
|
|
|
823
849
|
source: "loop-agent-command",
|
|
824
850
|
label,
|
|
825
851
|
workerRunId: this.eventCtx.workerRunId,
|
|
852
|
+
featureId: this.eventCtx.featureId,
|
|
826
853
|
taskId: this.eventCtx.taskId,
|
|
827
854
|
outputPreview: redactForPreview(truncatePreview(chunk)),
|
|
828
855
|
});
|
|
@@ -2,9 +2,13 @@ import { createHash } from "node:crypto";
|
|
|
2
2
|
import { readFile, writeFile, mkdir } from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import YAML from "yaml";
|
|
5
|
+
import { controllerIdentityAnchor } from "../../shared/package-metadata.js";
|
|
5
6
|
import { controllerIdentitiesMatch, controllerIdentityExpectationFailure, resolveControllerIdentity, } from "../loop-agent/loop-agent-client.js";
|
|
7
|
+
import { buildPublishedControllerProtocolEnvelope } from "../loop-agent/controller-protocol.js";
|
|
6
8
|
import { deriveFailureRoute, deriveFailureRouteFromError, } from "../pool/failure-routing.js";
|
|
7
9
|
import { findRunByWorkerRunId, getTaskPoolRoot, readFeatureTaskPoolStates, recordTaskPoolRun, writeTaskPoolState, } from "../pool/run-store.js";
|
|
10
|
+
import { releaseAttemptLease } from "../pool/attempt-lease.js";
|
|
11
|
+
import { beginWorkerAttemptWithLease } from "../pool/begin-attempt-with-lease.js";
|
|
8
12
|
import { readVerifiedOutcome } from "../outcomes/store.js";
|
|
9
13
|
import { runTaskSpec, } from "../run-task/run-task.js";
|
|
10
14
|
import { formatDuration, noopProgressReporter, } from "../progress-reporter.js";
|
|
@@ -100,6 +104,7 @@ export async function runReadyTasks(options) {
|
|
|
100
104
|
source: "worker",
|
|
101
105
|
label: `task ${taskId}: reuse existing run ${workerRunId}`,
|
|
102
106
|
batchRunId,
|
|
107
|
+
featureId,
|
|
103
108
|
taskId,
|
|
104
109
|
workerRunId,
|
|
105
110
|
status: "reused",
|
|
@@ -116,32 +121,44 @@ export async function runReadyTasks(options) {
|
|
|
116
121
|
}
|
|
117
122
|
const taskStartedAt = Date.now();
|
|
118
123
|
progress.task(`task ${index}/${total} ${taskId} "${taskSpec.title}" (${workerRunId})`);
|
|
119
|
-
emit(progress, {
|
|
120
|
-
type: "task.started",
|
|
121
|
-
source: "worker",
|
|
122
|
-
label: `task ${index}/${total} ${taskId}`,
|
|
123
|
-
batchRunId,
|
|
124
|
-
taskId,
|
|
125
|
-
workerRunId,
|
|
126
|
-
status: "running",
|
|
127
|
-
});
|
|
128
124
|
progress.step(`materialize → task advance → report`);
|
|
129
125
|
let result;
|
|
126
|
+
let leaseToken;
|
|
130
127
|
try {
|
|
131
|
-
await
|
|
132
|
-
|
|
128
|
+
const begun = await beginWorkerAttemptWithLease({
|
|
129
|
+
repoRoot: options.repoRoot,
|
|
130
|
+
featureId,
|
|
131
|
+
taskId,
|
|
132
|
+
workerRunId,
|
|
133
|
+
batchRunId,
|
|
134
|
+
now,
|
|
135
|
+
...(controllerIdentity
|
|
136
|
+
? {
|
|
137
|
+
controllerAnchor: controllerIdentityAnchor(controllerIdentity),
|
|
138
|
+
protocolEnvelope: buildPublishedControllerProtocolEnvelope(controllerIdentity.packageVersion),
|
|
139
|
+
}
|
|
140
|
+
: {}),
|
|
141
|
+
stateExtras: {
|
|
142
|
+
...(retryOfWorkerRunId ? { retryOfWorkerRunId } : {}),
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
leaseToken = begun.leaseRegistration.lease.token;
|
|
146
|
+
emit(progress, {
|
|
147
|
+
type: "task.started",
|
|
148
|
+
source: "worker",
|
|
149
|
+
label: `task ${index}/${total} ${taskId}`,
|
|
150
|
+
batchRunId,
|
|
133
151
|
featureId,
|
|
134
152
|
taskId,
|
|
135
|
-
status: "Running",
|
|
136
|
-
updatedAt: new Date().toISOString(),
|
|
137
153
|
workerRunId,
|
|
138
|
-
|
|
154
|
+
status: "running",
|
|
139
155
|
});
|
|
140
156
|
emit(progress, {
|
|
141
157
|
type: "state.updated",
|
|
142
158
|
source: "worker",
|
|
143
159
|
label: `task pool state: ${taskId} → Running`,
|
|
144
160
|
batchRunId,
|
|
161
|
+
featureId,
|
|
145
162
|
taskId,
|
|
146
163
|
workerRunId,
|
|
147
164
|
status: "running",
|
|
@@ -178,6 +195,7 @@ export async function runReadyTasks(options) {
|
|
|
178
195
|
source: "worker",
|
|
179
196
|
label: `task ${taskId} run-error`,
|
|
180
197
|
batchRunId,
|
|
198
|
+
featureId,
|
|
181
199
|
taskId,
|
|
182
200
|
workerRunId,
|
|
183
201
|
status: "failed",
|
|
@@ -215,6 +233,16 @@ export async function runReadyTasks(options) {
|
|
|
215
233
|
}
|
|
216
234
|
if (recorded)
|
|
217
235
|
await options.onTaskFinalized?.({ status: "run-error", taskSpec, workerRunId });
|
|
236
|
+
if (leaseToken) {
|
|
237
|
+
await releaseAttemptLease({
|
|
238
|
+
repoRoot: options.repoRoot,
|
|
239
|
+
featureId,
|
|
240
|
+
taskId,
|
|
241
|
+
token: leaseToken,
|
|
242
|
+
workerRunId,
|
|
243
|
+
now,
|
|
244
|
+
}).catch(() => { });
|
|
245
|
+
}
|
|
218
246
|
tasks.push({
|
|
219
247
|
taskId,
|
|
220
248
|
workerRunId,
|
|
@@ -236,6 +264,7 @@ export async function runReadyTasks(options) {
|
|
|
236
264
|
source: "worker",
|
|
237
265
|
label: `task ${taskId} ${result.status}`,
|
|
238
266
|
batchRunId,
|
|
267
|
+
featureId,
|
|
239
268
|
taskId,
|
|
240
269
|
workerRunId: result.workerRunId,
|
|
241
270
|
status: result.status,
|
|
@@ -247,6 +276,7 @@ export async function runReadyTasks(options) {
|
|
|
247
276
|
source: "worker",
|
|
248
277
|
label: `failure routed: ${failure.category}`,
|
|
249
278
|
batchRunId,
|
|
279
|
+
featureId,
|
|
250
280
|
taskId,
|
|
251
281
|
workerRunId: result.workerRunId,
|
|
252
282
|
failureCategory: failure.category,
|
|
@@ -299,6 +329,16 @@ export async function runReadyTasks(options) {
|
|
|
299
329
|
status: result.status,
|
|
300
330
|
runRecordPath: result.runRecordPath,
|
|
301
331
|
});
|
|
332
|
+
if (leaseToken) {
|
|
333
|
+
await releaseAttemptLease({
|
|
334
|
+
repoRoot: options.repoRoot,
|
|
335
|
+
featureId,
|
|
336
|
+
taskId,
|
|
337
|
+
token: leaseToken,
|
|
338
|
+
workerRunId: result.workerRunId,
|
|
339
|
+
now,
|
|
340
|
+
}).catch(() => { });
|
|
341
|
+
}
|
|
302
342
|
}
|
|
303
343
|
catch (error) {
|
|
304
344
|
if (result.status !== "succeeded") {
|
|
@@ -344,6 +384,16 @@ export async function runReadyTasks(options) {
|
|
|
344
384
|
catch {
|
|
345
385
|
// Best-effort; batch still reports record-error.
|
|
346
386
|
}
|
|
387
|
+
if (leaseToken) {
|
|
388
|
+
await releaseAttemptLease({
|
|
389
|
+
repoRoot: options.repoRoot,
|
|
390
|
+
featureId,
|
|
391
|
+
taskId,
|
|
392
|
+
token: leaseToken,
|
|
393
|
+
workerRunId: result.workerRunId,
|
|
394
|
+
now,
|
|
395
|
+
}).catch(() => { });
|
|
396
|
+
}
|
|
347
397
|
tasks.push({
|
|
348
398
|
taskId,
|
|
349
399
|
workerRunId: result.workerRunId,
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
+
import { controllerIdentityAnchor } from "../../shared/package-metadata.js";
|
|
2
|
+
import { buildPublishedControllerProtocolEnvelope } from "../loop-agent/controller-protocol.js";
|
|
3
|
+
import { releaseAttemptLease } from "../pool/attempt-lease.js";
|
|
1
4
|
import { deriveFailureRoute, deriveFailureRouteFromError, } from "../pool/failure-routing.js";
|
|
5
|
+
import { beginWorkerAttemptWithLease } from "../pool/begin-attempt-with-lease.js";
|
|
2
6
|
import { recordTaskPoolRun, writeTaskPoolState } from "../pool/run-store.js";
|
|
3
7
|
/**
|
|
4
8
|
* Shared Worker attempt used by batch run-ready and Night Scheduler.
|
|
@@ -7,24 +11,33 @@ import { recordTaskPoolRun, writeTaskPoolState } from "../pool/run-store.js";
|
|
|
7
11
|
export async function runSingleTaskAttempt(input) {
|
|
8
12
|
const now = input.ctx.now ?? new Date();
|
|
9
13
|
const { ctx } = input;
|
|
10
|
-
await
|
|
11
|
-
|
|
14
|
+
const begun = await beginWorkerAttemptWithLease({
|
|
15
|
+
repoRoot: ctx.controlRepoRoot,
|
|
12
16
|
featureId: ctx.featureId,
|
|
13
17
|
taskId: ctx.taskId,
|
|
14
|
-
status: "Running",
|
|
15
|
-
updatedAt: now.toISOString(),
|
|
16
18
|
workerRunId: ctx.workerRunId,
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
? { nightWorktreePath: ctx.night.nightWorktreePath }
|
|
19
|
+
batchRunId: ctx.batchRunId,
|
|
20
|
+
now,
|
|
21
|
+
...(ctx.controllerIdentity
|
|
22
|
+
? {
|
|
23
|
+
controllerAnchor: controllerIdentityAnchor(ctx.controllerIdentity),
|
|
24
|
+
protocolEnvelope: buildPublishedControllerProtocolEnvelope(ctx.controllerIdentity.packageVersion),
|
|
25
|
+
}
|
|
25
26
|
: {}),
|
|
26
|
-
|
|
27
|
+
stateExtras: {
|
|
28
|
+
...(ctx.night?.nightScheduleId
|
|
29
|
+
? { nightScheduleId: ctx.night.nightScheduleId }
|
|
30
|
+
: {}),
|
|
31
|
+
...(ctx.night?.admissionPath
|
|
32
|
+
? { admissionPath: ctx.night.admissionPath }
|
|
33
|
+
: {}),
|
|
34
|
+
...(ctx.night?.nightWorktreePath
|
|
35
|
+
? { nightWorktreePath: ctx.night.nightWorktreePath }
|
|
36
|
+
: {}),
|
|
37
|
+
...(ctx.night?.nightBranch ? { nightBranch: ctx.night.nightBranch } : {}),
|
|
38
|
+
},
|
|
27
39
|
});
|
|
40
|
+
const leaseToken = begun.leaseRegistration.lease.token;
|
|
28
41
|
let result;
|
|
29
42
|
try {
|
|
30
43
|
result = await input.execute(ctx);
|
|
@@ -70,6 +83,14 @@ export async function runSingleTaskAttempt(input) {
|
|
|
70
83
|
: {}),
|
|
71
84
|
...(ctx.night?.nightBranch ? { nightBranch: ctx.night.nightBranch } : {}),
|
|
72
85
|
});
|
|
86
|
+
await releaseAttemptLease({
|
|
87
|
+
repoRoot: ctx.controlRepoRoot,
|
|
88
|
+
featureId: ctx.featureId,
|
|
89
|
+
taskId: ctx.taskId,
|
|
90
|
+
token: leaseToken,
|
|
91
|
+
workerRunId: ctx.workerRunId,
|
|
92
|
+
now,
|
|
93
|
+
}).catch(() => { });
|
|
73
94
|
return {
|
|
74
95
|
status: "run-error",
|
|
75
96
|
workerRunId: ctx.workerRunId,
|
|
@@ -137,6 +158,14 @@ export async function runSingleTaskAttempt(input) {
|
|
|
137
158
|
...(ctx.night?.nightBranch ? { nightBranch: ctx.night.nightBranch } : {}),
|
|
138
159
|
};
|
|
139
160
|
await writeTaskPoolState(ctx.controlRepoRoot, poolState);
|
|
161
|
+
await releaseAttemptLease({
|
|
162
|
+
repoRoot: ctx.controlRepoRoot,
|
|
163
|
+
featureId: ctx.featureId,
|
|
164
|
+
taskId: ctx.taskId,
|
|
165
|
+
token: leaseToken,
|
|
166
|
+
workerRunId: ctx.workerRunId,
|
|
167
|
+
now,
|
|
168
|
+
}).catch(() => { });
|
|
140
169
|
return {
|
|
141
170
|
status: result.status,
|
|
142
171
|
workerRunId: result.workerRunId,
|
|
@@ -21,6 +21,9 @@ export const acceptanceItemSchema = z
|
|
|
21
21
|
implementation_task_refs: z.array(z.string().min(1)).optional(),
|
|
22
22
|
verification_task_refs: z.array(z.string().min(1)).optional(),
|
|
23
23
|
required_evidence: z.array(z.string().min(1)).optional(),
|
|
24
|
+
/** Phase 6: ADR 0007 authority / evidence kinds on required ACs. */
|
|
25
|
+
authority: z.string().min(1).optional(),
|
|
26
|
+
required_evidence_kinds: z.array(z.string().min(1)).optional(),
|
|
24
27
|
integration: z
|
|
25
28
|
.enum(["not-applicable", "mock-allowed", "real-required"])
|
|
26
29
|
.optional(),
|
package/docs/README.md
CHANGED
|
@@ -29,7 +29,9 @@
|
|
|
29
29
|
| 运行 DAG、查看报告或处理失败 | `runtime/agent-dag-runner.md`、`runtime/agent-dag-recovery-playbook.md` |
|
|
30
30
|
| 按 TDD、验证和调试纪律推进修复 | `governance/harness-methodology-tdd.md`、`governance/harness-methodology-verification.md`、`governance/harness-methodology-debugging.md` |
|
|
31
31
|
| 执行真实 backend-test provider 验证 | `runtime/backend-test-live-campaign.md` |
|
|
32
|
-
|
|
|
32
|
+
| 判断单任务 loop-agent Production Readiness | `operations/production-readiness.md` |
|
|
33
|
+
| 判断 agent-worker Feature/Attempt Production Readiness v1 | `operations/agent-worker-production-readiness.md`、`templates/agent-worker-production-readiness-checklist.md` |
|
|
34
|
+
| 分阶段推进 agent-worker Production Readiness v1 | `exec-plans/active/2026-08-09-agent-worker-production-readiness-v1-program.md`、`exec-plans/active/README.md` |
|
|
33
35
|
| 合并分支并留下 source-SHA 报告 | `operations/branch-merge-guideline.md` |
|
|
34
36
|
| 使用仓库内 GitHub 协作方式 | `operations/github-collaboration.md` |
|
|
35
37
|
| 排查本机开发环境问题 | `operations/local-development-environment.md` |
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
| Backend-test | **Markdown-first 8 节点**;Markdown 映射限定 pytest 执行,生成 Markdown 与分层 HTML/脱敏请求响应详情 | completed `2026-07-24-backend-test-scoped-execution-report-ui.md`;`CHANGELOG.md [0.21.0]` / `[0.22.0]` |
|
|
21
21
|
| Frontend-test | 默认 short-chain RAG;内容/evidence 质量进入 advisory findings,路径与安全边界仍 fail-closed | `CHANGELOG.md [0.21.0]` / `[0.22.0]` |
|
|
22
22
|
| Frontend-implementation | Contract / trace / repair / Mock assess;`ai_workspace` + 知识库 + `openspec` 规范发现;lint 基线债务隔离 | `CHANGELOG.md [0.22.0]` |
|
|
23
|
-
| Inspect(原 Observe) | 统一 Console 的 `/inspect/`
|
|
23
|
+
| Inspect(原 Observe) | 统一 Console 的 `/inspect/` 只读运营面与富时间线;独立 `observe serve` 已硬下线 | `website/docs/guides/observe-ui.md`、`CHANGELOG.md [Unreleased]` |
|
|
24
24
|
| Local Operator Console | `agent-worker console serve\|doctor`(loopback);Operate + Inspect、Happy Path / Interview / split view / recovery CTA;**0.23.x 起含 General Operator Chat**(Pi SDK services session、operator-only tool surface);**非**远端多用户 Console | unify design;ADR 0005;completed `2026-07-25-console-phase-4-general-operator-chat.md` |
|
|
25
25
|
| Task Contract / operator surface | journaled `task contract *`;machine envelope;**DagSpec v4 `taskContractBinding`**(exclusive writer 强制) | `CHANGELOG.md [0.17.0]`–`[0.17.2]`;ADR 0005 |
|
|
26
26
|
| DagSpec / repair | v3 `runtimeContract` + 显式 `repairNodeId`;新 writer 生成默认 v4 binding | `dag-execution.md`、`CHANGELOG.md [0.11.0]` / `[0.17.0]` |
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
- [`branch-merge-guideline.md`](branch-merge-guideline.md):按风险选择合并模式并留下 source-SHA 证据。
|
|
9
9
|
- [`github-collaboration.md`](github-collaboration.md):仓库内 GitHub 协作约定及自动/人工发布通道。
|
|
10
10
|
- [`production-readiness.md`](production-readiness.md):交付前的生产就绪判断。
|
|
11
|
+
- [`agent-worker-production-readiness.md`](agent-worker-production-readiness.md):agent-worker Feature/Task Pool 外层编排的 Production Readiness v1 操作合同。
|
|
11
12
|
- [`backend-test-jacoco-coverage.md`](backend-test-jacoco-coverage.md):Java 被测服务挂载 JaCoCo tcpserver agent 的 Maven、`java -jar` 与 Docker 操作手册。
|
|
12
13
|
|
|
13
14
|
验证命令仍以 [`../governance/verification-matrix.md`](../governance/verification-matrix.md) 为准。
|
package/docs/templates/README.md
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
- `branch-merge-report.md` — source-SHA 分支合并报告。
|
|
15
15
|
- `init-evolution-review.md` — 初始化能力演化审查。
|
|
16
16
|
- `production-readiness-checklist.md` — Production Readiness 检查。
|
|
17
|
+
- `agent-worker-production-readiness-checklist.md` — agent-worker Feature/Task Pool Production Readiness v1 campaign 检查清单。
|
|
17
18
|
- `worker-dogfood-setup.md`、`worker-dogfood-evidence.md` — 已发布控制器下的 Worker dogfood 设置与证据。
|
|
18
19
|
- `interactive-ui-round2-experiment.md` — 交互式 UI 对照实验。
|
|
19
20
|
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Agent Worker Production Readiness v1 Checklist
|
|
2
|
+
|
|
3
|
+
用于 Phase 8 campaign / 发布门禁。勾选前必须有新鲜命令输出或 report ref。
|
|
4
|
+
|
|
5
|
+
正式 pin(2026-08-09):`@tea-agent/loop-agent@0.32.0`(tag `v0.32.0` / `b4d9e500`)。scorecard 在 burn-in / live 门禁完成前保持 **NOT_READY**。证据:`docs/reports/feature/2026-08-09-agent-worker-production-readiness-v1.md`。
|
|
6
|
+
|
|
7
|
+
## 包络与身份
|
|
8
|
+
|
|
9
|
+
- [x] 支持包络已冻结(单机/单用户/单仓)
|
|
10
|
+
- [x] controller packageVersion + fingerprint 已记录(`0.32.0`;npm shasum `8932749b1583523043a9889c84f9d316e57e451d`;canary fingerprint `sha256:b08404f5…`)
|
|
11
|
+
- [x] published canary / 隔离 install **无** npm link / workspace bin(live burn-in 仍须每日复核)
|
|
12
|
+
- [x] protocol/capabilities preflight(unit)通过;live preflight 仍待
|
|
13
|
+
|
|
14
|
+
## Ownership / Attempt
|
|
15
|
+
|
|
16
|
+
- [x] Running 投影不依赖 terminal ledger(unit / Phase 1)
|
|
17
|
+
- [x] Task-scoped events 含 featureId(unit)
|
|
18
|
+
- [x] dual Feature 同名 Task 隔离(unit C2)
|
|
19
|
+
- [x] ownership warning 按根因聚合(≤1 finding/根因)(unit)
|
|
20
|
+
|
|
21
|
+
## Lifecycle / Recovery
|
|
22
|
+
|
|
23
|
+
- [x] safe run-error → Failed → `task retry` 无需 mark-failed(unit)
|
|
24
|
+
- [x] Blocked 保留 contract/human 语义(unit)
|
|
25
|
+
- [x] resume / retry / reconcile / revise / decide 决策一致(unit)
|
|
26
|
+
|
|
27
|
+
## Lease
|
|
28
|
+
|
|
29
|
+
- [x] `{featureId, taskId}` 单 active writer(unit C3)
|
|
30
|
+
- [ ] begin/finalize crash injection 有 doctor finding(进程级仍缺)
|
|
31
|
+
- [x] 不盲目偷取 live DAG lease(unit reclaim)
|
|
32
|
+
|
|
33
|
+
## Acceptance / Delivery
|
|
34
|
+
|
|
35
|
+
- [x] Task Done ≠ AC covered(unit)
|
|
36
|
+
- [x] `feature verify-final` 唯一 writer(unit)
|
|
37
|
+
- [ ] verify-final → delivery → closeout **live** 可收口
|
|
38
|
+
- [x] dirty HEAD / tamper fail-closed(unit)
|
|
39
|
+
|
|
40
|
+
## Campaign / SLO
|
|
41
|
+
|
|
42
|
+
- [x] C0–C11 已执行或明确 blocked-external(partial:unit + published canary;live Pi blocked)
|
|
43
|
+
- [ ] burn-in 窗口达标(7 日或 30 Attempt)— **OPEN day 0**
|
|
44
|
+
- [ ] SLO 分子/分母已记录(正式样本不足)
|
|
45
|
+
- [x] promote + rollback drill 完成(install-level vs `0.31.1`)
|
|
46
|
+
- [ ] scorecard: READY 或合法 CONDITIONALLY_READY — 当前 **`NOT_READY`**
|
|
47
|
+
- [x] open P0 = 0
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
4. 涉及测试纪律/验证声明/调试时继续读:`docs/harness-methodology-*.md`。
|
|
38
38
|
5. 查看最近提交、相关 plan/progress/report;`git status --short --branch`;跑最小基线验证。
|
|
39
39
|
6. 后端/接口/pytest → `taskKind: "backend-test"`(不是 `--profile`);知识回写 `knowledge-sync`;图谱开荒 `knowledge-graph-bootstrap`。`--profile` 仅 `auto|minimal|standard|reviewed|supervised`。
|
|
40
|
-
7. 看板/observe → `agent-worker console`(默认 repo=当前目录、port=8790;兼容 `agent-worker console serve --repo . --port 8790`)(`/inspect/` 只读);`observe serve`
|
|
40
|
+
7. 看板/observe → `agent-worker console`(默认 repo=当前目录、port=8790;兼容 `agent-worker console serve --repo . --port 8790`)(`/inspect/` 只读);`observe serve` 已下线(REMOVED / exit 2);`observe snapshot` 仍可用。
|
|
41
41
|
8. 分支合并 → 先读 `docs/operations/branch-merge-guideline.md`。
|
|
42
42
|
|
|
43
43
|
## 会话协议
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
10. 检查 `git status --short --branch`。
|
|
55
55
|
11. 运行本次任务相关的最小基线验证。
|
|
56
56
|
12. 如果用户提到"后端测试"、"接口测试"、"pytest"、"自动化测试",在任务 `task.json` 中设置 `taskKind: "backend-test"` 再 `task advance`;不要用 `--profile backend-test`(CLI 不接受该值,专用模板只走 taskKind)。知识回写用 `taskKind: "knowledge-sync"`(须 `featureId`),图谱开荒用 `taskKind: "knowledge-graph-bootstrap"`。`--profile` 仅表示治理强度:`auto|minimal|standard|reviewed|supervised`。
|
|
57
|
-
13. 如果用户提到"看板"、"observe"、"监控面板"、"启动看板",使用 `agent-worker console` 启动统一 Operator Console(默认 repo=当前目录、port=8790;兼容入口 `agent-worker console serve --repo . --port 8790`);`/inspect/` 提供只读检视。`agent-worker observe serve
|
|
57
|
+
13. 如果用户提到"看板"、"observe"、"监控面板"、"启动看板",使用 `agent-worker console` 启动统一 Operator Console(默认 repo=当前目录、port=8790;兼容入口 `agent-worker console serve --repo . --port 8790`);`/inspect/` 提供只读检视。`agent-worker observe serve` 已下线(REMOVED / exit 2)。
|
|
58
58
|
14. 如果用户要求“合并 `<source>` 到 `<target>`”或“合并 origin/main 到当前分支”,先阅读 `docs/operations/branch-merge-guideline.md`,按影响自动选择快速、标准或深度模式;始终冻结 source SHA、审查双方功能、运行 merge-tree、生成 source-SHA 合并报告,并在提交前再次 fetch 防止主干前进。
|
|
59
59
|
|
|
60
60
|
## 会话协议
|
|
@@ -131,7 +131,7 @@ agent-worker console # 默认 repo=当前目录,port=879
|
|
|
131
131
|
agent-worker console serve --repo . --port 8790 # 兼容入口,等价于上面裸入口
|
|
132
132
|
```
|
|
133
133
|
|
|
134
|
-
浏览器打开 `http://127.0.0.1:8790/`;检视面为 `http://127.0.0.1:8790/inspect/`。默认绑定本机 `127.0.0.1`;不要直接暴露到公开网络。端口被占用时不会自动更换,请用 `--port <port>` 显式指定。`agent-worker observe serve`
|
|
134
|
+
浏览器打开 `http://127.0.0.1:8790/`;检视面为 `http://127.0.0.1:8790/inspect/`。默认绑定本机 `127.0.0.1`;不要直接暴露到公开网络。端口被占用时不会自动更换,请用 `--port <port>` 显式指定。`agent-worker observe serve` 已下线(REMOVED / exit 2)。
|
|
135
135
|
|
|
136
136
|
### DAG 诊断与收口
|
|
137
137
|
|
|
@@ -1,3 +1,14 @@
|
|
|
1
1
|
schema_version: 1
|
|
2
2
|
feature_id: F-2099-901
|
|
3
3
|
profile: generic
|
|
4
|
+
acceptance_policy:
|
|
5
|
+
schema_version: 1
|
|
6
|
+
authority: feature-verify-final
|
|
7
|
+
independent_qa_required: true
|
|
8
|
+
coverage_writer: feature-verify-final
|
|
9
|
+
final_verification:
|
|
10
|
+
command: agent-worker feature verify-final
|
|
11
|
+
delivery_sequence:
|
|
12
|
+
- verify-final
|
|
13
|
+
- delivery
|
|
14
|
+
- closeout
|
|
@@ -1,3 +1,14 @@
|
|
|
1
1
|
schema_version: 1
|
|
2
2
|
feature_id: F-2099-903
|
|
3
3
|
profile: generic
|
|
4
|
+
acceptance_policy:
|
|
5
|
+
schema_version: 1
|
|
6
|
+
authority: feature-verify-final
|
|
7
|
+
independent_qa_required: true
|
|
8
|
+
coverage_writer: feature-verify-final
|
|
9
|
+
final_verification:
|
|
10
|
+
command: agent-worker feature verify-final
|
|
11
|
+
delivery_sequence:
|
|
12
|
+
- verify-final
|
|
13
|
+
- delivery
|
|
14
|
+
- closeout
|
|
@@ -1,3 +1,14 @@
|
|
|
1
1
|
schema_version: 1
|
|
2
2
|
feature_id: F-2099-902
|
|
3
3
|
profile: generic
|
|
4
|
+
acceptance_policy:
|
|
5
|
+
schema_version: 1
|
|
6
|
+
authority: feature-verify-final
|
|
7
|
+
independent_qa_required: true
|
|
8
|
+
coverage_writer: feature-verify-final
|
|
9
|
+
final_verification:
|
|
10
|
+
command: agent-worker feature verify-final
|
|
11
|
+
delivery_sequence:
|
|
12
|
+
- verify-final
|
|
13
|
+
- delivery
|
|
14
|
+
- closeout
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tea-agent/loop-agent",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.32.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"loop-agent": "bin/loop-agent.js",
|
|
@@ -46,11 +46,12 @@
|
|
|
46
46
|
"clean": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
|
|
47
47
|
"brand:sync": "node scripts/sync-brand-assets.mjs",
|
|
48
48
|
"build": "npm run brand:sync && npm run clean && tsc -p tsconfig.build.json && node -e \"const fs=require('node:fs');const p='dist/worker/observe/static';fs.mkdirSync(p,{recursive:true});fs.cpSync('src/worker/observe/static',p,{recursive:true});\" && npm run console:build",
|
|
49
|
-
"console:
|
|
49
|
+
"console:typecheck": "tsc -p src/worker/console/tsconfig.json",
|
|
50
|
+
"console:build": "npm run console:typecheck && vite build --config src/worker/console/vite.config.ts",
|
|
50
51
|
"prepack": "npm run build",
|
|
51
52
|
"prepublishOnly": "node scripts/check-npm-publish-policy.mjs && npm run typecheck && npm test && npm run build",
|
|
52
|
-
"lint": "
|
|
53
|
-
"typecheck": "tsc --noEmit",
|
|
53
|
+
"lint": "npm run typecheck",
|
|
54
|
+
"typecheck": "tsc --noEmit && npm run console:typecheck",
|
|
54
55
|
"test": "node scripts/run-tests.mjs",
|
|
55
56
|
"test:host": "vitest run test/init-upgrade.test.ts --maxWorkers=1 -t \"records and reuses|controller-authorized semantic merge|authority-sensitive\"",
|
|
56
57
|
"test:fast": "vitest run --config vitest.fast.config.ts",
|
|
@@ -16,7 +16,7 @@ references:
|
|
|
16
16
|
- **允许**:`agent-worker` / `loop-agent` CLI;只读 `pool doctor`、`observe`、status/report;冻结 controller identity;选择 Ready 工作与 recovery 命令。
|
|
17
17
|
- **禁止**:绕过 CLI 直接 Edit 业务实现;Worker/DAG 失败后主会话「救火改文件」。
|
|
18
18
|
- **失败时只允许**:保留 evidence → `task retry` / `task reconcile` / `pool mark-failed` / human gate → 再经 CLI 重跑;实现写入仍只经 published `loop-agent` DAG。
|
|
19
|
-
- **Official vs Compatibility**:`agent-worker console` 是 Official 本地控制面(裸入口直接启动;默认 repo=当前目录、port=8790;兼容入口 `agent-worker console serve --repo . --port 8790` 等价)。同进程提供 Operate + Inspect,Inspect 路径 `/inspect/#/...`;openCode 等主会话仍是 Compatibility Assist
|
|
19
|
+
- **Official vs Compatibility**:`agent-worker console` 是 Official 本地控制面(裸入口直接启动;默认 repo=当前目录、port=8790;兼容入口 `agent-worker console serve --repo . --port 8790` 等价)。同进程提供 Operate + Inspect,Inspect 路径 `/inspect/#/...`;openCode 等主会话仍是 Compatibility Assist,二者**不是**同等保证。`observe serve` 已硬下线(`OBSERVE_SERVE_REMOVED` + exit 2,不监听端口);只读检视请用 Console `/inspect/`;`observe snapshot` 仍输出 GlobalSnapshot JSON。
|
|
20
20
|
|
|
21
21
|
## Route the Work
|
|
22
22
|
|
|
@@ -54,7 +54,7 @@ Leaf DAG nodes 不得递归启动 `agent-worker`。Worker 负责 DAG 之外的 s
|
|
|
54
54
|
```
|
|
55
55
|
|
|
56
56
|
doctor 只读;migrate 默认零写入,apply 失败全回滚且不改 JSONL。
|
|
57
|
-
8. Inspect(原 Observe
|
|
57
|
+
8. Inspect(原 Observe)只读:仅推荐 `agent-worker console`(或 `console serve`)的 `/inspect/#/...`;`observe snapshot` 仍可用。`observe serve` 已下线(REMOVED / exit 2)。canonical Task 路由为 `/api/features/:featureId/tasks/:taskId` 与 `#/feature/:featureId/task/:taskId`。8790 `/api/health` 为 `OperatorSurfaceHealthV1`。
|
|
58
58
|
9. Official Console:`agent-worker console serve|doctor`(默认 loopback;可 `--host 0.0.0.0` / `--debug`)。Recovery CTA 为 report/doctor/decision/resume/reconcile/regenerate/打开检视;无 Cancel、无主 CTA「直接改代码」。主会话 Compatibility Assist 不得替代 Console/CLI 执法。
|
|
59
59
|
|
|
60
60
|
## Feature Packet Scaffold
|
|
@@ -576,7 +576,7 @@ agent-worker scheduler transition <schedule-id> --repo <repo-root> --to <status>
|
|
|
576
576
|
agent-worker console [--repo <repo-root>] [--port 8790] [--host 127.0.0.1] # Official 裸入口;repo 默认当前目录
|
|
577
577
|
agent-worker console serve --repo <repo-root> [--port 8790] [--host 127.0.0.1] # 兼容入口,等价于裸入口
|
|
578
578
|
agent-worker console doctor --repo <repo-root> [--json] [--console-url <url>]
|
|
579
|
-
agent-worker observe serve
|
|
579
|
+
agent-worker observe serve ... # REMOVED:stderr OBSERVE_SERVE_REMOVED,exit 2,不监听端口;请用 console + /inspect/
|
|
580
580
|
agent-worker observe snapshot --repo <repo-root> # 输出 GlobalSnapshot JSON 到 stdout
|
|
581
581
|
```
|
|
582
582
|
|
|
@@ -600,7 +600,7 @@ agent-worker observe snapshot --repo <repo-root> # 输出 GlobalSnapshot JSON
|
|
|
600
600
|
- `report metrics` 按 UTC 月去重投影 Feature/Failure/Follow-up/Delivery/AC/decision/recovery/boundary 指标,同时写 JSON 与 Markdown;每项保留 numerator、denominator、sampleSize 和 missingData。
|
|
601
601
|
- `task draft-followup` 会按全部 failure category 生成 TaskDraft 或人工行动卡:ProductBug/TestBug/FlakyTest/DependencyFailure 可批准;EnvFailure 连续两次后才生成 ENV-CHECK;Spec/Contract/Risk/Human/Unknown 只给行动卡。人工以 `feature approve-followup --dry-run` 预览,再带非空 `--owner` 批准 TaskDraft;行动卡不能批准。批准在 staging validation 后写 TaskSpec、graph、Ready/approval/event,原失败事实不改写,并有 rename/state/approval/index/event 回滚门禁。
|
|
602
602
|
- `task retry` 是失败 Task 的唯一重试入口。它会保留原有运行记录和 failure handoff,并让下一次 `batch run-ready` 使用新的 `workerRunId`;不要删除运行态文件或手动修改状态来重试。
|
|
603
|
-
- **推荐**裸入口 `agent-worker console`(repo 默认当前目录,默认 `127.0.0.1:8790`)提供 Operate + Inspect;`console serve` 是等价兼容入口。Inspect 路径为 `/inspect/#/...`,API 仍为根 `/api/**`。`observe serve`
|
|
603
|
+
- **推荐**裸入口 `agent-worker console`(repo 默认当前目录,默认 `127.0.0.1:8790`)提供 Operate + Inspect;`console serve` 是等价兼容入口。Inspect 路径为 `/inspect/#/...`,API 仍为根 `/api/**`。`observe serve` 已硬下线(`OBSERVE_SERVE_REMOVED` + exit 2,不监听);`observe snapshot` 保留。Inspect 本身不会启动、暂停或重试 Task / Worker / DAG。
|
|
604
604
|
- Night Scheduler(本地夜间自治):白天 `admission prepare` 冻结 worktree + DAG writeSet gate;`scheduler add` 消费 gate 并预约 Task Pool `Queued`(不立即执行);`scheduler clock install` 安装本机 user-level OS timer(launchd / systemd --user / schtasks)周期调用 `scheduler tick`;tick 写统一 Clock receipt,doctor/morning/status 可解释 missing/stale/error/busy/drift;成功后 `pending-harvest`,早晨 `scheduler harvest`(exact-base FF)或 `scheduler discard`;`report morning --window night` 与 Inspect `#/night` / Operate 夜间面板读取同一套 facts。Clock install/status/uninstall 为 CLI-only。
|
|
605
605
|
- 当前 Worker 仍是 v0(库 + CLI + dogfood);日间批处理未强制定时/CI 驱动;`report morning` 默认可从 Task Pool runs 汇总,并支持 `--window night` 投影 Scheduler facts。
|
|
606
606
|
|