Add a source file to the processing queue. Checks for duplicates, creates archive folder, moves source from inbox, creates extract task, and updates queue. Triggers on "/seed", "/seed [file]", "queue this for processing".
Target: $ARGUMENTS
The target MUST be a file path. If no target provided, list {DOMAIN:inbox}/ contents and ask which to seed.
Read ops/derivation-manifest.md (or fall back to ops/derivation.md) for domain vocabulary mapping. All output must use domain-native terms. If neither file exists, use universal terms.
START NOW. Seed the source file into the processing queue.
Confirm the target file exists. If it does not, check common locations:
{DOMAIN:inbox}/{filename}If the file cannot be found, report error and stop:
ERROR: Source file not found: {path}
Checked: {locations checked}
Read the file to understand:
Check if this source has already been processed. Two levels of detection:
Search the queue file and archive folders for matching source names:
SOURCE_NAME=$(basename "$FILE" .md | tr ' ' '-' | tr '[:upper:]' '[:lower:]')
# Check queue for existing entry
# Search in ops/queue.yaml, ops/queue/queue.yaml, or ops/queue/queue.json
grep -l "$SOURCE_NAME" ops/queue*.yaml ops/queue/*.yaml ops/queue/*.json 2>/dev/null
# Check archive folders
ls -d ops/queue/archive/*-${SOURCE_NAME}* 2>/dev/null
If semantic search is available (qmd MCP tools or CLI), check for content overlap:
mcp__qmd__search query="claims from {source filename}" limit=5
Or via keyword search in the {DOMAIN:notes}/ directory:
grep -rl "{key terms from source title}" {DOMAIN:notes}/ 2>/dev/null | head -5
If either check finds a match:
Create the archive folder. The date-prefixed folder name ensures uniqueness.
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"
The archive folder serves two purposes:
Move the source file from its current location to the archive folder. This is the claiming step — once moved, the source is owned by this processing batch.
{DOMAIN:inbox} sources get moved:
if [[ "$FILE" == *"{DOMAIN:inbox}"* ]] || [[ "$FILE" == *"inbox"* ]]; then
mv "$FILE" "$ARCHIVE_DIR/"
FINAL_SOURCE="$ARCHIVE_DIR/$(basename "$FILE")"
fi
Sources outside {DOMAIN:inbox} stay in place:
# Living docs (like configuration files) stay where they are
# Archive folder is still created for task files
FINAL_SOURCE="$FILE"
Use $FINAL_SOURCE in the task file — this is the path all downstream phases reference.
Why move immediately: All references (task files, {DOMAIN:note_plural}' Source footers) use the final archived path from the start. No path updates needed later. If it is in {DOMAIN:inbox}, it is unclaimed. Claimed sources live in archive.
Find the highest existing claim number across the queue and archive to ensure globally unique claim IDs.
# Check queue for highest claim number in file references
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}
# Check archive for highest claim number
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 starts after the highest
NEXT_CLAIM_START=$((QUEUE_MAX > ARCHIVE_MAX ? QUEUE_MAX + 1 : ARCHIVE_MAX + 1))
Claim numbers are globally unique and never reused across batches. This ensures every claim file name ({source}-{NNN}.md) is unique vault-wide.
Write the task file to ops/queue/${SOURCE_BASENAME}.md:
---