task-store-data-integrity.test.mjs
80 lines 2.8 KB
Raw
sha256:b5f647cb9c409f563d4671fe3fc05ddea01fabfed9b41fc11cb923588e1c1baf mirror: GitHub Phase A durable MCP OAuth (#270) Human minor ⚠ breaking 10 days ago
1 /**
2 * Tier 5 — DATA INTEGRITY: SD-2 reciprocal link and starter round-trip.
3 *
4 * @see docs/TASK-STORE-CONTRACT-2G.md §9
5 */
6 import { describe, it, beforeEach, afterEach } from 'node:test';
7 import assert from 'node:assert/strict';
8 import fs from 'node:fs';
9 import path from 'node:path';
10 import { fileURLToPath } from 'node:url';
11 import {
12 getTask,
13 seedStarterTasks,
14 seedSd2AnchorRun,
15 validateTaskRecord,
16 } from '../lib/task/task-store.mjs';
17 import { loadFlowStore } from '../lib/flow/flow-store.mjs';
18 import { handleTaskGetRequest } from '../lib/task/task-handlers.mjs';
19 import { getRepoRoot } from '../lib/repo-root.mjs';
20
21 const __dirname = path.dirname(fileURLToPath(import.meta.url));
22 const tmpRoot = path.join(__dirname, 'fixtures', 'tmp-task-integrity');
23 const starterDir = path.join(getRepoRoot(), 'tasks/starter');
24
25 describe('Task store — data integrity', () => {
26 const dataDir = path.join(tmpRoot, 'data');
27 const vaultId = 'default';
28 const visible = new Set(['personal', 'project', 'org']);
29
30 beforeEach(() => {
31 fs.rmSync(tmpRoot, { recursive: true, force: true });
32 fs.mkdirSync(dataDir, { recursive: true });
33 seedStarterTasks(dataDir, vaultId, { starterDir });
34 seedSd2AnchorRun(dataDir, vaultId);
35 });
36
37 afterEach(() => {
38 fs.rmSync(tmpRoot, { recursive: true, force: true });
39 });
40
41 it('I-T-SD2-01: task.run_ref and run.task_ref are reciprocal on anchor pair', () => {
42 const task = getTask(dataDir, vaultId, 'task_2g_handover_001', { visibleScopes: visible });
43 assert.ok(task);
44 assert.equal(task.run_ref, 'run_overseer_in_progress');
45
46 const store = loadFlowStore(dataDir);
47 const run = store.vaults[vaultId].runs.find((r) => r.run_id === 'run_overseer_in_progress');
48 assert.ok(run);
49 assert.equal(run.task_ref, 'task_2g_handover_001');
50 });
51
52 it('seed → get preserves starter bundle fields', () => {
53 const bundle = JSON.parse(
54 fs.readFileSync(path.join(starterDir, 'task_2g_handover_001.json'), 'utf8'),
55 );
56 const got = handleTaskGetRequest({
57 dataDir,
58 vaultId,
59 taskId: 'task_2g_handover_001',
60 role: 'admin',
61 starterDir,
62 });
63 assert.equal(got.ok, true);
64 const task = got.payload.task;
65 assert.equal(task.task_id, bundle.task_id);
66 assert.equal(task.scope, bundle.scope);
67 assert.equal(task.run_ref, bundle.run_ref);
68 assert.equal(task.artifact_links.length, bundle.artifact_links.length);
69 });
70
71 it('artifact_links remain pointer-only (no body fields)', () => {
72 const validated = validateTaskRecord(
73 JSON.parse(fs.readFileSync(path.join(starterDir, 'task_2g_handover_001.json'), 'utf8')),
74 );
75 assert.equal(validated.ok, true);
76 for (const link of validated.task.artifact_links) {
77 assert.deepEqual(Object.keys(link).sort(), ['kind', 'ref']);
78 }
79 });
80 });
File History 1 commit
sha256:b5f647cb9c409f563d4671fe3fc05ddea01fabfed9b41fc11cb923588e1c1baf mirror: GitHub Phase A durable MCP OAuth (#270) Human minor 10 days ago