geo-ai-search-optimization 1.2.13 → 1.2.15
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/README.md +58 -0
- package/package.json +1 -1
- package/resources/geo-ai-search-optimization/references/skill-bundle-map.md +20 -0
- package/resources/geo-ai-search-optimization-agent-checkpoint/SKILL.md +23 -0
- package/resources/geo-ai-search-optimization-agent-checkpoint/agents/openai.yaml +4 -0
- package/resources/geo-ai-search-optimization-agent-decision-log/SKILL.md +23 -0
- package/resources/geo-ai-search-optimization-agent-decision-log/agents/openai.yaml +4 -0
- package/resources/geo-ai-search-optimization-usage/SKILL.md +24 -14
- package/src/agent-checkpoint.js +378 -0
- package/src/agent-decision-log.js +368 -0
- package/src/agent-progress-tracker.js +70 -0
- package/src/agent-session.js +20 -0
- package/src/agent-status-board.js +35 -0
- package/src/auto-flow.js +67 -0
- package/src/cli.js +72 -0
- package/src/index.js +2 -0
- package/src/skills.js +6 -0
package/README.md
CHANGED
|
@@ -186,6 +186,46 @@ geo-ai-search-optimization agent-status-board ./reports/agent-progress-tracker.j
|
|
|
186
186
|
- 建议下一步命令
|
|
187
187
|
- 可直接复制给 agent 的 status board prompt
|
|
188
188
|
|
|
189
|
+
## Agent Checkpoint 命令
|
|
190
|
+
|
|
191
|
+
如果你希望在每一轮执行结束时,产出一个明确的阶段决策,而不只是状态展示,可以直接用 `agent-checkpoint`:
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
geo-ai-search-optimization agent-checkpoint ./your-site
|
|
195
|
+
geo-ai-search-optimization agent-checkpoint ./reports/agent-status-board.json --completed fix-01 --current fix-02
|
|
196
|
+
geo-ai-search-optimization agent-checkpoint ./reports/agent-progress-tracker.json --blocked "缺少仓库权限" --format json --out ./reports/agent-checkpoint.json
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
`agent-checkpoint` 会输出:
|
|
200
|
+
|
|
201
|
+
- 当前检查点类型
|
|
202
|
+
- 当前决策是继续、解除阻塞还是进入收尾
|
|
203
|
+
- gate checks
|
|
204
|
+
- 决策清单
|
|
205
|
+
- 建议下一步命令
|
|
206
|
+
- 备选命令
|
|
207
|
+
- 交接说明
|
|
208
|
+
- 可直接复制给 agent 的 checkpoint prompt
|
|
209
|
+
|
|
210
|
+
## Agent Decision Log 命令
|
|
211
|
+
|
|
212
|
+
如果你希望把每一轮 checkpoint 累积成“为什么之前这样决定”的历史,而不是只保留单轮状态,可以直接用 `agent-decision-log`:
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
geo-ai-search-optimization agent-decision-log ./your-site
|
|
216
|
+
geo-ai-search-optimization agent-decision-log ./reports/agent-checkpoint.json --note "本轮先解除模板缺失问题"
|
|
217
|
+
geo-ai-search-optimization agent-decision-log ./your-site --append-from ./reports/agent-decision-log.json --blocked "缺少模板文件" --format json --out ./reports/agent-decision-log.json
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
`agent-decision-log` 会输出:
|
|
221
|
+
|
|
222
|
+
- 当前累计决策次数
|
|
223
|
+
- 最新检查点类型与决策
|
|
224
|
+
- 当前重点与开放阻塞
|
|
225
|
+
- 决策时间线
|
|
226
|
+
- 最新建议下一步命令
|
|
227
|
+
- 可直接复制给 agent 的 decision log prompt
|
|
228
|
+
|
|
189
229
|
## Quick Start
|
|
190
230
|
|
|
191
231
|
如果你要从 0 到 1 启动一个 GEO 项目,建议照这个顺序做。
|
|
@@ -586,6 +626,8 @@ geo-ai-search-optimization agent-executor ./your-site
|
|
|
586
626
|
geo-ai-search-optimization agent-batch-executor ./your-site
|
|
587
627
|
geo-ai-search-optimization agent-progress-tracker ./your-site
|
|
588
628
|
geo-ai-search-optimization agent-status-board ./your-site
|
|
629
|
+
geo-ai-search-optimization agent-checkpoint ./your-site
|
|
630
|
+
geo-ai-search-optimization agent-decision-log ./your-site
|
|
589
631
|
geo-ai-search-optimization skills
|
|
590
632
|
geo-ai-search-optimization where
|
|
591
633
|
geo-ai-search-optimization doctor
|
|
@@ -656,6 +698,20 @@ geo-ai-search-optimization help
|
|
|
656
698
|
- 输出 do-now checklist、stop checklist、success checklist、验证命令和回报模板
|
|
657
699
|
- 新增 `geo-ai-search-optimization-agent-executor` skill
|
|
658
700
|
|
|
701
|
+
## New in 1.2.15
|
|
702
|
+
|
|
703
|
+
- 新增 `agent-decision-log` 命令
|
|
704
|
+
- 把多轮 checkpoint 沉淀成可继承的决策历史,而不是只有单轮阶段判断
|
|
705
|
+
- 支持从 `agent-checkpoint`、`agent-status-board`、`agent-progress-tracker`、目录、网址等输入继续生成或追加决策记录
|
|
706
|
+
- 新增 `geo-ai-search-optimization-agent-decision-log` skill
|
|
707
|
+
|
|
708
|
+
## New in 1.2.14
|
|
709
|
+
|
|
710
|
+
- 新增 `agent-checkpoint` 命令
|
|
711
|
+
- 把每一轮执行状态压成 continue / unblock / closeout 的阶段决策工件
|
|
712
|
+
- 支持从 `agent-progress-tracker`、`agent-status-board`、`apply-plan` 等工件继续生成检查点
|
|
713
|
+
- 新增 `geo-ai-search-optimization-agent-checkpoint` skill
|
|
714
|
+
|
|
659
715
|
## New in 1.2.13
|
|
660
716
|
|
|
661
717
|
- 新增 `agent-status-board` 命令
|
|
@@ -870,6 +926,8 @@ The installed package now includes a bundled GEO skill pack, including:
|
|
|
870
926
|
- `geo-ai-search-optimization-agent-batch-executor`
|
|
871
927
|
- `geo-ai-search-optimization-agent-progress-tracker`
|
|
872
928
|
- `geo-ai-search-optimization-agent-status-board`
|
|
929
|
+
- `geo-ai-search-optimization-agent-checkpoint`
|
|
930
|
+
- `geo-ai-search-optimization-agent-decision-log`
|
|
873
931
|
- `geo-ai-search-optimization-usage`
|
|
874
932
|
- `geo-ai-search-optimization-agent-handoff`
|
|
875
933
|
- `geo-ai-search-optimization-repair-loop`
|
package/package.json
CHANGED
|
@@ -92,6 +92,26 @@ Best for:
|
|
|
92
92
|
- showing done, in-progress, blocked, next, and queued packets in one artifact
|
|
93
93
|
- turning progress tracking into a more shareable coordination output
|
|
94
94
|
|
|
95
|
+
### `geo-ai-search-optimization-agent-checkpoint`
|
|
96
|
+
|
|
97
|
+
Use this when the next agent should make a stage decision, not just show the current state.
|
|
98
|
+
|
|
99
|
+
Best for:
|
|
100
|
+
|
|
101
|
+
- deciding whether the round should continue, unblock, or close out
|
|
102
|
+
- producing a clean handoff note at the end of one execution round
|
|
103
|
+
- giving PM and the next agent one checkpoint artifact to align on
|
|
104
|
+
|
|
105
|
+
### `geo-ai-search-optimization-agent-decision-log`
|
|
106
|
+
|
|
107
|
+
Use this when the next agent should inherit decision history, not just one checkpoint.
|
|
108
|
+
|
|
109
|
+
Best for:
|
|
110
|
+
|
|
111
|
+
- preserving why previous rounds continued, paused, or moved to closeout
|
|
112
|
+
- giving PM and the next agent a reusable decision history across rounds
|
|
113
|
+
- appending a fresh checkpoint onto an existing GEO execution history
|
|
114
|
+
|
|
95
115
|
## Usage guide
|
|
96
116
|
|
|
97
117
|
### `geo-ai-search-optimization-usage`
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: geo-ai-search-optimization-agent-checkpoint
|
|
3
|
+
description: Turn GEO execution state into a stage checkpoint decision. Use when an agent should decide whether the current round should continue, first resolve blockers, or move into closeout, based on progress trackers, status boards, apply-plan artifacts, or related execution outputs.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# GEO Agent Checkpoint
|
|
7
|
+
|
|
8
|
+
Use this skill when the next agent should make a round-level execution decision, not just summarize state.
|
|
9
|
+
|
|
10
|
+
`GEO = Generative Engine Optimization`
|
|
11
|
+
|
|
12
|
+
## What it does
|
|
13
|
+
|
|
14
|
+
- converts current GEO execution state into a checkpoint artifact
|
|
15
|
+
- decides whether to continue, unblock, or close out
|
|
16
|
+
- adds gate checks and a decision checklist
|
|
17
|
+
- produces a handoff note and next command for the next agent
|
|
18
|
+
|
|
19
|
+
## Best use
|
|
20
|
+
|
|
21
|
+
- when one execution round ends and the team needs a checkpoint
|
|
22
|
+
- when PM asks whether the team should keep going or stop and unblock first
|
|
23
|
+
- when another agent should take over from a stable checkpoint instead of raw state
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "GEO Agent Checkpoint"
|
|
3
|
+
short_description: "Decide continue, unblock, or closeout for this GEO round"
|
|
4
|
+
default_prompt: "Use $geo-ai-search-optimization-agent-checkpoint to turn this GEO execution state into a checkpoint decision with gate checks, next command, and handoff note."
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: geo-ai-search-optimization-agent-decision-log
|
|
3
|
+
description: Turn GEO checkpoints into a reusable decision history. Use when an agent or PM should preserve why each GEO round continued, paused for blockers, or moved to closeout, so the next agent can inherit the reasoning instead of re-evaluating the entire chain from scratch.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# GEO Agent Decision Log
|
|
7
|
+
|
|
8
|
+
Use this skill when the team needs durable decision memory across multiple GEO execution rounds.
|
|
9
|
+
|
|
10
|
+
`GEO = Generative Engine Optimization`
|
|
11
|
+
|
|
12
|
+
## What it does
|
|
13
|
+
|
|
14
|
+
- converts the current GEO round into a loggable decision entry
|
|
15
|
+
- preserves why the round continued, paused for blockers, or moved to closeout
|
|
16
|
+
- keeps the latest checkpoint, current packet, next packet, blockers, and handoff note together
|
|
17
|
+
- gives the next agent a stable history instead of isolated one-round artifacts
|
|
18
|
+
|
|
19
|
+
## Best use
|
|
20
|
+
|
|
21
|
+
- when one checkpoint is not enough and the next agent should see decision history
|
|
22
|
+
- when PM asks why the team chose to continue, unblock, or close out in previous rounds
|
|
23
|
+
- when you want to append a new decision to an existing GEO execution history
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "GEO Agent Decision Log"
|
|
3
|
+
short_description: "Preserve GEO round decisions as reusable history"
|
|
4
|
+
default_prompt: "Use $geo-ai-search-optimization-agent-decision-log to turn this GEO execution state into a reusable decision history with latest checkpoint, rationale, and next command."
|
|
@@ -13,7 +13,7 @@ Treat this tool as a PM-friendly GEO workflow for websites.
|
|
|
13
13
|
|
|
14
14
|
`GEO = Generative Engine Optimization`
|
|
15
15
|
|
|
16
|
-
The package is best explained as twenty layers:
|
|
16
|
+
The package is best explained as twenty-two layers:
|
|
17
17
|
|
|
18
18
|
1. `auto-flow`: auto-select the next skill and command chain
|
|
19
19
|
2. `agent-session`: build a runnable session for the next agent
|
|
@@ -22,19 +22,21 @@ The package is best explained as twenty layers:
|
|
|
22
22
|
5. `agent-batch-executor`: queue the first few packets, but still advance one packet at a time
|
|
23
23
|
6. `agent-progress-tracker`: track which packet is done, which one is active, and what comes next
|
|
24
24
|
7. `agent-status-board`: turn the execution state into a board view for PM and agents
|
|
25
|
-
8. `
|
|
26
|
-
9. `
|
|
27
|
-
10. `
|
|
28
|
-
11. `
|
|
29
|
-
12. `
|
|
30
|
-
13. `
|
|
31
|
-
14. `
|
|
32
|
-
15. `
|
|
33
|
-
16. `
|
|
34
|
-
17. `
|
|
35
|
-
18. `
|
|
36
|
-
19. `
|
|
37
|
-
20. `
|
|
25
|
+
8. `agent-checkpoint`: freeze the current round into a continue / unblock / closeout decision
|
|
26
|
+
9. `agent-decision-log`: preserve why each round continued, paused, or closed out
|
|
27
|
+
10. `skills`: inspect the bundled skill package
|
|
28
|
+
11. `onboard-url` / `onboard`: first look
|
|
29
|
+
12. `scan`: raw signal check
|
|
30
|
+
13. `audit` / `report`: diagnosis
|
|
31
|
+
14. `fix-plan` / `owner-board`: execution planning
|
|
32
|
+
15. `agent-handoff`: agent takeover package
|
|
33
|
+
16. `apply-plan`: execution loop
|
|
34
|
+
17. `completion-report`: closeout
|
|
35
|
+
18. `handoff-bundle`: all-in-one package
|
|
36
|
+
19. `share-pack`: audience-ready delivery
|
|
37
|
+
20. `export-pack`: folder export
|
|
38
|
+
21. `html-pack` / `publish-pack`: browsable and final delivery output
|
|
39
|
+
22. `pm-brief` / `roadmap`: stakeholder alignment
|
|
38
40
|
|
|
39
41
|
## Recommended command order
|
|
40
42
|
|
|
@@ -48,6 +50,8 @@ npx geo-ai-search-optimization agent-executor https://example.com
|
|
|
48
50
|
npx geo-ai-search-optimization agent-batch-executor https://example.com
|
|
49
51
|
npx geo-ai-search-optimization agent-progress-tracker https://example.com
|
|
50
52
|
npx geo-ai-search-optimization agent-status-board https://example.com
|
|
53
|
+
npx geo-ai-search-optimization agent-checkpoint https://example.com
|
|
54
|
+
npx geo-ai-search-optimization agent-decision-log https://example.com
|
|
51
55
|
npx geo-ai-search-optimization onboard-url https://example.com
|
|
52
56
|
npx geo-ai-search-optimization pm-brief https://example.com
|
|
53
57
|
npx geo-ai-search-optimization roadmap https://example.com
|
|
@@ -63,6 +67,8 @@ npx geo-ai-search-optimization agent-executor ./your-site
|
|
|
63
67
|
npx geo-ai-search-optimization agent-batch-executor ./your-site
|
|
64
68
|
npx geo-ai-search-optimization agent-progress-tracker ./your-site
|
|
65
69
|
npx geo-ai-search-optimization agent-status-board ./your-site
|
|
70
|
+
npx geo-ai-search-optimization agent-checkpoint ./your-site
|
|
71
|
+
npx geo-ai-search-optimization agent-decision-log ./your-site
|
|
66
72
|
npx geo-ai-search-optimization scan ./your-site
|
|
67
73
|
npx geo-ai-search-optimization audit ./your-site
|
|
68
74
|
npx geo-ai-search-optimization fix-plan ./your-site
|
|
@@ -87,6 +93,8 @@ npx geo-ai-search-optimization roadmap ./your-site
|
|
|
87
93
|
- `agent-batch-executor`: line up the first few packets in execution order while preserving one-packet-at-a-time discipline
|
|
88
94
|
- `agent-progress-tracker`: show execution progress, current packet, blockers, and the next packet to advance
|
|
89
95
|
- `agent-status-board`: present the current execution state as a board with done, in-progress, blocked, next, and queued columns
|
|
96
|
+
- `agent-checkpoint`: convert the current round into a checkpoint decision for continue, unblock, or closeout
|
|
97
|
+
- `agent-decision-log`: preserve multiple rounds of checkpoint history so the next agent can inherit the reasoning
|
|
90
98
|
- `onboard-url`: first-time website check from a live URL
|
|
91
99
|
- `onboard`: interactive first-time onboarding
|
|
92
100
|
- `skills`: list the bundled skills and decide which skill or command chain fits the task
|
|
@@ -118,6 +126,8 @@ When explaining the tool to a user:
|
|
|
118
126
|
- if the user wants the next agent to continuously advance the first 2 to 3 packets in order, move them to `agent-batch-executor`
|
|
119
127
|
- if the user wants the next agent to explain current progress, blockers, and the next packet, move them to `agent-progress-tracker`
|
|
120
128
|
- if the user wants the next agent to present execution state as a board for PM and agent coordination, move them to `agent-status-board`
|
|
129
|
+
- if the user wants a per-round decision artifact that says continue, unblock, or close out, move them to `agent-checkpoint`
|
|
130
|
+
- if the user wants cross-round decision memory and not just one checkpoint, move them to `agent-decision-log`
|
|
121
131
|
- explain the result in PM language, not implementation jargon
|
|
122
132
|
- if the user sounds new, start with `onboard-url` or `quick-start`
|
|
123
133
|
- if the user wants another agent to take over, move them to `agent-handoff`
|
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import {
|
|
4
|
+
createAgentStatusBoard,
|
|
5
|
+
renderAgentStatusBoardMarkdown,
|
|
6
|
+
writeAgentStatusBoardOutput
|
|
7
|
+
} from "./agent-status-board.js";
|
|
8
|
+
|
|
9
|
+
const VALID_FORMATS = new Set(["markdown", "json"]);
|
|
10
|
+
|
|
11
|
+
function normalizeFormat(format) {
|
|
12
|
+
const resolved = (format || "markdown").toLowerCase();
|
|
13
|
+
if (!VALID_FORMATS.has(resolved)) {
|
|
14
|
+
throw new Error(`不支持的 agent-checkpoint 格式:${format}。可选值:${Array.from(VALID_FORMATS).join(", ")}`);
|
|
15
|
+
}
|
|
16
|
+
return resolved;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async function pathExists(targetPath) {
|
|
20
|
+
try {
|
|
21
|
+
await fs.access(targetPath);
|
|
22
|
+
return true;
|
|
23
|
+
} catch {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async function resolveStatusBoard(input, options = {}) {
|
|
29
|
+
const resolvedPath = path.resolve(input);
|
|
30
|
+
if (await pathExists(resolvedPath)) {
|
|
31
|
+
try {
|
|
32
|
+
const raw = await fs.readFile(resolvedPath, "utf8");
|
|
33
|
+
const parsed = JSON.parse(raw);
|
|
34
|
+
if (parsed?.kind === "geo-agent-checkpoint" && parsed.statusBoard?.kind === "geo-agent-status-board") {
|
|
35
|
+
return createAgentStatusBoard(parsed.statusBoard.source || input, {
|
|
36
|
+
format: "json",
|
|
37
|
+
currentTaskId: options.currentTaskId || parsed.currentPacket?.id || parsed.statusBoard.tracker?.currentTaskId,
|
|
38
|
+
completedPacketIds:
|
|
39
|
+
options.completedPacketIds != null
|
|
40
|
+
? options.completedPacketIds
|
|
41
|
+
: (parsed.statusBoard.tracker?.completedPacketIds || []).join(","),
|
|
42
|
+
blockedReasons:
|
|
43
|
+
options.blockedReasons != null
|
|
44
|
+
? options.blockedReasons
|
|
45
|
+
: (parsed.statusBoard.tracker?.blockedReasons || []).join(",")
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
if (parsed?.kind === "geo-agent-decision-log" && parsed.latestCheckpoint?.statusBoard?.kind === "geo-agent-status-board") {
|
|
49
|
+
return createAgentStatusBoard(
|
|
50
|
+
parsed.latestCheckpoint.statusBoard.source || parsed.latestCheckpoint.source || input,
|
|
51
|
+
{
|
|
52
|
+
format: "json",
|
|
53
|
+
currentTaskId:
|
|
54
|
+
options.currentTaskId ||
|
|
55
|
+
parsed.latestCheckpoint.currentPacket?.id ||
|
|
56
|
+
parsed.latestCheckpoint.statusBoard.tracker?.currentTaskId,
|
|
57
|
+
completedPacketIds:
|
|
58
|
+
options.completedPacketIds != null
|
|
59
|
+
? options.completedPacketIds
|
|
60
|
+
: (parsed.latestCheckpoint.completedPackets || []).map((packet) => packet.id).join(","),
|
|
61
|
+
blockedReasons:
|
|
62
|
+
options.blockedReasons != null
|
|
63
|
+
? options.blockedReasons
|
|
64
|
+
: (parsed.latestCheckpoint.blockedItems || []).map((item) => item.title).join(",")
|
|
65
|
+
}
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
} catch {
|
|
69
|
+
// Fall through to status board generation
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return createAgentStatusBoard(input, {
|
|
74
|
+
format: "json",
|
|
75
|
+
currentTaskId: options.currentTaskId,
|
|
76
|
+
completedPacketIds: options.completedPacketIds,
|
|
77
|
+
blockedReasons: options.blockedReasons
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function inferDecision(board) {
|
|
82
|
+
switch (board.boardStatus) {
|
|
83
|
+
case "blocked":
|
|
84
|
+
return "resolve-blockers";
|
|
85
|
+
case "completed":
|
|
86
|
+
return "move-to-closeout";
|
|
87
|
+
case "in-progress":
|
|
88
|
+
return "continue-current-packet";
|
|
89
|
+
case "not-started":
|
|
90
|
+
return "start-first-packet";
|
|
91
|
+
default:
|
|
92
|
+
return "gather-context";
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function inferCheckpointType(decision) {
|
|
97
|
+
switch (decision) {
|
|
98
|
+
case "resolve-blockers":
|
|
99
|
+
return "blocker-checkpoint";
|
|
100
|
+
case "move-to-closeout":
|
|
101
|
+
return "closeout-checkpoint";
|
|
102
|
+
case "continue-current-packet":
|
|
103
|
+
case "start-first-packet":
|
|
104
|
+
return "execution-checkpoint";
|
|
105
|
+
default:
|
|
106
|
+
return "context-checkpoint";
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function buildDecisionReason(board, decision) {
|
|
111
|
+
switch (decision) {
|
|
112
|
+
case "resolve-blockers":
|
|
113
|
+
return `当前存在 ${board.columns.blocked.length} 个阻塞项,先解除阻塞,再继续推进 ${board.columns.inProgress[0]?.id || "当前包"}。`;
|
|
114
|
+
case "move-to-closeout":
|
|
115
|
+
return "当前执行包已经全部完成,适合进入复盘、交接和交付阶段。";
|
|
116
|
+
case "continue-current-packet":
|
|
117
|
+
return `当前已有明确执行包 ${board.columns.inProgress[0]?.id || ""},且没有阻塞,可以继续推进。`;
|
|
118
|
+
case "start-first-packet":
|
|
119
|
+
return `当前尚未开始,但第一包 ${board.columns.inProgress[0]?.id || ""} 已经明确,可以直接启动。`;
|
|
120
|
+
default:
|
|
121
|
+
return "当前还缺执行上下文,先补充上下文再做下一步决策。";
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function buildGateChecks(board, decision) {
|
|
126
|
+
const hasActive = board.columns.inProgress.length > 0;
|
|
127
|
+
const hasBlockers = board.columns.blocked.length > 0;
|
|
128
|
+
const canCloseout = board.boardStatus === "completed";
|
|
129
|
+
const hasNextCommand = Boolean(board.suggestedNextCommand);
|
|
130
|
+
|
|
131
|
+
return [
|
|
132
|
+
{
|
|
133
|
+
id: "gate-active-packet",
|
|
134
|
+
label: "当前是否有明确执行包",
|
|
135
|
+
status: hasActive ? "pass" : "fail",
|
|
136
|
+
detail: hasActive ? `当前包:${board.columns.inProgress[0].id}` : "当前没有明确执行包。"
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
id: "gate-blockers",
|
|
140
|
+
label: "当前是否无阻塞",
|
|
141
|
+
status: hasBlockers ? "fail" : "pass",
|
|
142
|
+
detail: hasBlockers ? `阻塞数:${board.columns.blocked.length}` : "当前没有阻塞。"
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
id: "gate-closeout",
|
|
146
|
+
label: "是否达到收尾条件",
|
|
147
|
+
status: canCloseout ? "pass" : "warn",
|
|
148
|
+
detail: canCloseout ? "已可进入 closeout。" : "当前仍处于执行中或待开始。"
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
id: "gate-next-command",
|
|
152
|
+
label: "是否有下一步命令",
|
|
153
|
+
status: hasNextCommand ? "pass" : "fail",
|
|
154
|
+
detail: hasNextCommand ? board.suggestedNextCommand : "还没有稳定的下一步命令。"
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
id: "gate-decision-fit",
|
|
158
|
+
label: "当前决策是否匹配状态",
|
|
159
|
+
status:
|
|
160
|
+
(decision === "resolve-blockers" && hasBlockers) ||
|
|
161
|
+
(decision === "move-to-closeout" && canCloseout) ||
|
|
162
|
+
(decision === "continue-current-packet" && hasActive && !hasBlockers) ||
|
|
163
|
+
(decision === "start-first-packet" && board.boardStatus === "not-started") ||
|
|
164
|
+
(decision === "gather-context" && board.boardStatus === "needs-context")
|
|
165
|
+
? "pass"
|
|
166
|
+
: "warn",
|
|
167
|
+
detail: `当前决策:${decision}`
|
|
168
|
+
}
|
|
169
|
+
];
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function buildDecisionChecklist(decision) {
|
|
173
|
+
switch (decision) {
|
|
174
|
+
case "resolve-blockers":
|
|
175
|
+
return [
|
|
176
|
+
"先确认阻塞是不是会影响当前包验收。",
|
|
177
|
+
"先补权限、仓库、模板或关键上下文。",
|
|
178
|
+
"阻塞解除后,重新生成 progress tracker 或 status board。"
|
|
179
|
+
];
|
|
180
|
+
case "move-to-closeout":
|
|
181
|
+
return [
|
|
182
|
+
"确认本轮执行包已全部完成。",
|
|
183
|
+
"进入 completion-report,总结已完成、剩余风险和下一轮任务。",
|
|
184
|
+
"进入 handoff-bundle 或 publish-pack 进行交接或交付。"
|
|
185
|
+
];
|
|
186
|
+
case "continue-current-packet":
|
|
187
|
+
return [
|
|
188
|
+
"继续推进当前执行包,不要切换到其他包。",
|
|
189
|
+
"先完成当前包的验证与回报,再进入下一包。",
|
|
190
|
+
"完成后重新生成 progress tracker 或 status board。"
|
|
191
|
+
];
|
|
192
|
+
case "start-first-packet":
|
|
193
|
+
return [
|
|
194
|
+
"从第一包开始执行。",
|
|
195
|
+
"不要同时展开多包任务。",
|
|
196
|
+
"开始后马上用 progress tracker 记录当前包。"
|
|
197
|
+
];
|
|
198
|
+
default:
|
|
199
|
+
return [
|
|
200
|
+
"先补仓库、模板、页面或执行工件上下文。",
|
|
201
|
+
"补完上下文后重新生成 checkpoint。",
|
|
202
|
+
"不要假装已经进入执行阶段。"
|
|
203
|
+
];
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function buildSuggestedNextCommand(board, decision) {
|
|
208
|
+
if (decision === "move-to-closeout") {
|
|
209
|
+
return `geo-ai-search-optimization completion-report ${board.source}`;
|
|
210
|
+
}
|
|
211
|
+
if (decision === "gather-context") {
|
|
212
|
+
return `geo-ai-search-optimization agent-session ${board.source}`;
|
|
213
|
+
}
|
|
214
|
+
return board.suggestedNextCommand;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function buildAlternateCommands(board, decision) {
|
|
218
|
+
const commands = new Set();
|
|
219
|
+
|
|
220
|
+
if (decision === "resolve-blockers") {
|
|
221
|
+
commands.add(board.suggestedNextCommand);
|
|
222
|
+
commands.add(`geo-ai-search-optimization agent-status-board ${board.source}`);
|
|
223
|
+
commands.add(`geo-ai-search-optimization agent-progress-tracker ${board.source}`);
|
|
224
|
+
} else if (decision === "move-to-closeout") {
|
|
225
|
+
commands.add(`geo-ai-search-optimization handoff-bundle ${board.source}`);
|
|
226
|
+
commands.add(`geo-ai-search-optimization publish-pack ${board.source}`);
|
|
227
|
+
} else if (decision === "continue-current-packet" || decision === "start-first-packet") {
|
|
228
|
+
commands.add(board.suggestedNextCommand);
|
|
229
|
+
commands.add(`geo-ai-search-optimization agent-progress-tracker ${board.source}`);
|
|
230
|
+
commands.add(`geo-ai-search-optimization agent-status-board ${board.source}`);
|
|
231
|
+
} else {
|
|
232
|
+
commands.add(`geo-ai-search-optimization agent-session ${board.source}`);
|
|
233
|
+
commands.add(`geo-ai-search-optimization agent-runbook ${board.source}`);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return Array.from(commands).filter(Boolean);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function buildHandoffNote(board, decision) {
|
|
240
|
+
switch (decision) {
|
|
241
|
+
case "resolve-blockers":
|
|
242
|
+
return "下一位 agent 先不要继续修代码,先解除阻塞项,再回到当前执行包。";
|
|
243
|
+
case "move-to-closeout":
|
|
244
|
+
return "下一位 agent 可以直接进入复盘、交接和交付流程。";
|
|
245
|
+
case "continue-current-packet":
|
|
246
|
+
return `下一位 agent 继续当前包 ${board.columns.inProgress[0]?.id || ""},不要切换任务。`;
|
|
247
|
+
case "start-first-packet":
|
|
248
|
+
return `下一位 agent 从第一包 ${board.columns.inProgress[0]?.id || ""} 开始。`;
|
|
249
|
+
default:
|
|
250
|
+
return "下一位 agent 先补上下文,不要直接开始修改。";
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function buildCheckpointPrompt(checkpoint) {
|
|
255
|
+
const lines = [
|
|
256
|
+
"你现在进入 GEO 阶段检查点模式。",
|
|
257
|
+
`当前输入:${checkpoint.source}`,
|
|
258
|
+
`检查点类型:${checkpoint.checkpointType}`,
|
|
259
|
+
`当前状态:${checkpoint.boardStatus}`,
|
|
260
|
+
`当前决策:${checkpoint.decision}`,
|
|
261
|
+
`决策原因:${checkpoint.decisionReason}`
|
|
262
|
+
];
|
|
263
|
+
|
|
264
|
+
if (checkpoint.currentPacket) {
|
|
265
|
+
lines.push(`当前包:${checkpoint.currentPacket.id}|${checkpoint.currentPacket.title}`);
|
|
266
|
+
}
|
|
267
|
+
if (checkpoint.nextPacket) {
|
|
268
|
+
lines.push(`下一包:${checkpoint.nextPacket.id}|${checkpoint.nextPacket.title}`);
|
|
269
|
+
}
|
|
270
|
+
if (checkpoint.blockedItems.length > 0) {
|
|
271
|
+
lines.push(`阻塞项:${checkpoint.blockedItems.map((item) => item.title).join(";")}`);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
lines.push("请先回答:现在该继续、该解除阻塞,还是该进入收尾。");
|
|
275
|
+
lines.push("然后给出本轮 checkpoint 结论、下一步命令和交接说明。");
|
|
276
|
+
return lines.join("\n");
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
export async function createAgentCheckpoint(input, options = {}) {
|
|
280
|
+
const format = normalizeFormat(options.format);
|
|
281
|
+
const statusBoard = await resolveStatusBoard(input, options);
|
|
282
|
+
const decision = inferDecision(statusBoard);
|
|
283
|
+
|
|
284
|
+
const checkpoint = {
|
|
285
|
+
kind: "geo-agent-checkpoint",
|
|
286
|
+
input,
|
|
287
|
+
source: statusBoard.source,
|
|
288
|
+
sourceType: statusBoard.sourceType,
|
|
289
|
+
artifactKind: statusBoard.kind,
|
|
290
|
+
format,
|
|
291
|
+
checkpointType: inferCheckpointType(decision),
|
|
292
|
+
boardStatus: statusBoard.boardStatus,
|
|
293
|
+
decision,
|
|
294
|
+
decisionReason: buildDecisionReason(statusBoard, decision),
|
|
295
|
+
progressPercent: statusBoard.progressPercent,
|
|
296
|
+
currentPacket: statusBoard.columns.inProgress[0] || null,
|
|
297
|
+
nextPacket: statusBoard.columns.nextUp[0] || null,
|
|
298
|
+
completedPackets: statusBoard.columns.completed,
|
|
299
|
+
blockedItems: statusBoard.columns.blocked,
|
|
300
|
+
gateChecks: buildGateChecks(statusBoard, decision),
|
|
301
|
+
decisionChecklist: buildDecisionChecklist(decision),
|
|
302
|
+
suggestedNextCommand: buildSuggestedNextCommand(statusBoard, decision),
|
|
303
|
+
alternateCommands: buildAlternateCommands(statusBoard, decision),
|
|
304
|
+
handoffNote: buildHandoffNote(statusBoard, decision),
|
|
305
|
+
checkpointPrompt: "",
|
|
306
|
+
statusBoard
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
checkpoint.checkpointPrompt = buildCheckpointPrompt(checkpoint);
|
|
310
|
+
return checkpoint;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
export function renderAgentCheckpointMarkdown(checkpoint) {
|
|
314
|
+
const lines = [
|
|
315
|
+
"# GEO Agent Checkpoint",
|
|
316
|
+
"",
|
|
317
|
+
`- 输入:\`${checkpoint.source}\``,
|
|
318
|
+
`- 来源类型:\`${checkpoint.sourceType}\``,
|
|
319
|
+
`- 工件类型:\`${checkpoint.artifactKind}\``,
|
|
320
|
+
`- 检查点类型:\`${checkpoint.checkpointType}\``,
|
|
321
|
+
`- 当前状态:\`${checkpoint.boardStatus}\``,
|
|
322
|
+
`- 当前决策:\`${checkpoint.decision}\``,
|
|
323
|
+
`- 进度:\`${checkpoint.progressPercent}%\``,
|
|
324
|
+
`- 决策原因:${checkpoint.decisionReason}`,
|
|
325
|
+
""
|
|
326
|
+
];
|
|
327
|
+
|
|
328
|
+
if (checkpoint.currentPacket) {
|
|
329
|
+
lines.push("## 当前包", "");
|
|
330
|
+
lines.push(`- ${checkpoint.currentPacket.id}|${checkpoint.currentPacket.title}`);
|
|
331
|
+
lines.push(`- Owner:${checkpoint.currentPacket.owner}`);
|
|
332
|
+
lines.push(`- 优先级:${checkpoint.currentPacket.priority}`);
|
|
333
|
+
lines.push("");
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
if (checkpoint.nextPacket) {
|
|
337
|
+
lines.push("## 下一包", "");
|
|
338
|
+
lines.push(`- ${checkpoint.nextPacket.id}|${checkpoint.nextPacket.title}`);
|
|
339
|
+
lines.push(`- Owner:${checkpoint.nextPacket.owner}`);
|
|
340
|
+
lines.push(`- 优先级:${checkpoint.nextPacket.priority}`);
|
|
341
|
+
lines.push("");
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
lines.push("## Gate Checks", "");
|
|
345
|
+
for (const gate of checkpoint.gateChecks) {
|
|
346
|
+
lines.push(`- [${gate.status}] ${gate.label}:${gate.detail}`);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
lines.push("", "## 决策清单", "");
|
|
350
|
+
for (const item of checkpoint.decisionChecklist) {
|
|
351
|
+
lines.push(`- [ ] ${item}`);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
lines.push("", "## 建议下一步命令", "");
|
|
355
|
+
lines.push(`- \`${checkpoint.suggestedNextCommand}\``);
|
|
356
|
+
|
|
357
|
+
lines.push("", "## 备选命令", "");
|
|
358
|
+
for (const command of checkpoint.alternateCommands) {
|
|
359
|
+
lines.push(`- \`${command}\``);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
lines.push("", "## 交接说明", "");
|
|
363
|
+
lines.push(`- ${checkpoint.handoffNote}`);
|
|
364
|
+
|
|
365
|
+
lines.push("", "## 可直接复制给 Agent 的 Checkpoint Prompt", "", "```text");
|
|
366
|
+
lines.push(checkpoint.checkpointPrompt);
|
|
367
|
+
lines.push("```");
|
|
368
|
+
|
|
369
|
+
lines.push("", "## 状态看板", "");
|
|
370
|
+
lines.push(renderAgentStatusBoardMarkdown(checkpoint.statusBoard).trim());
|
|
371
|
+
lines.push("");
|
|
372
|
+
|
|
373
|
+
return `${lines.join("\n")}\n`;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
export async function writeAgentCheckpointOutput(outputPath, content) {
|
|
377
|
+
return writeAgentStatusBoardOutput(outputPath, content);
|
|
378
|
+
}
|