diff --git a/src/constants.mjs b/src/constants.mjs index 8e5a653..05748e2 100644 --- a/src/constants.mjs +++ b/src/constants.mjs @@ -21,6 +21,7 @@ export const DEFAULT_MAX_QUARANTINE_COOLDOWN_MS = 300_000; export const DEFAULT_SNAPSHOT_INTERVAL_MS = 60_000; export const VALID_CADENCES = new Set(['daily', 'weekly']); export const KIND_APP_DATA = 30078; +export const MS_PER_SECOND = 1000; export const USAGE_TEXT = `Usage: torch-lock [options] diff --git a/src/context/CONTEXT_2026-02-19T21-26-08Z.md b/src/context/CONTEXT_2026-02-19T21-26-08Z.md new file mode 100644 index 0000000..0a37d2c --- /dev/null +++ b/src/context/CONTEXT_2026-02-19T21-26-08Z.md @@ -0,0 +1,5 @@ +# Context for Constant Refactor + +- **Goal:** Find and refactor duplicated numeric constants. +- **Scope:** `src/` directory. +- **Constraints:** Keep changes minimal and safe. diff --git a/src/decisions/DECISIONS_2026-02-19T21-26-08Z.md b/src/decisions/DECISIONS_2026-02-19T21-26-08Z.md new file mode 100644 index 0000000..a0f60e2 --- /dev/null +++ b/src/decisions/DECISIONS_2026-02-19T21-26-08Z.md @@ -0,0 +1,12 @@ +# 2026-02-19T21-26-08Z: Extracted MS_PER_SECOND + +## Decision +Extracted `1000` (milliseconds per second) to `MS_PER_SECOND` constant in `src/constants.mjs`. + +## Rationale +- Multiple files (`src/relay-health.mjs`, `src/utils.mjs`, `src/lib.mjs`, `src/lock-ops.mjs`) were using the literal `1000` for time conversion. +- Using a named constant improves readability and maintainability. +- Reduces risk of "magic number" confusion. + +## Alternatives Considered +- Leaving as literal (rejected: hard to search/replace if logic changes, less semantic). diff --git a/src/lib.mjs b/src/lib.mjs index 1330522..08eb265 100644 --- a/src/lib.mjs +++ b/src/lib.mjs @@ -18,6 +18,7 @@ import { KIND_APP_DATA, RACE_CHECK_DELAY_MS, USAGE_TEXT, + MS_PER_SECOND, } from './constants.mjs'; import { cmdInit, cmdUpdate } from './ops.mjs'; import { parseArgs } from './cli-parser.mjs'; @@ -215,7 +216,7 @@ export async function cmdLock(agent, cadence, optionsOrDryRun = false, deps = {} error(`Locking: namespace=${namespace}, agent=${agent}, cadence=${cadence}, date=${dateStr}`); error(`Hashtag: #${hashtag}`); - error(`TTL: ${ttl}s, expires: ${new Date(expiresAt * 1000).toISOString()}`); + error(`TTL: ${ttl}s, expires: ${new Date(expiresAt * MS_PER_SECOND).toISOString()}`); error(`Relays: ${relays.join(', ')}`); if (gitCommit) error(`Git Commit: ${gitCommit}`); if (promptHash) error(`Prompt Hash: ${promptHash.slice(0, 12)}...`); @@ -277,8 +278,8 @@ export async function cmdLock(agent, cadence, optionsOrDryRun = false, deps = {} date: dateStr, platform: platform || process.env.AGENT_PLATFORM || detectPlatform() || 'unknown', model: model || process.env.AGENT_MODEL || 'unknown', - lockedAt: new Date(now * 1000).toISOString(), - expiresAt: new Date(expiresAt * 1000).toISOString(), + lockedAt: new Date(now * MS_PER_SECOND).toISOString(), + expiresAt: new Date(expiresAt * MS_PER_SECOND).toISOString(), gitCommit, promptPath, promptHash, @@ -326,7 +327,7 @@ export async function cmdLock(agent, cadence, optionsOrDryRun = false, deps = {} log(`LOCK_CADENCE=${cadence}`); log(`LOCK_DATE=${dateStr}`); log(`LOCK_EXPIRES=${expiresAt}`); - log(`LOCK_EXPIRES_ISO=${new Date(expiresAt * 1000).toISOString()}`); + log(`LOCK_EXPIRES_ISO=${new Date(expiresAt * MS_PER_SECOND).toISOString()}`); if (gitCommit) log(`LOCK_GIT_COMMIT=${gitCommit}`); if (promptHash) log(`LOCK_PROMPT_HASH=${promptHash}`); return { status: 'ok', eventId: event.id }; @@ -497,7 +498,7 @@ export async function cmdComplete(agent, cadence, optionsOrDryRun = false, deps platform: platform || process.env.AGENT_PLATFORM || detectPlatform() || 'unknown', model: model || process.env.AGENT_MODEL || 'unknown', startedAt: startedAtIso, - completedAt: new Date(now * 1000).toISOString(), + completedAt: new Date(now * MS_PER_SECOND).toISOString(), }), }, sk, diff --git a/src/lock-ops.mjs b/src/lock-ops.mjs index 8b1830a..4408b5f 100644 --- a/src/lock-ops.mjs +++ b/src/lock-ops.mjs @@ -14,6 +14,7 @@ import { DEFAULT_QUARANTINE_COOLDOWN_MS, DEFAULT_MAX_QUARANTINE_COOLDOWN_MS, DEFAULT_SNAPSHOT_INTERVAL_MS, + MS_PER_SECOND, } from './constants.mjs'; import { nowUnix } from './utils.mjs'; @@ -43,9 +44,9 @@ export function parseLockEvent(event) { eventId: event.id, pubkey: event.pubkey, createdAt: event.created_at, - createdAtIso: new Date(event.created_at * 1000).toISOString(), + createdAtIso: new Date(event.created_at * MS_PER_SECOND).toISOString(), expiresAt, - expiresAtIso: expiresAt ? new Date(expiresAt * 1000).toISOString() : null, + expiresAtIso: expiresAt ? new Date(expiresAt * MS_PER_SECOND).toISOString() : null, dTag, agent: content.agent ?? null, cadence: content.cadence ?? null, diff --git a/src/relay-health.mjs b/src/relay-health.mjs index 0c0a824..d1d8800 100644 --- a/src/relay-health.mjs +++ b/src/relay-health.mjs @@ -3,6 +3,7 @@ import path from 'node:path'; import WebSocket from 'ws'; import { finalizeEvent, generateSecretKey, getPublicKey } from 'nostr-tools/pure'; import { getNamespace, getRelays } from './torch-config.mjs'; +import { MS_PER_SECOND } from './constants.mjs'; const PROBE_KIND = 27235; @@ -97,7 +98,7 @@ async function probePublishRead(relayUrl, namespace, timeoutMs) { const ws = new WebSocket(relayUrl); const sk = generateSecretKey(); const pk = getPublicKey(sk); - const createdAt = Math.floor(Date.now() / 1000); + const createdAt = Math.floor(Date.now() / MS_PER_SECOND); const nonce = `${Date.now()}-${Math.random().toString(16).slice(2, 10)}`; const probeTag = `${namespace}-health-probe-${nonce}`; const event = finalizeEvent({ diff --git a/src/test_logs/TEST_LOG_2026-02-19T21-26-08Z.md b/src/test_logs/TEST_LOG_2026-02-19T21-26-08Z.md new file mode 100644 index 0000000..e7a194f --- /dev/null +++ b/src/test_logs/TEST_LOG_2026-02-19T21-26-08Z.md @@ -0,0 +1,8 @@ +- Command: npm run lint +- Result: Passed + +- Command: npm run validate:scheduler-failure-schema +- Result: Passed + +- Command: npm test +- Result: Passed diff --git a/src/todo/TODO_2026-02-19T21-26-08Z.md b/src/todo/TODO_2026-02-19T21-26-08Z.md new file mode 100644 index 0000000..5d6cd63 --- /dev/null +++ b/src/todo/TODO_2026-02-19T21-26-08Z.md @@ -0,0 +1,7 @@ +# Pending + +- Identify more duplicated constants (e.g. `5000` for timeouts). + +# Completed + +- Refactored `1000` to `MS_PER_SECOND`. diff --git a/src/utils.mjs b/src/utils.mjs index 3c198fd..06de496 100644 --- a/src/utils.mjs +++ b/src/utils.mjs @@ -1,11 +1,12 @@ import fs from 'node:fs'; +import { MS_PER_SECOND } from './constants.mjs'; export function todayDateStr() { return new Date().toISOString().slice(0, 10); } export function nowUnix() { - return Math.floor(Date.now() / 1000); + return Math.floor(Date.now() / MS_PER_SECOND); } export function getIsoWeekStr(dateInput) { diff --git a/task-logs/daily/2026-02-19T21-26-08Z__const-refactor-agent__completed.md b/task-logs/daily/2026-02-19T21-26-08Z__const-refactor-agent__completed.md new file mode 100644 index 0000000..1aec8e7 --- /dev/null +++ b/task-logs/daily/2026-02-19T21-26-08Z__const-refactor-agent__completed.md @@ -0,0 +1,7 @@ +--- +agent: const-refactor-agent +status: completed +date: 2026-02-19 +timestamp: 2026-02-19T21-26-08Z +--- +Refactored `1000` to `MS_PER_SECOND` in `src/constants.mjs` and usage sites. diff --git a/test/scheduler-lock-failure-schema.contract.test.mjs b/test/scheduler-lock-failure-schema.contract.test.mjs index 5a955d9..27b3868 100644 --- a/test/scheduler-lock-failure-schema.contract.test.mjs +++ b/test/scheduler-lock-failure-schema.contract.test.mjs @@ -96,6 +96,7 @@ async function setupFixture({ lockShellBody }) { await fs.copyFile(path.resolve('scripts/agent/scheduler-utils.mjs'), path.join(scriptsDir, 'scheduler-utils.mjs')); await fs.copyFile(path.resolve('scripts/agent/scheduler-lock.mjs'), path.join(scriptsDir, 'scheduler-lock.mjs')); await fs.copyFile(path.resolve('src/utils.mjs'), path.join(root, 'src', 'utils.mjs')); + await fs.copyFile(path.resolve('src/constants.mjs'), path.join(root, 'src', 'constants.mjs')); await fs.writeFile(path.join(scriptsDir, 'verify-run-artifacts.mjs'), '#!/usr/bin/env node\nprocess.exit(0);\n', 'utf8'); await fs.writeFile(path.join(root, 'src', 'prompts', 'roster.json'), JSON.stringify({ daily: ['agent-a'] }, null, 2), 'utf8'); await fs.writeFile(path.join(root, 'src', 'prompts', 'daily', 'agent-a.md'), '# agent-a\n', 'utf8');