mirror of
https://github.com/PR0M3TH3AN/TORCH.git
synced 2026-11-06 12:51:54 +00:00
chore(ai): document src/lib.mjs
- Added JSDoc to all exported functions in src/lib.mjs - Added detailed flow comments for cmdLock and cmdComplete - Created docs/lib-overview.md with high-level architectural documentation - Created src/context/CONTEXT_2026-02-14T21-30-00Z.md - Updated task-logs/daily/ with completion record Co-authored-by: PR0M3TH3AN <[email protected]>
This commit is contained in:
1 parent
556e480926
commit
426b3221b5
4 files changed
+157
No files matched your search
@@ -0,0 +1,58 @@
|
|||||||
|
# src/lib.mjs: Core Logic Overview
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
`src/lib.mjs` is the orchestration engine for Torch. It implements the high-level commands (`check`, `lock`, `list`, `complete`) that coordinate between local configuration, the file system (task logs), and Nostr relays (distributed locks).
|
||||||
|
|
||||||
|
It is designed to be:
|
||||||
|
- **Stateless**: No persistent local database; relies on Nostr events and flat files.
|
||||||
|
- **Race-Condition Safe**: Uses a commit-wait-reveal pattern to handle concurrent agent starts.
|
||||||
|
- **Dependency Injected**: Nearly all external side-effects (relays, time, FS) can be mocked.
|
||||||
|
|
||||||
|
## Public API
|
||||||
|
|
||||||
|
### `cmdCheck(cadence, deps)`
|
||||||
|
Aggregates the current state of the world for a given cadence.
|
||||||
|
- **Inputs**: Cadence ('daily'/'weekly').
|
||||||
|
- **Outputs**: JSON object with lists of `locked`, `completed`, `paused`, and `available` agents.
|
||||||
|
- **Side Effects**: Queries relays, reads `task-logs/`, reads `torch-config.json`.
|
||||||
|
|
||||||
|
### `cmdLock(agent, cadence, dryRun, deps)`
|
||||||
|
Attempts to claim a task.
|
||||||
|
- **Returns**: `{ status: 'ok', eventId: '...' }`
|
||||||
|
- **Throws**: `ExitError(3)` if the lock is denied (already active, completed, or race lost).
|
||||||
|
|
||||||
|
### `cmdComplete(agent, cadence, dryRun, deps)`
|
||||||
|
Finalizes a task.
|
||||||
|
- **Action**: Publishes a permanent event (no expiration) with `status: 'completed'`.
|
||||||
|
- **Constraint**: Requires an existing active lock for the agent.
|
||||||
|
|
||||||
|
### `cmdList(cadence, deps)`
|
||||||
|
Displays a CLI-friendly table of active locks.
|
||||||
|
|
||||||
|
## Locking Flow (Sequence)
|
||||||
|
|
||||||
|
1. **Check**: Query relays for any existing valid lock for `(agent, cadence, date)`.
|
||||||
|
- If found and `status=completed`: **Abort** (Task done).
|
||||||
|
- If found and `status=started` (and not expired): **Abort** (Agent busy).
|
||||||
|
2. **Generate**: Create a new ephemeral Nostr keypair.
|
||||||
|
3. **Build**: Create a signed event (Kind 30078) with:
|
||||||
|
- Tags: `d` (identifier), `expiration`, `t` (search tags).
|
||||||
|
- Content: JSON payload with metadata.
|
||||||
|
4. **Publish**: Send to all configured relays.
|
||||||
|
5. **Race Check**:
|
||||||
|
- Wait `RACE_CHECK_DELAY_MS` (default 2000ms).
|
||||||
|
- Query relays again.
|
||||||
|
- If another valid event exists with an *earlier* `created_at`: **Abort** (Race lost).
|
||||||
|
- Otherwise: **Success**.
|
||||||
|
|
||||||
|
## Key Invariants
|
||||||
|
|
||||||
|
- **Uniqueness**: Only one valid lock per (agent, cadence, date) should exist at a time.
|
||||||
|
- **Expiration**: All locks must have an `expiration` tag (NIP-40) to prevent zombies, except completion events.
|
||||||
|
- **Completion**: A completion event is permanent (no expiration) and effectively "freezes" the slot for that date.
|
||||||
|
|
||||||
|
## When to Change
|
||||||
|
|
||||||
|
- **Protocol Upgrades**: If changing the Nostr event structure or tags.
|
||||||
|
- **Concurrency Tuning**: Adjusting `RACE_CHECK_DELAY_MS` or retry logic.
|
||||||
|
- **New Commands**: Adding new lifecycle states (e.g., `failed` or `paused` via CLI).
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# Context: 2026-02-14T21:30:00Z - docs-code-investigator
|
||||||
|
|
||||||
|
## Plan
|
||||||
|
1. **Target**: `src/lib.mjs` (Core logic, ~700 LOC).
|
||||||
|
2. **Goal**: Add JSDoc and flow comments to clarify locking, checking, and completion logic.
|
||||||
|
3. **Rationale**: This file orchestrates the entire Torch system but lacks detailed documentation for its exported functions.
|
||||||
|
4. **Artifacts**:
|
||||||
|
* Inline JSDoc in `src/lib.mjs`.
|
||||||
|
* `docs/lib-overview.md` for high-level documentation.
|
||||||
+75
@@ -40,6 +40,15 @@ useWebSocketImplementation(WebSocket);
|
|||||||
// Re-export for backward compatibility/library usage
|
// Re-export for backward compatibility/library usage
|
||||||
export { parseLockEvent, cmdDashboard, _queryLocks as queryLocks, _publishLock as publishLock };
|
export { parseLockEvent, cmdDashboard, _queryLocks as queryLocks, _publishLock as publishLock };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scans the local log directory to identify agents that have already completed their task
|
||||||
|
* for the current period (daily or weekly).
|
||||||
|
*
|
||||||
|
* @param {string} cadence - 'daily' or 'weekly'
|
||||||
|
* @param {string} logDir - Path to the log directory (e.g., 'task-logs')
|
||||||
|
* @param {Object} deps - Dependency injection for testing
|
||||||
|
* @returns {Promise<Set<string>>} - Set of agent names that have completed their task
|
||||||
|
*/
|
||||||
async function getCompletedAgents(cadence, logDir, deps) {
|
async function getCompletedAgents(cadence, logDir, deps) {
|
||||||
const { readdir = fs.readdir, getDateStr = todayDateStr, getIsoWeek = getIsoWeekStr } = deps;
|
const { readdir = fs.readdir, getDateStr = todayDateStr, getIsoWeek = getIsoWeekStr } = deps;
|
||||||
const completed = new Set();
|
const completed = new Set();
|
||||||
@@ -77,6 +86,20 @@ async function getCompletedAgents(cadence, logDir, deps) {
|
|||||||
return completed;
|
return completed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks the status of the repository locks for a given cadence.
|
||||||
|
*
|
||||||
|
* It aggregates data from three sources:
|
||||||
|
* 1. Configuration (paused agents)
|
||||||
|
* 2. Local logs (completed agents)
|
||||||
|
* 3. Nostr relays (current active locks)
|
||||||
|
*
|
||||||
|
* It outputs a JSON object describing the state (locked, available, excluded agents).
|
||||||
|
*
|
||||||
|
* @param {string} cadence - 'daily' or 'weekly'
|
||||||
|
* @param {Object} [deps] - Dependency injection
|
||||||
|
* @returns {Promise<Object>} - The check result object
|
||||||
|
*/
|
||||||
export async function cmdCheck(cadence, deps = {}) {
|
export async function cmdCheck(cadence, deps = {}) {
|
||||||
const {
|
const {
|
||||||
getRelays = _getRelays,
|
getRelays = _getRelays,
|
||||||
@@ -145,6 +168,23 @@ export async function cmdCheck(cadence, deps = {}) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to acquire an exclusive lock for an agent on the specified cadence.
|
||||||
|
*
|
||||||
|
* Algorithm:
|
||||||
|
* 1. Validate agent against the roster.
|
||||||
|
* 2. Query relays for existing valid locks (checking for conflicts).
|
||||||
|
* 3. Generate a new ephemeral keypair and build a lock event (kind 30078).
|
||||||
|
* 4. Publish the lock event to relays.
|
||||||
|
* 5. Wait for propagation (raceCheckDelayMs) and re-query to confirm no earlier lock won the race.
|
||||||
|
*
|
||||||
|
* @param {string} agent - Agent name
|
||||||
|
* @param {string} cadence - 'daily' or 'weekly'
|
||||||
|
* @param {boolean} [dryRun=false] - If true, skips publishing
|
||||||
|
* @param {Object} [deps] - Dependency injection
|
||||||
|
* @returns {Promise<{status: string, eventId: string}>}
|
||||||
|
* @throws {ExitError} If lock is denied (already locked, completed, or race lost)
|
||||||
|
*/
|
||||||
export async function cmdLock(agent, cadence, dryRun = false, deps = {}) {
|
export async function cmdLock(agent, cadence, dryRun = false, deps = {}) {
|
||||||
const {
|
const {
|
||||||
getRelays = _getRelays,
|
getRelays = _getRelays,
|
||||||
@@ -278,6 +318,14 @@ export async function cmdLock(agent, cadence, dryRun = false, deps = {}) {
|
|||||||
return { status: 'ok', eventId: event.id };
|
return { status: 'ok', eventId: event.id };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lists all active locks for the specified cadence (or all cadences if null).
|
||||||
|
* It prints a formatted table to stdout with lock age, TTL, and event ID.
|
||||||
|
*
|
||||||
|
* @param {string|null} cadence - Filter by cadence ('daily', 'weekly') or null for all
|
||||||
|
* @param {Object} [deps] - Dependency injection
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
export async function cmdList(cadence, deps = {}) {
|
export async function cmdList(cadence, deps = {}) {
|
||||||
const {
|
const {
|
||||||
getRelays = _getRelays,
|
getRelays = _getRelays,
|
||||||
@@ -350,6 +398,21 @@ export async function cmdList(cadence, deps = {}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks a task as permanently completed by publishing a new lock event with
|
||||||
|
* `status: 'completed'` and no expiration.
|
||||||
|
*
|
||||||
|
* This function:
|
||||||
|
* 1. Verifies that the agent currently holds a valid lock.
|
||||||
|
* 2. Publishes a replacement event that preserves the original `startedAt` time.
|
||||||
|
*
|
||||||
|
* @param {string} agent - Agent name
|
||||||
|
* @param {string} cadence - 'daily' or 'weekly'
|
||||||
|
* @param {boolean} [dryRun=false] - If true, skips publishing
|
||||||
|
* @param {Object} [deps] - Dependency injection
|
||||||
|
* @returns {Promise<{status: string, eventId: string}>}
|
||||||
|
* @throws {ExitError} If no active lock exists for the agent
|
||||||
|
*/
|
||||||
export async function cmdComplete(agent, cadence, dryRun = false, deps = {}) {
|
export async function cmdComplete(agent, cadence, dryRun = false, deps = {}) {
|
||||||
const {
|
const {
|
||||||
getRelays = _getRelays,
|
getRelays = _getRelays,
|
||||||
@@ -440,6 +503,12 @@ export async function cmdComplete(agent, cadence, dryRun = false, deps = {}) {
|
|||||||
return { status: 'completed', eventId: event.id };
|
return { status: 'completed', eventId: event.id };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses command-line arguments into a structured object.
|
||||||
|
*
|
||||||
|
* @param {string[]} argv - Arguments from process.argv.slice(2)
|
||||||
|
* @returns {Object} - Parsed arguments (command, flags, values)
|
||||||
|
*/
|
||||||
function parseArgs(argv) {
|
function parseArgs(argv) {
|
||||||
const args = {
|
const args = {
|
||||||
command: null,
|
command: null,
|
||||||
@@ -568,6 +637,12 @@ Exit codes:
|
|||||||
3 Lock denied (already locked or race lost)`);
|
3 Lock denied (already locked or race lost)`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main entry point for the torch-lock CLI.
|
||||||
|
* Dispatches to specific commands (check, lock, complete, etc.) based on argv.
|
||||||
|
*
|
||||||
|
* @param {string[]} argv - Arguments from process.argv.slice(2)
|
||||||
|
*/
|
||||||
export async function main(argv) {
|
export async function main(argv) {
|
||||||
try {
|
try {
|
||||||
const args = parseArgs(argv);
|
const args = parseArgs(argv);
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
---
|
||||||
|
agent: docs-code-investigator
|
||||||
|
status: completed
|
||||||
|
created_at: 2026-02-14T21:30:00Z
|
||||||
|
---
|
||||||
|
# docs-code-investigator (daily) - 2026-02-14
|
||||||
|
|
||||||
|
## Task
|
||||||
|
Document `src/lib.mjs`.
|
||||||
|
|
||||||
|
## Outcome
|
||||||
|
- Added JSDoc for exported functions (`cmdCheck`, `cmdLock`, `cmdList`, `cmdComplete`).
|
||||||
|
- Added flow comments for complex logic (`cmdLock`, `cmdComplete`).
|
||||||
|
- Created `docs/lib-overview.md`.
|
||||||
|
- Verified with `npm test` and `npm run lint`.
|
||||||
Reference in new issue
Block a user