@tea-agent/loop-agent 0.28.2-beta.1 → 0.28.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/AGENTS.md +1 -1
- package/CHANGELOG.md +25 -0
- package/README.md +11 -1
- package/dist/cli/command-definitions.js +2 -1
- package/dist/commands/client-recovery.js +111 -8
- package/dist/commands/dag-init-hybrid.js +1 -1
- package/dist/commands/init-upgrade.js +2479 -0
- package/dist/commands/init.js +120 -9
- package/dist/governance/manifest-types.js +65 -0
- package/dist/shared/operator/capabilities.js +350 -2
- package/dist/task/worktree.js +256 -39
- package/dist/worker/cli.js +22 -12
- package/dist/worker/console/chat/workspace-landing.js +16 -6
- package/dist/worker/console/observe-health-match.js +2 -0
- package/dist/worker/console/observe-link.js +4 -0
- package/dist/worker/console/operator-actions.js +183 -4
- package/dist/worker/console/operator-selection.js +13 -0
- package/dist/worker/console/static/assets/index-BfRgtLF4.js +29 -0
- package/dist/worker/console/static/index.html +1 -1
- package/dist/worker/observe/health.js +1 -0
- package/dist/worker/observe/night-jobs.js +104 -0
- package/dist/worker/observe/routes.js +48 -0
- package/dist/worker/observe/static/app.js +3 -0
- package/dist/worker/observe/static/constants.js +1 -0
- package/dist/worker/observe/static/index.html +47 -0
- package/dist/worker/observe/static/router.js +10 -0
- package/dist/worker/observe/static/shell-chrome.js +1 -0
- package/dist/worker/observe/static/views/night.js +201 -0
- package/dist/worker/report/morning-report.js +56 -16
- package/dist/worker/run-task/execute-prepared-task.js +153 -0
- package/dist/worker/runner/single-task-attempt.js +147 -0
- package/dist/worker/scheduler/admission.js +536 -0
- package/dist/worker/scheduler/auto-followup.js +99 -0
- package/dist/worker/scheduler/cli.js +539 -0
- package/dist/worker/scheduler/dispatcher.js +503 -0
- package/dist/worker/scheduler/doctor.js +346 -0
- package/dist/worker/scheduler/evidence.js +170 -0
- package/dist/worker/scheduler/git-base.js +52 -0
- package/dist/worker/scheduler/index.js +23 -0
- package/dist/worker/scheduler/lease.js +114 -0
- package/dist/worker/scheduler/lifecycle.js +348 -0
- package/dist/worker/scheduler/lock.js +80 -0
- package/dist/worker/scheduler/morning-window.js +161 -0
- package/dist/worker/scheduler/night-git-finalizer.js +88 -0
- package/dist/worker/scheduler/night-harvest.js +421 -0
- package/dist/worker/scheduler/paths.js +84 -0
- package/dist/worker/scheduler/prepared-attempt-recovery.js +471 -0
- package/dist/worker/scheduler/recovery.js +277 -0
- package/dist/worker/scheduler/reservation.js +146 -0
- package/dist/worker/scheduler/retry.js +199 -0
- package/dist/worker/scheduler/scheduler-loop.js +272 -0
- package/dist/worker/scheduler/store.js +275 -0
- package/dist/worker/scheduler/traceability.js +54 -0
- package/dist/worker/scheduler/trigger.js +258 -0
- package/dist/worker/scheduler/types.js +369 -0
- package/dist/worker/scheduler/workspace-adapter.js +91 -0
- package/dist/workflows/dag/frontend-implementation-contract.js +2 -102
- package/docs/architecture/runtime-boundaries.md +9 -0
- package/docs/init-surface.manifest.json +9 -2
- package/docs/templates/harness.schema.json +107 -0
- package/docs/templates/init-managed-agents.md +18 -8
- package/harness.json +22 -0
- package/package.json +1 -1
- package/skills/loop-agent/SKILL.md +28 -36
- package/skills/loop-agent/references/command-reference.md +40 -16
- package/skills/loop-agent/references/hybrid-dag.md +1 -1
- package/dist/worker/console/static/assets/index-CNO7n6qB.js +0 -29
package/AGENTS.md
CHANGED
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
|
|
52
52
|
DAG 执行期间主 agent 必须持续轮询监视直到 run 结束(FINISHED / FAILED / 需要 approve),不能轮询一次就停下等用户;轮询间隔应合理(避免频繁唤醒浪费 token,也不得住一个节点上赌一次就走)。判活必须用可靠方式:看 `state.json` 的 `runner.heartbeatAt` 是否持续刷新 + `session-events.jsonl` 是否在增长 + `dag doctor` 的 `liveness` 字段,不要只用 `tasklist /FI "PID eq X"` 这类过滤语法在 Git Bash 下会误报 DEAD,从而错判一个正常工作的 run 为 orphaned。遇到疑似 stall 先按 `docs/runtime/agent-dag-runner.md` 查 `lastMeaningfulProgressAt` / provider 活动,有真实进展就继续等,绝不盲目 supersede。
|
|
53
53
|
|
|
54
|
-
DAG 执行期间,主 agent 不得修改 writeSet 外的任何工作区文件(包括 AGENTS.md、docs、根配置等)。bounded writer 节点的 write guard 用「节点运行期间的工作区 diff」作为越界证据,不区分改动来自 pi 还是主会话——主会话在 pi 节点跑的时候改了 writeSet 外文件,会让 write guard 把账算到 pi 头上、判节点 ERROR、下游 cascade skip。需要改文档/约束时,要么在 DAG 启动前改完,要么等 run 结束后改;务必与 DAG 写入节点在时间上互斥。排查任务路由问题时优先用 `resolveTaskDagTemplateSelection` / `classifyTaskDemand` 等纯函数探针或 `--output` 指定临时路径,不要反复 `dag execute --dry-run` / 无必要的 lifecycle
|
|
54
|
+
DAG 执行期间,主 agent 不得修改 writeSet 外的任何工作区文件(包括 AGENTS.md、docs、根配置等)。bounded writer 节点的 write guard 用「节点运行期间的工作区 diff」作为越界证据,不区分改动来自 pi 还是主会话——主会话在 pi 节点跑的时候改了 writeSet 外文件,会让 write guard 把账算到 pi 头上、判节点 ERROR、下游 cascade skip。需要改文档/约束时,要么在 DAG 启动前改完,要么等 run 结束后改;务必与 DAG 写入节点在时间上互斥。排查任务路由问题时优先用 `resolveTaskDagTemplateSelection` / `classifyTaskDemand` 等纯函数探针或 `--output` 指定临时路径,不要反复 `dag execute --dry-run` / 无必要的 lifecycle 探测。dry-run 不执行节点;若确需预演,检查命令返回的 `.harness/dag-runs/dry-run/<runId>/` `runDir`,它不进入 active overview,也不能作为 `dag resume` 目标。优先用纯函数探针或 `task status`。
|
|
55
55
|
|
|
56
56
|
## 项目地图
|
|
57
57
|
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.28.2] - 2026-08-05
|
|
6
|
+
|
|
7
|
+
### 重点更新
|
|
8
|
+
|
|
9
|
+
- Night Scheduler 实现了夜间任务的完整调度闭环,支持准入控制、执行调度、证据归档与结果回收
|
|
10
|
+
- 控制台新增夜间任务只读视图与操作面板,支持通过 CLI 和人工审批执行准入与调度操作
|
|
11
|
+
- 新增可恢复的项目初始化升级流程,支持状态复核与安全断点恢复
|
|
12
|
+
|
|
13
|
+
### 新增
|
|
14
|
+
|
|
15
|
+
- Night Scheduler 核心调度能力:支持一次性夜间计划准备、准入控制、队列预约、执行调度、证据归档及结果回收
|
|
16
|
+
- Night Scheduler 异常恢复机制:支持过期租约恢复、环境失败与不稳定测试的有界自动重试
|
|
17
|
+
- Night Scheduler 自动跟进功能(默认关闭),开启后仅生成任务草稿,永不自动审批
|
|
18
|
+
- 控制台夜间任务只读视图与操作面板,支持通过 CLI 和人工审批执行准入与调度操作
|
|
19
|
+
- 可恢复的项目初始化升级流程,支持断点恢复与状态报告查询
|
|
20
|
+
|
|
21
|
+
### 改进
|
|
22
|
+
|
|
23
|
+
- 统一并修正了 DAG 模拟运行(dry-run)的指导说明,明确了预览快照的保存位置与限制
|
|
24
|
+
- 更新了项目路线图与计划索引,将已完成的可靠性计划归档并校准至最新基线
|
|
25
|
+
|
|
26
|
+
### 修复
|
|
27
|
+
|
|
28
|
+
- 对齐了各处 DAG 模拟运行的指导说明,消除了文档与实际行为不一致的问题
|
|
29
|
+
|
|
5
30
|
## [0.28.1] - 2026-08-05
|
|
6
31
|
|
|
7
32
|
### 改进
|
package/README.md
CHANGED
|
@@ -48,6 +48,16 @@ loop-agent init reconcile --repo-root .
|
|
|
48
48
|
|
|
49
49
|
`init reconcile` 在 surface 缺失、存在 human decisions、存在活跃 DAG/Worker 或无法确认 Worker 状态时零写入,并返回 `needs-baseline`、`needs-human-decision` 或 `blocked-active-runtime`;其余情况复用 `init update --apply-safe` 的安全动作并复查返回 `clean`、`needs-model-merge` 或 `needs-safe-update`。
|
|
50
50
|
|
|
51
|
+
写入型自然语言请求「`loop-agent初始化更新`」或「`loop-agent 初始化更新`」必须进入可恢复的统一闭环,而不是只做检查:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
loop-agent init upgrade --repo-root . --json
|
|
55
|
+
# controller 返回单文件 merge task 后:
|
|
56
|
+
loop-agent init upgrade --repo-root . --run-id <run-id> --continue --json
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
它在 `.harness/init-upgrades/<run-id>/` 保存身份、扫描、动作收据、合并任务、验证与报告;`--status` / `--report` 只读。默认管理项目 `.opencode/plugins/`、`.pi/extensions/` 和 `.pi/settings.json`,不会默认写 `~/.pi/agent/settings.json`。旧项目首次执行后需 reload 宿主会话,以加载更新后的 AGENTS、skills 与 recovery 产物。明确「检查初始化更新」「只检查,不要修改」仍只运行 `init check-update`。
|
|
60
|
+
|
|
51
61
|
完整说明见[初始化目标项目](website/docs/quick-start/init-target-project.md)。
|
|
52
62
|
|
|
53
63
|
### 运行第一个任务
|
|
@@ -102,7 +112,7 @@ agent-worker console doctor --repo .
|
|
|
102
112
|
|
|
103
113
|
## 核心边界
|
|
104
114
|
|
|
105
|
-
- `.harness/` 保存任务、DAG run、one-shot run
|
|
115
|
+
- `.harness/` 保存任务、DAG run、one-shot run、可选 Task Pool 与 `init-upgrades/` 可恢复升级运行事实。
|
|
106
116
|
- `ai_workspace/loop-agent/` 保存目标项目的长期治理资料。
|
|
107
117
|
- `.agents/skills/` 保存目标项目可审计的 repo-local skills。
|
|
108
118
|
- `agent-worker` 通过已发布的 `loop-agent` 子进程执行 DAG,不维护第二套 runtime kernel。
|
|
@@ -77,6 +77,7 @@ const INIT_SUBCOMMANDS = [
|
|
|
77
77
|
"check-update",
|
|
78
78
|
"update",
|
|
79
79
|
"reconcile",
|
|
80
|
+
"upgrade",
|
|
80
81
|
];
|
|
81
82
|
const EXAMPLES_SUBCOMMANDS = ["list", "show", "copy"];
|
|
82
83
|
const EVAL_SUBCOMMANDS = [
|
|
@@ -202,7 +203,7 @@ export const COMMAND_DEFINITIONS = [
|
|
|
202
203
|
adapter: "none",
|
|
203
204
|
tier: "primary",
|
|
204
205
|
intent: "Initialize a target repository with loop-agent harness capabilities.",
|
|
205
|
-
usage: "init [instructions|doctor|check-update|update|reconcile] [--profile full|minimal] [--merge] [--json|--markdown] [--bootstrap-surface|--apply-safe] [--client-recovery=auto|project|user|off]",
|
|
206
|
+
usage: "init [instructions|doctor|check-update|update|reconcile|upgrade] [--profile full|minimal] [--merge] [--json|--markdown] [--bootstrap-surface|--apply-safe] [--client-recovery=auto|project|user|off] [--run-id <id> --status|--continue|--report]",
|
|
206
207
|
subcommands: [...INIT_SUBCOMMANDS],
|
|
207
208
|
handler: async ({ repoRoot, subcommand, rest }) => {
|
|
208
209
|
await runInit(repoRoot, [subcommand, ...rest].filter(Boolean), { readRuntimeActivity: readInitRuntimeActivity });
|
|
@@ -10,6 +10,8 @@ export const CLIENT_RECOVERY_MODES = [
|
|
|
10
10
|
export const OPENCODE_TRANSIENT_RETRY_PLUGIN_PATH = ".opencode/plugins/loop-agent-transient-retry.js";
|
|
11
11
|
export const OPENCODE_CONTEXT_OVERFLOW_COMPACT_PLUGIN_PATH = ".opencode/plugins/loop-agent-context-overflow-compact.js";
|
|
12
12
|
export const PI_CONTEXT_OVERFLOW_EXTENSION_PATH = ".pi/extensions/loop-agent-context-overflow.js";
|
|
13
|
+
/** Pi project settings are part of the managed init surface; never default to home. */
|
|
14
|
+
export const PI_PROJECT_SETTINGS_PATH = ".pi/settings.json";
|
|
13
15
|
export const PERMANENT_ERROR_INTERACTION = "plugin-ignore-permanent-error";
|
|
14
16
|
export const BACKOFF_MS = [2000, 4000, 8000, 16000, 30000];
|
|
15
17
|
export const MAX_SESSION_RETRIES = 5;
|
|
@@ -24,6 +26,7 @@ export const PI_RECOMMENDED_RETRY = {
|
|
|
24
26
|
maxRetryDelayMs: 60000,
|
|
25
27
|
},
|
|
26
28
|
};
|
|
29
|
+
export const PI_RECOMMENDED_COMPACTION = { enabled: true };
|
|
27
30
|
/**
|
|
28
31
|
* Shared overflow phrase sources used by isContextOverflow and generated plugins.
|
|
29
32
|
* Keep English + Chinese intranet gateway messages in one place to avoid drift.
|
|
@@ -418,7 +421,7 @@ export function planPiRetryMerge(existing) {
|
|
|
418
421
|
export function piSettingsPath(homeDir) {
|
|
419
422
|
return path.join(homeDir, ".pi", "agent", "settings.json");
|
|
420
423
|
}
|
|
421
|
-
async function
|
|
424
|
+
async function writeJsonAtomic(filePath, value) {
|
|
422
425
|
await mkdir(path.dirname(filePath), { recursive: true });
|
|
423
426
|
const tempPath = path.join(path.dirname(filePath), `.${path.basename(filePath)}.${process.pid}.${Date.now()}.tmp`);
|
|
424
427
|
try {
|
|
@@ -449,7 +452,7 @@ export async function applyPiRetryMerge(input) {
|
|
|
449
452
|
if (raw === undefined) {
|
|
450
453
|
const plan = planPiRetryMerge(undefined);
|
|
451
454
|
if (plan.action === "write" && plan.next) {
|
|
452
|
-
await
|
|
455
|
+
await writeJsonAtomic(settingsPath, plan.next);
|
|
453
456
|
return { ...plan, path: settingsPath, wrote: true };
|
|
454
457
|
}
|
|
455
458
|
return { ...plan, path: settingsPath, wrote: false };
|
|
@@ -478,7 +481,7 @@ export async function applyPiRetryMerge(input) {
|
|
|
478
481
|
}
|
|
479
482
|
const plan = planPiRetryMerge(parsed);
|
|
480
483
|
if (plan.action === "write" && plan.next) {
|
|
481
|
-
await
|
|
484
|
+
await writeJsonAtomic(settingsPath, plan.next);
|
|
482
485
|
// Best-effort cleanup of any stray temp files from interrupted prior runs.
|
|
483
486
|
try {
|
|
484
487
|
const dir = path.dirname(settingsPath);
|
|
@@ -1147,6 +1150,104 @@ export async function installProjectPiContextOverflowExtension(input) {
|
|
|
1147
1150
|
onlyIfMissing: input.onlyIfMissing,
|
|
1148
1151
|
});
|
|
1149
1152
|
}
|
|
1153
|
+
/**
|
|
1154
|
+
* Nested merge plan for the project-owned Pi settings surface. Existing values
|
|
1155
|
+
* (including explicit disabled flags) always win over recommendations.
|
|
1156
|
+
*/
|
|
1157
|
+
export function planProjectPiSettingsMerge(existing) {
|
|
1158
|
+
if (existing === undefined) {
|
|
1159
|
+
return {
|
|
1160
|
+
action: "write",
|
|
1161
|
+
reason: "missing-file",
|
|
1162
|
+
path: PI_PROJECT_SETTINGS_PATH,
|
|
1163
|
+
next: {
|
|
1164
|
+
retry: { ...PI_RECOMMENDED_RETRY, provider: { ...PI_RECOMMENDED_RETRY.provider } },
|
|
1165
|
+
compaction: { ...PI_RECOMMENDED_COMPACTION },
|
|
1166
|
+
},
|
|
1167
|
+
};
|
|
1168
|
+
}
|
|
1169
|
+
if (!isRecord(existing)) {
|
|
1170
|
+
return {
|
|
1171
|
+
action: "report",
|
|
1172
|
+
reason: "invalid-json",
|
|
1173
|
+
path: PI_PROJECT_SETTINGS_PATH,
|
|
1174
|
+
message: "project .pi/settings.json root must be a JSON object",
|
|
1175
|
+
};
|
|
1176
|
+
}
|
|
1177
|
+
const retryPlan = planPiRetryMerge(existing);
|
|
1178
|
+
if (retryPlan.reason === "invalid-json") {
|
|
1179
|
+
return { ...retryPlan, path: PI_PROJECT_SETTINGS_PATH };
|
|
1180
|
+
}
|
|
1181
|
+
const retryDisabled = retryPlan.reason === "enabled-false";
|
|
1182
|
+
const next = retryPlan.next ? { ...retryPlan.next } : { ...existing };
|
|
1183
|
+
const compaction = isRecord(next.compaction) ? { ...next.compaction } : {};
|
|
1184
|
+
let changed = (!retryDisabled && retryPlan.action === "write") ||
|
|
1185
|
+
!isRecord(next.compaction);
|
|
1186
|
+
if (compaction.enabled === undefined) {
|
|
1187
|
+
compaction.enabled = PI_RECOMMENDED_COMPACTION.enabled;
|
|
1188
|
+
changed = true;
|
|
1189
|
+
}
|
|
1190
|
+
next.compaction = compaction;
|
|
1191
|
+
if (changed) {
|
|
1192
|
+
return {
|
|
1193
|
+
action: "write",
|
|
1194
|
+
reason: "missing-fields",
|
|
1195
|
+
path: PI_PROJECT_SETTINGS_PATH,
|
|
1196
|
+
next,
|
|
1197
|
+
};
|
|
1198
|
+
}
|
|
1199
|
+
if (retryDisabled) {
|
|
1200
|
+
return {
|
|
1201
|
+
action: "report",
|
|
1202
|
+
reason: "enabled-false",
|
|
1203
|
+
path: PI_PROJECT_SETTINGS_PATH,
|
|
1204
|
+
next,
|
|
1205
|
+
message: "retry.enabled=false is preserved; compaction settings already require no migration",
|
|
1206
|
+
};
|
|
1207
|
+
}
|
|
1208
|
+
return {
|
|
1209
|
+
action: "noop",
|
|
1210
|
+
reason: "matches",
|
|
1211
|
+
path: PI_PROJECT_SETTINGS_PATH,
|
|
1212
|
+
next,
|
|
1213
|
+
};
|
|
1214
|
+
}
|
|
1215
|
+
async function readJsonMergeTarget(filePath) {
|
|
1216
|
+
try {
|
|
1217
|
+
return JSON.parse(await readFile(filePath, "utf-8"));
|
|
1218
|
+
}
|
|
1219
|
+
catch (error) {
|
|
1220
|
+
if (isMissingFileError(error))
|
|
1221
|
+
return undefined;
|
|
1222
|
+
if (error instanceof SyntaxError)
|
|
1223
|
+
return "__invalid_json__";
|
|
1224
|
+
throw error;
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
export async function inspectProjectPiSettings(input) {
|
|
1228
|
+
const settingsPath = path.join(input.repoRoot, PI_PROJECT_SETTINGS_PATH);
|
|
1229
|
+
const parsed = await readJsonMergeTarget(settingsPath);
|
|
1230
|
+
if (parsed === "__invalid_json__") {
|
|
1231
|
+
return { action: "report", reason: "invalid-json", path: PI_PROJECT_SETTINGS_PATH, wrote: false };
|
|
1232
|
+
}
|
|
1233
|
+
return { ...planProjectPiSettingsMerge(parsed), wrote: false };
|
|
1234
|
+
}
|
|
1235
|
+
export async function applyProjectPiSettingsMerge(input) {
|
|
1236
|
+
const settingsPath = path.join(input.repoRoot, PI_PROJECT_SETTINGS_PATH);
|
|
1237
|
+
const parsed = await readJsonMergeTarget(settingsPath);
|
|
1238
|
+
if (parsed === "__invalid_json__") {
|
|
1239
|
+
return { action: "report", reason: "invalid-json", path: PI_PROJECT_SETTINGS_PATH, wrote: false, message: "project .pi/settings.json is not valid JSON; refusing to write" };
|
|
1240
|
+
}
|
|
1241
|
+
const plan = planProjectPiSettingsMerge(parsed);
|
|
1242
|
+
if (plan.action === "write" && plan.next) {
|
|
1243
|
+
await writeJsonAtomic(settingsPath, plan.next);
|
|
1244
|
+
return { ...plan, wrote: true };
|
|
1245
|
+
}
|
|
1246
|
+
return { ...plan, wrote: false };
|
|
1247
|
+
}
|
|
1248
|
+
export function buildProjectPiSettingsSource() {
|
|
1249
|
+
return `${JSON.stringify({ retry: PI_RECOMMENDED_RETRY, compaction: PI_RECOMMENDED_COMPACTION }, null, 2)}\n`;
|
|
1250
|
+
}
|
|
1150
1251
|
export async function inspectPiRetryConfig(input) {
|
|
1151
1252
|
const homeDir = input.homeDir ?? os.homedir();
|
|
1152
1253
|
const settingsPath = piSettingsPath(homeDir);
|
|
@@ -1191,8 +1292,8 @@ function skippedInstall(relativePath) {
|
|
|
1191
1292
|
}
|
|
1192
1293
|
/**
|
|
1193
1294
|
* Install project recovery artifacts and optionally merge Pi user settings.
|
|
1194
|
-
* - auto/project:
|
|
1195
|
-
* - user: the
|
|
1295
|
+
* - auto/project: recovery plugins/extensions plus project `.pi/settings.json` (no home writes)
|
|
1296
|
+
* - user: the same project files plus explicit legacy Pi home retry merge
|
|
1196
1297
|
* - off: skip all
|
|
1197
1298
|
*/
|
|
1198
1299
|
export async function runClientRecovery(input) {
|
|
@@ -1203,6 +1304,7 @@ export async function runClientRecovery(input) {
|
|
|
1203
1304
|
plugin: skippedInstall(OPENCODE_TRANSIENT_RETRY_PLUGIN_PATH),
|
|
1204
1305
|
overflowPlugin: skippedInstall(OPENCODE_CONTEXT_OVERFLOW_COMPACT_PLUGIN_PATH),
|
|
1205
1306
|
piExtension: skippedInstall(PI_CONTEXT_OVERFLOW_EXTENSION_PATH),
|
|
1307
|
+
pi: { action: "report", reason: "skipped-mode", path: PI_PROJECT_SETTINGS_PATH, wrote: false },
|
|
1206
1308
|
};
|
|
1207
1309
|
}
|
|
1208
1310
|
const plugin = await installProjectOpenCodePlugin({
|
|
@@ -1214,10 +1316,11 @@ export async function runClientRecovery(input) {
|
|
|
1214
1316
|
const piExtension = await installProjectPiContextOverflowExtension({
|
|
1215
1317
|
repoRoot: input.repoRoot,
|
|
1216
1318
|
});
|
|
1319
|
+
const pi = await applyProjectPiSettingsMerge({ repoRoot: input.repoRoot });
|
|
1217
1320
|
if (mode !== "user") {
|
|
1218
|
-
return { mode, plugin, overflowPlugin, piExtension };
|
|
1321
|
+
return { mode, plugin, overflowPlugin, piExtension, pi };
|
|
1219
1322
|
}
|
|
1220
1323
|
const homeDir = input.homeDir ?? os.homedir();
|
|
1221
|
-
const
|
|
1222
|
-
return { mode, plugin, overflowPlugin, piExtension, pi };
|
|
1324
|
+
const userPi = await applyPiRetryMerge({ homeDir });
|
|
1325
|
+
return { mode, plugin, overflowPlugin, piExtension, pi, userPi };
|
|
1223
1326
|
}
|
|
@@ -51,7 +51,7 @@ export async function runDagInitHybrid(repoRoot, rawArgs) {
|
|
|
51
51
|
next: [
|
|
52
52
|
`Review ${result.outputPath}`,
|
|
53
53
|
`npm run dev -- dag validate --dag ${result.outputPath}`,
|
|
54
|
-
"
|
|
54
|
+
"This command's outputPath is a DAG draft; only a later dag execute --dry-run returned runDir is the preview snapshot, outside the active overview and not a dag resume target.",
|
|
55
55
|
],
|
|
56
56
|
}, null, 2));
|
|
57
57
|
}
|