@a5c-ai/git-a5c 1.0.5 → 1.0.7
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/args.d.ts +2 -0
- package/dist/args.d.ts.map +1 -1
- package/dist/args.js +4 -0
- package/dist/args.js.map +1 -1
- package/dist/commands/help.d.ts.map +1 -1
- package/dist/commands/help.js +2 -0
- package/dist/commands/help.js.map +1 -1
- package/dist/commands/server.d.ts +3 -0
- package/dist/commands/server.d.ts.map +1 -0
- package/dist/commands/server.js +34 -0
- package/dist/commands/server.js.map +1 -0
- package/dist/commands/ui.d.ts +3 -0
- package/dist/commands/ui.d.ts.map +1 -0
- package/dist/commands/ui.js +43 -0
- package/dist/commands/ui.js.map +1 -0
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +4 -0
- package/dist/run.js.map +1 -1
- package/package.json +8 -3
- package/src/args.ts +0 -87
- package/src/bin/git-a5c.ts +0 -14
- package/src/commands/agent.ts +0 -70
- package/src/commands/block.ts +0 -34
- package/src/commands/gate.ts +0 -32
- package/src/commands/help.ts +0 -38
- package/src/commands/hooks.ts +0 -40
- package/src/commands/issue.ts +0 -146
- package/src/commands/journal.ts +0 -75
- package/src/commands/ops.ts +0 -41
- package/src/commands/pr.ts +0 -147
- package/src/commands/status.ts +0 -18
- package/src/commands/types.ts +0 -20
- package/src/commands/verify.ts +0 -20
- package/src/commands/webhook.ts +0 -63
- package/src/git.ts +0 -38
- package/src/run.ts +0 -99
- package/src/time.ts +0 -16
- package/test/_util.ts +0 -88
- package/test/cli.flow.integration.test.ts +0 -86
- package/test/cli.snapshots.test.ts +0 -50
- package/test/cli.webhook.integration.test.ts +0 -62
- package/test/cli.write.integration.test.ts +0 -70
- package/tsconfig.json +0 -13
- package/vitest.config.ts +0 -20
package/src/time.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
export function parseSinceToEpochMs(since: string, nowMs: number): number {
|
|
2
|
-
// Accept:
|
|
3
|
-
// - ISO timestamp
|
|
4
|
-
// - durations like 2h, 15m, 30s, 7d
|
|
5
|
-
const iso = Date.parse(since);
|
|
6
|
-
if (Number.isFinite(iso)) return iso;
|
|
7
|
-
|
|
8
|
-
const m = /^(\d+)(s|m|h|d)$/.exec(since.trim());
|
|
9
|
-
if (!m) throw new Error(`Invalid --since: ${since}`);
|
|
10
|
-
const n = Number(m[1]);
|
|
11
|
-
const unit = m[2];
|
|
12
|
-
const mult = unit === "s" ? 1000 : unit === "m" ? 60_000 : unit === "h" ? 3_600_000 : 86_400_000;
|
|
13
|
-
return nowMs - n * mult;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
|
package/test/_util.ts
DELETED
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import { spawn } from "node:child_process";
|
|
2
|
-
import fs from "node:fs/promises";
|
|
3
|
-
import http from "node:http";
|
|
4
|
-
import os from "node:os";
|
|
5
|
-
import path from "node:path";
|
|
6
|
-
|
|
7
|
-
export function run(cmd: string, args: string[], cwd: string): Promise<{ stdout: string; stderr: string }> {
|
|
8
|
-
return new Promise((resolve, reject) => {
|
|
9
|
-
const child = spawn(cmd, args, { cwd, stdio: ["ignore", "pipe", "pipe"], windowsHide: true });
|
|
10
|
-
const out: Buffer[] = [];
|
|
11
|
-
const err: Buffer[] = [];
|
|
12
|
-
child.stdout.on("data", (d) => out.push(Buffer.from(d)));
|
|
13
|
-
child.stderr.on("data", (d) => err.push(Buffer.from(d)));
|
|
14
|
-
child.on("error", reject);
|
|
15
|
-
child.on("close", (code) => {
|
|
16
|
-
const stdout = Buffer.concat(out).toString("utf8");
|
|
17
|
-
const stderr = Buffer.concat(err).toString("utf8");
|
|
18
|
-
if (code === 0) return resolve({ stdout, stderr });
|
|
19
|
-
reject(new Error(`${cmd} ${args.join(" ")} failed (code=${code}): ${stderr}`));
|
|
20
|
-
});
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export async function copyDir(src: string, dst: string) {
|
|
25
|
-
await fs.mkdir(dst, { recursive: true });
|
|
26
|
-
const entries = await fs.readdir(src, { withFileTypes: true });
|
|
27
|
-
for (const e of entries) {
|
|
28
|
-
const s = path.join(src, e.name);
|
|
29
|
-
const d = path.join(dst, e.name);
|
|
30
|
-
if (e.isDirectory()) await copyDir(s, d);
|
|
31
|
-
else if (e.isFile()) await fs.copyFile(s, d);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export async function makeRepoFromFixture(fixtureName: string): Promise<string> {
|
|
36
|
-
const root = path.resolve(import.meta.dirname, "../../..");
|
|
37
|
-
const fixture = path.join(root, "fixtures", fixtureName);
|
|
38
|
-
const dir = await fs.mkdtemp(path.join(os.tmpdir(), `a5cforge-cli-${fixtureName}-`));
|
|
39
|
-
await copyDir(fixture, dir);
|
|
40
|
-
await run("git", ["init", "-q", "-b", "main"], dir);
|
|
41
|
-
await run("git", ["add", "-A"], dir);
|
|
42
|
-
await run("git", ["add", "-f", ".collab"], dir);
|
|
43
|
-
await run("git", ["-c", "user.name=test", "-c", "user.email=test@example.com", "commit", "-q", "-m", "fixture"], dir);
|
|
44
|
-
return dir;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export async function makeEmptyRepo(tmpPrefix = "a5cforge-cli-write-"): Promise<string> {
|
|
48
|
-
const dir = await fs.mkdtemp(path.join(os.tmpdir(), tmpPrefix));
|
|
49
|
-
await run("git", ["init", "-q", "-b", "main"], dir);
|
|
50
|
-
await run("git", ["-c", "user.name=test", "-c", "user.email=test@example.com", "commit", "--allow-empty", "-q", "-m", "init"], dir);
|
|
51
|
-
return dir;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export function listenOnce(handler: (req: http.IncomingMessage, body: Buffer) => Promise<void> | void): Promise<{ url: string; close: () => Promise<void> }> {
|
|
55
|
-
const srv = http.createServer(async (req, res) => {
|
|
56
|
-
const chunks: Buffer[] = [];
|
|
57
|
-
req.on("data", (d) => chunks.push(Buffer.from(d)));
|
|
58
|
-
req.on("end", async () => {
|
|
59
|
-
try {
|
|
60
|
-
await handler(req, Buffer.concat(chunks));
|
|
61
|
-
res.statusCode = 200;
|
|
62
|
-
res.setHeader("content-type", "text/plain");
|
|
63
|
-
res.end("ok\n");
|
|
64
|
-
} catch (e: any) {
|
|
65
|
-
res.statusCode = 500;
|
|
66
|
-
res.setHeader("content-type", "text/plain");
|
|
67
|
-
res.end(String(e?.message ?? e));
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
return new Promise((resolve, reject) => {
|
|
73
|
-
srv.on("error", reject);
|
|
74
|
-
srv.listen(0, "127.0.0.1", () => {
|
|
75
|
-
const addr = srv.address();
|
|
76
|
-
if (!addr || typeof addr === "string") return reject(new Error("bad listen addr"));
|
|
77
|
-
resolve({
|
|
78
|
-
url: `http://127.0.0.1:${addr.port}`,
|
|
79
|
-
close: async () =>
|
|
80
|
-
await new Promise<void>((r) => {
|
|
81
|
-
srv.close(() => r());
|
|
82
|
-
})
|
|
83
|
-
});
|
|
84
|
-
});
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
|
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { runCli } from "../src/run.js";
|
|
3
|
-
import { makeEmptyRepo } from "./_util.js";
|
|
4
|
-
|
|
5
|
-
describe("CLI real workflow (maturization)", () => {
|
|
6
|
-
it("can run a basic issue + pr workflow end-to-end", async () => {
|
|
7
|
-
const repo = await makeEmptyRepo("a5cforge-cli-flow-");
|
|
8
|
-
process.env.A5C_ACTOR = "alice";
|
|
9
|
-
|
|
10
|
-
// 1) Create issue
|
|
11
|
-
let out = "";
|
|
12
|
-
let code = await runCli(["issue", "new", "--repo", repo, "--id", "issue-flow-1", "--title", "Flow issue", "--commit"], {
|
|
13
|
-
stdout: (s) => (out += s),
|
|
14
|
-
stderr: () => {}
|
|
15
|
-
});
|
|
16
|
-
expect(code).toBe(0);
|
|
17
|
-
expect(out.trim()).toBe("issue-flow-1");
|
|
18
|
-
|
|
19
|
-
// 2) Add a comment
|
|
20
|
-
out = "";
|
|
21
|
-
code = await runCli(["issue", "comment", "issue-flow-1", "--repo", repo, "--comment-id", "c-flow-1", "-m", "hello", "--commit"], {
|
|
22
|
-
stdout: (s) => (out += s),
|
|
23
|
-
stderr: () => {}
|
|
24
|
-
});
|
|
25
|
-
expect(code).toBe(0);
|
|
26
|
-
expect(out.trim()).toBe("c-flow-1");
|
|
27
|
-
|
|
28
|
-
// 3) Needs-human gate
|
|
29
|
-
out = "";
|
|
30
|
-
code = await runCli(["gate", "needs-human", "issue-flow-1", "--repo", repo, "--topic", "review", "-m", "needs eyes", "--commit"], {
|
|
31
|
-
stdout: (s) => (out += s),
|
|
32
|
-
stderr: () => {}
|
|
33
|
-
});
|
|
34
|
-
expect(code).toBe(0);
|
|
35
|
-
expect(out).toContain(".collab/");
|
|
36
|
-
|
|
37
|
-
// 4) Claim the work (agent dispatch is what an agent would react to)
|
|
38
|
-
out = "";
|
|
39
|
-
code = await runCli(["agent", "dispatch", "--repo", repo, "--entity", "issue-flow-1", "--dispatch-id", "d-flow-1", "--task", "implement"], {
|
|
40
|
-
stdout: (s) => (out += s),
|
|
41
|
-
stderr: () => {}
|
|
42
|
-
});
|
|
43
|
-
expect(code).toBe(0);
|
|
44
|
-
expect(out).toContain(".collab/agents/events/");
|
|
45
|
-
|
|
46
|
-
// 5) Create PR request
|
|
47
|
-
out = "";
|
|
48
|
-
code = await runCli(["pr", "request", "--repo", repo, "--id", "pr-flow-1", "--base", "refs/heads/main", "--title", "Do the thing", "--commit"], {
|
|
49
|
-
stdout: (s) => (out += s),
|
|
50
|
-
stderr: () => {}
|
|
51
|
-
});
|
|
52
|
-
expect(code).toBe(0);
|
|
53
|
-
expect(out.trim()).toBe("pr-flow-1");
|
|
54
|
-
|
|
55
|
-
// 6) Sanity: status + show JSON reflect the repo
|
|
56
|
-
out = "";
|
|
57
|
-
code = await runCli(["status", "--repo", repo, "--json"], { stdout: (s) => (out += s), stderr: () => {} });
|
|
58
|
-
expect(code).toBe(0);
|
|
59
|
-
const st = JSON.parse(out);
|
|
60
|
-
expect(st).toMatchObject({ treeish: "HEAD", issues: 1, prs: 1 });
|
|
61
|
-
|
|
62
|
-
out = "";
|
|
63
|
-
code = await runCli(["issue", "show", "issue-flow-1", "--repo", repo, "--json"], { stdout: (s) => (out += s), stderr: () => {} });
|
|
64
|
-
expect(code).toBe(0);
|
|
65
|
-
const issue = JSON.parse(out);
|
|
66
|
-
expect(issue.issueId).toBe("issue-flow-1");
|
|
67
|
-
expect(issue.comments.map((c: any) => c.commentId)).toContain("c-flow-1");
|
|
68
|
-
|
|
69
|
-
out = "";
|
|
70
|
-
code = await runCli(["pr", "show", "pr-flow-1", "--repo", repo, "--json"], { stdout: (s) => (out += s), stderr: () => {} });
|
|
71
|
-
expect(code).toBe(0);
|
|
72
|
-
const pr = JSON.parse(out);
|
|
73
|
-
expect(pr).toMatchObject({ prKey: "pr-flow-1", kind: "request" });
|
|
74
|
-
|
|
75
|
-
// 7) Journal includes the new events
|
|
76
|
-
process.env.A5C_NOW_ISO = new Date().toISOString();
|
|
77
|
-
out = "";
|
|
78
|
-
code = await runCli(["journal", "--repo", repo, "--since", "2h", "--types", "issue.*,comment.*,pr.*"], { stdout: (s) => (out += s), stderr: () => {} });
|
|
79
|
-
expect(code).toBe(0);
|
|
80
|
-
expect(out).toContain("issue.event.created");
|
|
81
|
-
expect(out).toContain("comment.created");
|
|
82
|
-
expect(out).toContain("pr.request.created");
|
|
83
|
-
}, 20_000);
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { runCli } from "../src/run.js";
|
|
3
|
-
import { makeRepoFromFixture } from "./_util.js";
|
|
4
|
-
|
|
5
|
-
describe("CLI (Phase 4)", () => {
|
|
6
|
-
it("status (repo-basic)", async () => {
|
|
7
|
-
const repo = await makeRepoFromFixture("repo-basic");
|
|
8
|
-
let out = "";
|
|
9
|
-
const code = await runCli(["status", "--repo", repo], { stdout: (s) => (out += s), stderr: () => {} });
|
|
10
|
-
expect(code).toBe(0);
|
|
11
|
-
expect(out).toBe(["treeish: HEAD", "issues: 2", "prs: 2", ""].join("\n"));
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
it("issue list (repo-basic)", async () => {
|
|
15
|
-
const repo = await makeRepoFromFixture("repo-basic");
|
|
16
|
-
let out = "";
|
|
17
|
-
const code = await runCli(["issue", "list", "--repo", repo], { stdout: (s) => (out += s), stderr: () => {} });
|
|
18
|
-
expect(code).toBe(0);
|
|
19
|
-
expect(out).toBe(["issue-1", "issue-2", ""].join("\n"));
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it("pr show --json (repo-basic)", async () => {
|
|
23
|
-
const repo = await makeRepoFromFixture("repo-basic");
|
|
24
|
-
let out = "";
|
|
25
|
-
const code = await runCli(["pr", "show", "pr-2", "--json", "--repo", repo], { stdout: (s) => (out += s), stderr: () => {} });
|
|
26
|
-
expect(code).toBe(0);
|
|
27
|
-
const pr = JSON.parse(out);
|
|
28
|
-
expect(pr).toMatchObject({
|
|
29
|
-
prKey: "pr-2",
|
|
30
|
-
kind: "request",
|
|
31
|
-
baseRef: "refs/heads/main"
|
|
32
|
-
});
|
|
33
|
-
expect(pr.events).toHaveLength(2);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it("journal filters by --since and --types", async () => {
|
|
37
|
-
const repo = await makeRepoFromFixture("repo-basic");
|
|
38
|
-
process.env.A5C_NOW_ISO = "2025-12-19T14:50:00Z";
|
|
39
|
-
let out = "";
|
|
40
|
-
const code = await runCli(
|
|
41
|
-
["journal", "--repo", repo, "--since", "20m", "--types", "pr.*"],
|
|
42
|
-
{ stdout: (s) => (out += s), stderr: () => {} }
|
|
43
|
-
);
|
|
44
|
-
expect(code).toBe(0);
|
|
45
|
-
// Should include pr-related events only, newest first.
|
|
46
|
-
expect(out).toContain("pr.event.created");
|
|
47
|
-
});
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import fs from "node:fs/promises";
|
|
4
|
-
import { runCli } from "../src/run.js";
|
|
5
|
-
import { makeEmptyRepo, run, listenOnce } from "./_util.js";
|
|
6
|
-
|
|
7
|
-
async function makeRepoWithWebhooks(): Promise<string> {
|
|
8
|
-
const dir = await makeEmptyRepo("a5cforge-cli-webhook-");
|
|
9
|
-
await fs.mkdir(path.join(dir, ".collab"), { recursive: true });
|
|
10
|
-
await fs.writeFile(
|
|
11
|
-
path.join(dir, ".collab", "webhooks.json"),
|
|
12
|
-
JSON.stringify(
|
|
13
|
-
{
|
|
14
|
-
schema: "a5cforge/v1",
|
|
15
|
-
endpoints: [{ id: "e1", url: "https://example.invalid/webhook", events: ["git.ref.updated"], enabled: true }]
|
|
16
|
-
},
|
|
17
|
-
null,
|
|
18
|
-
2
|
|
19
|
-
) + "\n",
|
|
20
|
-
"utf8"
|
|
21
|
-
);
|
|
22
|
-
await run("git", ["add", "-A"], dir);
|
|
23
|
-
await run("git", ["-c", "user.name=test", "-c", "user.email=test@example.com", "commit", "-q", "-m", "add webhooks"], dir);
|
|
24
|
-
return dir;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
describe("CLI webhook helpers (Phase 8)", () => {
|
|
28
|
-
it("webhook status reads from treeish (HEAD)", async () => {
|
|
29
|
-
const repo = await makeRepoWithWebhooks();
|
|
30
|
-
let out = "";
|
|
31
|
-
const code = await runCli(["webhook", "status", "--repo", repo], { stdout: (s) => (out += s), stderr: () => {} });
|
|
32
|
-
expect(code).toBe(0);
|
|
33
|
-
expect(out).toContain("schema: a5cforge/v1");
|
|
34
|
-
expect(out).toContain("endpoints: 1");
|
|
35
|
-
expect(out).toContain("- e1: https://example.invalid/webhook (git.ref.updated)");
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it("webhook test posts an envelope to the given url", async () => {
|
|
39
|
-
const repo = await makeRepoWithWebhooks();
|
|
40
|
-
let got: any = null;
|
|
41
|
-
const rcv = await listenOnce((req, body) => {
|
|
42
|
-
expect(req.method).toBe("POST");
|
|
43
|
-
expect(String(req.headers["content-type"] ?? "")).toContain("application/json");
|
|
44
|
-
got = JSON.parse(body.toString("utf8"));
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
try {
|
|
48
|
-
let out = "";
|
|
49
|
-
const code = await runCli(["webhook", "test", "--repo", repo, "--url", `${rcv.url}/recv`, "--type", "git.ref.updated"], {
|
|
50
|
-
stdout: (s) => (out += s),
|
|
51
|
-
stderr: () => {}
|
|
52
|
-
});
|
|
53
|
-
expect(code).toBe(0);
|
|
54
|
-
expect(out).toContain("status: 200");
|
|
55
|
-
expect(got).toMatchObject({ schema: "a5cforge/v1", type: "git.ref.updated", source: { serverId: "cli" } });
|
|
56
|
-
} finally {
|
|
57
|
-
await rcv.close();
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import path from "node:path";
|
|
3
|
-
import fs from "node:fs/promises";
|
|
4
|
-
import { runCli } from "../src/run.js";
|
|
5
|
-
import { makeEmptyRepo, run } from "./_util.js";
|
|
6
|
-
|
|
7
|
-
describe("CLI write commands (Phase 5)", () => {
|
|
8
|
-
it("issue new --stage-only creates and stages a file", async () => {
|
|
9
|
-
const repo = await makeEmptyRepo();
|
|
10
|
-
let out = "";
|
|
11
|
-
const code = await runCli(["issue", "new", "--title", "T", "--repo", repo, "--stage-only"], {
|
|
12
|
-
stdout: (s) => (out += s),
|
|
13
|
-
stderr: () => {}
|
|
14
|
-
});
|
|
15
|
-
expect(code).toBe(0);
|
|
16
|
-
expect(out.trim()).toMatch(/^issue-/);
|
|
17
|
-
const st = (await run("git", ["status", "--porcelain"], repo)).stdout;
|
|
18
|
-
expect(st).toContain("A ");
|
|
19
|
-
expect(st).toContain(".collab/");
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it("hooks install is idempotent", async () => {
|
|
23
|
-
const repo = await makeEmptyRepo();
|
|
24
|
-
let out1 = "";
|
|
25
|
-
const c1 = await runCli(["hooks", "install", "--repo", repo], { stdout: (s) => (out1 += s), stderr: () => {} });
|
|
26
|
-
expect(c1).toBe(0);
|
|
27
|
-
expect(out1.trim()).toBe("ok");
|
|
28
|
-
|
|
29
|
-
let out2 = "";
|
|
30
|
-
const c2 = await runCli(["hooks", "install", "--repo", repo], { stdout: (s) => (out2 += s), stderr: () => {} });
|
|
31
|
-
expect(c2).toBe(0);
|
|
32
|
-
expect(out2.trim()).toBe("ok");
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it("hooks uninstall only removes managed hooks", async () => {
|
|
36
|
-
const repo = await makeEmptyRepo();
|
|
37
|
-
// Install managed hook first.
|
|
38
|
-
await runCli(["hooks", "install", "--repo", repo], { stdout: () => {}, stderr: () => {} });
|
|
39
|
-
|
|
40
|
-
// Create an unmanaged hook and ensure uninstall doesn't delete it.
|
|
41
|
-
const hooksDir = (await run("git", ["rev-parse", "--git-path", "hooks"], repo)).stdout.trim();
|
|
42
|
-
await fs.mkdir(hooksDir, { recursive: true });
|
|
43
|
-
const unmanaged = path.join(hooksDir, "pre-commit");
|
|
44
|
-
await fs.writeFile(unmanaged, "#!/bin/sh\necho unmanaged\n", "utf8");
|
|
45
|
-
|
|
46
|
-
let out = "";
|
|
47
|
-
const code = await runCli(["hooks", "uninstall", "--repo", repo], { stdout: (s) => (out += s), stderr: () => {} });
|
|
48
|
-
expect(code).toBe(0);
|
|
49
|
-
expect(out.trim()).toBe("ok");
|
|
50
|
-
|
|
51
|
-
const still = await fs.readFile(unmanaged, "utf8");
|
|
52
|
-
expect(still).toContain("unmanaged");
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it("agent dispatch writes agent.dispatch.created event", async () => {
|
|
56
|
-
const repo = await makeEmptyRepo();
|
|
57
|
-
process.env.A5C_ACTOR = "agent1";
|
|
58
|
-
let out = "";
|
|
59
|
-
const code = await runCli(["agent", "dispatch", "--repo", repo, "--entity", "issue-1", "--stage-only"], {
|
|
60
|
-
stdout: (s) => (out += s),
|
|
61
|
-
stderr: () => {}
|
|
62
|
-
});
|
|
63
|
-
expect(code).toBe(0);
|
|
64
|
-
expect(out).toContain(".collab/agents/events/");
|
|
65
|
-
const st = (await run("git", ["status", "--porcelain"], repo)).stdout;
|
|
66
|
-
expect(st).toContain(".collab/agents/events/");
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
|
package/tsconfig.json
DELETED
package/vitest.config.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from "vitest/config";
|
|
2
|
-
|
|
3
|
-
export default defineConfig({
|
|
4
|
-
test: {
|
|
5
|
-
coverage: {
|
|
6
|
-
reportsDirectory: "coverage",
|
|
7
|
-
reporter: ["text", "lcov", "json-summary"],
|
|
8
|
-
include: ["src/**/*.ts"],
|
|
9
|
-
exclude: ["src/bin/**", "test/**", "**/*.d.ts"],
|
|
10
|
-
thresholds: {
|
|
11
|
-
statements: 55,
|
|
12
|
-
branches: 45,
|
|
13
|
-
functions: 65,
|
|
14
|
-
lines: 55
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
|