task-write-parity-integration.test.mjs
105 lines 3.4 KB
Raw
sha256:b5f647cb9c409f563d4671fe3fc05ddea01fabfed9b41fc11cb923588e1c1baf mirror: GitHub Phase A durable MCP OAuth (#270) Human minor ⚠ breaking 10 days ago
1 /**
2 * Tier 2 — INTEGRATION: CLI = MCP = Hub parity + disabled gate.
3 */
4 import { describe, it, beforeEach, afterEach } from 'node:test';
5 import assert from 'node:assert/strict';
6 import fs from 'node:fs';
7 import path from 'node:path';
8 import { fileURLToPath } from 'node:url';
9
10 import { handleTaskProposeRequest } from '../lib/task/task-write.mjs';
11 import { createProposal, listProposals } from '../hub/proposals-store.mjs';
12 import { sampleTaskCreatePayload } from './fixtures/task/write-helpers.mjs';
13
14 const __dirname = path.dirname(fileURLToPath(import.meta.url));
15 const tmpRoot = path.join(__dirname, 'fixtures', 'tmp-task-write-parity');
16
17 function stripVolatile(payload) {
18 const copy = structuredClone(payload);
19 delete copy.proposal_id;
20 return copy;
21 }
22
23 describe('task write — triple-surface parity', () => {
24 beforeEach(() => {
25 fs.rmSync(tmpRoot, { recursive: true, force: true });
26 fs.mkdirSync(tmpRoot, { recursive: true });
27 process.env.TASK_WRITES_ENABLED = '1';
28 });
29 afterEach(() => {
30 delete process.env.TASK_WRITES_ENABLED;
31 });
32
33 it('Hub, CLI, MCP produce deep-equal envelope', async () => {
34 const body = sampleTaskCreatePayload();
35 const hub = await handleTaskProposeRequest({
36 dataDir: path.join(tmpRoot, 'hub'),
37 vaultId: 'default',
38 role: 'admin',
39 proposalKind: 'task_create',
40 body,
41 intent: 'add it',
42 createProposal,
43 });
44 const cli = await handleTaskProposeRequest({
45 dataDir: path.join(tmpRoot, 'cli'),
46 vaultId: 'default',
47 cliScopes: ['personal', 'project', 'org'],
48 proposalKind: 'task_create',
49 body,
50 intent: 'add it',
51 createProposal,
52 });
53 const mcp = await handleTaskProposeRequest({
54 dataDir: path.join(tmpRoot, 'mcp'),
55 vaultId: 'default',
56 cliScopes: ['personal', 'project', 'org'],
57 proposalKind: 'task_create',
58 body,
59 intent: 'add it',
60 createProposal,
61 });
62 assert.equal(hub.ok, true);
63 assert.equal(cli.ok, true);
64 assert.equal(mcp.ok, true);
65 assert.deepEqual(stripVolatile(hub.payload), stripVolatile(cli.payload));
66 assert.deepEqual(stripVolatile(cli.payload), stripVolatile(mcp.payload));
67 });
68
69 it('creates exactly one proposal with source task', async () => {
70 const dir = path.join(tmpRoot, 'one');
71 fs.mkdirSync(dir, { recursive: true });
72 await handleTaskProposeRequest({
73 dataDir: dir,
74 vaultId: 'default',
75 role: 'admin',
76 proposalKind: 'task_create',
77 body: sampleTaskCreatePayload(),
78 intent: 'add',
79 createProposal,
80 });
81 const { total, proposals } = listProposals(dir, { source: 'task' });
82 assert.equal(total, 1);
83 assert.equal(proposals[0].source, 'task');
84 assert.equal(proposals[0].task_meta.proposal_kind, 'task_create');
85 });
86
87 it('TASK_WRITES_ENABLED=off refuses all surfaces', async () => {
88 delete process.env.TASK_WRITES_ENABLED;
89 const dir = path.join(tmpRoot, 'off');
90 fs.mkdirSync(dir, { recursive: true });
91 for (const ctx of [{ role: 'admin' }, { cliScopes: ['personal'] }]) {
92 const result = await handleTaskProposeRequest({
93 dataDir: dir,
94 vaultId: 'default',
95 proposalKind: 'task_create',
96 body: sampleTaskCreatePayload(),
97 intent: 'add',
98 createProposal,
99 ...ctx,
100 });
101 assert.equal(result.ok, false);
102 assert.equal(result.code, 'TASK_WRITES_DISABLED');
103 }
104 });
105 });
File History 1 commit
sha256:b5f647cb9c409f563d4671fe3fc05ddea01fabfed9b41fc11cb923588e1c1baf mirror: GitHub Phase A durable MCP OAuth (#270) Human minor 10 days ago