mirror of
https://github.com/PR0M3TH3AN/TORCH.git
synced 2026-10-27 07:51:52 +00:00
Merge branch 'main' of https://github.com/PR0M3TH3AN/TORCH
This commit is contained in:
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
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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', () => {
|
||||
|
||||
@@ -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'));
|
||||
|
||||
Reference in new issue
Block a user