From cbc5054b94b1061ec6eb03e6f46033a892e4abd1 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Sun, 15 Feb 2026 18:54:46 +0000 Subject: [PATCH] feat: make lock event hashtag configurable via config and env var - Added `getHashtag` function to `src/torch-config.mjs` to resolve hashtag from `NOSTR_LOCK_HASHTAG` env var, `dashboard.hashtag` config, or default to `${namespace}-agent-lock`. - Updated `src/lib.mjs` to use `getHashtag()` in `cmdLock` and `cmdComplete` for publishing events. - Updated `dashboard/index.html` to remove hardcoded `#torch-agent-lock` string and rely on dynamic configuration. - Updated `src/docs/TORCH.md` and `README.md` to document the new configuration options. - Verified changes with unit tests and frontend verification script. Co-authored-by: PR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> --- README.md | 2 ++ dashboard/index.html | 2 +- src/docs/TORCH.md | 2 ++ src/lib.mjs | 11 +++++++++-- src/torch-config.mjs | 13 +++++++++++++ 5 files changed, 27 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2f9ce91..ef505f0 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,7 @@ Configuration options: - `nostrLock.dailyRoster` / `nostrLock.weeklyRoster` (explicit rosters) - `dashboard.defaultCadenceView` (`daily`, `weekly`, or `all`) - `dashboard.defaultStatusView` (`active` or `all`) +- `dashboard.hashtag` (custom hashtag for lock events) - `scheduler.firstPromptByCadence.daily` / `.weekly` (first prompt to run) - `scheduler.paused.daily` / `.weekly` (array of agent names to pause locally) @@ -88,6 +89,7 @@ npx --no-install torch-lock dashboard --port 4173 You can override configuration using environment variables: - `NOSTR_LOCK_NAMESPACE` +- `NOSTR_LOCK_HASHTAG` - `NOSTR_LOCK_RELAYS` (comma-separated) - `NOSTR_LOCK_TTL` - `NOSTR_LOCK_QUERY_TIMEOUT_MS` diff --git a/dashboard/index.html b/dashboard/index.html index 6e28b08..cc640b9 100644 --- a/dashboard/index.html +++ b/dashboard/index.html @@ -37,7 +37,7 @@ > lock events published by AI agents working on this TORCH project. Events are kind 30078 filtered by the - #torch-agent-lock hashtag on public + ... hashtag on public Nostr relays.

diff --git a/src/docs/TORCH.md b/src/docs/TORCH.md index 6a2a362..cdfe40e 100644 --- a/src/docs/TORCH.md +++ b/src/docs/TORCH.md @@ -44,6 +44,7 @@ node bin/torch-lock.mjs health --cadence daily ## Environment variables - `NOSTR_LOCK_NAMESPACE` +- `NOSTR_LOCK_HASHTAG` - `NOSTR_LOCK_RELAYS` - `NOSTR_LOCK_TTL` - `NOSTR_LOCK_QUERY_TIMEOUT_MS` @@ -77,6 +78,7 @@ Common settings: - `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 `-agent-lock`). - `scheduler.firstPromptByCadence.daily` / `.weekly` — first-run scheduler starting agent. - `scheduler.handoffCommandByCadence.daily` / `.weekly` — shell command run after lock acquisition; command must use `SCHEDULER_AGENT`, `SCHEDULER_CADENCE`, and `SCHEDULER_PROMPT_PATH` provided by `scripts/agent/run-scheduler-cycle.mjs`. - `scheduler.paused.daily` / `.weekly` — array of agent names to exclude from scheduler rotation. diff --git a/src/lib.mjs b/src/lib.mjs index 9541615..eaf4b72 100644 --- a/src/lib.mjs +++ b/src/lib.mjs @@ -11,6 +11,7 @@ import { getRelays as _getRelays, getNamespace as _getNamespace, getTtl as _getTtl, + getHashtag as _getHashtag, } from './torch-config.mjs'; import { DEFAULT_DASHBOARD_PORT, @@ -191,6 +192,7 @@ export async function cmdLock(agent, cadence, dryRun = false, deps = {}) { const { getRelays = _getRelays, getNamespace = _getNamespace, + getHashtag = _getHashtag, getTtl = _getTtl, queryLocks = _queryLocks, getRoster = _getRoster, @@ -206,12 +208,14 @@ export async function cmdLock(agent, cadence, dryRun = false, deps = {}) { const relays = getRelays(); const namespace = getNamespace(); + const hashtag = getHashtag(); const dateStr = getDateStr(); const ttl = getTtl(); const now = nowUnix(); const expiresAt = now + ttl; error(`Locking: namespace=${namespace}, agent=${agent}, cadence=${cadence}, date=${dateStr}`); + error(`Hashtag: #${hashtag}`); error(`TTL: ${ttl}s, expires: ${new Date(expiresAt * 1000).toISOString()}`); error(`Relays: ${relays.join(', ')}`); @@ -259,7 +263,7 @@ export async function cmdLock(agent, cadence, dryRun = false, deps = {}) { created_at: now, tags: [ ['d', `${namespace}-lock/${cadence}/${agent}/${dateStr}`], - ['t', `${namespace}-agent-lock`], + ['t', hashtag], ['t', `${namespace}-lock-${cadence}`], ['t', `${namespace}-lock-${cadence}-${dateStr}`], ['expiration', String(expiresAt)], @@ -313,6 +317,7 @@ export async function cmdLock(agent, cadence, dryRun = false, deps = {}) { log(`LOCK_EVENT_ID=${event.id}`); log(`LOCK_PUBKEY=${pk}`); log(`LOCK_AGENT=${agent}`); + log(`LOCK_HASHTAG=${hashtag}`); log(`LOCK_CADENCE=${cadence}`); log(`LOCK_DATE=${dateStr}`); log(`LOCK_EXPIRES=${expiresAt}`); @@ -419,6 +424,7 @@ export async function cmdComplete(agent, cadence, dryRun = false, deps = {}) { const { getRelays = _getRelays, getNamespace = _getNamespace, + getHashtag = _getHashtag, queryLocks = _queryLocks, publishLock = _publishLock, generateSecretKey = _generateSecretKey, @@ -431,6 +437,7 @@ export async function cmdComplete(agent, cadence, dryRun = false, deps = {}) { const relays = getRelays(); const namespace = getNamespace(); + const hashtag = getHashtag(); const dateStr = getDateStr(); const now = nowUnix(); @@ -466,7 +473,7 @@ export async function cmdComplete(agent, cadence, dryRun = false, deps = {}) { created_at: now, tags: [ ['d', `${namespace}-lock/${cadence}/${agent}/${dateStr}`], - ['t', `${namespace}-agent-lock`], + ['t', hashtag], ['t', `${namespace}-lock-${cadence}`], ['t', `${namespace}-lock-${cadence}-${dateStr}`], // No expiration tag -> permanent diff --git a/src/torch-config.mjs b/src/torch-config.mjs index cd8204e..b7ea2bc 100644 --- a/src/torch-config.mjs +++ b/src/torch-config.mjs @@ -282,3 +282,16 @@ export function getMinActiveRelayPool() { assertPositiveCount(value, 'effective min active relay pool'); return value; } + +export function getHashtag() { + const config = loadTorchConfig(); + const envValue = process.env.NOSTR_LOCK_HASHTAG; + if (envValue) { + return envValue.trim(); + } + if (config.dashboard.hashtag) { + return config.dashboard.hashtag; + } + const namespace = getNamespace(); + return `${namespace}-agent-lock`; +}