support explicit [keys: ...] resource hints for parallel autonomy conflict control

This commit is contained in:
DBT
2026-02-24 12:30:26 +00:00
parent e5c942ab39
commit 9ecb5c9b47
3 changed files with 65 additions and 4 deletions

View File

@@ -35,6 +35,14 @@
这些优化提升了高并发场景下的稳定性、可观测性与可维护性。
### 并行任务冲突控制Autonomy
支持基于 `resource_keys` 的锁调度。任务可在内容中显式声明资源键,提升并行判冲突精度:
- 示例:`[keys: repo:clawgo, file:pkg/agent/loop.go, branch:main] 修复对话流程`
- 未显式声明时,系统会从任务文本自动推断资源键。
- 冲突任务进入 `resource_lock` 等待,默认 30 秒后重试抢锁,并带公平加权(等待越久优先级越高)。
## 🏁 快速开始
1. 初始化配置与工作区

View File

@@ -35,6 +35,14 @@ A recent architecture pass leveraged core Go strengths:
These changes improve stability, observability, and maintainability under concurrency.
### Parallel task conflict control (Autonomy)
Autonomy now supports lock scheduling via `resource_keys`. You can explicitly declare keys in task text for precise conflict detection:
- Example: `[keys: repo:clawgo, file:pkg/agent/loop.go, branch:main] fix dialog flow`
- Without explicit keys, the engine derives keys from task text heuristically.
- Conflicting tasks enter `resource_lock` waiting, retry lock acquisition after 30s, and use fairness weighting (longer wait => higher scheduling priority).
## 🏁 Quick Start
1. Initialize config and workspace

View File

@@ -353,10 +353,14 @@ func schedulingScore(st *taskState, now time.Time) int {
}
func deriveResourceKeys(content string) []string {
content = strings.TrimSpace(strings.ToLower(content))
if content == "" {
raw := strings.TrimSpace(content)
if raw == "" {
return nil
}
if explicit := parseExplicitResourceKeys(raw); len(explicit) > 0 {
return explicit
}
content = strings.ToLower(raw)
keys := make([]string, 0, 8)
hasRepo := false
for _, token := range strings.Fields(content) {
@@ -380,10 +384,51 @@ func deriveResourceKeys(content string) []string {
if len(keys) == 0 {
keys = append(keys, "scope:general")
}
return normalizeResourceKeys(keys)
}
func parseExplicitResourceKeys(content string) []string {
lower := strings.ToLower(content)
start := strings.Index(lower, "[keys:")
if start < 0 {
return nil
}
rest := content[start+6:]
end := strings.Index(rest, "]")
if end < 0 {
return nil
}
body := strings.TrimSpace(rest[:end])
if body == "" {
return nil
}
parts := strings.Split(body, ",")
keys := make([]string, 0, len(parts))
for _, p := range parts {
k := strings.ToLower(strings.TrimSpace(p))
if k == "" {
continue
}
if !strings.Contains(k, ":") {
k = "file:" + k
}
keys = append(keys, k)
}
return normalizeResourceKeys(keys)
}
func normalizeResourceKeys(keys []string) []string {
if len(keys) == 0 {
return nil
}
sort.Strings(keys)
uniq := keys[:0]
for i, k := range keys {
if i == 0 || k != keys[i-1] {
for _, k := range keys {
k = strings.TrimSpace(strings.ToLower(k))
if k == "" {
continue
}
if len(uniq) == 0 || k != uniq[len(uniq)-1] {
uniq = append(uniq, k)
}
}