This commit is contained in:
thePR0M3TH3AN committed 2026-02-18 14:35:25 -05:00
commit d290bf684d
5 files changed
+99 -7

No files matched your search

@@ -0,0 +1,27 @@
test_integrity_note:
change_type: ["refactor_tests", "new_tests", "spec_correction"]
scenarios:
- id: SCN-MEMORY-SCHEDULER-DETERMINISM
given: "A memory maintenance scheduler with retry logic"
when: "A job fails transiently and retries are scheduled"
then: "The scheduler waits exactly the retry delay without using real time sleep"
- id: SCN-LOCK-PARSE-MALFORMED
given: "A lock event with invalid JSON content or missing fields"
when: "The event is parsed"
then: "The parser returns a lock object with null content fields instead of throwing or returning partial data"
- id: SCN-DASHBOARD-CONFIG-SANITIZATION
given: "A dashboard configuration with sensitive fields (roster, auth)"
when: "The /torch-config.json endpoint is accessed"
then: "Sensitive fields are stripped from the response"
observable_outcomes:
- "Scheduler tests run deterministically using mock timers"
- "Lock parser handles garbage input gracefully"
- "Dashboard config endpoint does not leak sensitive roster data"
determinism_controls:
- "Replaced setTimeout/wait with node:test mock.timers"
anti_cheat_rationale:
prevents:
- "retry/sleep-based flake masking"
- "hard-coded return value (dashboard config fix)"
relaxation:
did_relax_any_assertion: false
+1 -1
View File
@@ -129,7 +129,7 @@ export async function cmdDashboard(port = DEFAULT_DASHBOARD_PORT, host = '127.0.
}
res.writeHead(200, { ...SECURITY_HEADERS, 'Content-Type': 'application/json' });
res.end(JSON.stringify(safeConfig, null, 2));
res.end(JSON.stringify(publicConfig, null, 2));
return;
} catch (err) {
console.error('Error parsing torch-config.json:', err);
+8
View File
@@ -1,5 +1,13 @@
> **Shared contract (required):** Follow [`Scheduler Flow → Shared Agent Run Contract`](../scheduler-flow.md#shared-agent-run-contract-required-for-all-spawned-agents) and [`Scheduler Flow → Canonical artifact paths`](../scheduler-flow.md#canonical-artifact-paths) before and during this run.
## Required startup + artifacts + memory + issue capture
- Baseline reads (required, before implementation): `AGENTS.md`, `CLAUDE.md`, `KNOWN_ISSUES.md`, and `docs/agent-handoffs/README.md`.
- Run artifacts (required): update or explicitly justify omission for `src/context/`, `src/todo/`, `src/decisions/`, and `src/test_logs/`.
- Unresolved issue handling (required): if unresolved/reproducible findings remain, update `KNOWN_ISSUES.md` and add or update an incidents note in `docs/agent-handoffs/incidents/`.
- Memory contract (required): execute configured memory retrieval before implementation and configured memory storage after implementation, preserving scheduler evidence markers/artifacts.
- Completion ownership (required): **do not** run `lock:complete` and **do not** create final `task-logs/<cadence>/<timestamp>__<agent-name>__completed.md` or `__failed.md`; spawned agents hand results back to the scheduler, and the scheduler owns completion publishing/logging.
[SYSTEM] You are the Test Integrity & Scenario Spec Agent. Your purpose is to keep validation truthful.
You do not optimize for green CI. You optimize for reality.
+38
View File
@@ -35,6 +35,44 @@ describe('lock-ops', () => {
assert.strictEqual(result.agent, 'test-agent');
assert.strictEqual(result.platform, 'test-platform');
});
it('returns nulls when content is invalid JSON', () => {
const event = {
id: 'mock-id',
pubkey: 'mock-pubkey',
created_at: 1678886400,
tags: [],
content: 'invalid json',
};
const result = parseLockEvent(event);
assert.strictEqual(result.agent, null);
assert.strictEqual(result.cadence, null);
});
it('returns nulls when required content fields are missing', () => {
const event = {
id: 'mock-id',
pubkey: 'mock-pubkey',
created_at: 1678886400,
tags: [],
content: JSON.stringify({}),
};
const result = parseLockEvent(event);
assert.strictEqual(result.agent, null);
assert.strictEqual(result.cadence, null);
});
it('returns nulls when content is an array (not object)', () => {
const event = {
id: 'mock-id',
pubkey: 'mock-pubkey',
created_at: 1678886400,
tags: [],
content: JSON.stringify(['not', 'an', 'object']),
};
const result = parseLockEvent(event);
assert.strictEqual(result.agent, null);
});
});
describe('queryLocks', () => {
+25 -6
View File
@@ -1,4 +1,4 @@
import { test } from 'node:test';
import { test, mock } from 'node:test';
import assert from 'node:assert/strict';
import {
@@ -6,8 +6,6 @@ import {
startMemoryMaintenanceScheduler,
} from '../src/services/memory/scheduler.js';
const wait = (ms = 0) => new Promise((resolve) => setTimeout(resolve, ms));
test('createDbAdvisoryLockProvider acquires and releases postgres advisory locks', async () => {
const calls = [];
const db = {
@@ -32,6 +30,8 @@ test('createDbAdvisoryLockProvider acquires and releases postgres advisory locks
});
test('startMemoryMaintenanceScheduler runs all jobs and emits metrics including retries', async () => {
mock.timers.enable({ apis: ['Date', 'setTimeout', 'setInterval'] });
const metrics = [];
let ingestAttempts = 0;
@@ -71,8 +71,22 @@ test('startMemoryMaintenanceScheduler runs all jobs and emits metrics including
},
});
await wait(25);
// Advance time to allow async jobs and retries to complete.
// We tick enough to cover the retryDelayMs (1ms).
// We also need to allow the promise microtask queue to drain between ticks
// if necessary, but tick() usually handles the timer callbacks.
// Since the scheduler logic uses await, we need to ensure those promises resolve.
// Tick time forward and yield to event loop to allow promise chains to progress.
// The job involves multiple async steps (lock, handler, retry wait, lock, handler).
// We tick multiple times to ensure the retry timer fires and subsequent microtasks run.
for (let i = 0; i < 10; i++) {
mock.timers.tick(5);
await new Promise((resolve) => setImmediate(resolve));
}
scheduler.stop();
mock.timers.reset();
const byJob = metrics.reduce((acc, entry) => {
const key = entry.payload.job;
@@ -81,7 +95,7 @@ test('startMemoryMaintenanceScheduler runs all jobs and emits metrics including
return acc;
}, {});
assert.equal(byJob.ingestRecentRuntimeEvents.length, 1);
assert.equal(byJob.ingestRecentRuntimeEvents?.length, 1, 'Expected 1 ingest metric');
assert.equal(byJob.ingestRecentRuntimeEvents[0].payload.status, 'success');
assert.equal(byJob.ingestRecentRuntimeEvents[0].payload.itemCount, 3);
assert.equal(byJob.ingestRecentRuntimeEvents[0].payload.retries, 1);
@@ -93,6 +107,8 @@ test('startMemoryMaintenanceScheduler runs all jobs and emits metrics including
test('startMemoryMaintenanceScheduler skips jobs when feature flags disable memory', async () => {
mock.timers.enable({ apis: ['Date', 'setTimeout', 'setInterval'] });
const metrics = [];
const called = [];
@@ -118,8 +134,11 @@ test('startMemoryMaintenanceScheduler skips jobs when feature flags disable memo
},
});
await wait(10);
mock.timers.tick(10);
await new Promise(resolve => setImmediate(resolve));
scheduler.stop();
mock.timers.reset();
assert.deepEqual(called, []);
assert.ok(metrics.some((entry) => entry.payload.status === 'skipped_flag_disabled'));