- Created `torch/` directory and initialized package.json - Installed TORCH dependency from https://github.com/PR0M3TH3AN/TORCH - Initialized TORCH environment with `npx torch-lock init` - Updated .gitignore to exclude node_modules and generated files Co-authored-by: PR0M3TH3AN <[email protected]>
9.5 KiB
TORCH: Task Orchestration via Relay-Coordinated Handoff
TORCH is a decentralized task-locking protocol for multi-agent software development.
Dashboard & Protocol Overview
The TORCH dashboard subscribes to Nostr relays for kind 30078 events tagged with the #torch-agent-lock hashtag. These are the same events agents publish via bin/torch-lock.mjs when they claim tasks using the TORCH protocol.
Relays: wss://relay.damus.io, wss://nos.lol, wss://relay.primal.net
Filter: {"kinds":[30078],"#t":["torch-agent-lock"]}
Unique identifier: All events use the torch-lock/ namespace in the d-tag and the #torch-agent-lock hashtag. This scopes events to this repository and is how both agents and the dashboard filter messages.
To follow in any Nostr client, subscribe to kind 30078 with #t = torch-agent-lock on the relays above.
Quick start
# Check active locks
node bin/torch-lock.mjs check --cadence daily
# Machine-readable lock output (recommended for automation)
node bin/torch-lock.mjs check --cadence daily --json --quiet --json-file /tmp/torch-lock-check.json
# Claim a task
AGENT_PLATFORM=codex node bin/torch-lock.mjs lock --agent docs-agent --cadence daily
# List all active locks
node bin/torch-lock.mjs list
# Probe relay health before scheduler lock acquisition
node bin/torch-lock.mjs health --cadence daily
Defaults
- Kind:
30078(NIP-33 parameterized replaceable) - Expiration:
NIP-40viaexpirationtag - TTL:
7200s(2h) - Namespace:
torch - Relays:
wss://relay.damus.iowss://nos.lolwss://relay.primal.net
Environment variables
NOSTR_LOCK_NAMESPACENOSTR_LOCK_HASHTAGNOSTR_LOCK_RELAYSNOSTR_LOCK_TTLNOSTR_LOCK_QUERY_TIMEOUT_MSNOSTR_LOCK_PUBLISH_TIMEOUT_MSNOSTR_LOCK_MIN_SUCCESSFUL_PUBLISHESNOSTR_LOCK_RELAY_FALLBACKSNOSTR_LOCK_MIN_ACTIVE_RELAY_POOLNOSTR_LOCK_DAILY_ROSTERNOSTR_LOCK_WEEKLY_ROSTERTORCH_CONFIG_PATHAGENT_PLATFORM(supportscodex,claude, orlinuxfor simulated/manual execution)TORCH_MEMORY_ENABLED(true/false; global memory kill switch, defaults to enabled)TORCH_MEMORY_INGEST_ENABLED(true/falseor comma-separated canaryagent_idallow list)TORCH_MEMORY_RETRIEVAL_ENABLED(true/falseor comma-separated canaryagent_idallow list)TORCH_MEMORY_PRUNE_ENABLED(true,false, ordry-run)
torch-config.json
You can configure TORCH per repository with a root-level torch-config.json file.
Common settings:
nostrLock.namespace— namespace prefix used in d-tags and hashtags.nostrLock.relays— relay list for check/lock/list operations.nostrLock.ttlSeconds— default lock TTL.nostrLock.queryTimeoutMs— relay query timeout (ms, valid range: 100..120000).nostrLock.publishTimeoutMs— per-relay publish timeout (ms, valid range: 100..120000).nostrLock.minSuccessfulRelayPublishes— minimum successful publishes required before lock acquisition continues (default:1).nostrLock.relayFallbacks— optional fallback relay URLs used when primary query/publish attempts fail quorum.nostrLock.minActiveRelayPool— minimum number of relays kept active even when lower-ranked relays are quarantined (default:1).nostrLock.dailyRoster/nostrLock.weeklyRoster— optional per-project roster overrides.dashboard.defaultCadenceView— default dashboard view (daily,weekly,all).dashboard.defaultStatusView— default dashboard status filter (active,all).dashboard.hashtag— custom hashtag for lock events (defaults to<namespace>-agent-lock).scheduler.firstPromptByCadence.daily/.weekly— first-run scheduler starting agent.scheduler.handoffCommandByCadence.daily/.weekly— shell command run after lock acquisition; command must useSCHEDULER_AGENT,SCHEDULER_CADENCE, andSCHEDULER_PROMPT_PATHprovided byscripts/agent/run-scheduler-cycle.mjs.scheduler.paused.daily/.weekly— array of agent names to exclude from scheduler rotation.scheduler.strict_lock— lock backend policy switch (default:true); whenfalse, scheduler defers backend-unavailable lock failures before converting the run to failed.scheduler.degraded_lock_retry_window— non-strict deferral window in milliseconds; backend lock failures outside this window immediately consume failure budget and mark run failed.scheduler.max_deferrals— max number of non-strict lock deferrals allowed in-window before scheduler records a hard failure.
Default first-run daily scheduler prompt is scheduler-update-agent.
For weekly repository-fit maintenance, TORCH also includes src/prompts/weekly/repo-fit-agent.md to periodically adjust defaults and docs to the host repository.
Operational note: scheduler handoff commands are treated as required execution steps. A non-zero exit code (or missing command) is a hard failure: the scheduler writes a _failed.md task log, exits immediately, and does not publish lock:complete for that run.
Scheduler failure classes in task logs:
backend_unavailable— legacy compatibility field for lock backend unavailable failures.prompt_validation_error— legacy compatibility field for prompt/runtime validation failures.
Scheduler failure categories in task logs:
lock_backend_error— lock backend unavailable preflight failures and lock acquisition backend exit code2failures/deferrals; includes relay health alert metadata, retry window guidance, health check command, and incident runbook link.prompt_parse_error— scheduler could not read/parse the selected prompt file; prompt execution is skipped.prompt_schema_error— selected prompt file or generated run artifacts failed schema/contract checks; prompt run is treated as invalid.execution_error— runtime execution failures in handoff callbacks, memory commands, or configured validation commands.
Lock backend production defaults
Recommended baseline for production scheduler runs:
nostrLock.relays: 3+ geographically-diverse primary relays.nostrLock.relayFallbacks: 2 additional relays not present in primary list.nostrLock.queryTimeoutMs:10000nostrLock.publishTimeoutMs:8000nostrLock.minSuccessfulRelayPublishes:2nostrLock.minActiveRelayPool:2
Validation behavior:
- Relay URLs must be absolute
ws://orwss://URLs. - Invalid relay URLs or invalid timeout/count ranges are fatal startup errors.
- Lock backend errors include phase (
query:primary,query:fallback,publish:primary,publish:fallback), relay endpoint, and timeout value used. - When scheduler preflight fails before lock acquisition, task logs must explicitly state
prompt not executedto make lock-vs-prompt root cause obvious in UI/CLI summaries. - Interpret
relay_publish_quorum_failure(derived fromlock_publish_quorum_failedtelemetry) as quorum not met even after retries/fallbacks. Expected operator actions:- Run
npm run lock:health -- --cadence <daily|weekly>to confirm relay readiness and identify failing relays/reasons. - Review task log metadata (
lock_failure_reason_distribution,backend_category,lock_correlation_id) for dominant failure modes (timeouts, DNS, auth, malformed relay URL). - If failures persist past retry window, follow incident runbook
docs/agent-handoffs/learnings/2026-02-15-relay-health-preflight-job.mdand escalate relay/network remediation.
- Run
- Relay health snapshots are emitted periodically and whenever lock publish/query fails; snapshots include success rate, timeout rate, rolling latency, and quarantine state per relay.
Scheduler lock reliability reporting
Run the lock reliability summary to aggregate recent scheduler outcomes by platform, cadence, backend error category, and relay endpoint:
npm run report:lock-reliability
Outputs:
artifacts/lock-reliability/lock-reliability-summary.mdartifacts/lock-reliability/lock-reliability-summary.json
Roster precedence
The lock CLI resolves roster names in this order:
NOSTR_LOCK_DAILY_ROSTER/NOSTR_LOCK_WEEKLY_ROSTER(comma-separated env overrides).torch-config.json(nostrLock.dailyRoster/nostrLock.weeklyRoster).src/prompts/roster.json(daily/weeklycanonical scheduler roster).- Built-in fallback roster (used only if
src/prompts/roster.jsonis unreadable).
lock --agent validates names against the resolved cadence roster, and check/list report lock events whose agent names do not match scheduler roster entries exactly.
Exit codes
0: success1: usage error2: relay/network error3: lock denied (already locked or race lost)
Memory rollout plan
- Deploy memory schema changes with scheduler jobs disabled (
TORCH_MEMORY_ENABLED=falseor subsystem flags set tofalse). - Enable ingest for one canary
agent_idviaTORCH_MEMORY_INGEST_ENABLED=<agent_id>. - Validate retrieval quality and storage growth metrics before expanding scope.
- Enable broader retrieval (
TORCH_MEMORY_RETRIEVAL_ENABLED=<allow-list>thentrue). - Enable pruning in
dry-runmode first, then switch to active pruning after revalidation.
Memory rollback plan
- Disable memory flags (
TORCH_MEMORY_ENABLED=falseand/or set ingest/retrieval/prune flags tofalse). - Stop memory maintenance scheduler processes.
- Preserve database state for post-incident analysis; do not drop or rewrite memory tables during rollback.
- Keep prune actions in
dry-run(or disabled) until lifecycle policy and data integrity are revalidated.