PUBLIC MODULE · lib/jobs.js

Jobs

Portable, folder-only project Jobs. ai-jobs enables, ai-jobs-disabled disables. Operations are best effort: there are no locks, daemon identity records, or cross-process coordination. Concurrent scans/mutations may duplicate work, lose updates, or race archives. Atomic single-file replacement remains used.

class Jobs class

Frozen static namespace for folder-only Jobs operations.

taskFilename(value) function

File selectors are leaf Markdown names, not task IDs or paths. IDs remain opaque parser values.

Defined in lib/jobs/operations.js

async validateJobsLayout(root) function

Refuse missing/redirected durable directories; this query never repairs layout.

Defined in lib/jobs/operations.js

async validateJobsOperational(root, options = {…}) function

Operational eligibility is checked at publication and invocation from folder state.

Defined in lib/jobs/operations.js

async readTaskEntries(root) function

Pure filesystem snapshot: no admission, error reporting, state writes, or symlink following.

Defined in lib/jobs/operations.js

async scheduleJobs(root, command, options = {…}) function

Shared task command boundary. Throws actionable JobsError or filesystem errors; never runs tasks. Create refuses existing files; update replaces whole source (last writer wins); remove does not cancel. Calls validate the current folder before operating. Concurrent mutations are best effort: atomic create refuses an existing file and updates may be last-writer-wins.

Defined in lib/jobs/operations.js

async jobsStatus(projectRoot, options = {…}) function

Read-only status projection. It never creates folders, starts daemons, or coordinates processes.

Defined in lib/jobs/status.js

normalizeDays(value, code = "JOBS_TASK_SCHEDULE") function

Normalize aliases or unique lowercase named arrays; omitted input means all days.

Defined in lib/jobs/days.js

class JobsError extends Error class

Coded jobs-domain error shared by validation, scheduling and execution.

Defined in lib/jobs/errors-base.js

constructor(code, message, details = {…}) constructor

Construct a coded domain failure; details are caller diagnostics, not safe-to-log source.

JOBS_DATA_DIRECTORY = "ai-jobs" constant

Active portable Jobs directory name.

Defined in lib/jobs/paths.js

JOBS_DISABLED_DIRECTORY = "ai-jobs-disabled" constant

Disabled portable Jobs directory name.

Defined in lib/jobs/paths.js

JOBS_PATH_NAMES = Object.freeze({ tasks: "tasks", completed: "completed", state: "state… constant

Names inside the portable Jobs directory.

Defined in lib/jobs/paths.js

jobsPaths(projectRoot) function

Return absolute paths derived from the caller's active project root.

Defined in lib/jobs/paths.js

async canonicalProjectRoot(projectRoot, io = {…}) function

Canonical paths are process-local inputs, never Jobs data.

Defined in lib/jobs/project.js

parseTask(filename, source) function

Parse one task without filesystem side effects; declared bad frontmatter rejects the task.

Defined in lib/jobs/tasks.js

parseTasks(tasks) function

Parse independently so duplicate ids and empty prompts remain task-local rejections.

Defined in lib/jobs/tasks.js

taskId(filename) function

Validate and return a nonempty filename-derived default task ID.

Defined in lib/jobs/tasks.js

taskStateKey(id) function

Map opaque IDs to bounded safe ledger filenames; unsafe IDs use a stable hash.

Defined in lib/jobs/tasks.js

async loadTasks(projectRoot, entries, io) function

Parse entries purely, then durably report only all-or-nothing frontmatter fallbacks.

Defined in lib/jobs/errors.js

async reportTaskDiagnostic(projectRoot, diagnostic, io = {…}) function

Atomically record one frontmatter fallback without retaining source text, metadata names, values, or filenames. Repeated reports overwrite one stable hash-named record for the same task and failure class.

Defined in lib/jobs/errors.js

taskDiagnosticKey(diagnostic) function

Stable SHA-256 key for a filename/failure code; contains no source text.

Defined in lib/jobs/errors.js

JOBS_STATE_VERSION = 2 constant

Persisted occurrence schema version; unsupported versions are refused.

Defined in lib/jobs/state.js

createTaskState(task) function

Create the durable, task-local occurrence ledger.

Defined in lib/jobs/state.js

statePath(projectRoot, taskId) function

Resolve a task ledger path through the domain-owned safe ID mapping.

Defined in lib/jobs/state.js

validateTaskState(value, taskId) function

Validate the complete persisted v2 schema before it is used for admission.

Defined in lib/jobs/state.js

validateArchiveReference(value) function

A durable archive location is portable project-local data, never a host path.

Defined in lib/jobs/state.js

resolveArchiveReference(projectRoot, reference) function

Resolve only a previously validated relative reference against this active Jobs root.

Defined in lib/jobs/state.js

async loadTaskState(projectRoot, task, io = fs) function

Read and validate a ledger, or return a fresh state when absent; does not persist.

Defined in lib/jobs/state.js

async saveTaskState(projectRoot, state, io = fs) function

Atomic replace of one task ledger; callers own cross-file reconciliation.

Defined in lib/jobs/state.js

admitOccurrence(state, task, now) function

Admit one execution per scan, coalescing earlier eligible and excluded history.

Defined in lib/jobs/state.js

recordAttempt(state, occurrenceId, attempt) function

Persist a new attempt before any irreversible source move.

Defined in lib/jobs/state.js

reconcileAttempt(state, occurrenceId, attemptId, archivePresent) function

Reconciliation is visible: an interrupted archive is consumed, never due again.

Defined in lib/jobs/state.js

finalizeAttempt(state, occurrenceId, attemptId, outcome, archivePresent, session = null) function

Finalize the current attempt in the same dispatch cycle, without crash reconciliation.

Defined in lib/jobs/state.js

async loadAllTaskStates(projectRoot, io = fs) function

Read all ledgers, including removed one-shots, for crash reconciliation.

Defined in lib/jobs/state.js

newAttemptId(occurrence, sequence = occurrence.attempts.length) function

Derive an occurrence-local attempt ID; callers persist it before archival.

Defined in lib/jobs/state.js

async allocateArchive(projectRoot, localDate, sourceFilename, io = fs) function

Allocate an unused date-local archival name. The integer field has no 999 cap.

Defined in lib/jobs/archive.js

async moveToArchive(source, archive, io = fs) function

Atomically claim destination without overwrite, then remove source hardlink.

Defined in lib/jobs/archive.js

async snapshotAndArchive(source, archive, io = fs) function

Snapshot source bytes before move. Execution must consume snapshot, not disk.

Defined in lib/jobs/archive.js

async archiveExists(path, io = fs) function

Check archive presence; absence returns false, other I/O failures throw JobsError.

Defined in lib/jobs/archive.js

async ensureJobsLayout(projectRoot, io = fs) function

Ensure the standard active layout. Call only from explicit initialization.

Defined in lib/jobs/lifecycle.js

async initializeJobs(projectRoot, settings = {…}, options = {…}) function

Enable folder-only Jobs, restoring a disabled directory without changing bytes.

Defined in lib/jobs/lifecycle.js

async validateJobsActivation(projectRoot, settings = {…}, options = {…}) function

Validate active folder state without writing or coordinating with other processes.

Defined in lib/jobs/lifecycle.js

async disableJobs(projectRoot, options = {…}) function

Disable by renaming the active directory. Concurrent work is best effort.

Defined in lib/jobs/lifecycle.js

cycleRecord(at) function

Create the location-neutral public result record for one Jobs scan.

Defined in lib/jobs/dispatcher.js

async dispatchJobs(projectRoot, options = {…}) function

Best-effort serial scan. Concurrent scans may duplicate execution or lose state updates.

Defined in lib/jobs/dispatcher.js

async runJobAgent(task, options = {…}) function

One fresh, headless Agent run against a SHARED per-wake Env. Cancellation is deliberate (the caller's AbortSignal); any request/tool timeout remains Agent/IO policy, never a Jobs schedule watchdog. The caller owns the Env and its teardown; factories are trusted embedding/test boundaries. Retries, context limits, tool timeouts and transcript writes remain Agent/IO-owned.

Defined in lib/jobs/agent-execution.js

async foregroundJobsDaemon(projectRoot, options = {…}) function

Run a foreground, cwd-bound best-effort daemon. No daemon identity or control record is persisted; multiple foreground daemons may run concurrently.

Defined in lib/jobs/daemon.js