@tea-agent/loop-agent 0.35.1-beta.1 → 0.35.1-beta.2
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/CHANGELOG.md +10 -2
- package/dist/build-stamp.json +3 -3
- package/dist/executors/dag-pi-executor.js +44 -0
- package/dist/shared/package-metadata.js +10 -0
- package/dist/worker/console/static/assets/{index-fsjzREob.js → index-CvsQgALl.js} +26 -26
- package/dist/worker/console/static/index.html +1 -1
- package/dist/worker/console/static-src/app/useRecoveryConsole.js +5 -0
- package/dist/worker/loop-agent/loop-agent-client.js +4 -3
- package/dist/worker/observability/read-model.js +20 -0
- package/dist/worker/preflight.js +2 -1
- package/dist/workflows/dag/backend-test-scenario-param.js +33 -23
- package/dist/workflows/dag/frontend-recovery-plan.js +73 -0
- package/dist/workflows/dag/frontend-recovery-root-manifest.js +123 -0
- package/dist/workflows/dag/frontend-recovery-run.js +539 -0
- package/dist/workflows/dag/frontend-writer-recovery.js +106 -0
- package/dist/workflows/dag/frontend-writer-rollback.js +821 -0
- package/dist/workflows/dag/recovery-recommendation.js +58 -0
- package/dist/workflows/dag/runner.js +201 -16
- package/dist/workflows/dag/scheduler.js +159 -0
- package/dist/workflows/dag/types.js +107 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
# 更新日志
|
|
2
2
|
|
|
3
|
-
## [
|
|
3
|
+
## [0.35.1-beta.2] - 2026-08-14
|
|
4
|
+
|
|
5
|
+
> frontend-implementation DAG 优化 v9 全六阶段 + Console 展示层(beta,发布到 `beta` dist-tag)。
|
|
4
6
|
|
|
5
|
-
## [
|
|
7
|
+
## [Unreleased]
|
|
6
8
|
|
|
7
9
|
### 改进
|
|
8
10
|
|
|
@@ -21,6 +23,12 @@
|
|
|
21
23
|
- `review` 失败不再默认可自动修复:只有 finding 同时具备明确文件、行或符号、requirement/AC 且修复范围 ⊆ writeSet、不需重新规划 contract 时才进入自动 repair,否则转人工
|
|
22
24
|
- `frontendRepairAssessment` 扩展结构化证据字段(verificationTargetId / commandLabel / exitCode / commandCategory / requirementIds / acceptanceCriteriaIds / fixScope / changedPaths / traceRef),缺必要证据时不再判定 repairable
|
|
23
25
|
- `frontend-implement-pi` 与 `frontend-repair-pi` 共享同一 prompt builder / contract loader / writeSet guard,仅 phase 与 baseline 不同
|
|
26
|
+
- 新增 `frontend-recovery-state-v1` / `frontend-recovery-result-v1` 类型与 schema;prewrite 判定 retryable-invalid 时不再直接失败,改为 parent 先终态收敛、写 recovery intent(phase=child-staging)
|
|
27
|
+
- 新增 candidate continuation:带 commit point 的 staged child 创建(staging 目录 + rename + activation marker + requestId 幂等)、facts import 与 reset closure,parent/child 以 recoveryRootRunId 归一到同一全链统计
|
|
28
|
+
- scheduler 对 recovery child 施加 activation marker 门禁(无有效 marker 不可调度/执行),fail-closed;continuation 配额按 root 统一限制(至多一次)
|
|
29
|
+
- 新增 writer transient rollback 基元(`frontend-writer-rollback.ts`):writeSet 内容快照(existing files + allowed-new)、逐文件 CAS 恢复(current hash 与 attempt hash 一致才恢复,否则 auto-recovery-blocked,禁止 `git reset --hard`)、可恢复事务式 rollback journal(pending→restoring→completed|blocked,含崩溃恢复 hash/CAS 重判)
|
|
30
|
+
- 接入 writer transient partial-write 自动恢复(`frontend-writer-recovery.ts`):writer provider 调用前捕获 baseline 快照、调用后记录 attempt 变更;终态聚合时对 transient partial write 先 CAS 回滚、再写 recovery intent 并顺序创建 child(重跑 `frontend-implement-pi`,导入上游 facts);回滚无法证明完整 → `auto-recovery-blocked`,不建 child
|
|
31
|
+
- 新增 frontend recovery root manifest(`frontend-recovery-root-manifest-v1`):全链按 `recoveryRootRunId` 去重统计(parent/child 不重复计),`recovered` 收敛为逻辑 `finished`;6 个 outcome(none/recovered/candidate-contract-invalid/prewrite-blocked/repair-exhausted/auto-recovery-blocked)映射到稳定 recovery CTA
|
|
24
32
|
|
|
25
33
|
## [0.35.0] - 2026-08-13
|
|
26
34
|
|
package/dist/build-stamp.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"version": "0.35.1-beta.
|
|
4
|
-
"gitSha": "
|
|
5
|
-
"builtAt": "2026-08-
|
|
3
|
+
"version": "0.35.1-beta.2",
|
|
4
|
+
"gitSha": "91471612918747b6f3d56271eb0198dc83f177a7",
|
|
5
|
+
"builtAt": "2026-08-14T16:38:30.567Z"
|
|
6
6
|
}
|
|
@@ -520,6 +520,33 @@ export async function executeDagPiNode(input, meta, piStepFn = executePiStep, wr
|
|
|
520
520
|
}
|
|
521
521
|
let result;
|
|
522
522
|
try {
|
|
523
|
+
// Phase 5 (P1-9): capture the writeSet baseline BEFORE the writer provider
|
|
524
|
+
// call so a transient partial write can be rolled back and recovered via a
|
|
525
|
+
// staged child. Only frontend-implementation writers; a failed capture is a
|
|
526
|
+
// hard fail (no baseline → no rollback → no recovery). Dynamic import avoids
|
|
527
|
+
// an executor ↔ scheduler static cycle.
|
|
528
|
+
if (isWriteTask &&
|
|
529
|
+
(input.task.id === "frontend-implement-pi" ||
|
|
530
|
+
input.task.id === "frontend-repair-pi") &&
|
|
531
|
+
(input.task.writeSet?.length ?? 0) > 0) {
|
|
532
|
+
try {
|
|
533
|
+
const { captureFrontendWriterAttemptIntent } = await import("../workflows/dag/frontend-writer-recovery.js");
|
|
534
|
+
await captureFrontendWriterAttemptIntent({
|
|
535
|
+
cwd: input.cwd,
|
|
536
|
+
runDir: meta.runDir,
|
|
537
|
+
writeSet: input.task.writeSet,
|
|
538
|
+
});
|
|
539
|
+
}
|
|
540
|
+
catch (error) {
|
|
541
|
+
return {
|
|
542
|
+
ok: false,
|
|
543
|
+
stdout: "",
|
|
544
|
+
stderr: `frontend writer attempt baseline capture failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
545
|
+
failureCategory: "write-guard",
|
|
546
|
+
durationMs: Date.now() - started,
|
|
547
|
+
};
|
|
548
|
+
}
|
|
549
|
+
}
|
|
523
550
|
result = await piStepFn({
|
|
524
551
|
attachedFiles: [],
|
|
525
552
|
modelConfig: resolveDagPiModelConfig(input.model, input.thinking ? { thinking: input.thinking } : undefined),
|
|
@@ -691,6 +718,23 @@ export async function executeDagPiNode(input, meta, piStepFn = executePiStep, wr
|
|
|
691
718
|
const changedFiles = pathsChangedDuringRun(snapshotGitStatusPorcelain(beforeStatus), afterSnapshot, beforePathFingerprints, afterPathFingerprints);
|
|
692
719
|
changeManifestAfterStatus = afterStatus;
|
|
693
720
|
changeManifestChangedFiles = changedFiles;
|
|
721
|
+
// Phase 5: record the attempt changed paths/hashes into the rollback
|
|
722
|
+
// intent so a transient partial write can be CAS-restored.
|
|
723
|
+
if ((input.task.id === "frontend-implement-pi" ||
|
|
724
|
+
input.task.id === "frontend-repair-pi") &&
|
|
725
|
+
(input.task.writeSet?.length ?? 0) > 0) {
|
|
726
|
+
try {
|
|
727
|
+
const { recordFrontendWriterAttempt } = await import("../workflows/dag/frontend-writer-recovery.js");
|
|
728
|
+
await recordFrontendWriterAttempt({
|
|
729
|
+
cwd: input.cwd,
|
|
730
|
+
runDir: meta.runDir,
|
|
731
|
+
changedPaths: changedFiles,
|
|
732
|
+
});
|
|
733
|
+
}
|
|
734
|
+
catch {
|
|
735
|
+
// best-effort: a missing intent (no baseline captured) is a no-op
|
|
736
|
+
}
|
|
737
|
+
}
|
|
694
738
|
const guard = validateShellWriteGuardFromDiff({
|
|
695
739
|
changedFiles,
|
|
696
740
|
task: input.task,
|
|
@@ -77,6 +77,16 @@ export function readCliVersionLabel(packageDir) {
|
|
|
77
77
|
return version;
|
|
78
78
|
return `${version} (build ${stamp.gitSha.slice(0, 8)} ${stamp.builtAt.slice(0, 10)})`;
|
|
79
79
|
}
|
|
80
|
+
/**
|
|
81
|
+
* Strip the build-stamp suffix from a CLI `--version` label, returning the bare
|
|
82
|
+
* SemVer. Controller-identity/preflight comparisons must use this rather than
|
|
83
|
+
* the raw label so a build-stamped `0.35.0 (build 7f8c5b5b …)` still matches
|
|
84
|
+
* `packageVersion === "0.35.0"`.
|
|
85
|
+
*/
|
|
86
|
+
export function normalizeCliVersionLabel(label) {
|
|
87
|
+
const match = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?/.exec(label.trim());
|
|
88
|
+
return match ? match[0] : label.trim();
|
|
89
|
+
}
|
|
80
90
|
/**
|
|
81
91
|
* Compute the SHA-256 hash of a file on disk.
|
|
82
92
|
*
|