@de-otio/repo-aegis-mcp 0.5.0 → 0.7.0
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/package.json +4 -3
- package/dist/server.test.d.ts +0 -2
- package/dist/server.test.d.ts.map +0 -1
- package/dist/server.test.js +0 -171
- package/dist/server.test.js.map +0 -1
- package/dist/tools/first-touch.test.d.ts +0 -2
- package/dist/tools/first-touch.test.d.ts.map +0 -1
- package/dist/tools/first-touch.test.js +0 -224
- package/dist/tools/first-touch.test.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@de-otio/repo-aegis-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Model Context Protocol server wrapping repo-aegis as agent-readable tools",
|
|
5
5
|
"license": "GPL-3.0-or-later",
|
|
6
6
|
"author": "Richard Myers",
|
|
@@ -22,13 +22,14 @@
|
|
|
22
22
|
}
|
|
23
23
|
},
|
|
24
24
|
"files": [
|
|
25
|
-
"dist"
|
|
25
|
+
"dist",
|
|
26
|
+
"!**/*.test.*"
|
|
26
27
|
],
|
|
27
28
|
"scripts": {
|
|
28
29
|
"build": "tsc && chmod +x dist/index.js"
|
|
29
30
|
},
|
|
30
31
|
"dependencies": {
|
|
31
|
-
"@de-otio/repo-aegis-core": "^0.
|
|
32
|
+
"@de-otio/repo-aegis-core": "^0.7.0",
|
|
32
33
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
33
34
|
"zod": "^4.4.3"
|
|
34
35
|
}
|
package/dist/server.test.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"server.test.d.ts","sourceRoot":"","sources":["../src/server.test.ts"],"names":[],"mappings":""}
|
package/dist/server.test.js
DELETED
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
-
// Copyright (C) 2026 Richard Myers and contributors.
|
|
3
|
-
// Smoke test for the MCP server: boot it with an in-memory transport pair,
|
|
4
|
-
// list tools, and call one tool end-to-end. Verifies that:
|
|
5
|
-
// - every tool the server should register is actually registered;
|
|
6
|
-
// - a non-trivial tool (status) returns valid JSON of the expected shape;
|
|
7
|
-
// - the redaction policy holds (no literal markers in any output).
|
|
8
|
-
//
|
|
9
|
-
// Skips gracefully if the MCP SDK isn't installed in node_modules — useful
|
|
10
|
-
// in environments where the workspace install hasn't run yet.
|
|
11
|
-
import { describe, it, before, after } from "node:test";
|
|
12
|
-
import assert from "node:assert/strict";
|
|
13
|
-
import { execFileSync } from "node:child_process";
|
|
14
|
-
import { mkdirSync, mkdtempSync, rmSync, writeFileSync, } from "node:fs";
|
|
15
|
-
import { tmpdir } from "node:os";
|
|
16
|
-
import { join } from "node:path";
|
|
17
|
-
const EXPECTED_TOOLS = [
|
|
18
|
-
"repo_aegis_status",
|
|
19
|
-
"repo_aegis_check_path",
|
|
20
|
-
"repo_aegis_check_staged",
|
|
21
|
-
"repo_aegis_engagements_list",
|
|
22
|
-
"repo_aegis_engagements_show",
|
|
23
|
-
"repo_aegis_markers_test",
|
|
24
|
-
"repo_aegis_markers_list",
|
|
25
|
-
"repo_aegis_audit",
|
|
26
|
-
"aegis_classify_first_touch",
|
|
27
|
-
];
|
|
28
|
-
async function loadHarness() {
|
|
29
|
-
try {
|
|
30
|
-
const [{ buildServer }, { Client }, { InMemoryTransport }] = await Promise.all([
|
|
31
|
-
import("./server.js"),
|
|
32
|
-
import("@modelcontextprotocol/sdk/client/index.js"),
|
|
33
|
-
import("@modelcontextprotocol/sdk/inMemory.js"),
|
|
34
|
-
]);
|
|
35
|
-
return { buildServer, Client, InMemoryTransport };
|
|
36
|
-
}
|
|
37
|
-
catch {
|
|
38
|
-
return null;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
const harness = await loadHarness();
|
|
42
|
-
if (!harness) {
|
|
43
|
-
describe("repo-aegis MCP server (skipped: SDK not installed)", () => {
|
|
44
|
-
it("skips when @modelcontextprotocol/sdk isn't resolvable", { skip: true }, () => {
|
|
45
|
-
/* skipped */
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
else {
|
|
50
|
-
const { buildServer, Client, InMemoryTransport } = harness;
|
|
51
|
-
let tmp;
|
|
52
|
-
let home;
|
|
53
|
-
let repo;
|
|
54
|
-
before(async () => {
|
|
55
|
-
tmp = mkdtempSync(join(tmpdir(), "repo-aegis-mcp-test-"));
|
|
56
|
-
home = join(tmp, "home");
|
|
57
|
-
const markersDir = join(home, "markers");
|
|
58
|
-
const stateDir = join(home, "state");
|
|
59
|
-
mkdirSync(markersDir, { recursive: true });
|
|
60
|
-
mkdirSync(stateDir, { recursive: true });
|
|
61
|
-
// No engagements / no marker files: status should report an empty
|
|
62
|
-
// deny set and zero patterns. We do NOT scaffold a registry.yaml here
|
|
63
|
-
// because we're testing the "fresh install" path; loadRegistry's
|
|
64
|
-
// RegistryNotFoundError is silently absorbed by the status tool.
|
|
65
|
-
process.env["REPO_AEGIS_HOME"] = home;
|
|
66
|
-
repo = join(tmp, "repo");
|
|
67
|
-
mkdirSync(repo, { recursive: true });
|
|
68
|
-
execFileSync("git", ["init", "-q"], { cwd: repo });
|
|
69
|
-
execFileSync("git", ["config", "user.name", "test"], { cwd: repo });
|
|
70
|
-
execFileSync("git", ["config", "user.email", "test@example.com"], { cwd: repo });
|
|
71
|
-
// Class: private-strict (default). No engagements.
|
|
72
|
-
});
|
|
73
|
-
after(() => {
|
|
74
|
-
delete process.env["REPO_AEGIS_HOME"];
|
|
75
|
-
rmSync(tmp, { recursive: true, force: true });
|
|
76
|
-
});
|
|
77
|
-
describe("repo-aegis MCP server", () => {
|
|
78
|
-
it("registers every expected tool", async () => {
|
|
79
|
-
const server = buildServer();
|
|
80
|
-
const client = new Client({ name: "test-client", version: "0.0.0" });
|
|
81
|
-
const [serverTransport, clientTransport] = InMemoryTransport.createLinkedPair();
|
|
82
|
-
await Promise.all([server.connect(serverTransport), client.connect(clientTransport)]);
|
|
83
|
-
try {
|
|
84
|
-
const list = await client.listTools();
|
|
85
|
-
const names = list.tools.map(t => t.name).sort();
|
|
86
|
-
for (const expected of EXPECTED_TOOLS) {
|
|
87
|
-
assert.ok(names.includes(expected), `expected tool ${expected} to be registered; got ${names.join(", ")}`);
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
finally {
|
|
91
|
-
await client.close();
|
|
92
|
-
await server.close();
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
|
-
it("repo_aegis_status returns the canonical shape against a tmp git repo", async () => {
|
|
96
|
-
const server = buildServer();
|
|
97
|
-
const client = new Client({ name: "test-client", version: "0.0.0" });
|
|
98
|
-
const [serverTransport, clientTransport] = InMemoryTransport.createLinkedPair();
|
|
99
|
-
await Promise.all([server.connect(serverTransport), client.connect(clientTransport)]);
|
|
100
|
-
try {
|
|
101
|
-
const result = await client.callTool({
|
|
102
|
-
name: "repo_aegis_status",
|
|
103
|
-
arguments: { cwd: repo },
|
|
104
|
-
});
|
|
105
|
-
assert.equal(result.isError, undefined);
|
|
106
|
-
const content = result.content;
|
|
107
|
-
assert.ok(content && content.length > 0, "expected content array");
|
|
108
|
-
const text = content[0].text;
|
|
109
|
-
assert.ok(typeof text === "string", "expected text content");
|
|
110
|
-
const parsed = JSON.parse(text);
|
|
111
|
-
assert.equal(parsed.repo.isGitRepo, true);
|
|
112
|
-
assert.equal(parsed.repo.class, "private-strict");
|
|
113
|
-
assert.deepEqual(parsed.repo.engagements, []);
|
|
114
|
-
assert.equal(parsed.denySet.patternCount, 0);
|
|
115
|
-
assert.deepEqual(parsed.allowedEngagements, []);
|
|
116
|
-
}
|
|
117
|
-
finally {
|
|
118
|
-
await client.close();
|
|
119
|
-
await server.close();
|
|
120
|
-
}
|
|
121
|
-
});
|
|
122
|
-
it("repo_aegis_markers_test redacts the input and returns no hits when deny set is empty", async () => {
|
|
123
|
-
const server = buildServer();
|
|
124
|
-
const client = new Client({ name: "test-client", version: "0.0.0" });
|
|
125
|
-
const [serverTransport, clientTransport] = InMemoryTransport.createLinkedPair();
|
|
126
|
-
await Promise.all([server.connect(serverTransport), client.connect(clientTransport)]);
|
|
127
|
-
try {
|
|
128
|
-
const result = await client.callTool({
|
|
129
|
-
name: "repo_aegis_markers_test",
|
|
130
|
-
arguments: { input: "some-private-string", cwd: repo },
|
|
131
|
-
});
|
|
132
|
-
assert.equal(result.isError, undefined);
|
|
133
|
-
const content = result.content;
|
|
134
|
-
const parsed = JSON.parse(content[0].text);
|
|
135
|
-
// Input must be redacted in the response — never returned verbatim.
|
|
136
|
-
assert.notEqual(parsed.input, "some-private-string");
|
|
137
|
-
assert.ok(parsed.input.length > 0);
|
|
138
|
-
assert.deepEqual(parsed.hits, []);
|
|
139
|
-
// Avoid asserting "input does not contain literal" too eagerly — the
|
|
140
|
-
// redactMatch preview keeps a short prefix. The important invariant
|
|
141
|
-
// is "not equal to literal", which we check above.
|
|
142
|
-
void writeFileSync; // keep import used
|
|
143
|
-
}
|
|
144
|
-
finally {
|
|
145
|
-
await client.close();
|
|
146
|
-
await server.close();
|
|
147
|
-
}
|
|
148
|
-
});
|
|
149
|
-
it("repo_aegis_engagements_list returns REGISTRY_NOT_FOUND when no registry exists", async () => {
|
|
150
|
-
const server = buildServer();
|
|
151
|
-
const client = new Client({ name: "test-client", version: "0.0.0" });
|
|
152
|
-
const [serverTransport, clientTransport] = InMemoryTransport.createLinkedPair();
|
|
153
|
-
await Promise.all([server.connect(serverTransport), client.connect(clientTransport)]);
|
|
154
|
-
try {
|
|
155
|
-
const result = await client.callTool({
|
|
156
|
-
name: "repo_aegis_engagements_list",
|
|
157
|
-
arguments: {},
|
|
158
|
-
});
|
|
159
|
-
assert.equal(result.isError, true);
|
|
160
|
-
const content = result.content;
|
|
161
|
-
const parsed = JSON.parse(content[0].text);
|
|
162
|
-
assert.equal(parsed.code, "REGISTRY_NOT_FOUND");
|
|
163
|
-
}
|
|
164
|
-
finally {
|
|
165
|
-
await client.close();
|
|
166
|
-
await server.close();
|
|
167
|
-
}
|
|
168
|
-
});
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
|
-
//# sourceMappingURL=server.test.js.map
|
package/dist/server.test.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"server.test.js","sourceRoot":"","sources":["../src/server.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"first-touch.test.d.ts","sourceRoot":"","sources":["../../src/tools/first-touch.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,224 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
2
|
-
// Copyright (C) 2026 Richard Myers and contributors.
|
|
3
|
-
//
|
|
4
|
-
// Unit tests for the `aegis_classify_first_touch` MCP tool. The tests
|
|
5
|
-
// drive `firstTouchClassify` directly (the impl function exported from
|
|
6
|
-
// the tool module) so we can spin up real git fixtures and a real
|
|
7
|
-
// registry per case without paying the MCP transport overhead. The
|
|
8
|
-
// server-side smoke test in server.test.ts covers tool registration
|
|
9
|
-
// and one end-to-end call.
|
|
10
|
-
import { describe, it, before, after, beforeEach } from "node:test";
|
|
11
|
-
import assert from "node:assert/strict";
|
|
12
|
-
import { execFileSync } from "node:child_process";
|
|
13
|
-
import { mkdtempSync, mkdirSync, rmSync, writeFileSync, } from "node:fs";
|
|
14
|
-
import { tmpdir } from "node:os";
|
|
15
|
-
import { join } from "node:path";
|
|
16
|
-
import { firstTouchClassify, redactOrg } from "./first-touch.js";
|
|
17
|
-
let tmp;
|
|
18
|
-
let gitDir;
|
|
19
|
-
let nonGitDir;
|
|
20
|
-
let registryPath;
|
|
21
|
-
function git(cwd, args) {
|
|
22
|
-
execFileSync("git", args, {
|
|
23
|
-
cwd,
|
|
24
|
-
stdio: ["ignore", "pipe", "ignore"],
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
function setRemote(cwd, url) {
|
|
28
|
-
try {
|
|
29
|
-
git(cwd, ["remote", "remove", "origin"]);
|
|
30
|
-
}
|
|
31
|
-
catch {
|
|
32
|
-
/* not set */
|
|
33
|
-
}
|
|
34
|
-
git(cwd, ["remote", "add", "origin", url]);
|
|
35
|
-
}
|
|
36
|
-
function removeRemote(cwd) {
|
|
37
|
-
try {
|
|
38
|
-
git(cwd, ["remote", "remove", "origin"]);
|
|
39
|
-
}
|
|
40
|
-
catch {
|
|
41
|
-
/* not set */
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
function unsetClass(cwd) {
|
|
45
|
-
try {
|
|
46
|
-
execFileSync("git", ["config", "--unset", "repo-aegis.class"], {
|
|
47
|
-
cwd,
|
|
48
|
-
stdio: ["ignore", "ignore", "ignore"],
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
catch {
|
|
52
|
-
/* not set */
|
|
53
|
-
}
|
|
54
|
-
try {
|
|
55
|
-
execFileSync("git", ["config", "--unset-all", "repo-aegis.engagement"], {
|
|
56
|
-
cwd,
|
|
57
|
-
stdio: ["ignore", "ignore", "ignore"],
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
catch {
|
|
61
|
-
/* not set */
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
function writeRegistry(body) {
|
|
65
|
-
writeFileSync(registryPath, body, { mode: 0o600 });
|
|
66
|
-
}
|
|
67
|
-
before(() => {
|
|
68
|
-
tmp = mkdtempSync(join(tmpdir(), "repo-aegis-first-touch-"));
|
|
69
|
-
gitDir = join(tmp, "git");
|
|
70
|
-
nonGitDir = join(tmp, "non-git");
|
|
71
|
-
registryPath = join(tmp, "engagements.yaml");
|
|
72
|
-
mkdirSync(gitDir, { recursive: true });
|
|
73
|
-
mkdirSync(nonGitDir, { recursive: true });
|
|
74
|
-
git(gitDir, ["init", "-q", "-b", "main"]);
|
|
75
|
-
git(gitDir, ["config", "user.email", "test@example.com"]);
|
|
76
|
-
git(gitDir, ["config", "user.name", "test"]);
|
|
77
|
-
process.env["REPO_AEGIS_REGISTRY"] = registryPath;
|
|
78
|
-
});
|
|
79
|
-
after(() => {
|
|
80
|
-
delete process.env["REPO_AEGIS_REGISTRY"];
|
|
81
|
-
rmSync(tmp, { recursive: true, force: true });
|
|
82
|
-
});
|
|
83
|
-
beforeEach(() => {
|
|
84
|
-
unsetClass(gitDir);
|
|
85
|
-
removeRemote(gitDir);
|
|
86
|
-
});
|
|
87
|
-
describe("firstTouchClassify — skipped paths", () => {
|
|
88
|
-
it("non-git cwd → status: skipped, reason: non-git", () => {
|
|
89
|
-
const result = firstTouchClassify({ cwd: nonGitDir });
|
|
90
|
-
assert.equal(result.status, "skipped");
|
|
91
|
-
if (result.status === "skipped") {
|
|
92
|
-
assert.equal(result.reason, "non-git");
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
|
-
it("git repo with no remote → status: skipped, reason: no-remote", () => {
|
|
96
|
-
writeRegistry(`schemaVersion: 2\nengagements: []\n`);
|
|
97
|
-
const result = firstTouchClassify({ cwd: gitDir });
|
|
98
|
-
assert.equal(result.status, "skipped");
|
|
99
|
-
if (result.status === "skipped") {
|
|
100
|
-
assert.equal(result.reason, "no-remote");
|
|
101
|
-
}
|
|
102
|
-
});
|
|
103
|
-
it("non-github remote → status: skipped, reason: non-github-host", () => {
|
|
104
|
-
writeRegistry(`schemaVersion: 2\nengagements: []\n`);
|
|
105
|
-
setRemote(gitDir, "git@gitlab.com:foo/bar.git");
|
|
106
|
-
const result = firstTouchClassify({ cwd: gitDir });
|
|
107
|
-
assert.equal(result.status, "skipped");
|
|
108
|
-
if (result.status === "skipped") {
|
|
109
|
-
assert.equal(result.reason, "non-github-host");
|
|
110
|
-
}
|
|
111
|
-
});
|
|
112
|
-
it("registry not found → status: skipped, reason: registry-not-found", () => {
|
|
113
|
-
rmSync(registryPath, { force: true });
|
|
114
|
-
setRemote(gitDir, "git@github.com:foo/bar.git");
|
|
115
|
-
const result = firstTouchClassify({ cwd: gitDir });
|
|
116
|
-
assert.equal(result.status, "skipped");
|
|
117
|
-
if (result.status === "skipped") {
|
|
118
|
-
assert.equal(result.reason, "registry-not-found");
|
|
119
|
-
}
|
|
120
|
-
});
|
|
121
|
-
});
|
|
122
|
-
describe("firstTouchClassify — already-classified", () => {
|
|
123
|
-
it("returns status: already-classified when class is already set", () => {
|
|
124
|
-
writeRegistry(`schemaVersion: 2\nengagements: []\n`);
|
|
125
|
-
setRemote(gitDir, "git@github.com:foo/bar.git");
|
|
126
|
-
execFileSync("git", ["config", "repo-aegis.class", "private-strict"], {
|
|
127
|
-
cwd: gitDir,
|
|
128
|
-
});
|
|
129
|
-
const result = firstTouchClassify({ cwd: gitDir });
|
|
130
|
-
assert.equal(result.status, "already-classified");
|
|
131
|
-
if (result.status === "already-classified") {
|
|
132
|
-
assert.equal(result.class, "private-strict");
|
|
133
|
-
}
|
|
134
|
-
});
|
|
135
|
-
});
|
|
136
|
-
describe("firstTouchClassify — applied", () => {
|
|
137
|
-
it("personalOrgs match → applied, class: public-eligible", () => {
|
|
138
|
-
writeRegistry(`schemaVersion: 2
|
|
139
|
-
personalOrgs: [my-handle]
|
|
140
|
-
engagements: []
|
|
141
|
-
`);
|
|
142
|
-
setRemote(gitDir, "git@github.com:my-handle/dotfiles.git");
|
|
143
|
-
const result = firstTouchClassify({ cwd: gitDir });
|
|
144
|
-
assert.equal(result.status, "applied");
|
|
145
|
-
if (result.status === "applied") {
|
|
146
|
-
assert.equal(result.class, "public-eligible");
|
|
147
|
-
assert.equal(result.engagement, null);
|
|
148
|
-
assert.equal(result.markerWarning, null);
|
|
149
|
-
}
|
|
150
|
-
});
|
|
151
|
-
it("engagement match with markers → applied, class: customer-coupled, markerWarning: null", () => {
|
|
152
|
-
writeRegistry(`schemaVersion: 2
|
|
153
|
-
engagements:
|
|
154
|
-
- id: foo-corp
|
|
155
|
-
name: Foo Corp
|
|
156
|
-
githubOrgs: [foo-corp]
|
|
157
|
-
markers: [foo-marker]
|
|
158
|
-
`);
|
|
159
|
-
setRemote(gitDir, "git@github.com:foo-corp/proj.git");
|
|
160
|
-
const result = firstTouchClassify({ cwd: gitDir });
|
|
161
|
-
assert.equal(result.status, "applied");
|
|
162
|
-
if (result.status === "applied") {
|
|
163
|
-
assert.equal(result.class, "customer-coupled");
|
|
164
|
-
assert.equal(result.engagement, "foo-corp");
|
|
165
|
-
assert.equal(result.markerWarning, null);
|
|
166
|
-
}
|
|
167
|
-
});
|
|
168
|
-
it("[SEC H-5] engagement match with zero markers → applied with markerWarning", () => {
|
|
169
|
-
writeRegistry(`schemaVersion: 2
|
|
170
|
-
engagements:
|
|
171
|
-
- id: bare-co
|
|
172
|
-
name: Bare Co
|
|
173
|
-
githubOrgs: [bare-co]
|
|
174
|
-
markers: []
|
|
175
|
-
`);
|
|
176
|
-
setRemote(gitDir, "git@github.com:bare-co/proj.git");
|
|
177
|
-
const result = firstTouchClassify({ cwd: gitDir });
|
|
178
|
-
assert.equal(result.status, "applied");
|
|
179
|
-
if (result.status === "applied") {
|
|
180
|
-
assert.deepEqual(result.markerWarning, {
|
|
181
|
-
engagementId: "bare-co",
|
|
182
|
-
count: 0,
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
});
|
|
186
|
-
});
|
|
187
|
-
describe("firstTouchClassify — needs-confirmation", () => {
|
|
188
|
-
it("unknown org → status: needs-confirmation with redactedOrg", () => {
|
|
189
|
-
writeRegistry(`schemaVersion: 2\nengagements: []\n`);
|
|
190
|
-
setRemote(gitDir, "git@github.com:unknown-org/proj.git");
|
|
191
|
-
const result = firstTouchClassify({ cwd: gitDir });
|
|
192
|
-
assert.equal(result.status, "needs-confirmation");
|
|
193
|
-
if (result.status === "needs-confirmation") {
|
|
194
|
-
assert.equal(result.org, "unknown-org");
|
|
195
|
-
assert.notEqual(result.redactedOrg, result.org);
|
|
196
|
-
assert.match(result.redactedOrg, /^un\*\*\*g$/);
|
|
197
|
-
assert.ok("newEngagement" in result.suggestion);
|
|
198
|
-
}
|
|
199
|
-
});
|
|
200
|
-
it("does not mutate per-repo config on needs-confirmation", () => {
|
|
201
|
-
writeRegistry(`schemaVersion: 2\nengagements: []\n`);
|
|
202
|
-
setRemote(gitDir, "git@github.com:another-unknown/proj.git");
|
|
203
|
-
firstTouchClassify({ cwd: gitDir });
|
|
204
|
-
// git config --get exits 0 with value, or 1 if unset; we expect 1.
|
|
205
|
-
let threw = false;
|
|
206
|
-
try {
|
|
207
|
-
execFileSync("git", ["config", "--get", "repo-aegis.class"], {
|
|
208
|
-
cwd: gitDir,
|
|
209
|
-
stdio: ["ignore", "pipe", "ignore"],
|
|
210
|
-
});
|
|
211
|
-
}
|
|
212
|
-
catch {
|
|
213
|
-
threw = true;
|
|
214
|
-
}
|
|
215
|
-
assert.equal(threw, true, "class should not be set");
|
|
216
|
-
});
|
|
217
|
-
it("[SEC H-5] redactedOrg is the same as org when org < 4 chars", () => {
|
|
218
|
-
assert.equal(redactOrg("ab"), "ab");
|
|
219
|
-
assert.equal(redactOrg("abc"), "abc");
|
|
220
|
-
assert.equal(redactOrg("abcd"), "ab***d");
|
|
221
|
-
assert.equal(redactOrg("acme-corp"), "ac***p");
|
|
222
|
-
});
|
|
223
|
-
});
|
|
224
|
-
//# sourceMappingURL=first-touch.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"first-touch.test.js","sourceRoot":"","sources":["../../src/tools/first-touch.test.ts"],"names":[],"mappings":"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"}
|