Backlog Manager

Backlog Manager is a small file-oriented utility layer for reading, updating, and persisting task lists stored as .backlog files together with their associated .history files. In the current repository, it should be understood as a persistence helper for structured task tracking rather than as a skill subsystem or a separate agent runtime.

Structured Task Files

The component exists because some coordination problems are easier to manage as explicit task artefacts than as volatile conversational state. A backlog file provides a durable list of pending tasks, while the corresponding history file records tasks that have already been completed. This separation is simple, but it creates a stable external memory surface that other tools or workflows can inspect without relying on the internal memory of an agent session.

The storage model is narrower than the previous page suggested. The component does not implement a generic task-management subsystem with arbitrary status models. It works with a concrete task shape containing description, options, and resolution. Pending tasks live in the .backlog file. Completed tasks are moved into the paired .history file. The runtime therefore supports explicit task evolution, but inside a small fixed data model rather than inside a broader workflow engine.

project-specs.backlog
project-specs.history

Operational API

The exported API in BacklogManager/BacklogManager.mjs focuses on a narrow set of file-level operations. loadBacklog() returns the current tasks, the stored history, and basic file metadata when available. createBacklog() initializes a new empty backlog-history pair. getTask(), updateTask(), addTask(), and addTasksFromText() operate on the pending task list. approveTask() sets a resolution and clears any remaining options. addOptionsFromText() parses numbered text into candidate options for an existing task. markDone() moves a task from the active backlog into the history file, carrying forward a resolution or using the default text Executed. when no explicit resolution exists.

The text parsing path is also deliberately limited. Numbered lines such as 1. or 1) are treated as separate option entries or separate tasks, and indented or subsequent non-empty lines are appended as detail text to the current item. This means the component supports compact human-authored backlog updates, but it does not attempt to interpret arbitrary prose or infer a broader planning structure.

Note

Task indices are one-based at the public API level. Internally, the manager converts them to zero-based array positions before reading or updating the task list.

Persistence Model

The persistence logic lives in BacklogManager/backlogIO.mjs. Files are normalized so that the active file always ends in .backlog and the paired history path always ends in .history. Loaded backlog entries are cached in memory inside a process-local save queue. Subsequent updates modify that cached entry and mark it as dirty rather than writing immediately to disk. A timed save loop then flushes modified entries at a bounded interval, which defaults to five seconds.

This design is important for understanding the operational behavior of the module. A call such as saveBacklogFile() updates the in-memory cache and marks the entry as modified, but it does not necessarily write to disk immediately. When an immediate write is needed, forceSave() or the higher-level flush() function performs an explicit flush of the modified entry. The component therefore trades strict write-through persistence for a simpler buffered save model.

The same module also normalizes task and history records on load and on save. Missing fields are coerced into the expected shape, non-string options are stringified, and missing files are treated as empty structures. This keeps the persisted shape stable even when the input data is incomplete or loosely typed.

Supporting Domain Helper

The file BacklogManager/backlogDomain.mjs currently exposes a single helper, ChangeQueue. It is a minimal in-memory queue for collecting task-reference changes, sorting them deterministically by task reference, draining them, and clearing the queue. In the current implementation it is a small supporting utility rather than a full domain layer.