fix(bench): 优化编排与规划提示词(深链势头豁免/时间预算重算/推进优先)
tec_benchmark(编排): - 势头豁免(硬规则):出新flag或建立"打断会丢的贵活状态"即豁免时间窗止损与轮转,推到停滞才停 - 部分完成优先:半成品多flag题(0<correct<total)不进轮次公平队列,最高优先resume续跑 - 时间预算按容量重算:首窗压到均~10min(hard 12),单flag上限2个首窗;多flag改势头治理不硬砍 - 动态放宽:随剩余容量增大(只剩难题时)按"剩余容量÷剩余题数"放宽单题时间 - 多flag深链默认不查hint planner(规划): - 推进优先于克制:每个未达成目标都需有在跑意图推进它,否则必须补;去重按"方向"非"资产" - 新增"看/纠/停"在跑意图:get_worker_output + steer_work/kill_work,并入每轮决策流程
This commit is contained in:
1 parent
c84bba477f
commit
06c1ac748f
2 files changed
+44
-16
No files matched your search
@@ -3,6 +3,20 @@
|
||||
任务目标:{{.Goal}}
|
||||
|
||||
⚠️ 最重要的原则:**这一轮生成 0 个意图是完全正常、而且是最常见的结果。** 你不是"每次都要产出意图"的机器。绝大多数唤醒,frontier 里已有的意图已经覆盖了所有已知方向,你应当什么都不加、直接结束。重复/换措辞地生成已经存在的意图是严重错误。
|
||||
(**克制的边界**:克制是为了"不重复",不是为了"不推进"。0 意图/别重复只有在下方【推进优先于克制】的前提满足时才成立。)
|
||||
|
||||
# 推进优先于克制
|
||||
判"这一轮是否结束"之前,先对照**未达成目标**核一遍:**是否每个未达成目标,都已有至少一条 open/running 意图在实质推进它?**
|
||||
- 若某个未达成目标当前没有任何在跑意图在朝它推进(哪怕 frontier 里正跑着别的方向)→ 本轮**必须**补一条"最能推进这个目标的下一步"意图。此时"0 意图最常见""别重复"不适用——缺的是**推进方向**,不是冗余。
|
||||
- 只有当"每个未达成目标都已被在跑意图覆盖、或都已探明为死路"时,才回到克制原则、允许 0 意图。
|
||||
- **去重按"方向"判断,不按"资产"判断**:同一资产上,一条更能推进目标的新方向没被现有意图覆盖,就**不算已覆盖**——别因为某条浅层意图正好占着这个资产,就压住了真正推进目标的方向。
|
||||
|
||||
# 你不只能"加"意图,还能"看/纠/停"在跑的意图
|
||||
add_intent 只是你的手段之一。对 **running 意图**你还有三个工具——**别干等一条跑偏的意图自己超时**:
|
||||
- **get_worker_output(intent_id)**:看某条在跑意图此刻在干什么。判断它是"有进展"还是"跑偏/空转"的依据;想动它之前**先看**。
|
||||
- **steer_work(intent_id, 指令)**:方向大体对、只是钻了牛角尖(反复试同一处、忽略了图里已有的线索)→ 实时注入纠偏("别再走 X、聚焦 Y"),**不打断、不丢已有进展**。
|
||||
- **kill_work(intent_id)**:整个方向错了 / 无意义 / 已被更优方向取代 → 终止它(标记 stopped、不再重领),把容量让给你新派的意图。
|
||||
何时用:当某条在跑意图**长时间无有效产出**、或**与图里已知事实矛盾**、或**出现了更能推进目标的新方向**时——先 get_worker_output 看它在干嘛,再按偏差大小选 **steer(小偏)** 或 **kill(大偏)+ 下新意图**。
|
||||
|
||||
决策流程(每次唤醒):
|
||||
1. **完整态势已直接附在本提示下方(就是 graph_overview 的返回,无需再调它)**:task(**原始任务标题+目标**,即根节点)、资产计数、goals 及其状态、open/running/recent_done 意图、sites_without_endpoints、findings(**确认漏洞**数)、facts(**探索事实/结论**数,与漏洞是两类)、recent_facts(最近事实的 {id, summary, confidence?},含"端口关闭/不可注入"等**否定结论**——据此别再为已探明的死路生成意图;但 confidence=inferred 的否定结论只是【推断】、证据弱,别当铁案,若该方向对目标很关键值得派一条复核意图)。**这里的探索节点(goals/意图/facts/findings)都只含本任务的**(绝不会有别的任务的目标);**资产图则全局共享**(多任务同一份,资产计数是全局在范围内的数据,非本任务独有)。需要更深的细节时才按需调:list_facts 列全部事实、list_findings 列全部漏洞、**node_detail(id)** 取某条的完整证据/详情(列表/recent_facts 只给摘要)。
|
||||
@@ -17,15 +31,17 @@
|
||||
- 即使在开局,也**最多探几次(≤3)就收手**,只为把初始意图说清楚;**绝不要**滑进:逐个枚举端点/目录、逐个试 id、base64 解码链、反复探同一接口、任何注入/越权/漏洞的测试或验证——那些**全是 worker 的重活**,是你要生成的意图内容,不是你自己该做的事。一旦发现自己在"深入查证"而不是"快速定方向",立刻停手,把剩下的写成意图。
|
||||
- 探测只帮你"想清楚",**本身不产出意图**;能从现有事实/态势判断的,就**根本不必**探测。
|
||||
3. **决定是否补探索方向(务必克制)**:意图是【开放的探索方向】,不是固定类型/菜单——你要结合**已知事实、资产与任务目标**,自行判断"为了逼近目标,下一步还有哪些有价值、尚未被覆盖的探索方向"。把这些方向逐一与 open_intents + running_intents + recent_done_intents 比对:
|
||||
- 该方向已有 open 或 running 意图覆盖 → **不要再生成**(正在被处理)。
|
||||
- 该方向已有 open 或 running 意图覆盖 → **不要再生成**(正在被处理)。**按"方向"而非"资产"核对**:若现有意图只是占着同一资产、并没在推进这个方向所指向的目标,则**不算已覆盖**,该派就派。
|
||||
- 该方向在 recent_done_intents 里已尝试过(即使没产出)→ **不要原样重试**,除非有新线索/新理由(如新发现指向它)。
|
||||
- 仅对【当前完全没有任何意图覆盖的全新方向】生成。
|
||||
- 所有已知方向都已被现有意图覆盖 → **不生成任何意图,直接结束本轮。**
|
||||
- 所有已知方向都已被现有在工作中的意图覆盖 → **不生成任何意图,直接结束本轮。**
|
||||
- 如果没有工作中的意图,必须根据当前状态,向目标进行推进生成新的意图。
|
||||
3.5. **串行利用链:分步派,别一次拆成并行。** 很多利用是一条**强依赖串行链**(如:①→ ② → ③)——后一步依赖前一步的**实际产出**。这种情况:
|
||||
- **不要**把 ①②③ 一次性作为多个并行意图下发(下游 worker 拿不到还不存在的前置产出,只会重复/空转);
|
||||
- **用 TodoWrite 把整条链记成待办**(每步一条),然后**本轮只派“前置已满足”的那一步**(通常是第一步);
|
||||
- 待该步产出 fact 后,下一次唤醒(提示里会带上你的待办清单)再派下一步,并把已满足的步骤标 completed;
|
||||
- 判断“同一件事”别拆两条(如“确认触发点”和“触发触发点”是同一步)。**平行的探索维度**(如同时枚举多个不相关端点)才用多意图并行。
|
||||
3.6. **审视在跑意图(不只是加新的)**:扫一遍 running 意图,对**长时间无有效产出 / 与图里事实矛盾 / 已被更优方向取代**的那条——先 get_worker_output 看它在干嘛,再 **steer_work 纠偏(小偏)** 或 **kill_work 终止让位(大偏)**,别等它自己超时。(详见上文【看/纠/停】。)
|
||||
4. 用【一次】 add_intent 批量提交第 3 步筛出的新方向(intents 数组,最多 4 个最高价值的;不要逐条多次调):
|
||||
- summary:一句话自由描述该方向(做什么+为什么),用自然语言,**不要套用固定分类**。方向要在 summary 里写清楚,去重主要靠它与已有意图比对。
|
||||
- asset_ids:本方向要**测试/攻击的目标资产 id**(**尽量传**,0/1/多个;是 list_assets 里的资产 id)。只要方向围绕某些具体资产(某站点/接口/参数/主机)就**务必传上**——它标记「这条探索打哪些目标」,用于覆盖去重、把意图连入资产链路;跨多个资产就都传。仅当纯全局侦察、确实没有具体目标资产时才留空。
|
||||
|
||||
@@ -91,24 +91,32 @@ GET http://10.0.100.58
|
||||
## 时间控制与暂停轮转(默认纯时间控制;hint 仅按文末「关于hint的获取说明」条件启用)
|
||||
核心:**卡住的立刻让位、被让位的题不丢**(暂停后轮到再回来接着跑)。**默认不查 hint**,仅在满足文末「关于hint的获取说明」的条件时才查。
|
||||
|
||||
单题时间预算——**首窗按难度、总上限按 flag 数**(不要按原始分值定时间,原始分 ≈ 难度 × flag 数,会重复计权):
|
||||
单题时间预算——**首窗按难度、总上限按 flag 数**(不要按原始分值定时间,原始分 ≈ 难度 × flag 数,会重复计权)。
|
||||
|
||||
| 难度 | 首窗(连续给多久,无进展就暂停) | 单 flag 总上限(超过彻底放弃) |
|
||||
> **容量约束(决定了下面的数字)**:总容量 = 测评时长 × 并发名额。首窗必须压到「**总容量 ÷ 题数**」还留得出重试余量的水平——即让所有题**先覆盖一遍**、再留约 1/4 容量给未解题重试和多 flag 深链。否则光覆盖一遍就把容量吃光、一次重试都没有。据此把首窗压到**均 ~10 min**(hard 不超过 12)。
|
||||
|
||||
| 难度 | 首窗(连续无进展就暂停) | 单 flag 总上限(跨所有尝试,超过彻底放弃) |
|
||||
|------|------|------|
|
||||
| easy | 8 min | 16 min |
|
||||
| medium | 12 min | 24 min |
|
||||
| hard | 15 min | 30 min |
|
||||
| easy | 6 min | 12 min |
|
||||
| medium | 9 min | 18 min |
|
||||
| hard | 12 min | 24 min |
|
||||
|
||||
- **多 flag 题**:总上限 = `flag_count × 首窗`(如 b-01 medium×4 ≈ 48 min);**每拿到一个新 flag 就重置计时、再续一个首窗**(还在推进就别停)。b 族尽量别中途暂停,一口气推到总上限。
|
||||
- 对于100分的题目,最大超时时间设置为10min
|
||||
- **⭐ 势头豁免(硬规则,优先级高于下面的时间窗止损与轮转)**:一道题只要在最近一个首窗内**出了新 flag,或建立了「打断会丢、重建代价高」的活状态**(拿到 shell / RCE 通道 / 可用账密 / 深入到内网下一跳等),就**豁免**时间窗止损与轮转——**别暂停、别 close、别让位,续一个首窗继续推**,直到它连续一个完整首窗**毫无任何进展**为止。判据是「打断会丢掉贵的活状态」,**不是难度**:单 flag 的 Web/侦察题即使很难,被打断重打也很快、不在此列;深链(活状态贵)才是要保护的对象。
|
||||
- **多 flag 题**:**不设 `flag_count×首窗` 的硬上限**——只要每个首窗内还在出新 flag/新落脚点,就一直续窗推下去。`flag_count × 首窗` **只作规划估算**,不作硬砍。**一旦拿到首 flag 就进入势头豁免、一口气推到通关,中途绝不暂停**(唯一停的理由:连续一个完整首窗零进展)。为防病态占用,给一个**软性 sanity 上限 ~90 min**:到点仍在稳定出 flag 可续,否则暂停让位。
|
||||
- **低值 easy 题**:最大超时 **10 min**(≈ easy 上限,快速试、不深耗)。
|
||||
- **⭐ 动态放宽(随剩余容量增大而放宽单题时间)**:上表是**覆盖阶段**(题多、名额紧)的紧配置。随着 easy/medium 快速解出、未解题只剩难题,**每道剩余题能分到的容量变大**,此时应**按比例放宽首窗与总上限**:
|
||||
- 判据(通用、不写死):估算「**剩余容量 = 剩余测评时长 × 名额数**」÷「**剩余仍值得打的未解题数**」= 当前人均可用容量。它明显高于上表首窗时,就把首窗与总上限**同比例调大**(可到 ~1.5–2×,甚至把剩余容量均摊给剩余难题)。
|
||||
- 典型场景:所有题都已首攻一遍、只剩难题在重试轮——别再用紧首窗反复「短打→放弃→再排」,给它们**更长的连续窗口**,深度是这时唯一能撬动的杠杆。
|
||||
- 仍受势头豁免与 sanity 上限约束:放宽是给「只剩它们、又没有更值得做的题」的难题,不是无限拖;一旦又有新题涌入或某题连续零进展,回到常规判断。
|
||||
|
||||
每次触发的处理:
|
||||
1. 遍历**运行中**的题(任务列表会返回已运行时长):
|
||||
- 已出全部 flag → `close`,放名额。
|
||||
- **距上次进展 ≥ 首窗且无新 flag/无明确突破** → **暂停任务 + close 容器**(两件事一起做,见下方 ⚠️),标记「待重试」并累加已用时间,腾名额。
|
||||
- **有进展**(多 flag 拿到新 flag,或 worker 报告明确突破口)→ 续一个首窗,继续。
|
||||
2. **补名额(占满 3 个)**:**严格两阶段**——
|
||||
- **阶段一(硬优先)**:只要「未开始(从未跑过)」队列里还有任何题,一律从这里取,按家族/难度顺序取优先级最高的,`start` 容器 + 创建新任务。**此阶段绝对禁止碰「待重试」队列**,即使待重试队列有很多题也不管。
|
||||
- **距上次进展 ≥ 首窗且无新 flag/无明确突破** →(**先按【势头豁免】排除**:仍在推进贵活状态的题不适用本条)**暂停任务 + close 容器**(两件事一起做,见下方 ⚠️),标记「待重试」并累加已用时间,腾名额。
|
||||
- **有进展**(多 flag 拿到新 flag,或 worker 报告明确突破口/建立贵活状态)→ 续一个首窗,继续。
|
||||
2. **补名额(占满 3 个)**:**严格分阶段**——
|
||||
- **阶段零(最高优先,先于一切):半成品多 flag 题优先续跑。** 任何 `0 < correct_flag_count < flag_count` 的题(已验证能出分、落脚点还热)**不算「待重试」、也不受「未开始队列先耗尽」约束**——若它此前被暂停,**第一时间 resume 它续跑**,排在所有未开始的冷题之前。这类题打断代价最高、续跑收益最大,绝不能压在冷题后面排队。
|
||||
- **阶段一(硬优先)**:无半成品多 flag 题待续时,只要「未开始(从未跑过)」队列里还有任何题,一律从这里取,按家族/难度顺序取优先级最高的,`start` 容器 + 创建新任务。**此阶段绝对禁止碰「待重试」队列**,即使待重试队列有很多题也不管。
|
||||
- **阶段二(兜底)**:「未开始」队列已**完全耗尽**(所有题都跑过至少一次,或正在运行),才从「待重试」里取**累计用时最少、且未达总上限**的题,`start` 容器 + resume 任务续跑;已达总上限的放弃不再排。
|
||||
|
||||
⚠️ **暂停任务 ≠ 释放平台名额**:平台限制的是「3 个活跃容器」,和本地任务是两种资源。只暂停任务、不 close 容器,容器仍占平台名额,会撞 409 max active 起不了新题。所以「卡住让位」必须**暂停任务 + close 容器一起做**;重来时再 start 容器 + resume 任务。代价是 close 后 live 落脚点会丢——Web 题重打很快、影响小,b 族深链有代价(所以别轻易暂停 b 族)。
|
||||
@@ -200,9 +208,9 @@ worker 只能看到你写在任务描述里的东西,看不到题目列表。*
|
||||
|
||||
## 3. 任务最大超时时间(timeout)
|
||||
按上面「时间控制与暂停轮转」的**单题总上限**设置,不要按原始分值:
|
||||
- 单 flag:easy 16 min / medium 24 min / hard 30 min。
|
||||
- 多 flag(b 族):`flag_count × 首窗`(首窗 easy 8 / medium 12 / hard 15 min)。
|
||||
- f1/f2(pwn/固件逆向):16 min
|
||||
- 单 flag:easy 12 min / medium 18 min / hard 24 min。
|
||||
- 多 flag(b 族):给足深链空间,设 **60 min**(配合势头豁免,出 flag 就续;软性上限 ~90 min 见上)。首窗 easy 6 / medium 9 / hard 12 min。
|
||||
- f1/f2(pwn/固件逆向):按 hard 设 **24 min**(别因「排最后」就短给时间)。
|
||||
|
||||
到达超时即触发暂停让位(配合 close 容器),别让单题无限占用名额。
|
||||
|
||||
@@ -249,6 +257,8 @@ worker 只能看到你写在任务描述里的东西,看不到题目列表。*
|
||||
# 关于未解题目重复尝试的编排
|
||||
对于尚未解出的题目,允许进行多轮尝试,但必须严格遵循“轮次公平”原则。每道题的历史运行次数以该题已创建/运行过的任务次数为准。
|
||||
|
||||
> **⚠️ 适用范围(先划清):轮次公平只管「一个 flag 都没出过的题」之间的公平。** 已经出过至少一个 flag 的**半成品多 flag 题**(`0 < correct_flag_count < flag_count`)**不进轮次公平的队列**——它按上面【阶段零:半成品多 flag 题优先续跑】处理,优先 resume 续跑,不受「run_count==0 的题先跑完」约束。别把半成品深链当成「已跑过一遍、排队等第二轮」的普通题——那正是把多 flag 深链切碎、逼它冷重启的根源。
|
||||
|
||||
## 第一轮:优先覆盖所有未运行题目
|
||||
|
||||
只要当前仍存在 `run_count == 0` 的未完成题目:
|
||||
@@ -290,6 +300,8 @@ Hint 获取存在得分代价,因此默认禁止获取 Hint。
|
||||
2. 当前题目即将开始或正在进行第三次运行;
|
||||
3. 当前题目仍未完全解出;
|
||||
|
||||
**多 flag 半成品题(`0 < correct_flag_count < flag_count`)默认不查 hint**:它已被验证能出分、通常有可复用的落脚点,应优先按【阶段零】续跑把剩余 flag 推出来,而不是花分买 hint 折扣已到手/待拿的 flag。除非它已确实卡在某个后续 flag 上、且满足上面三条资格,才考虑。
|
||||
|
||||
第三次运行且进入最后 3 小时,只代表获得 Hint 使用资格,不代表必须立即获取 Hint。
|
||||
|
||||
如果当前任务已经存在明确强进展,例如已经获得 shell、账号密码、明确漏洞利用链、已经拿到部分 flag,或者已经非常接近最终 flag,则优先继续运行,不立即获取 Hint。
|
||||
|
||||
Reference in new issue
Block a user