关于 autoresearch
autoresearch 是用于代码或配置优化的自主实验循环技能,面向希望按指定命令和指标持续试验的 Agent。它通过 Git、JSONL 状态记录、工作日志与仪表板跟踪实验结果。
主要功能
- 01按目标与指标运行实验循环
- 02自动比较并保留改进结果
- 03JSONL 记录实验状态
- 04通过工作日志追踪过程
- 05生成实验结果仪表板
- 06备份与恢复实验状态
适用场景
- 01迭代优化基准测试指标
- 02跨会话恢复实验进度
- 03审查实验变更和结果
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ moedesux/ autoresearch-opencode --skill autoresearch安装后在 Claude Code 中输入/autoresearch确认已加载。
详细介绍
Autoresearch
自主实验循环:尝试想法,保留有效的,舍弃无效的,永不停止。
设置
- 询问(或推断):目标、命令、指标(+ 方向)、范围内的文件、约束条件。
git checkout -b autoresearch/<goal>-<date>- 阅读源文件。动手前深入理解工作负载。
- 执行
mkdir -p experiments,然后编写autoresearch.md、autoresearch.sh和experiments/worklog.md(见下文)。提交这三个文件。 - 初始化实验(将配置标头写入
autoresearch.jsonl)→ 运行基线 → 记录结果 → 立即开始循环。
autoresearch.md
这是本次会话的核心。一个没有上下文的新 Agent 应该能够阅读此文件并有效运行循环。投入时间把它打磨好。
# Autoresearch: <goal>
## Objective
<Specific description of what we're optimizing and the workload.>
## Metrics
- **Primary**: <name> (<unit>, lower/higher is better)
- **Secondary**: <name>, <name>, ...
## How to Run
`./autoresearch.sh` — outputs `METRIC name=number` lines.
## Files in Scope
<Every file the agent may modify, with a brief note on what it does.>
## Off Limits
<What must NOT be touched.>
## Constraints
<Hard rules: tests must pass, no new deps, etc.>
## What's Been Tried
<Update this section as experiments accumulate. Note key wins, dead ends,
and architectural insights so the agent doesn't repeat failed approaches.>
定期更新 autoresearch.md——尤其是“已尝试的内容”部分——以便恢复工作的 Agent 能掌握完整上下文。
autoresearch.sh
Bash 脚本(set -euo pipefail),用于:快速预检查(语法错误检查在 <1s 内完成)、运行基准测试、输出 METRIC name=number 行。保持脚本快速——每秒都会在数百次运行中累积。根据需要在循环期间更新脚本。
JSONL 状态协议
所有实验状态都保存在 autoresearch.jsonl 中。这是跨会话恢复工作时的事实来源。
配置标头
第一行(以及任何重新初始化行)都是配置标头:
{"type":"config","name":"<session name>","metricName":"<primary metric name>","metricUnit":"<unit>","bestDirection":"lower|higher"}
规则:
- 文件的第一行始终是配置标头。
- 每个后续配置标头(重新初始化)都会开启一个新的段。段索引随每个配置标头递增。
- 一个段的基线是配置标头之后的第一条结果行。
结果行
每个实验结果都以 JSON 行的形式追加:
{"run":1,"commit":"abc1234","metric":42.3,"metrics":{"secondary_metric":123},"status":"keep","description":"baseline","timestamp":1234567890,"segment":0}
字段:
run:连续的运行编号(从 1 开始,涵盖所有段)commit:7 位 Git 短哈希(保留时自动提交后的提交哈希,或舍弃/崩溃时的当前 HEAD)metric:主要指标值(崩溃时为 0)metrics:次要指标值对象——一旦开始跟踪次要指标,就必须在之后的每条结果中都包含该指标status:keep|discard|crashdescription:对本次实验尝试内容的简短描述timestamp:Unix 纪元秒数segment:当前段索引
初始化(相当于 init_experiment)
要初始化,请将配置标头写入 autoresearch.jsonl:
echo '{"type":"config","name":"<name>","metricName":"<metric>","metricUnit":"<unit>","bestDirection":"<lower|higher>"}' > autoresearch.jsonl
要重新初始化(更改优化目标),请追加一个新的配置标头:
echo '{"type":"config","name":"<name>","metricName":"<metric>","metricUnit":"<unit>","bestDirection":"<lower|higher>"}' >> autoresearch.jsonl
数据完整性协议
重要:JSONL 数据绝不能损坏或丢失。
写入前验证(追加到 JSONL 之前)
写入任何新的实验结果之前,请验证 JSONL 文件:
# Validate JSONL file before writing
validate_jsonl() {
local jsonl_file="autoresearch.jsonl"
if [[ -f "$jsonl_file" ]]; then
# Count existing runs
local run_count=$(grep -c '"run":' "$jsonl_file" 2>/dev/null || echo 0)
echo "Current runs in JSONL: $run_count" >&2
# Verify last 5 lines are valid JSON
tail -n 5 "$jsonl_file" 2>/dev/null | while IFS= read -r line; do
if ! echo "$line" | python3 -m json.tool >/dev/null 2>&1; then
echo "WARNING: Invalid JSON found in state file" >&2
return 1
fi
done
echo "JSONL validation: OK" >&2
return 0
fi
return 0 # File doesn't exist yet, that's OK
}
# Call validation before any write
validate_jsonl || {
echo " WARNING: JSONL validation failed. Proceeding with caution." >&2
}
原子写入模式
切勿直接追加到 JSONL。请使用原子写入模式:
write_jsonl_entry() {
local entry="$1"
local jsonl_file="autoresearch.jsonl"
local temp_file="${jsonl_file}.tmp.$$"
# Create temp file
cat "$jsonl_file" > "$temp_file" 2>/dev/null || touch "$temp_file"
# Append entry
echo "$entry" >> "$temp_file"
# Validate the new entry
if ! echo "$entry" | python3 -m json.tool >/dev/null 2>&1; then
rm -f "$temp_file"
echo " WARNING: Invalid JSON entry, not writing" >&2
return 1
fi
# Atomic move (guaranteed all-or-nothing)
mv "$temp_file" "$jsonl_file"
# Verify write succeeded
local new_count=$(grep -c '"run":' "$jsonl_file" 2>/dev/null || echo 0)
echo "Write verification: $new_count runs in JSONL" >&2
return 0
}
写入后验证
每次写入操作后,都要验证数据是否正确写入:
verify_write() {
local expected_run=$1
local jsonl_file="autoresearch.jsonl"
if [[ -f "$jsonl_file" ]]; then
local actual_count=$(grep -c '"run":' "$jsonl_file" 2>/dev/null || echo 0)
if [[ "$actual_count" -lt "$expected_run" ]]; then
echo " WARNING: Run count mismatch! Expected $expected_run, got $actual_count" >&2
echo "This may indicate data loss in previous writes." >&2
return 1
fi
echo "Write verification: OK (run $expected_run present)" >&2
return 0
fi
return 1
}
需要用户确认的操作
在执行任何需要用户确认的操作(例如人工干预、重大更改、舍弃多个实验)之前,请创建备份:
# Backup state before user-confirmable action
backup_before_confirm() {
echo " User confirmation required. Creating backup..." >&2
# Use backup utility if available
if [[ -f "./scripts/backup-state.sh" ]]; then
./scripts/backup-state.sh backup autoresearch.jsonl 2>/dev/null || true
else
# Fallback: simple backup
cp autoresearch.jsonl "autoresearch.jsonl.backup.$(date +%s)" 2>/dev/null || true
fi
echo "Backup created. Awaiting user confirmation..." >&2
}
在执行任何需要用户批准的操作之前,始终调用 backup_before_confirm。
仪表板数据一致性检查
生成仪表板时,检查数据是否一致:
数据一致性检查
如果 autoresearch.jsonl 中的运行次数与 experiments/worklog.md 中的条目数不一致:
- 检查是否有备份:
scripts/backup-state.sh list autoresearch.jsonl - 如果存在备份:使用
scripts/backup-state.sh restore-auto恢复 - 如果没有备份:根据工作日志中的记录手动重新创建缺失的运行
- 在仪表板标题中注明差异
检测到不一致时,请在仪表板中添加此警告横幅:
**DATA INCONSISTENCY DETECTED**
- **Worklog documents**: <WORKLOG_RUN_COUNT> experiments
- **JSONL contains**: <JSONL_RUN_COUNT> runs
- **Missing**: <DIFF> runs **LOST!**
**Recovery steps:**
1. Check backups: `scripts/backup-state.sh list autoresearch.jsonl`
2. Restore if available: `scripts/backup-state.sh restore-auto`
3. Otherwise, manually recreate missing runs from worklog
运行实验(相当于 run_experiment)
运行基准测试命令,并捕获耗时和输出:
START_TIME=$(date +%s%N)
bash -c "./autoresearch.sh" 2>&1 | tee /tmp/autoresearch-output.txt
EXIT_CODE=$?
END_TIME=$(date +%s%N)
DURATION=$(echo "scale=3; ($END_TIME - $START_TIME) / 1000000000" | bc)
echo "Duration: ${DURATION}s, Exit code: ${EXIT_CODE}"
运行后:
- 从输出中解析
METRIC name=number行,提取指标值 - 如果退出代码 != 0 → 这是一次崩溃
- 阅读输出,了解发生了什么
记录结果(相当于 log_experiment)
每次实验运行后,请严格遵循以下流程:
1. 确定状态
- keep:主要指标有所改善(当
bestDirection=lower时数值更低;当bestDirection=higher时数值更高) - discard:主要指标比当前保留结果更差或相同
- crash:命令失败(退出代码非零)
次要指标仅用于监控,几乎不会影响保留或丢弃的决定。只有当次要指标严重恶化时,才丢弃主要指标有所改善的结果,并在描述中说明原因。
2. Git 操作
如果保留:
git add -A
git diff --cached --quiet && echo "nothing to commit" || git commit -m "<description>
Result: {\"status\":\"keep\",\"<metricName>\":<value>,<secondary metrics>}"
然后获取新的提交哈希:
git rev-parse --short=7 HEAD
如果丢弃或崩溃:
git checkout -- .
git clean -fd
将当前 HEAD 哈希(还原前)用作提交字段。
3. 将结果追加到 JSONL
echo '{"run":<N>,"commit":"<hash>","metric":<value>,"metrics":{<secondaries>},"status":"<status>","description":"<desc>","timestamp":'$(date +%s)',"segment":<seg>}' >> autoresearch.jsonl
4. 更新仪表板
每次记录后,重新生成 autoresearch-dashboard.md(参见下方的“仪表板”部分)。
5. 追加到工作日志
每次实验后,向 experiments/worklog.md 追加一条简短记录。该文件可在上下文压缩和崩溃后保留,为任何恢复工作的 Agent(或用户)完整记录会话过程。格式:
### Run N: <short description> — <primary_metric>=<value> (<STATUS>)
- Timestamp: YYYY-MM-DD HH:MM
- What changed: <1-2 sentences describing the code/config change>
- Result: <metric values>, <delta vs best>
- Insight: <what was learned, why it worked/failed>
- Next: <what to try next based on this result>
学到新内容时,也要更新工作日志底部的“关键见解”和“后续想法”部分。
设置时,创建 experiments/worklog.md,其中包含会话标题、数据摘要和基准结果。恢复时,阅读 experiments/worklog.md 以恢复上下文。
6. 次要指标一致性
开始跟踪某项次要指标后,后续每个结果都必须包含该指标。解析 JSONL,查看跟踪过哪些次要指标,并确保结果中都包含这些指标。
如果希望在会话中途添加新的次要指标,也可以——但从此以后,必须始终包含该指标。
仪表板
每次实验后,重新生成 autoresearch-dashboard.md:
# Autoresearch Dashboard: <name>
**Runs:** 12 | **Kept:** 8 | **Discarded:** 3 | **Crashed:** 1
**Baseline:** <metric_name>: <value><unit> (#1)
**Best:** <metric_name>: <value><unit> (#8, -26.2%)
| # | commit | <metric_name> | status | description |
|---|--------|---------------|--------|-------------|
| 1 | abc1234 | 42.3s | keep | baseline |
| 2 | def5678 | 40.1s (-5.2%) | keep | optimize hot loop |
| 3 | abc1234 | 43.0s (+1.7%) | discard | try vectorization |
...
为每个指标值包含相对于基准的变化百分比。显示当前分段中的所有运行记录(不只是最近的记录)。
状态文件备份(增强版)
在用户可确认的操作之前,创建备份:
# Before any major operation requiring user confirmation
if [[ -f "./scripts/backup-state.sh" ]]; then
./scripts/backup-state.sh backup autoresearch.jsonl 2>/dev/null || true
else
cp autoresearch.jsonl "autoresearch.jsonl.backup.$(date +%s)" 2>/dev/null || true
fi
最佳实践:
- 在重大更改或等待用户确认前,始终创建备份
- 保留最近 5 个备份(删除更早的备份)
- 如果实验崩溃或状态损坏,则从备份恢复
自动清理:
# Keep only last 5 backups
ls -t autoresearch.jsonl.bak.* 2>/dev/null | tail -n +6 | xargs rm -f 2>/dev/null || true
警告:如果检测到 JSONL 数据丢失,请立即检查备份,再继续操作。
数据丢失检测和恢复
如果检测到数据丢失(例如,仪表板显示不一致,或 JSONL 记录数与工作日志不匹配):
-
立即采取措施:
# Check for data loss JSONL_COUNT=$(grep -c '"run":' autoresearch.jsonl 2>/dev/null || echo 0) WORKLOG_COUNT=$(grep -c "^### Run" experiments/worklog.md 2>/dev/null || echo 0) if [[ "$JSONL_COUNT" -ne "$WORKLOG_COUNT" ]]; then echo " DATA LOSS DETECTED: JSONL has $JSONL_COUNT runs, worklog has $WORKLOG_COUNT runs" >&2 fi -
检查备份:
./scripts/backup-state.sh list autoresearch.jsonl -
恢复选项:
- 最佳方案:如果备份时间足够近,则从备份恢复
- 替代方案:根据工作日志记录手动重建缺失的运行记录
- 最后手段:使用新的配置标题启动新分段
-
预防:在用户可确认的操作前始终创建备份(参见上文“用户可确认的操作”)
循环规则
永远循环。 不要问“要继续吗?”——用户期待自主工作。
- 主要指标至上。 有提升 →
keep。变差或持平 →discard。次要指标很少会影响这一点。 - 越简单越好。 性能相同但代码更少 = 保留。为了微小收益引入难看的复杂性 = 很可能放弃。
- 不要反复折腾。 如果反复撤销同一个想法,尝试从结构上不同的方向入手。
- 崩溃: 如果修复很简单就修复,否则记录下来并继续。不要投入过多精力。
- 遇到瓶颈时深入思考。 重新阅读源文件,研究性能分析数据,推理 CPU 实际在做什么。最好的想法来自深入理解,而不是尝试随机变体。
- 恢复工作: 如果存在
autoresearch.md,先检查autoresearch.jsonl是否存在:- 如果存在:读取它、
experiments/worklog.md和 git log,然后继续循环 - 如果不存在:查看下方的“状态文件缺失”部分(回退处理方式)
- 如果存在:读取它、
绝不停止。 用户可能会离开数小时。持续工作,直到收到中断。
状态文件缺失
恢复工作时,如果缺少 autoresearch.jsonl:
- 保留
autoresearch.md中的上下文——阅读目标、指标和涉及的文件 - 征求用户确认——“状态文件缺失。可选操作:
- A) 创建新的状态(从头开始)
- B) 仅凭 autoresearch.md 中的上下文继续
- C) 从备份恢复(如果有) ”
- 如果从头开始:使用配置头初始化新的 JSONL
- 如果仅凭上下文继续:根据 autoresearch.md 中的数据继续,但注明这一限制
想法待办列表
发现复杂但有希望、决定暂时不尝试的优化时,将它们以项目符号列表的形式追加到 autoresearch.ideas.md。不要让好想法被遗漏。
如果循环停止(达到上下文限制、崩溃等),且存在 autoresearch.ideas.md,系统会要求你:
- 阅读想法文件,并以此启发新的实验方向
- 清除重复、已尝试或明显不可行的想法
- 根据剩余想法设计实验
- 如果没有剩余想法,尝试提出新的想法
- 如果所有方向都已穷尽,删除
autoresearch.ideas.md并撰写最终总结报告
如果不存在 autoresearch.ideas.md,且循环结束,则研究已完成。
用户引导
实验进行期间收到的用户消息应记录下来,并纳入下一次实验。先完成当前实验——不要停止,也不要请求确认。在下一次实验中纳入用户的想法。
更新 autoresearch.md
定期更新 autoresearch.md,尤其是“已尝试事项”部分,确保接手循环的新 Agent 能充分了解哪些方法有效、哪些无效,以及获得了哪些架构方面的见解。每进行 5–10 次实验后,或取得重大突破后,更新一次。