name: seed description: 将源文件添加到处理队列。检查重复项、创建归档文件夹、从收件箱移动源文件、创建提取任务并更新队列。触发命令:“/seed”、“/seed [文件]”、“queue this for processing”。 version: “1.0” generated_from: “arscontexta-v1.6” user-invocable: true context: fork model: sonnet allowed-tools: Read, Write, Edit, Grep, Glob, Bash argument-hint: “[文件] — 要加入处理队列的源文件路径”
立即执行
目标: $ARGUMENTS
目标必须是文件路径。如果未提供目标,列出{DOMAIN:inbox}/的内容并询问要加入哪个文件。
步骤0:读取词汇表
读取ops/derivation-manifest.md(或回退到ops/derivation.md)获取领域词汇映射。所有输出必须使用领域原生术语。如果两个文件都不存在,使用通用术语。
立即开始。 将源文件加入处理队列。
步骤1:验证源文件
确认目标文件存在。如果不存在,检查常见位置:
{DOMAIN:inbox}/{文件名}- {DOMAIN:inbox}/的子目录
如果找不到文件,报告错误并停止:
错误:未找到源文件:{路径}
已检查:{已检查的位置}
读取文件以了解:
- 内容类型:这是什么类型的材料?(研究文章、文档、转录稿等)
- 大小:行数(影响/reduce中的分块决策)
- 格式:markdown、纯文本、结构化数据
步骤2:重复检测
检查此源是否已被处理。两个检测级别:
2a. 文件名匹配
在队列文件和归档文件夹中搜索匹配的源文件名:
SOURCE_NAME=$(basename "$FILE" .md | tr ' ' '-' | tr '[:upper:]' '[:lower:]')
# 检查队列中是否有现有条目
# 在ops/queue.yaml、ops/queue/queue.yaml或ops/queue/queue.json中搜索
grep -l "$SOURCE_NAME" ops/queue*.yaml ops/queue/*.yaml ops/queue/*.json 2>/dev/null
# 检查归档文件夹
ls -d ops/queue/archive/*-${SOURCE_NAME}* 2>/dev/null
2b. 内容相似性(如果语义搜索可用)
如果语义搜索可用(qmd MCP工具或CLI),检查内容重叠:
mcp__qmd__search query="来自{源文件名}的声明" limit=5
或通过{DOMAIN:notes}/目录中的关键词搜索:
grep -rl "{源标题中的关键词}" {DOMAIN:notes}/ 2>/dev/null | head -5
2c. 报告重复项
如果任一检查找到匹配项:
- 显示找到的内容(文件名匹配或内容重叠)
- 询问:“此源可能已被处理过。是否继续?(y/n)”
- 如果用户拒绝,干净地停止
- 如果用户确认(或未找到重复项),继续
步骤3:创建归档结构
创建归档文件夹。带日期前缀的文件夹名称确保唯一性。
DATE=$(date -u +"%Y-%m-%d")
SOURCE_BASENAME=$(basename "$FILE" .md | tr ' ' '-' | tr '[:upper:]' '[:lower:]')
ARCHIVE_DIR="ops/queue/archive/${DATE}-${SOURCE_BASENAME}"
mkdir -p "$ARCHIVE_DIR"
归档文件夹有两个用途:
- 源文件的永久存放位置(从{DOMAIN:inbox}移动)
- 批处理完成后任务文件的存放位置(/archive-batch将它们移动到这里)
步骤4:将源文件移动到归档
将源文件从其当前位置移动到归档文件夹。这是认领步骤——一旦移动,源文件就属于此处理批次。
{DOMAIN:inbox}源文件被移动:
if [[ "$FILE" == *"{DOMAIN:inbox}"* ]] || [[ "$FILE" == *"inbox"* ]]; then
mv "$FILE" "$ARCHIVE_DIR/"
FINAL_SOURCE="$ARCHIVE_DIR/$(basename "$FILE")"
fi
{DOMAIN:inbox}外的源文件保持原位:
# 活动文档(如配置文件)保持原位
# 仍创建归档文件夹用于存放任务文件
FINAL_SOURCE="$FILE"
在任务文件中使用$FINAL_SOURCE——这是所有下游阶段引用的路径。
为什么立即移动: 所有引用(任务文件、{DOMAIN:note_plural}的源脚注)从一开始就使用最终的归档路径。之后无需更新路径。如果在{DOMAIN:inbox}中,它是未认领的。已认领的源文件存放在归档中。
步骤5:确定声明编号
查找队列和归档中现有的最高声明编号,以确保全局唯一的声明ID。
# 检查队列中文件引用中的最高声明编号
QUEUE_MAX=$(grep -oE '[0-9]{3}\.md' ops/queue*.yaml ops/queue/*.yaml 2>/dev/null | \
grep -oE '[0-9]{3}' | sort -n | tail -1)
QUEUE_MAX=${QUEUE_MAX:-0}
# 检查归档中的最高声明编号
ARCHIVE_MAX=$(find ops/queue/archive -name "*-[0-9][0-9][0-9].md" 2>/dev/null | \
grep -v summary | sed 's/.*-\([0-9][0-9][0-9]\)\.md/\1/' | sort -n | tail -1)
ARCHIVE_MAX=${ARCHIVE_MAX:-0}
# 下一个声明从最高值之后开始
NEXT_CLAIM_START=$((QUEUE_MAX > ARCHIVE_MAX ? QUEUE_MAX + 1 : ARCHIVE_MAX + 1))
声明编号是全局唯一的,跨批次永不重复使用。这确保每个声明文件名({source}-{NNN}.md)在整个知识库中是唯一的。
步骤6:创建提取任务文件
将任务文件写入ops/queue/${SOURCE_BASENAME}.md:
---
id: {SOURCE_BASENAME}
type: extract
source: {FINAL_SOURCE}
original_path: {移动前的原始文件路径}
archive_folder: {ARCHIVE_DIR}
created: {UTC时间戳}
next_claim_start: {NEXT_CLAIM_START}
---
# 从{源文件名}提取{DOMAIN:note_plural}
## 源文件
原始路径:{原始文件路径}
归档路径:{FINAL_SOURCE}
大小:{行数}行
内容类型:{检测到的类型}
## 范围
{如果通过--scope提供范围指导,否则:"完整文档"}
## 验收标准
- 提取声明、实现想法、矛盾和可测试假设
- 在提取过程中对{DOMAIN:notes}/进行重复检查
- 近重复项创建丰富任务(不跳过)
- 每种输出类型得到适当处理
## 执行说明
(由/reduce填写)
## 输出
(由/reduce填写)
步骤7:更新队列
将提取任务条目添加到队列文件。
对于YAML队列(ops/queue.yaml):
- id: {SOURCE_BASENAME}
type: extract
status: pending
source: "{FINAL_SOURCE}"
file: "{SOURCE_BASENAME}.md"
created: "{UTC时间戳}"
next_claim_start: {NEXT_CLAIM_START}
对于JSON队列(ops/queue/queue.json):
{
"id": "{SOURCE_BASENAME}",
"type": "extract",
"status": "pending",
"source": "{FINAL_SOURCE}",
"file": "{SOURCE_BASENAME}.md",
"created": "{UTC时间戳}",
"next_claim_start": {NEXT_CLAIM_START}
}
如果队列文件不存在: 使用适当的模式头(phase_order定义)和此第一个任务条目创建一个。
步骤8:报告
--=={ seed }==--
已加入:{SOURCE_BASENAME}
源文件:{原始路径} -> {FINAL_SOURCE}
归档文件夹:{ARCHIVE_DIR}
大小:{行数}行
内容类型:{检测到的类型}
任务文件:ops/queue/{SOURCE_BASENAME}.md
声明将从:{NEXT_CLAIM_START}开始
声明文件将是:{SOURCE_BASENAME}-{NNN}.md(整个知识库唯一)
队列:已更新提取任务
后续步骤:
/ralph 1 --batch {SOURCE_BASENAME} (提取声明)
/pipeline 将自动处理此任务
此技能存在的原因
手动队列管理容易出错。此技能:
- 确保跨批次的任务文件格式一致
- 自动处理声明编号(全局唯一)
- 在创建不必要的工作前检查重复项
- 立即将源文件移动到其永久归档位置
- 为用户提供清晰的后续步骤
命名约定
任务文件使用源文件基本名称以提高可读性:
- 任务文件:
{source-basename}.md - 声明文件:
{source-basename}-{NNN}.md - 摘要:
{source-basename}-summary.md - 归档文件夹:
{date}-{source-basename}/
声明编号(NNN)在所有批次中全局唯一,确保每个文件名在整个知识库中是唯一的。这是必需的,因为wiki链接按文件名解析,而不是路径。
源文件处理模式
{DOMAIN:inbox}源文件(最常见):
{DOMAIN:inbox}/research/article.md
| /seed
v
ops/queue/archive/2026-01-30-article/article.md <- 源文件移动到这里
ops/queue/article.md <- 创建任务文件
活动文档({DOMAIN:inbox}外):
CLAUDE.md -> 保持为CLAUDE.md(不移动)
ops/queue/archive/2026-01-30-claude-md/ <- 仍创建文件夹
ops/queue/claude-md.md <- 创建任务文件
当稍后运行/archive-batch时,它将任务文件移动到现有的归档文件夹并生成摘要。
边缘情况
{DOMAIN:inbox}外的源文件: 有效——源文件保持原位,仅为任务文件创建归档文件夹。
无队列文件: 创建ops/queue/queue.yaml(或.json)并带有模式头和此第一个条目。
大型源文件(2500+行): 在输出中注明:“大型源文件({N}行)-- /reduce将自动分块。”
源文件是URL或非文件: 报告错误:“/seed需要文件路径。”
无ops/derivation-manifest.md: 对所有输出使用通用词汇。
关键约束
绝不:
- 跳过重复检测(防止浪费处理)
- 移动不在{DOMAIN:inbox}中的源文件(活动文档保持原位)
- 重用先前批次的声明编号(需要全局唯一)
- 创建任务文件而不更新队列(两者必须同时发生)
始终:
- 检测到重复项时询问是否继续
- 即使对于活动文档也创建归档文件夹(任务文件需要)
- 在任务文件中使用归档路径(而非原始路径)用于{DOMAIN:inbox}源文件
- 清晰地报告后续步骤,使用户知道下一步做什么
- 从队列和归档两者计算next_claim_start(不仅仅是其中一个)