@memnexus-ai/mx-agent-cli 0.1.174 → 0.1.176
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/config-command.test.js +20 -0
- package/dist/__tests__/config-command.test.js.map +1 -1
- package/dist/__tests__/coordination-brief.test.js +5 -1
- package/dist/__tests__/coordination-brief.test.js.map +1 -1
- package/dist/__tests__/coordination-command.test.js +2 -0
- package/dist/__tests__/coordination-command.test.js.map +1 -1
- package/dist/__tests__/coordination-history.test.js +5 -1
- package/dist/__tests__/coordination-history.test.js.map +1 -1
- package/dist/__tests__/coordination-memory.test.d.ts +14 -0
- package/dist/__tests__/coordination-memory.test.d.ts.map +1 -0
- package/dist/__tests__/coordination-memory.test.js +261 -0
- package/dist/__tests__/coordination-memory.test.js.map +1 -0
- package/dist/__tests__/coordination-provision.test.d.ts +12 -0
- package/dist/__tests__/coordination-provision.test.d.ts.map +1 -0
- package/dist/__tests__/coordination-provision.test.js +77 -0
- package/dist/__tests__/coordination-provision.test.js.map +1 -0
- package/dist/__tests__/coordination-token.test.d.ts +11 -0
- package/dist/__tests__/coordination-token.test.d.ts.map +1 -0
- package/dist/__tests__/coordination-token.test.js +166 -0
- package/dist/__tests__/coordination-token.test.js.map +1 -0
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +12 -0
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/coordination.d.ts +37 -17
- package/dist/commands/coordination.d.ts.map +1 -1
- package/dist/commands/coordination.js +145 -16
- package/dist/commands/coordination.js.map +1 -1
- package/dist/lib/coordination-client.d.ts +21 -0
- package/dist/lib/coordination-client.d.ts.map +1 -1
- package/dist/lib/coordination-client.js +24 -0
- package/dist/lib/coordination-client.js.map +1 -1
- package/dist/lib/coordination-memory.d.ts +125 -0
- package/dist/lib/coordination-memory.d.ts.map +1 -0
- package/dist/lib/coordination-memory.js +318 -0
- package/dist/lib/coordination-memory.js.map +1 -0
- package/dist/lib/coordination-token.d.ts +75 -0
- package/dist/lib/coordination-token.d.ts.map +1 -0
- package/dist/lib/coordination-token.js +168 -0
- package/dist/lib/coordination-token.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coordination-provision.test.js","sourceRoot":"","sources":["../../src/__tests__/coordination-provision.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAEzE,iFAAiF;AACjF,8EAA8E;AAC9E,EAAE,CAAC,IAAI,CAAC,8BAA8B,EAAE,GAAG,EAAE,CAAC,CAAC;IAC7C,wBAAwB,EAAE,EAAE,CAAC,EAAE,EAAE;CAClC,CAAC,CAAC,CAAC;AAEJ,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,OAAO,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AAExE,MAAM,WAAW,GAAG,wBAA+D,CAAC;AAEpF,MAAM,QAAQ,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;AACpC,IAAI,MAAgB,CAAC;AAErB,UAAU,CAAC,GAAG,EAAE;IACd,WAAW,CAAC,SAAS,EAAE,CAAC;IACxB,MAAM,GAAG,EAAE,CAAC;IACZ,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAU,EAAE,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,CAAU,CAAC,CAAC;IAC1H,OAAO,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC;IAC1C,OAAO,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;IACxC,OAAO,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;IACxC,OAAO,CAAC,GAAG,CAAC,oBAAoB,GAAG,OAAO,CAAC,CAAC,6BAA6B;AAC3E,CAAC,CAAC,CAAC;AACH,SAAS,CAAC,GAAG,EAAE;IACb,EAAE,CAAC,eAAe,EAAE,CAAC;IACrB,OAAO,CAAC,GAAG,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;AAChC,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,kCAAkC,EAAE,GAAG,EAAE;IAChD,EAAE,CAAC,0EAA0E,EAAE,GAAG,EAAE;QAClF,8DAA8D;QAC9D,WAAW,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAG,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACxH,IAAI,MAAoD,CAAC;QACzD,MAAM,CAAC,GAAG,EAAE,GAAG,MAAM,GAAG,aAAa,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QAC1D,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC;QAC1B,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,qCAAqC,CAAC,CAAC;IAC3E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6EAA6E,EAAE,GAAG,EAAE;QACrF,WAAW,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,yCAAyC,EAAE,CAAC,CAAC;QAC5G,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;QACnC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,qCAAqC,CAAC,CAAC;IAC3E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oFAAoF,EAAE,GAAG,EAAE;QAC5F,WAAW,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC;QAC7E,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;QACnC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,gDAAgD,CAAC,CAAC;IACtF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iFAAiF,EAAE,GAAG,EAAE;QACzF,MAAM,QAAQ,GAAG,EAAE,KAAK,CAAC,OAAO,KAAK,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAW,CAAC;QAC/F,MAAM,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC3D,MAAM,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IAC7C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,8CAA8C,EAAE,GAAG,EAAE;IAC5D,EAAE,CAAC,yEAAyE,EAAE,GAAG,EAAE;QACjF,OAAO,CAAC,GAAG,CAAC,oBAAoB,GAAG,uBAAuB,CAAC;QAC3D,WAAW,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;QACvG,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;QAC/B,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;QAC9B,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC1D,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8DAA8D,EAAE,GAAG,EAAE;QACtE,OAAO,CAAC,GAAG,CAAC,oBAAoB,GAAG,uBAAuB,CAAC;QAC3D,OAAO,CAAC,GAAG,CAAC,oBAAoB,GAAG,WAAW,CAAC,CAAC,wBAAwB;QACxE,WAAW,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;QACvG,aAAa,EAAE,CAAC;QAChB,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* coordination-token -- self-provisioning the coordination service token.
|
|
3
|
+
*
|
|
4
|
+
* Verifies the CLI reproduces the coordination-brief hook's isolation properties:
|
|
5
|
+
* marker-authoritative slug (MF-2), roster-gate before any az call (SF-2),
|
|
6
|
+
* slug-bound per-worktree cache (MF-1), born-0600 cache write (SF-3),
|
|
7
|
+
* fail-OPEN on infra errors, fail-CLOSED on a roster mismatch, and no token
|
|
8
|
+
* logging.
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=coordination-token.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coordination-token.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/coordination-token.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* coordination-token -- self-provisioning the coordination service token.
|
|
3
|
+
*
|
|
4
|
+
* Verifies the CLI reproduces the coordination-brief hook's isolation properties:
|
|
5
|
+
* marker-authoritative slug (MF-2), roster-gate before any az call (SF-2),
|
|
6
|
+
* slug-bound per-worktree cache (MF-1), born-0600 cache write (SF-3),
|
|
7
|
+
* fail-OPEN on infra errors, fail-CLOSED on a roster mismatch, and no token
|
|
8
|
+
* logging.
|
|
9
|
+
*/
|
|
10
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
11
|
+
import { mkdtempSync, rmSync, writeFileSync, readFileSync, statSync, existsSync } from 'fs';
|
|
12
|
+
import { join } from 'path';
|
|
13
|
+
import { tmpdir } from 'os';
|
|
14
|
+
// Mock the config store so we can simulate getConfigValue throwing (mkdirSync
|
|
15
|
+
// EACCES on an unwritable HOME) for the SF-A belt-and-suspenders test. Default
|
|
16
|
+
// returns undefined (no configured token) so the other tests reach the marker path.
|
|
17
|
+
vi.mock('../lib/config.js', () => ({ getConfigValue: vi.fn(() => undefined) }));
|
|
18
|
+
import { resolveCoordinationToken, KEYVAULT_NAME } from '../lib/coordination-token.js';
|
|
19
|
+
import { getConfigValue } from '../lib/config.js';
|
|
20
|
+
const mockGetConfigValue = getConfigValue;
|
|
21
|
+
let dir;
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
dir = mkdtempSync(join(tmpdir(), 'coord-token-'));
|
|
24
|
+
mockGetConfigValue.mockReset();
|
|
25
|
+
mockGetConfigValue.mockReturnValue(undefined);
|
|
26
|
+
});
|
|
27
|
+
afterEach(() => {
|
|
28
|
+
rmSync(dir, { recursive: true, force: true });
|
|
29
|
+
vi.restoreAllMocks();
|
|
30
|
+
});
|
|
31
|
+
/** In-memory readFileText backed by a path→contents map. */
|
|
32
|
+
function reader(files) {
|
|
33
|
+
return (p) => (p in files ? files[p] : undefined);
|
|
34
|
+
}
|
|
35
|
+
describe('resolveCoordinationToken', () => {
|
|
36
|
+
it('uses an already-set env token and never calls Key Vault', () => {
|
|
37
|
+
const fetchSecret = vi.fn();
|
|
38
|
+
const res = resolveCoordinationToken({
|
|
39
|
+
env: { MX_COORD_SERVICE_TOKEN: 'env-tok', CLAUDE_WORKTREE_PATH: dir },
|
|
40
|
+
fetchSecret,
|
|
41
|
+
});
|
|
42
|
+
expect(res.status).toBe('already-configured');
|
|
43
|
+
expect(res.token).toBe('env-tok');
|
|
44
|
+
expect(fetchSecret).not.toHaveBeenCalled();
|
|
45
|
+
});
|
|
46
|
+
it('uses the per-worktree cache when present and never calls Key Vault', () => {
|
|
47
|
+
const fetchSecret = vi.fn();
|
|
48
|
+
const marker = join(dir, '.mx-coordination-team');
|
|
49
|
+
const cache = join(dir, '.mx-coordination-token-eval');
|
|
50
|
+
const res = resolveCoordinationToken({
|
|
51
|
+
env: { CLAUDE_WORKTREE_PATH: dir },
|
|
52
|
+
readFileText: reader({ [marker]: 'eval\n', [cache]: 'cached-eval-tok\n' }),
|
|
53
|
+
fetchSecret,
|
|
54
|
+
});
|
|
55
|
+
expect(res.status).toBe('resolved');
|
|
56
|
+
expect(res.source).toBe('cache');
|
|
57
|
+
expect(res.token).toBe('cached-eval-tok');
|
|
58
|
+
expect(fetchSecret).not.toHaveBeenCalled();
|
|
59
|
+
});
|
|
60
|
+
it('fetches from Key Vault on a cache miss, caches born-0600, and returns it', () => {
|
|
61
|
+
// Real fs so we can assert the on-disk cache mode.
|
|
62
|
+
writeFileSync(join(dir, '.mx-coordination-team'), 'eval\n');
|
|
63
|
+
const fetchSecret = vi.fn((_vault, name) => {
|
|
64
|
+
expect(name).toBe('coordination-token-eval');
|
|
65
|
+
return 'kv-fetched-tok';
|
|
66
|
+
});
|
|
67
|
+
const res = resolveCoordinationToken({ env: { CLAUDE_WORKTREE_PATH: dir }, fetchSecret });
|
|
68
|
+
expect(res.status).toBe('resolved');
|
|
69
|
+
expect(res.source).toBe('keyvault');
|
|
70
|
+
expect(res.token).toBe('kv-fetched-tok');
|
|
71
|
+
expect(fetchSecret).toHaveBeenCalledWith(KEYVAULT_NAME, 'coordination-token-eval');
|
|
72
|
+
const cachePath = join(dir, '.mx-coordination-token-eval');
|
|
73
|
+
expect(existsSync(cachePath)).toBe(true);
|
|
74
|
+
expect(readFileSync(cachePath, 'utf-8')).toBe('kv-fetched-tok');
|
|
75
|
+
// SF-3: born 0600 — no group/other bits.
|
|
76
|
+
expect(statSync(cachePath).mode & 0o777).toBe(0o600);
|
|
77
|
+
});
|
|
78
|
+
it('fails CLOSED on an unknown-slug marker — no Key Vault fetch', () => {
|
|
79
|
+
const fetchSecret = vi.fn();
|
|
80
|
+
const marker = join(dir, '.mx-coordination-team');
|
|
81
|
+
const res = resolveCoordinationToken({
|
|
82
|
+
env: { CLAUDE_WORKTREE_PATH: dir },
|
|
83
|
+
readFileText: reader({ [marker]: 'not-a-real-team\n' }),
|
|
84
|
+
fetchSecret,
|
|
85
|
+
});
|
|
86
|
+
expect(res.status).toBe('not-on-roster');
|
|
87
|
+
expect(res.slug).toBe('not-a-real-team');
|
|
88
|
+
expect(res.token).toBeUndefined();
|
|
89
|
+
expect(fetchSecret).not.toHaveBeenCalled();
|
|
90
|
+
});
|
|
91
|
+
it('MF-1: a stale cross-team cache is never read — marker=marketing ignores eval cache', () => {
|
|
92
|
+
// The worktree was recycled from eval to marketing: eval's cache lingers, but
|
|
93
|
+
// the marketing marker must fetch marketing's token, never reuse eval's.
|
|
94
|
+
const marker = join(dir, '.mx-coordination-team');
|
|
95
|
+
const evalCache = join(dir, '.mx-coordination-token-eval');
|
|
96
|
+
const fetchSecret = vi.fn(() => 'marketing-tok');
|
|
97
|
+
const res = resolveCoordinationToken({
|
|
98
|
+
env: { CLAUDE_WORKTREE_PATH: dir },
|
|
99
|
+
readFileText: reader({ [marker]: 'marketing\n', [evalCache]: 'STALE-EVAL-TOKEN' }),
|
|
100
|
+
fetchSecret,
|
|
101
|
+
});
|
|
102
|
+
expect(res.slug).toBe('marketing');
|
|
103
|
+
expect(res.token).toBe('marketing-tok');
|
|
104
|
+
expect(res.token).not.toBe('STALE-EVAL-TOKEN');
|
|
105
|
+
// It fetched marketing's secret, never touched eval's.
|
|
106
|
+
expect(fetchSecret).toHaveBeenCalledWith(KEYVAULT_NAME, 'coordination-token-marketing');
|
|
107
|
+
});
|
|
108
|
+
it('fails OPEN when Key Vault / az errors — reports unprovisioned, never throws', () => {
|
|
109
|
+
const marker = join(dir, '.mx-coordination-team');
|
|
110
|
+
// Mock az failure: fetchSecret returns undefined (az not logged in / KV down).
|
|
111
|
+
const fetchSecret = vi.fn(() => undefined);
|
|
112
|
+
const res = resolveCoordinationToken({
|
|
113
|
+
env: { CLAUDE_WORKTREE_PATH: dir },
|
|
114
|
+
readFileText: reader({ [marker]: 'eval\n' }),
|
|
115
|
+
fetchSecret,
|
|
116
|
+
});
|
|
117
|
+
expect(res.status).toBe('unprovisioned');
|
|
118
|
+
expect(res.slug).toBe('eval');
|
|
119
|
+
expect(res.token).toBeUndefined();
|
|
120
|
+
expect(res.detail).toMatch(/Key Vault/);
|
|
121
|
+
});
|
|
122
|
+
it('fails OPEN when the marker is missing', () => {
|
|
123
|
+
const res = resolveCoordinationToken({
|
|
124
|
+
env: { CLAUDE_WORKTREE_PATH: dir },
|
|
125
|
+
readFileText: reader({}),
|
|
126
|
+
fetchSecret: vi.fn(),
|
|
127
|
+
});
|
|
128
|
+
expect(res.status).toBe('unprovisioned');
|
|
129
|
+
expect(res.detail).toMatch(/no coordination marker/);
|
|
130
|
+
});
|
|
131
|
+
it('fails OPEN when CLAUDE_WORKTREE_PATH is unset (no marker to read)', () => {
|
|
132
|
+
const res = resolveCoordinationToken({ env: {}, fetchSecret: vi.fn() });
|
|
133
|
+
expect(res.status).toBe('unprovisioned');
|
|
134
|
+
expect(res.detail).toMatch(/CLAUDE_WORKTREE_PATH/);
|
|
135
|
+
});
|
|
136
|
+
it('SF-A: never throws when the config read throws (unwritable HOME) — continues to the marker path', () => {
|
|
137
|
+
mockGetConfigValue.mockImplementation(() => { throw new Error("EACCES: permission denied, mkdir '/home/nobody/.mx-agent'"); });
|
|
138
|
+
const marker = join(dir, '.mx-coordination-team');
|
|
139
|
+
const cache = join(dir, '.mx-coordination-token-eval');
|
|
140
|
+
let res;
|
|
141
|
+
expect(() => {
|
|
142
|
+
res = resolveCoordinationToken({
|
|
143
|
+
env: { CLAUDE_WORKTREE_PATH: dir },
|
|
144
|
+
readFileText: reader({ [marker]: 'eval\n', [cache]: 'cached-eval-tok' }),
|
|
145
|
+
fetchSecret: vi.fn(),
|
|
146
|
+
});
|
|
147
|
+
}).not.toThrow();
|
|
148
|
+
// The config throw was swallowed → resolution proceeded to the cache.
|
|
149
|
+
expect(res?.status).toBe('resolved');
|
|
150
|
+
expect(res?.token).toBe('cached-eval-tok');
|
|
151
|
+
});
|
|
152
|
+
it('never logs the token to the console', () => {
|
|
153
|
+
const logSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
|
|
154
|
+
const errSpy = vi.spyOn(console, 'error').mockImplementation(() => { });
|
|
155
|
+
const marker = join(dir, '.mx-coordination-team');
|
|
156
|
+
const cache = join(dir, '.mx-coordination-token-eval');
|
|
157
|
+
resolveCoordinationToken({
|
|
158
|
+
env: { CLAUDE_WORKTREE_PATH: dir },
|
|
159
|
+
readFileText: reader({ [marker]: 'eval\n', [cache]: 'secret-token-value' }),
|
|
160
|
+
fetchSecret: vi.fn(() => 'secret-token-value'),
|
|
161
|
+
});
|
|
162
|
+
const all = [...logSpy.mock.calls, ...errSpy.mock.calls].flat().join(' ');
|
|
163
|
+
expect(all).not.toContain('secret-token-value');
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
//# sourceMappingURL=coordination-token.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coordination-token.test.js","sourceRoot":"","sources":["../../src/__tests__/coordination-token.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC;AAEhE,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,gBAAgB,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,MAAM,MAAM,gBAAgB,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC;AAEhE,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,gBAAgB,CAAC;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA8CD,wBAAgB,SAAS,CAAC,OAAO,EAAE,aAAa,GAAG,IAAI,CAuFtD"}
|
package/dist/commands/config.js
CHANGED
|
@@ -18,6 +18,12 @@ const KNOWN_KEYS = {
|
|
|
18
18
|
'coordination-service-url': 'MX Agent Coordination Service base URL (https://...)',
|
|
19
19
|
'coordination-service-token': 'Per-team bearer token for the MX Agent Coordination Service',
|
|
20
20
|
'coordination-brief-enabled': 'Run `mx-agent coordination brief` at session start (true to opt in; default off)',
|
|
21
|
+
'coordination-mode': 'Coordination backend: queue | memory (default memory; `queue` routes escalate/brief to the coordination service)',
|
|
22
|
+
'coordination-team': 'Sender team for memory-mode coordination when no .mx-coordination-team marker is present',
|
|
23
|
+
};
|
|
24
|
+
/** Config keys constrained to a fixed set of values, validated on `set`. */
|
|
25
|
+
const ENUM_KEYS = {
|
|
26
|
+
'coordination-mode': ['queue', 'memory'],
|
|
21
27
|
};
|
|
22
28
|
/** Keys whose value is a secret and must never be echoed in the clear. */
|
|
23
29
|
const SECRET_KEYS = new Set(['observability-api-token', 'coordination-service-token']);
|
|
@@ -55,6 +61,12 @@ export function runConfig(options) {
|
|
|
55
61
|
process.exit(1);
|
|
56
62
|
}
|
|
57
63
|
validateKey(key);
|
|
64
|
+
// Validate enum-constrained keys (e.g. coordination-mode).
|
|
65
|
+
const allowed = ENUM_KEYS[key];
|
|
66
|
+
if (allowed && !allowed.includes(value)) {
|
|
67
|
+
console.error(chalk.red(`Error: ${key} must be one of: ${allowed.join(', ')} (got "${value}").`));
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
58
70
|
// Validate HTTPS for webhook URLs
|
|
59
71
|
if (key === 'slack-webhook') {
|
|
60
72
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAUjG,MAAM,UAAU,GAA2B;IACzC,eAAe,EAAc,oDAAoD;IACjF,uBAAuB,EAAM,0EAA0E;IACvG,yBAAyB,EAAI,uFAAuF;IACpH,0BAA0B,EAAG,sDAAsD;IACnF,4BAA4B,EAAC,6DAA6D;IAC1F,4BAA4B,EAAC,kFAAkF;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,6 +10,37 @@
|
|
|
10
10
|
* only a local durable fallback file and flushes it on the next success.
|
|
11
11
|
*/
|
|
12
12
|
import { type CoordinationClient } from '../lib/coordination-client.js';
|
|
13
|
+
import { type MemoryStore } from '../lib/coordination-memory.js';
|
|
14
|
+
/**
|
|
15
|
+
* Build the HTTP client, self-provisioning the coordination token from Key Vault
|
|
16
|
+
* when none is configured. This ports the coordination-brief hook's KV-fetch into
|
|
17
|
+
* the CLI so a bare `mx-agent coordination brief` (and drain/escalate/history)
|
|
18
|
+
* works standalone with the SAME isolation the security review required (marker
|
|
19
|
+
* authoritative, roster-gated, slug-bound per-worktree 0600 cache, no global-
|
|
20
|
+
* config clobber, no token logging).
|
|
21
|
+
*
|
|
22
|
+
* Returns null — never throws — when a token cannot be provisioned, so the caller
|
|
23
|
+
* degrades cleanly (falls back to the manual channel) instead of crashing:
|
|
24
|
+
* - roster mismatch → fail-CLOSED (no KV fetch), one-line notice.
|
|
25
|
+
* - infra/no-marker → fail-OPEN, one-line notice.
|
|
26
|
+
* When a client IS injected (tests), provisioning is skipped entirely.
|
|
27
|
+
*
|
|
28
|
+
* The resolved token is set in-memory (process env for the request) and is NEVER
|
|
29
|
+
* written to the global ~/.mx-agent config (the MF-2 cross-worktree-clobber
|
|
30
|
+
* defect) and NEVER logged.
|
|
31
|
+
*/
|
|
32
|
+
export declare function prepareClient(deps?: {
|
|
33
|
+
client?: CoordinationClient;
|
|
34
|
+
}): CoordinationClient | null;
|
|
35
|
+
/**
|
|
36
|
+
* Injectable dependencies for the coordination commands. `client` stubs the
|
|
37
|
+
* queue service (queue mode); `memoryStore` stubs the named-memory backend
|
|
38
|
+
* (memory mode). Tests inject one or both; production uses the real defaults.
|
|
39
|
+
*/
|
|
40
|
+
export interface CoordinationDeps {
|
|
41
|
+
client?: CoordinationClient;
|
|
42
|
+
memoryStore?: MemoryStore;
|
|
43
|
+
}
|
|
13
44
|
export interface EscalateOptions {
|
|
14
45
|
to: string;
|
|
15
46
|
priority: string;
|
|
@@ -22,9 +53,7 @@ export interface EscalateOptions {
|
|
|
22
53
|
* (exit 0, non-lossy). On success, any previously queued-locally entries are
|
|
23
54
|
* flushed first.
|
|
24
55
|
*/
|
|
25
|
-
export declare function runEscalate(opts: EscalateOptions, deps?:
|
|
26
|
-
client?: CoordinationClient;
|
|
27
|
-
}): Promise<void>;
|
|
56
|
+
export declare function runEscalate(opts: EscalateOptions, deps?: CoordinationDeps): Promise<void>;
|
|
28
57
|
export interface DrainOptions {
|
|
29
58
|
all?: boolean;
|
|
30
59
|
limit?: string;
|
|
@@ -44,9 +73,7 @@ export interface DrainOptions {
|
|
|
44
73
|
* flushed to stdout, the batch is confirmed (MAJOR-2); a mid-render crash leaves
|
|
45
74
|
* it pending for re-queue. `--no-confirm` leaves the batch unconfirmed.
|
|
46
75
|
*/
|
|
47
|
-
export declare function runDrain(opts: DrainOptions, deps?:
|
|
48
|
-
client?: CoordinationClient;
|
|
49
|
-
}): Promise<void>;
|
|
76
|
+
export declare function runDrain(opts: DrainOptions, deps?: CoordinationDeps): Promise<void>;
|
|
50
77
|
export interface BriefOptions {
|
|
51
78
|
limit?: number;
|
|
52
79
|
/**
|
|
@@ -65,9 +92,7 @@ export interface BriefOptions {
|
|
|
65
92
|
* (a mid-render crash leaves it pending → re-queued). Bodies are truncated to
|
|
66
93
|
* keep the block under the token ceiling for any backlog.
|
|
67
94
|
*/
|
|
68
|
-
export declare function runBrief(opts?: BriefOptions, deps?:
|
|
69
|
-
client?: CoordinationClient;
|
|
70
|
-
}): Promise<void>;
|
|
95
|
+
export declare function runBrief(opts?: BriefOptions, deps?: CoordinationDeps): Promise<void>;
|
|
71
96
|
export interface WatchOptions {
|
|
72
97
|
intervalMs?: number;
|
|
73
98
|
limit?: number;
|
|
@@ -98,14 +123,11 @@ export declare function redactSecrets(s: string): string;
|
|
|
98
123
|
* hint. Full harness onInject + the Redis blocking-read server push stay OUT of
|
|
99
124
|
* scope (see README).
|
|
100
125
|
*/
|
|
101
|
-
export declare function runWatch(opts?: WatchOptions, deps?: {
|
|
102
|
-
client?: CoordinationClient;
|
|
126
|
+
export declare function runWatch(opts?: WatchOptions, deps?: CoordinationDeps & {
|
|
103
127
|
sleep?: (ms: number) => Promise<void>;
|
|
104
128
|
}): Promise<void>;
|
|
105
129
|
/** FR-7 ack. */
|
|
106
|
-
export declare function runAck(messageId: string, deps?:
|
|
107
|
-
client?: CoordinationClient;
|
|
108
|
-
}): Promise<void>;
|
|
130
|
+
export declare function runAck(messageId: string, deps?: CoordinationDeps): Promise<void>;
|
|
109
131
|
export interface HistoryOptions {
|
|
110
132
|
/** Page size (service default 50, cap 200). */
|
|
111
133
|
limit?: string;
|
|
@@ -120,7 +142,5 @@ export interface HistoryOptions {
|
|
|
120
142
|
* payload in a body stays inside the fence and is never emitted raw. `--all`
|
|
121
143
|
* follows the `nextBefore` cursor to page the full history (most-recent-first).
|
|
122
144
|
*/
|
|
123
|
-
export declare function runHistory(opts?: HistoryOptions, deps?:
|
|
124
|
-
client?: CoordinationClient;
|
|
125
|
-
}): Promise<void>;
|
|
145
|
+
export declare function runHistory(opts?: HistoryOptions, deps?: CoordinationDeps): Promise<void>;
|
|
126
146
|
//# sourceMappingURL=coordination.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"coordination.d.ts","sourceRoot":"","sources":["../../src/commands/coordination.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"coordination.d.ts","sourceRoot":"","sources":["../../src/commands/coordination.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAML,KAAK,kBAAkB,EAExB,MAAM,+BAA+B,CAAC;AAIvC,OAAO,EAML,KAAK,WAAW,EACjB,MAAM,+BAA+B,CAAC;AAiCvC;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,aAAa,CAAC,IAAI,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,kBAAkB,CAAA;CAAE,GAAG,kBAAkB,GAAG,IAAI,CAqC/F;AAkCD;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AASD,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAkDD;;;;;GAKG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,eAAe,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqC/F;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,wEAAwE;IACxE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,4EAA4E;IAC5E,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED;;;;;;;GAOG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,YAAY,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CA2BzF;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;GAMG;AACH,wBAAsB,QAAQ,CAAC,IAAI,GAAE,YAAiB,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CA+C9F;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,8EAA8E;IAC9E,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,kFAAkF;AAClF,qBAAa,cAAe,SAAQ,KAAK;;CAKxC;AAQD;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,QAAQ,CAC5B,IAAI,GAAE,YAAiB,EACvB,IAAI,CAAC,EAAE,gBAAgB,GAAG;IAAE,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,GAClE,OAAO,CAAC,IAAI,CAAC,CAyCf;AAED,gBAAgB;AAChB,wBAAsB,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAStF;AAED,MAAM,WAAW,cAAc;IAC7B,+CAA+C;IAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAKD;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAAC,IAAI,GAAE,cAAmB,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAyBlG"}
|
|
@@ -9,9 +9,11 @@
|
|
|
9
9
|
* `escalate` degrades safely when the service is unreachable (FR-8): it writes
|
|
10
10
|
* only a local durable fallback file and flushes it on the next success.
|
|
11
11
|
*/
|
|
12
|
-
import { HttpCoordinationClient, resolveClientConfig, ServiceUnreachableError, ServiceHttpError, } from '../lib/coordination-client.js';
|
|
12
|
+
import { HttpCoordinationClient, resolveClientConfig, resolveCoordinationMode, ServiceUnreachableError, ServiceHttpError, } from '../lib/coordination-client.js';
|
|
13
|
+
import { resolveCoordinationToken } from '../lib/coordination-token.js';
|
|
13
14
|
import { appendFallbackEntry, flushFallback } from '../lib/coordination-fallback.js';
|
|
14
15
|
import { renderMessages } from '../lib/coordination-render.js';
|
|
16
|
+
import { escalateToOutbox, readEscalationsForTeam, renderEscalationBlocks, resolveMemoryTeam, resolveProductSlug, } from '../lib/coordination-memory.js';
|
|
15
17
|
const VALID_PRIORITIES = new Set(['p0', 'p1', 'p2', 'p3']);
|
|
16
18
|
/** Truncate each body to this many chars in the brief (token-ceiling control). */
|
|
17
19
|
const BRIEF_BODY_MAX_CHARS = 500;
|
|
@@ -38,9 +40,60 @@ function flushStdout() {
|
|
|
38
40
|
process.stdout.write('', () => resolve());
|
|
39
41
|
});
|
|
40
42
|
}
|
|
41
|
-
/**
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
/**
|
|
44
|
+
* Build the HTTP client, self-provisioning the coordination token from Key Vault
|
|
45
|
+
* when none is configured. This ports the coordination-brief hook's KV-fetch into
|
|
46
|
+
* the CLI so a bare `mx-agent coordination brief` (and drain/escalate/history)
|
|
47
|
+
* works standalone with the SAME isolation the security review required (marker
|
|
48
|
+
* authoritative, roster-gated, slug-bound per-worktree 0600 cache, no global-
|
|
49
|
+
* config clobber, no token logging).
|
|
50
|
+
*
|
|
51
|
+
* Returns null — never throws — when a token cannot be provisioned, so the caller
|
|
52
|
+
* degrades cleanly (falls back to the manual channel) instead of crashing:
|
|
53
|
+
* - roster mismatch → fail-CLOSED (no KV fetch), one-line notice.
|
|
54
|
+
* - infra/no-marker → fail-OPEN, one-line notice.
|
|
55
|
+
* When a client IS injected (tests), provisioning is skipped entirely.
|
|
56
|
+
*
|
|
57
|
+
* The resolved token is set in-memory (process env for the request) and is NEVER
|
|
58
|
+
* written to the global ~/.mx-agent config (the MF-2 cross-worktree-clobber
|
|
59
|
+
* defect) and NEVER logged.
|
|
60
|
+
*/
|
|
61
|
+
export function prepareClient(deps) {
|
|
62
|
+
if (deps?.client)
|
|
63
|
+
return deps.client;
|
|
64
|
+
// SF-A never-crash contract: resolveCoordinationToken is documented never-throws,
|
|
65
|
+
// but its config read can still touch the filesystem (mkdirSync on an unwritable/
|
|
66
|
+
// read-only HOME → EACCES/EROFS). Keep the WHOLE resolve+build inside the
|
|
67
|
+
// try/catch so ANY throw degrades to the null fall-back path — a coordination
|
|
68
|
+
// hiccup must never crash `mx-agent coordination brief` (breaks session start).
|
|
69
|
+
let res = { status: 'unprovisioned', detail: 'token resolution failed' };
|
|
70
|
+
try {
|
|
71
|
+
res = resolveCoordinationToken();
|
|
72
|
+
if (res.status === 'resolved' && res.token) {
|
|
73
|
+
// In-memory only: resolveClientConfig reads MX_COORD_SERVICE_TOKEN in
|
|
74
|
+
// preference to the global config, so we never touch the shared config file.
|
|
75
|
+
process.env.MX_COORD_SERVICE_TOKEN = res.token;
|
|
76
|
+
// SF-B: arm the SF-1 verify-before-confirm interlock on the bare
|
|
77
|
+
// self-provisioned path, matching the hook (which set MX_COORD_EXPECT_TEAM).
|
|
78
|
+
// `??=` so an explicit hook-set value is never overwritten.
|
|
79
|
+
if (res.slug)
|
|
80
|
+
process.env.MX_COORD_EXPECT_TEAM ??= res.slug;
|
|
81
|
+
}
|
|
82
|
+
return new HttpCoordinationClient(resolveClientConfig());
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
// No usable token/URL (or a resolve-time throw). Report a non-secret, one-line
|
|
86
|
+
// fall-back notice and return null; the caller returns cleanly so the agent
|
|
87
|
+
// uses the old channel.
|
|
88
|
+
if (res.status === 'not-on-roster') {
|
|
89
|
+
process.stderr.write(`coordination: team "${res.slug}" is not on the coordination roster — falling back to the manual channel\n`);
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
const why = res.detail ?? (err instanceof Error ? err.message : String(err));
|
|
93
|
+
process.stderr.write(`coordination: could not provision a service token (${why}) — falling back to the manual channel\n`);
|
|
94
|
+
}
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
44
97
|
}
|
|
45
98
|
/**
|
|
46
99
|
* Opportunistically flush any queued-locally entries. Surfaces a flush FAILURE
|
|
@@ -74,6 +127,52 @@ function writeFallbackOrFail(entry) {
|
|
|
74
127
|
throw err;
|
|
75
128
|
}
|
|
76
129
|
}
|
|
130
|
+
/** One-line note printed when a queue-only subcommand runs in memory mode. */
|
|
131
|
+
function memoryModeQueueOnlyNote(subcommand) {
|
|
132
|
+
console.log(`coordination-mode=memory: ${subcommand} is queue-only; use \`mx-agent coordination brief\` to read the shared escalations doc`);
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* memory-mode escalate: append the entry to the sender's outbox memory
|
|
136
|
+
* `<slug>-escalations-<from-team>-outbox` via fetch-edit-verify. No token, no
|
|
137
|
+
* queue service. A failed byte-verify is a hard error (exit 1) so a clobbered
|
|
138
|
+
* or dropped write is never silently reported as success.
|
|
139
|
+
*/
|
|
140
|
+
async function runEscalateMemory(opts, deps) {
|
|
141
|
+
const team = resolveMemoryTeam(opts.team);
|
|
142
|
+
const slug = resolveProductSlug();
|
|
143
|
+
let res;
|
|
144
|
+
try {
|
|
145
|
+
res = escalateToOutbox({ fromTeam: team, to: opts.to, priority: opts.priority, body: opts.body, productSlug: slug }, deps?.memoryStore);
|
|
146
|
+
}
|
|
147
|
+
catch (err) {
|
|
148
|
+
// A MemNexus write failure is surfaced (not swallowed) — the message is not
|
|
149
|
+
// queued, so the operator must see it. Exit non-zero.
|
|
150
|
+
console.error(`Error: memory-mode escalate failed to write the outbox: ${err instanceof Error ? err.message : String(err)}`);
|
|
151
|
+
process.exit(1);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
if (!res.verified) {
|
|
155
|
+
console.error(`Error: memory-mode escalate could not verify the outbox write (${res.name}) — the entry may not have persisted. Not marking as sent.`);
|
|
156
|
+
process.exit(1);
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
console.log(`escalated to ${res.name} (memory mode) -> ${opts.to} [${opts.priority}]${res.created ? ' (outbox created)' : ''}`);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* memory-mode brief: read the shared escalations doc and render entries
|
|
163
|
+
* addressed to this team inside the provenance fence. Read-only — there is no
|
|
164
|
+
* drain/confirm in memory mode.
|
|
165
|
+
*/
|
|
166
|
+
async function runBriefMemory(opts, deps) {
|
|
167
|
+
const team = opts.expectedTeam ?? resolveMemoryTeam();
|
|
168
|
+
const slug = resolveProductSlug();
|
|
169
|
+
const { present, entries } = readEscalationsForTeam(team, slug, deps?.memoryStore);
|
|
170
|
+
if (!present || entries.length === 0) {
|
|
171
|
+
console.log('no cross-team coordination pending');
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
console.log(renderEscalationBlocks(entries));
|
|
175
|
+
}
|
|
77
176
|
/**
|
|
78
177
|
* FR-7 enqueue + FR-8 degraded fallback. On a transport failure the message is
|
|
79
178
|
* written to the local durable fallback file and reported as queued-locally
|
|
@@ -85,16 +184,17 @@ export async function runEscalate(opts, deps) {
|
|
|
85
184
|
console.error(`Error: --priority must be one of p0, p1, p2, p3 (got "${opts.priority}").`);
|
|
86
185
|
process.exit(1);
|
|
87
186
|
}
|
|
187
|
+
// Backend routing (PO one-interface design). memory mode requires NO token.
|
|
188
|
+
if (resolveCoordinationMode() === 'memory') {
|
|
189
|
+
return runEscalateMemory(opts, deps);
|
|
190
|
+
}
|
|
88
191
|
const team = resolveTeam(opts.team);
|
|
89
192
|
const entry = { team, to: opts.to, priority: opts.priority, body: opts.body, from: team };
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
catch (err) {
|
|
95
|
-
// No config at all — still degrade to the local fallback so nothing is lost.
|
|
193
|
+
const client = prepareClient(deps);
|
|
194
|
+
if (!client) {
|
|
195
|
+
// No token/URL could be provisioned (prepareClient already printed the reason).
|
|
196
|
+
// Degrade to the local fallback so the message is never lost.
|
|
96
197
|
writeFallbackOrFail(entry);
|
|
97
|
-
console.error(err instanceof Error ? err.message : String(err));
|
|
98
198
|
console.log('queued locally, will flush on reconnect');
|
|
99
199
|
return;
|
|
100
200
|
}
|
|
@@ -123,7 +223,13 @@ export async function runEscalate(opts, deps) {
|
|
|
123
223
|
* it pending for re-queue. `--no-confirm` leaves the batch unconfirmed.
|
|
124
224
|
*/
|
|
125
225
|
export async function runDrain(opts, deps) {
|
|
126
|
-
|
|
226
|
+
if (resolveCoordinationMode() === 'memory') {
|
|
227
|
+
memoryModeQueueOnlyNote('drain');
|
|
228
|
+
return; // exit 0 — no crash
|
|
229
|
+
}
|
|
230
|
+
const client = prepareClient(deps);
|
|
231
|
+
if (!client)
|
|
232
|
+
return; // could not provision — fall back (prepareClient printed why)
|
|
127
233
|
// Flush any queued-locally entries now that the service is reachable.
|
|
128
234
|
await opportunisticFlush(client);
|
|
129
235
|
const limit = opts.all ? undefined : opts.limit ? parseInt(opts.limit, 10) : undefined;
|
|
@@ -152,7 +258,12 @@ export async function runDrain(opts, deps) {
|
|
|
152
258
|
* keep the block under the token ceiling for any backlog.
|
|
153
259
|
*/
|
|
154
260
|
export async function runBrief(opts = {}, deps) {
|
|
155
|
-
|
|
261
|
+
if (resolveCoordinationMode() === 'memory') {
|
|
262
|
+
return runBriefMemory(opts, deps);
|
|
263
|
+
}
|
|
264
|
+
const client = prepareClient(deps);
|
|
265
|
+
if (!client)
|
|
266
|
+
return; // could not provision — fall back (prepareClient printed why)
|
|
156
267
|
await opportunisticFlush(client);
|
|
157
268
|
const limit = opts.limit ?? envInt('MX_COORD_BRIEF_LIMIT', 10);
|
|
158
269
|
const res = await client.drain({ limit });
|
|
@@ -226,7 +337,13 @@ export function redactSecrets(s) {
|
|
|
226
337
|
* scope (see README).
|
|
227
338
|
*/
|
|
228
339
|
export async function runWatch(opts = {}, deps) {
|
|
229
|
-
|
|
340
|
+
if (resolveCoordinationMode() === 'memory') {
|
|
341
|
+
memoryModeQueueOnlyNote('watch');
|
|
342
|
+
return; // exit 0 — no crash
|
|
343
|
+
}
|
|
344
|
+
const client = prepareClient(deps);
|
|
345
|
+
if (!client)
|
|
346
|
+
return; // could not provision — fall back (prepareClient printed why)
|
|
230
347
|
const intervalMs = opts.intervalMs ?? envInt('MX_COORD_PRIORITY_POLL_MS', 15_000);
|
|
231
348
|
const limit = opts.limit ?? envInt('MX_COORD_BRIEF_LIMIT', 10);
|
|
232
349
|
const sleep = deps?.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
@@ -266,7 +383,13 @@ export async function runWatch(opts = {}, deps) {
|
|
|
266
383
|
}
|
|
267
384
|
/** FR-7 ack. */
|
|
268
385
|
export async function runAck(messageId, deps) {
|
|
269
|
-
|
|
386
|
+
if (resolveCoordinationMode() === 'memory') {
|
|
387
|
+
memoryModeQueueOnlyNote('ack');
|
|
388
|
+
return; // exit 0 — no crash
|
|
389
|
+
}
|
|
390
|
+
const client = prepareClient(deps);
|
|
391
|
+
if (!client)
|
|
392
|
+
return; // could not provision — fall back (prepareClient printed why)
|
|
270
393
|
await client.ack(messageId);
|
|
271
394
|
console.log(`acked: ${messageId}`);
|
|
272
395
|
}
|
|
@@ -281,7 +404,13 @@ const HISTORY_MAX_PAGES = 500;
|
|
|
281
404
|
* follows the `nextBefore` cursor to page the full history (most-recent-first).
|
|
282
405
|
*/
|
|
283
406
|
export async function runHistory(opts = {}, deps) {
|
|
284
|
-
|
|
407
|
+
if (resolveCoordinationMode() === 'memory') {
|
|
408
|
+
memoryModeQueueOnlyNote('history');
|
|
409
|
+
return; // exit 0 — no crash
|
|
410
|
+
}
|
|
411
|
+
const client = prepareClient(deps);
|
|
412
|
+
if (!client)
|
|
413
|
+
return; // could not provision — fall back (prepareClient printed why)
|
|
285
414
|
const limit = opts.limit ? parseInt(opts.limit, 10) : undefined;
|
|
286
415
|
const collected = [];
|
|
287
416
|
let before;
|