This commit is contained in:
thePR0M3TH3AN committed 2026-02-19 22:22:45 -05:00
1 parent 1a534fc746
commit 5783f995d7
10 files changed
+436 -6

No files matched your search

+20
View File
@@ -16,6 +16,26 @@ Track only **active, reproducible, unresolved** issues.
## Active issues
### `test/scheduler-preflight-lock.e2e.test.mjs` fails in Codex due platform mismatch (`unknown` vs `codex`)
- **Status:** Active
- **Area:** Test
- **Symptom:** `npm test` fails in `test/scheduler-preflight-lock.e2e.test.mjs` first case, expecting frontmatter platform `unknown` but run log writes `codex`.
- **Trigger/Conditions:** Running full test suite in Codex environment where scheduler log frontmatter includes `platform: codex`.
- **Workaround:** Run targeted tests excluding `test/scheduler-preflight-lock.e2e.test.mjs` until assertion baseline is clarified for Codex.
- **Impact:** Medium — blocks `npm test` from passing in this environment.
- **Related notes:** `docs/agent-handoffs/incidents/2026-02-20-codex-test-failures-platform-and-telemetry.md`
- **Last verified:** 2026-02-20
### `test/memory-telemetry.test.mjs` expects child-process stdout/stderr that are empty in this environment
- **Status:** Active
- **Area:** Test / Tooling
- **Symptom:** Both telemetry tests fail because spawned fixture process returns empty `stdout` and `stderr`, causing `[PASS]`/`TORCH-MEMORY` assertions to fail.
- **Trigger/Conditions:** Running `node test/memory-telemetry.test.mjs` or memory test glob in this environment.
- **Workaround:** Run memory tests excluding `test/memory-telemetry.test.mjs` while investigating child-process output capture behavior.
- **Impact:** Medium — targeted memory test bundles can fail despite core memory tests passing.
- **Related notes:** `docs/agent-handoffs/incidents/2026-02-20-codex-test-failures-platform-and-telemetry.md`
- **Last verified:** 2026-02-20
### Goose Desktop: hermit "text file busy" (ETXTBSY) blocks all `node`/`npm` commands
- **Status:** Active (local workaround applied, upstream fix needed)
- **Area:** Tooling
@@ -0,0 +1,30 @@
# Codex environment test failures: scheduler platform assertion and memory telemetry capture
## Context
- Date: 2026-02-20
- Agent: `docs-code-investigator`
- Validation stage for documentation-only updates (`src/services/memory/index.js`).
## Observation
- `npm test` fails in `test/scheduler-preflight-lock.e2e.test.mjs`.
- Failure detail: first e2e assertion expects frontmatter platform to be `unknown`, but scheduler log in this environment reports `platform: codex`.
- Targeted memory test bundle (`node --test test/memory-*.test.mjs test/memory.test.js`) fails in `test/memory-telemetry.test.mjs`.
- Direct run (`node test/memory-telemetry.test.mjs`) shows fixture child process exits with code `0` but both `stdout` and `stderr` are empty, failing assertions that expect `[PASS]` and `TORCH-MEMORY` output.
## Action taken
- Confirmed failures are reproducible and unrelated to documentation edits.
- Captured reproductions with direct command runs to reveal assertion details.
- Updated `KNOWN_ISSUES.md` with active issue entries for both failures.
## Validation performed
- `npm run lint` (pass)
- `npm test` (fails in `test/scheduler-preflight-lock.e2e.test.mjs`)
- `node --test test/scheduler-preflight-lock.e2e.test.mjs`
- `node test/scheduler-preflight-lock.e2e.test.mjs`
- `node --test test/memory-*.test.mjs test/memory.test.js`
- `node test/memory-telemetry.test.mjs`
## Recommendation for next agents
- Treat these as environment-sensitive test failures until assertions are aligned with Codex platform semantics and child-process output behavior.
- If updating tests, follow spec-correction protocol and preserve strict behavioral intent.
- Keep `KNOWN_ISSUES.md` dates/status current after remediation.
+132
View File
@@ -0,0 +1,132 @@
# Memory Service Index Overview (`src/services/memory/index.js`)
## What this module does
`src/services/memory/index.js` is the orchestration layer for TORCH memory ingestion, retrieval, pruning, and admin operations.
It coordinates lower-level modules (`ingestor`, `retriever`, `pruner`, `cache`, `scheduler`, feature flags), persists a process-local `Map` store to `.scheduler-memory/memory-store.json`, and exposes APIs used by CLI commands and scheduler memory workflows.
## Where it fits
- Primary callers:
- CLI entrypoints in `src/lib.mjs:28` and command handling in `src/lib.mjs:640`.
- Scheduler memory pipelines in `scripts/memory/retrieve.mjs:1` and `scripts/memory/store.mjs:1`.
- Prompt context formatter via memory service interface in `src/services/memory/formatter.js:173`.
- Side effects:
- Filesystem read/write (`.scheduler-memory/memory-store.json`).
- In-process cache invalidation and stats mutation.
- Telemetry/metrics emission hooks.
## Typical sequence (ingest -> retrieve -> prune)
1. Caller sends raw events to `ingestEvents(events, options)`.
2. `ingestMemoryWindow` validates/transforms/summarizes and writes through repository.
3. Service clears retrieval cache to avoid stale ranked results.
4. Caller queries `getRelevantMemories({ agent_id, query, ... })`.
5. Service returns cache hit or ranks records, updates `last_seen`, and caches result.
6. Optional `runPruneCycle` removes stale unpinned records (or reports candidates in dry-run mode).
## Public API summary
- `ingestEvents(events, options)`
- Stores event-derived memory records.
- Observable outputs: persisted records + telemetry/metrics.
- `getRelevantMemories(params)`
- Returns ranked top-k memory records for query context.
- Observable outputs: ranked records + telemetry/metrics + updated `last_seen`.
- `runPruneCycle(options)`
- Executes prune in `on` mode, or returns skip/dry-run metadata for `off`/`dry-run` modes.
- `pinMemory(id, options)` / `unpinMemory(id, options)`
- Toggle `pinned` state for prune protection and retrieval weighting.
- `markMemoryMerged(id, mergedInto, options)`
- Marks record as archived into another id.
- `listMemories(filters, options)`
- Lists filtered memories sorted by `last_seen` descending.
- `inspectMemory(id, options)`
- Returns one memory by id.
- `triggerPruneDryRun(options)`
- Returns prune candidates without deleting.
- `memoryStats(options)`
- Returns aggregate counts/rates and ingest throughput estimate.
## Main execution paths
- Ingest path:
- Input: validated event list.
- Output: stored `MemoryRecord[]`.
- Side effects: repository inserts, cache clear, ingest metrics.
- Retrieval path:
- Input: `{agent_id, query, tags, timeframe, k}`.
- Output: ranked `MemoryRecord[]`.
- Side effects: cache hit/miss telemetry, usage timestamp updates, retrieval metrics.
- Prune path:
- Input: retention window + prune mode.
- Output: pruned records (or dry-run candidates / off-mode no-op).
- Side effects: deletes from store, save to disk, cache clear, prune metrics.
- Admin path:
- Input: id/filter operations from CLI/admin surfaces.
- Output: direct record/admin summaries.
- Side effects: pin/unpin/merge mutate store and clear cache.
## Assumptions and invariants
- `memoryStore` is process-local and shared by all exports in this module.
- All state mutations that influence retrieval semantics clear cache.
- Save operations are coalesced (`currentSavePromise` + `pendingSavePromise`) to avoid overlapping writes.
- Repository injection objects must implement the methods expected by each API path (`listMemories`, `setPinned`, `markMerged`, etc.).
- Telemetry payloads are sanitized by `toSafeTelemetryPayload` to avoid high-risk raw content fields.
## Edge cases and error paths
- JSON store load failures are caught and logged; module falls back to empty `Map`.
- Save failures are caught/logged in `performSave`; callers are not failed by persistence errors from that path.
- Feature flag can force ingest skip (`isMemoryIngestEnabled`), returning `[]` with telemetry.
- Prune mode edge handling:
- `off`: no deletion, skip telemetry event.
- `dry-run`: returns candidates only.
- Several APIs propagate repository/ranker exceptions directly (no catch wrapper).
- No explicit retry/backoff inside this module; retry strategy is expected in callers if needed.
## Performance and concurrency considerations
- Retrieval caching is keyed by serialized query params (`JSON.stringify`), reducing repeated ranking cost.
- Throughput sample arrays are capped at 10k entries to avoid unbounded growth.
- Save coalescing collapses concurrent write bursts to at most one active write plus one queued write.
- Process-level in-memory state means multi-process deployments can drift unless coordinated externally.
## Security considerations
- ⚠️ SECURITY: This module handles user/agent-provided memory content and telemetry emission.
- `toSafeTelemetryPayload` intentionally strips `content`, `summary`, `query`, and `raw` fields to reduce accidental leakage.
- Filesystem persistence path is under working directory `.scheduler-memory`; callers should treat it as sensitive operational data.
- No cryptographic/signing logic exists in this file; avoid introducing any here without security review.
## Related files and call graph
- Direct dependencies used by this module:
- `src/services/memory/cache.js:1`
- `src/services/memory/ingestor.js:1`
- `src/services/memory/retriever.js:1`
- `src/services/memory/pruner.js:1`
- `src/services/memory/scheduler.js:1`
- `src/services/memory/feature-flags.js:1`
- Inbound usage:
- `src/lib.mjs:28`
- `scripts/memory/retrieve.mjs:1`
- `scripts/memory/store.mjs:1`
- `test/memory-admin.test.mjs:15`
- `test/memory-ingest.test.mjs:3`
- `test/memory-run-prune-cycle.test.mjs:64`
## Why it works this way
- This design prioritizes deterministic scheduler-local operation with minimal dependencies: JSON-backed persistence + in-process cache + injectable repository hooks for tests.
- The module centralizes memory lifecycle events so scheduler contracts can call stable entrypoints (`ingestEvents`, `getRelevantMemories`) with marker verification.
## When to change
- Extract persistence if multi-process consistency or transactional guarantees are required.
- Split telemetry/stats into dedicated module if eventing complexity grows.
- Replace JSON store if memory volume makes full-file rewrites too expensive.
- Refactor if cache keying/ranking inputs require versioned schema or backward-compat layers.
## Tests validating behavior
- `test/memory-ingest.test.mjs`
- `test/memory-index.test.mjs`
- `test/memory-admin.test.mjs`
- `test/memory-run-prune-cycle.test.mjs`
- `test/memory-stats.test.mjs`
Run checks:
```bash
npm run lint
npm test
```
@@ -0,0 +1,15 @@
# Memory Update - docs-code-investigator - 20260220T023152Z
## Summary
- Documented `src/services/memory/index.js` with a top-level flow/invariants comment and comprehensive JSDoc across all exports.
- Added `docs/memory-index-overview.md` capturing behavior, API contracts, invariants, side effects, call graph, and change guidance.
## Validation outcomes
- `npm run lint` passes.
- `npm test` fails on existing environment-sensitive issue in `test/scheduler-preflight-lock.e2e.test.mjs` (platform mismatch: `unknown` vs `codex`).
- `test/memory-telemetry.test.mjs` also fails in this environment due empty captured child-process stdout/stderr.
- Targeted memory behavior subset passed: `test/memory-admin`, `test/memory-index`, `test/memory-ingest`, `test/memory-run-prune-cycle`, `test/memory-stats`.
## Reusable notes
- For environment-sensitive failures, capture direct non-`--test` runs (`node <testfile>`) to expose hidden assertion details.
- Keep documentation-only runs non-invasive: do not patch tests without spec-correction basis.
+37
View File
@@ -0,0 +1,37 @@
# Context - 20260220T023152Z
## Goal
Document one complex source file with behavior-focused comments/JSDoc and a companion overview doc without changing runtime behavior.
## Target Selection
- **Selected file:** `src/services/memory/index.js`
- **Line count:** 466 lines
- **Selection reason:** Core memory orchestration module with multiple exported entrypoints used by CLI and scheduler memory workflows; high complexity and stateful behavior (cache, persistence, pruning, telemetry).
- **Candidate evidence:** Top large-file scan showed this file in the top 10 and specifically in memory core paths.
- **Last significant commit touching file:** `c123dd9a7702fed425a96fc11517b0bac38925ca` (2026-02-18) — `perf: make saveMemoryStore async and non-blocking`.
## Baseline Reads Completed
- `AGENTS.md`
- `CLAUDE.md`
- `TORCH.md`
- `KNOWN_ISSUES.md`
- `docs/agent-handoffs/README.md`
- Recent handoff notes in `docs/agent-handoffs/learnings/` and `docs/agent-handoffs/incidents/`.
- Scheduler contract in `src/prompts/scheduler-flow.md`.
## Memory Contract Evidence (Pre-implementation)
- Retrieval command executed with scheduler env:
- `SCHEDULER_CADENCE=daily`
- `SCHEDULER_AGENT=docs-code-investigator`
- `SCHEDULER_RUN_ID=docs-code-investigator-20260220T023152Z`
- Marker observed: `MEMORY_RETRIEVED`
- Artifacts observed:
- `.scheduler-memory/docs-code-investigator-20260220T023152Z/retrieve.json`
- `.scheduler-memory/latest/daily/retrieve.ok`
- `.scheduler-memory/latest/daily/memories.md`
## Constraints
- Documentation-only changes for a single source file and optional overview doc.
- No behavior changes.
- No crypto/signing logic modifications.
- Scheduler-owned completion files and `lock:complete` are out of scope for spawned agent runs.
@@ -0,0 +1,27 @@
# Decisions - 20260220T023152Z
## Decision 1: Select `src/services/memory/index.js`
- **Decision:** Document `src/services/memory/index.js` only.
- **Alternatives considered:** `dashboard/app.js`, `src/lib.mjs`, `scripts/agent/run-scheduler-cycle.mjs`.
- **Rationale:** `src/services/memory/index.js` is a high-impact module with multiple exports and side effects (persistent store, prune lifecycle, telemetry, cache behavior), making documentation yield high maintenance value.
- **Consequence:** Keep PR narrowly scoped to one source file plus one overview doc.
## Decision 2: Keep edits documentation-only
- **Decision:** Only comments/JSDoc + external overview doc; no logic changes.
- **Rationale:** Mission requires non-invasive documentation and prohibits behavioral changes.
- **Consequence:** Any discovered correctness/security concerns will be documented, not fixed in this run.
## Decision 3: Omit scheduler-owned completion publishing
- **Decision:** Do not run `npm run lock:complete` and do not write `task-logs/...__completed.md|__failed.md`.
- **Rationale:** Shared scheduler contract assigns completion publish/logging to scheduler, not spawned agent.
- **Consequence:** Return artifacts and results to scheduler/user only.
## Decision 4: Omit `git pull --ff-only`
- **Decision:** Do not execute remote pull step from first-run checklist.
- **Rationale:** Environment has restricted network access and this run does not require branch sync for local documentation edits.
- **Consequence:** Proceed against current workspace state and report this omission explicitly.
## Decision 5: Capture unresolved validation failures as incidents (no test edits)
- **Decision:** Record reproducible test failures in `KNOWN_ISSUES.md` and `docs/agent-handoffs/incidents/` instead of changing tests.
- **Rationale:** Failures are environment-sensitive and outside scope of this documentation-only run; anti-cheat policy forbids weakening tests for green CI.
- **Consequence:** Preserve test integrity and provide actionable context for dedicated follow-up remediation.
+77 -6
View File
@@ -8,6 +8,17 @@ import fs from 'node:fs';
import path from 'node:path';
import util from 'node:util';
/*
* Memory service flow:
* 1) `ingestEvents` validates/transforms raw events via `ingestMemoryWindow`, persists records, and clears retrieval cache.
* 2) `getRelevantMemories` applies cached lookup + ranking, updates usage timestamps, emits telemetry/metrics, and caches results.
* 3) Admin flows (`runPruneCycle`, pin/unpin, merge, list/inspect/stats) mutate or inspect the same backing store.
*
* Key invariants:
* - `memoryStore` is the process-local source of truth and is asynchronously persisted to `.scheduler-memory/memory-store.json`.
* - Any mutation that affects retrieval semantics clears the in-memory cache.
* - Save operations are serialized/coalesced (`currentSavePromise` + `pendingSavePromise`) so concurrent writes do not overlap.
*/
const MEMORY_FILE_PATH = path.join(process.cwd(), '.scheduler-memory', 'memory-store.json');
const debug = util.debuglog('torch-memory');
@@ -193,8 +204,11 @@ function recordThroughput(samples, now) {
* Ingests agent events and stores them as memory records.
*
* @param {import('./schema.js').MemoryEvent[]} events - Ordered list of raw events to persist.
* @param {{ maxSummaryLength?: number, embedText?: (value: string) => Promise<number[]> | number[], repository?: typeof memoryRepository }} [options] - Optional ingest tuning.
* @param {{ agent_id?: string, env?: NodeJS.ProcessEnv, maxSummaryLength?: number, embedText?: (value: string) => Promise<number[]> | number[], repository?: typeof memoryRepository, emitTelemetry?: (event: string, payload: object) => void, telemetry?: { emit?: (event: string, payload: object) => void }, emitMetric?: (metric: string, payload: object) => void, metrics?: { emit?: (metric: string, payload: object) => void } }} [options] - Optional ingest tuning and dependency injection hooks.
* @returns {Promise<import('./schema.js').MemoryRecord[]>} Stored memory records.
* @throws {Error} Propagates validation/ingest failures from `ingestMemoryWindow` or repository calls.
* @example
* await ingestEvents([{ agent_id: 'agent-a', content: 'event payload', timestamp: Date.now() }], { agent_id: 'agent-a' });
*/
export async function ingestEvents(events, options = {}) {
const repository = options.repository ?? memoryRepository;
@@ -221,8 +235,11 @@ export async function ingestEvents(events, options = {}) {
/**
* Retrieves top-k memories for an agent query.
*
* @param {{ agent_id: string, query?: string, tags?: string[], timeframe?: { from?: number, to?: number }, k?: number, repository?: typeof memoryRepository }} params - Retrieval filter and ranking inputs.
* @param {{ agent_id: string, query?: string, tags?: string[], timeframe?: { from?: number, to?: number }, k?: number, repository?: typeof memoryRepository, ranker?: typeof filterAndRankMemories, cache?: { get: (key: string) => import('./schema.js').MemoryRecord[] | undefined, set: (key: string, value: import('./schema.js').MemoryRecord[]) => void }, emitTelemetry?: (event: string, payload: object) => void, telemetry?: { emit?: (event: string, payload: object) => void }, emitMetric?: (metric: string, payload: object) => void, metrics?: { emit?: (metric: string, payload: object) => void } }} params - Retrieval filter, ranking inputs, and optional hooks.
* @returns {Promise<import('./schema.js').MemoryRecord[]>} Sorted list of relevant memories.
* @throws {Error} Propagates repository/ranker/update failures.
* @example
* const top = await getRelevantMemories({ agent_id: 'agent-a', query: 'scheduler memory retrieval', k: 5 });
*/
export async function getRelevantMemories(params) {
const {
@@ -273,8 +290,11 @@ export async function getRelevantMemories(params) {
/**
* Runs a memory pruning pass and removes unpinned stale records.
*
* @param {{ retentionMs?: number, now?: number, scheduleEveryMs?: number, repository?: typeof memoryRepository }} [options] - Prune configuration; if scheduleEveryMs is set, returns a scheduler handle.
* @returns {Promise<{ pruned: import('./schema.js').MemoryRecord[], scheduler?: { stop: () => void } }>} Pruned records and optional scheduler handle.
* @param {{ retentionMs?: number, now?: number, scheduleEveryMs?: number, repository?: typeof memoryRepository, env?: NodeJS.ProcessEnv, pruneMode?: 'off' | 'dry-run' | 'on', emitTelemetry?: (event: string, payload: object) => void, telemetry?: { emit?: (event: string, payload: object) => void }, emitMetric?: (metric: string, payload: object) => void, metrics?: { emit?: (metric: string, payload: object) => void } }} [options] - Prune configuration and optional dependency hooks.
* @returns {Promise<{ pruned: import('./schema.js').MemoryRecord[], mode?: 'off' | 'dry-run', candidates?: import('./schema.js').MemoryRecord[], scheduler?: { stop: () => void } }>} Prune result. `mode`/`candidates` are returned for non-destructive modes.
* @throws {Error} Propagates repository listing or scheduler start failures.
* @example
* const result = await runPruneCycle({ retentionMs: 30 * 24 * 60 * 60 * 1000 });
*/
export async function runPruneCycle(options = {}) {
const repository = options.repository ?? memoryRepository;
@@ -340,7 +360,11 @@ export async function runPruneCycle(options = {}) {
* Pins a memory to prevent pruning and boost retrieval ranking.
*
* @param {string} id - Memory record identifier.
* @param {{ repository?: typeof memoryRepository }} [options] - Optional repository override for tests/integration wiring.
* @returns {Promise<import('./schema.js').MemoryRecord | null>} Updated memory record or null when not found.
* @throws {Error} Propagates repository update failures.
* @example
* await pinMemory('mem_123');
*/
export async function pinMemory(id, options = {}) {
const repository = options.repository ?? memoryRepository;
@@ -353,7 +377,11 @@ export async function pinMemory(id, options = {}) {
* Removes a pin from a memory so it can be pruned normally.
*
* @param {string} id - Memory record identifier.
* @param {{ repository?: typeof memoryRepository }} [options] - Optional repository override for tests/integration wiring.
* @returns {Promise<import('./schema.js').MemoryRecord | null>} Updated memory record or null when not found.
* @throws {Error} Propagates repository update failures.
* @example
* await unpinMemory('mem_123');
*/
export async function unpinMemory(id, options = {}) {
const repository = options.repository ?? memoryRepository;
@@ -365,8 +393,13 @@ export async function unpinMemory(id, options = {}) {
/**
* Marks one memory as merged into another.
*
* @param {string} id
* @param {string} mergedInto
* @param {string} id - Source memory identifier to mark as merged.
* @param {string} mergedInto - Destination memory identifier.
* @param {{ repository?: typeof memoryRepository }} [options] - Optional repository override for tests/integration wiring.
* @returns {Promise<boolean>} `true` when source memory existed and was marked; otherwise `false`.
* @throws {Error} Propagates repository update failures.
* @example
* await markMemoryMerged('mem_old', 'mem_canonical');
*/
export async function markMemoryMerged(id, mergedInto, options = {}) {
const repository = options.repository ?? memoryRepository;
@@ -375,6 +408,16 @@ export async function markMemoryMerged(id, mergedInto, options = {}) {
return merged;
}
/**
* Lists memory records with optional boundary-level filters and pagination.
*
* @param {{ agent_id?: string, type?: string, pinned?: boolean, includeMerged?: boolean, tags?: string[], offset?: number, limit?: number }} [filters] - Filter and pagination controls.
* @param {{ repository?: typeof memoryRepository }} [options] - Optional repository override.
* @returns {Promise<import('./schema.js').MemoryRecord[]>} Filtered records sorted by descending `last_seen`.
* @throws {Error} Propagates repository list failures.
* @example
* const rows = await listMemories({ agent_id: 'agent-a', pinned: true, limit: 20 });
*/
export async function listMemories(filters = {}, options = {}) {
const repository = options.repository ?? memoryRepository;
const source = typeof repository.listMemories === 'function'
@@ -392,6 +435,16 @@ export async function listMemories(filters = {}, options = {}) {
return filtered.slice(offset, offset + limit);
}
/**
* Retrieves a single memory by id.
*
* @param {string} id - Memory record identifier.
* @param {{ repository?: typeof memoryRepository }} [options] - Optional repository override.
* @returns {Promise<import('./schema.js').MemoryRecord | null>} Memory record or `null` if not found.
* @throws {Error} Propagates repository read failures.
* @example
* const memory = await inspectMemory('mem_123');
*/
export async function inspectMemory(id, options = {}) {
const repository = options.repository ?? memoryRepository;
if (typeof repository.getMemoryById === 'function') {
@@ -400,6 +453,15 @@ export async function inspectMemory(id, options = {}) {
return memoryStore.get(id) ?? null;
}
/**
* Simulates prune selection without deleting data.
*
* @param {{ retentionMs?: number, now?: number, repository?: typeof memoryRepository }} [options] - Dry-run selection controls.
* @returns {Promise<{ dryRun: true, retentionMs: number, candidateCount: number, candidates: Array<{ id: string, agent_id: string, type: string, pinned: boolean, last_seen: number, merged_into?: string | null }> }>} Dry-run summary and redacted candidates.
* @throws {Error} Propagates repository list/selection failures.
* @example
* const preview = await triggerPruneDryRun({ retentionMs: 7 * 24 * 60 * 60 * 1000 });
*/
export async function triggerPruneDryRun(options = {}) {
const repository = options.repository ?? memoryRepository;
const retentionMs = options.retentionMs ?? (1000 * 60 * 60 * 24 * 30);
@@ -430,6 +492,15 @@ export async function triggerPruneDryRun(options = {}) {
};
}
/**
* Returns aggregate memory counts and throughput estimates for observability.
*
* @param {{ repository?: typeof memoryRepository, now?: number, windowMs?: number }} [options] - Stats window and repository controls.
* @returns {Promise<{ countsByType: Record<string, number>, totals: { total: number, pinned: number, archived: number, deletedObserved: number }, rates: { archivedRate: number, deletedRate: number }, indexSizeEstimateBytes: number, ingestThroughputPerMinute: number }>} Current memory aggregate snapshot.
* @throws {Error} Propagates repository list failures.
* @example
* const stats = await memoryStats({ windowMs: 60 * 60 * 1000 });
*/
export async function memoryStats(options = {}) {
const repository = options.repository ?? memoryRepository;
const now = options.now ?? Date.now();
@@ -0,0 +1,35 @@
# Test Log - 20260220T023152Z
## Pre-validation setup
- Command: `SCHEDULER_CADENCE=daily SCHEDULER_AGENT=docs-code-investigator SCHEDULER_RUN_ID=docs-code-investigator-20260220T023152Z SCHEDULER_PROMPT_PATH=src/prompts/daily/docs-code-investigator.md node scripts/memory/retrieve.mjs`
- Result: PASS (`MEMORY_RETRIEVED`)
- Notes: Evidence created under `.scheduler-memory/docs-code-investigator-20260220T023152Z/` and `.scheduler-memory/latest/daily/`.
## Lint/Test Commands
- Command: `npm run lint`
- Result: PASS
- Notes: No lint violations after JSDoc/comment additions.
- Command: `npm test`
- Result: FAIL
- Notes: Fails in `test/scheduler-preflight-lock.e2e.test.mjs` due platform assertion mismatch (`expected unknown`, `actual codex`) in this environment.
- Command: `node --test test/scheduler-preflight-lock.e2e.test.mjs`
- Result: FAIL
- Notes: Reproduces suite failure but compact reporter output hides assertion details.
- Command: `node test/scheduler-preflight-lock.e2e.test.mjs`
- Result: FAIL
- Notes: Exposes assertion details; first test expects log frontmatter `platform: unknown`, observed `platform: codex`.
- Command: `node --test test/memory-*.test.mjs test/memory.test.js`
- Result: FAIL
- Notes: `test/memory-telemetry.test.mjs` fails due empty child-process stdout/stderr in this environment; other memory tests passed.
- Command: `node test/memory-telemetry.test.mjs`
- Result: FAIL
- Notes: Reproduces telemetry assertions failing at `test/memory-telemetry.test.mjs:86` and `:100` (`[PASS]` and `TORCH-MEMORY` output not present).
- Command: `node --test test/memory-admin.test.mjs test/memory-index.test.mjs test/memory-ingest.test.mjs test/memory-run-prune-cycle.test.mjs test/memory-stats.test.mjs`
- Result: PASS
- Notes: Targeted module-relevant behavior checks pass for the documented file.
+18
View File
@@ -0,0 +1,18 @@
# TODO - docs-code-investigator (20260220T023152Z)
## Pending
- [ ] Write post-run memory update and execute storage command (`MEMORY_STORED`).
## Completed
- [x] Baseline and scheduler contract reads.
- [x] Memory retrieval before implementation.
- [x] Candidate discovery and target file selection.
- [x] Add top-level flow/invariant comment in `src/services/memory/index.js`.
- [x] Add/expand JSDoc for all exported APIs in `src/services/memory/index.js`.
- [x] Create `docs/memory-index-overview.md` with module analysis (A-K sections).
- [x] Run `npm run lint` and `npm test` (with failure capture).
- [x] Record validation output in `src/test_logs/TEST_LOG_20260220T023152Z.md`.
- [x] Update `KNOWN_ISSUES.md` and incident note for unresolved reproducible failures.
## Blocked
- `npm test` is currently blocked by active environment-sensitive failures documented in `KNOWN_ISSUES.md`.
@@ -0,0 +1,45 @@
---
agent: docs-code-investigator
cadence: daily
date: 2026-02-20
platform: codex
status: completed
---
# docs-code-investigator Run
## Summary
Successfully documented `src/services/memory/index.js` with comprehensive JSDoc comments and module overview.
## Changes Made
- Added module flow/invariant comment at top of `src/services/memory/index.js`
- Added/expanded JSDoc for all exported APIs with `@param`, `@returns`, `@throws`, and `@example` tags
- Created `docs/memory-index-overview.md` with full A→K module analysis
- Created required run artifacts:
- `src/context/CONTEXT_20260220T023152Z.md`
- `src/todo/TODO_20260220T023152Z.md`
- `src/decisions/DECISIONS_20260220T023152Z.md`
- `src/test_logs/TEST_LOG_20260220T023152Z.md`
- Captured unresolved reproducible failures:
- Updated `KNOWN_ISSUES.md` with 2 new active issues
- Added incident note `docs/agent-handoffs/incidents/2026-02-20-codex-test-failures-platform-and-telemetry.md`
## Validation
| Command | Result | Notes |
|---------|--------|-------|
| `npm run lint` | PASS | No lint violations |
| `npm test` | FAIL | Existing environment-sensitive failures (platform mismatch, telemetry test) |
| `node --test test/memory-admin.test.mjs test/memory-index.test.mjs test/memory-ingest.test.mjs test/memory-run-prune-cycle.test.mjs test/memory-stats.test.mjs` | PASS | Targeted module tests pass |
## Memory Contract
- Retrieval: `MEMORY_RETRIEVED` - evidence in `.scheduler-memory/docs-code-investigator-20260220T023152Z/retrieve.json`
- Storage: `MEMORY_STORED` - evidence in `.scheduler-memory/docs-code-investigator-20260220T023152Z/store.json`
## Lock Events
- Lock acquired: `0b4996a22e591ec427d453b037e577ce8658a97a278920cf005b82237889b754`
- Completion published: `0727a8724551d294429f1a4aed907f4fc65a6a6a1e5b9ad3c5aa825d4b12ba03`