agentplane 0.1.5 → 0.1.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/assets/AGENTS.md +1 -1
- package/assets/agents/ORCHESTRATOR.json +1 -1
- package/assets/agents/UPGRADER.json +1 -1
- package/dist/cli/run-cli.d.ts.map +1 -1
- package/dist/cli/run-cli.js +22 -7
- package/dist/commands/branch/index.d.ts +60 -0
- package/dist/commands/branch/index.d.ts.map +1 -0
- package/dist/commands/branch/index.js +511 -0
- package/dist/commands/guard/index.d.ts +67 -0
- package/dist/commands/guard/index.d.ts.map +1 -0
- package/dist/commands/guard/index.js +367 -0
- package/dist/commands/hooks/index.d.ts +18 -0
- package/dist/commands/hooks/index.d.ts.map +1 -0
- package/dist/commands/hooks/index.js +290 -0
- package/dist/commands/pr/index.d.ts +46 -0
- package/dist/commands/pr/index.d.ts.map +1 -0
- package/dist/commands/pr/index.js +854 -0
- package/dist/commands/shared/git-diff.d.ts +9 -0
- package/dist/commands/shared/git-diff.d.ts.map +1 -0
- package/dist/commands/shared/git-diff.js +41 -0
- package/dist/commands/shared/git-ops.d.ts +24 -0
- package/dist/commands/shared/git-ops.d.ts.map +1 -0
- package/dist/commands/shared/git-ops.js +181 -0
- package/dist/commands/shared/git-worktree.d.ts +8 -0
- package/dist/commands/shared/git-worktree.d.ts.map +1 -0
- package/dist/commands/shared/git-worktree.js +48 -0
- package/dist/commands/shared/git.d.ts +4 -0
- package/dist/commands/shared/git.d.ts.map +1 -0
- package/dist/commands/shared/git.js +14 -0
- package/dist/commands/shared/path.d.ts +3 -0
- package/dist/commands/shared/path.d.ts.map +1 -0
- package/dist/commands/shared/path.js +14 -0
- package/dist/commands/shared/pr-meta.d.ts +21 -0
- package/dist/commands/shared/pr-meta.d.ts.map +1 -0
- package/dist/commands/shared/pr-meta.js +72 -0
- package/dist/commands/shared/task-backend.d.ts +15 -0
- package/dist/commands/shared/task-backend.d.ts.map +1 -0
- package/dist/commands/shared/task-backend.js +55 -0
- package/dist/commands/task/add.d.ts +8 -0
- package/dist/commands/task/add.d.ts.map +1 -0
- package/dist/commands/task/add.js +164 -0
- package/dist/commands/task/block.d.ts +19 -0
- package/dist/commands/task/block.d.ts.map +1 -0
- package/dist/commands/task/block.js +86 -0
- package/dist/commands/task/comment.d.ts +8 -0
- package/dist/commands/task/comment.d.ts.map +1 -0
- package/dist/commands/task/comment.js +29 -0
- package/dist/commands/task/doc.d.ts +17 -0
- package/dist/commands/task/doc.d.ts.map +1 -0
- package/dist/commands/task/doc.js +220 -0
- package/dist/commands/task/export.d.ts +5 -0
- package/dist/commands/task/export.d.ts.map +1 -0
- package/dist/commands/task/export.js +27 -0
- package/dist/commands/task/finish.d.ts +27 -0
- package/dist/commands/task/finish.d.ts.map +1 -0
- package/dist/commands/task/finish.js +131 -0
- package/dist/commands/task/index.d.ts +23 -0
- package/dist/commands/task/index.d.ts.map +1 -0
- package/dist/commands/task/index.js +22 -0
- package/dist/commands/task/lint.d.ts +5 -0
- package/dist/commands/task/lint.d.ts.map +1 -0
- package/dist/commands/task/lint.js +22 -0
- package/dist/commands/task/list.d.ts +11 -0
- package/dist/commands/task/list.d.ts.map +1 -0
- package/dist/commands/task/list.js +54 -0
- package/dist/commands/task/migrate.d.ts +6 -0
- package/dist/commands/task/migrate.d.ts.map +1 -0
- package/dist/commands/task/migrate.js +70 -0
- package/dist/commands/task/new.d.ts +8 -0
- package/dist/commands/task/new.d.ts.map +1 -0
- package/dist/commands/task/new.js +117 -0
- package/dist/commands/task/next.d.ts +6 -0
- package/dist/commands/task/next.d.ts.map +1 -0
- package/dist/commands/task/next.js +45 -0
- package/dist/commands/task/normalize.d.ts +6 -0
- package/dist/commands/task/normalize.d.ts.map +1 -0
- package/dist/commands/task/normalize.js +46 -0
- package/dist/commands/task/ready.d.ts +6 -0
- package/dist/commands/task/ready.d.ts.map +1 -0
- package/dist/commands/task/ready.js +57 -0
- package/dist/commands/task/scaffold.d.ts +8 -0
- package/dist/commands/task/scaffold.d.ts.map +1 -0
- package/dist/commands/task/scaffold.js +131 -0
- package/dist/commands/task/scrub.d.ts +8 -0
- package/dist/commands/task/scrub.d.ts.map +1 -0
- package/dist/commands/task/scrub.js +121 -0
- package/dist/commands/task/search.d.ts +7 -0
- package/dist/commands/task/search.d.ts.map +1 -0
- package/dist/commands/task/search.js +79 -0
- package/dist/commands/task/set-status.d.ts +19 -0
- package/dist/commands/task/set-status.d.ts.map +1 -0
- package/dist/commands/task/set-status.js +123 -0
- package/dist/commands/task/shared.d.ts +46 -0
- package/dist/commands/task/shared.d.ts.map +1 -0
- package/dist/commands/task/shared.js +283 -0
- package/dist/commands/task/show.d.ts +6 -0
- package/dist/commands/task/show.d.ts.map +1 -0
- package/dist/commands/task/show.js +35 -0
- package/dist/commands/task/start.d.ts +19 -0
- package/dist/commands/task/start.d.ts.map +1 -0
- package/dist/commands/task/start.js +109 -0
- package/dist/commands/task/update.d.ts +8 -0
- package/dist/commands/task/update.d.ts.map +1 -0
- package/dist/commands/task/update.js +144 -0
- package/dist/commands/task/verify.d.ts +14 -0
- package/dist/commands/task/verify.d.ts.map +1 -0
- package/dist/commands/task/verify.js +362 -0
- package/dist/commands/workflow.d.ts +5 -364
- package/dist/commands/workflow.d.ts.map +1 -1
- package/dist/commands/workflow.js +6 -4617
- package/package.json +2 -2
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function toGitPath(filePath: string): string;
|
|
2
|
+
export declare function gitShowFile(cwd: string, ref: string, relPath: string): Promise<string>;
|
|
3
|
+
export declare function gitDiffNames(cwd: string, base: string, branch: string): Promise<string[]>;
|
|
4
|
+
export declare function gitDiffStat(cwd: string, base: string, branch: string): Promise<string>;
|
|
5
|
+
export declare function gitAheadBehind(cwd: string, base: string, branch: string): Promise<{
|
|
6
|
+
ahead: number;
|
|
7
|
+
behind: number;
|
|
8
|
+
}>;
|
|
9
|
+
//# sourceMappingURL=git-diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-diff.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/git-diff.ts"],"names":[],"mappings":"AAIA,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAM5F;AAED,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAS/F;AAED,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAM5F;AAED,wBAAsB,cAAc,CAClC,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GACb,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAa5C"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { execFileAsync, gitEnv } from "./git.js";
|
|
3
|
+
export function toGitPath(filePath) {
|
|
4
|
+
return filePath.split(path.sep).join("/");
|
|
5
|
+
}
|
|
6
|
+
export async function gitShowFile(cwd, ref, relPath) {
|
|
7
|
+
const { stdout } = await execFileAsync("git", ["show", `${ref}:${relPath}`], {
|
|
8
|
+
cwd,
|
|
9
|
+
env: gitEnv(),
|
|
10
|
+
});
|
|
11
|
+
return stdout;
|
|
12
|
+
}
|
|
13
|
+
export async function gitDiffNames(cwd, base, branch) {
|
|
14
|
+
const { stdout } = await execFileAsync("git", ["diff", "--name-only", `${base}...${branch}`], {
|
|
15
|
+
cwd,
|
|
16
|
+
env: gitEnv(),
|
|
17
|
+
});
|
|
18
|
+
return stdout
|
|
19
|
+
.split("\n")
|
|
20
|
+
.map((line) => line.trim())
|
|
21
|
+
.filter((line) => line.length > 0);
|
|
22
|
+
}
|
|
23
|
+
export async function gitDiffStat(cwd, base, branch) {
|
|
24
|
+
const { stdout } = await execFileAsync("git", ["diff", "--stat", `${base}...${branch}`], {
|
|
25
|
+
cwd,
|
|
26
|
+
env: gitEnv(),
|
|
27
|
+
});
|
|
28
|
+
return stdout.trimEnd();
|
|
29
|
+
}
|
|
30
|
+
export async function gitAheadBehind(cwd, base, branch) {
|
|
31
|
+
const { stdout } = await execFileAsync("git", ["rev-list", "--left-right", "--count", `${base}...${branch}`], { cwd, env: gitEnv() });
|
|
32
|
+
const trimmed = stdout.trim();
|
|
33
|
+
if (!trimmed)
|
|
34
|
+
return { ahead: 0, behind: 0 };
|
|
35
|
+
const parts = trimmed.split(/\s+/);
|
|
36
|
+
if (parts.length !== 2)
|
|
37
|
+
return { ahead: 0, behind: 0 };
|
|
38
|
+
const behind = Number.parseInt(parts[0] ?? "0", 10) || 0;
|
|
39
|
+
const ahead = Number.parseInt(parts[1] ?? "0", 10) || 0;
|
|
40
|
+
return { ahead, behind };
|
|
41
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export declare function gitRevParse(cwd: string, args: string[]): Promise<string>;
|
|
2
|
+
export declare function gitCurrentBranch(cwd: string): Promise<string>;
|
|
3
|
+
export declare function gitBranchExists(cwd: string, branch: string): Promise<boolean>;
|
|
4
|
+
export declare function gitListBranches(cwd: string): Promise<string[]>;
|
|
5
|
+
export declare function gitStagedPaths(cwd: string): Promise<string[]>;
|
|
6
|
+
export declare function gitAddPaths(cwd: string, paths: string[]): Promise<void>;
|
|
7
|
+
export declare function gitCommit(cwd: string, message: string, opts?: {
|
|
8
|
+
env?: NodeJS.ProcessEnv;
|
|
9
|
+
skipHooks?: boolean;
|
|
10
|
+
}): Promise<void>;
|
|
11
|
+
export declare function gitInitRepo(cwd: string, branch: string): Promise<void>;
|
|
12
|
+
export declare function resolveInitBaseBranch(gitRoot: string, fallback: string): Promise<string>;
|
|
13
|
+
export declare function promptInitBaseBranch(opts: {
|
|
14
|
+
gitRoot: string;
|
|
15
|
+
fallback: string;
|
|
16
|
+
}): Promise<string>;
|
|
17
|
+
export declare function ensureInitCommit(opts: {
|
|
18
|
+
gitRoot: string;
|
|
19
|
+
baseBranch: string;
|
|
20
|
+
installPaths: string[];
|
|
21
|
+
version: string;
|
|
22
|
+
skipHooks: boolean;
|
|
23
|
+
}): Promise<void>;
|
|
24
|
+
//# sourceMappingURL=git-ops.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-ops.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/git-ops.ts"],"names":[],"mappings":"AAKA,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAK9E;AAED,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAkBnE;AAED,wBAAsB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAYnF;AAED,wBAAsB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CASpE;AAED,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CASnE;AAED,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAG7E;AAED,wBAAsB,SAAS,CAC7B,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IAAC,SAAS,CAAC,EAAE,OAAO,CAAA;CAAE,GACtD,OAAO,CAAC,IAAI,CAAC,CAKf;AAED,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAgB5E;AAED,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAe9F;AAED,wBAAsB,oBAAoB,CAAC,IAAI,EAAE;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB,GAAG,OAAO,CAAC,MAAM,CAAC,CAiDlB;AAED,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;CACpB,GAAG,OAAO,CAAC,IAAI,CAAC,CAwBhB"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { execFileAsync, gitEnv } from "./git.js";
|
|
2
|
+
import { setPinnedBaseBranch } from "@agentplaneorg/core";
|
|
3
|
+
import { promptChoice, promptInput } from "../../cli/prompts.js";
|
|
4
|
+
import { CliError } from "../../shared/errors.js";
|
|
5
|
+
export async function gitRevParse(cwd, args) {
|
|
6
|
+
const { stdout } = await execFileAsync("git", ["rev-parse", ...args], { cwd, env: gitEnv() });
|
|
7
|
+
const trimmed = stdout.trim();
|
|
8
|
+
if (!trimmed)
|
|
9
|
+
throw new Error("Failed to resolve git path");
|
|
10
|
+
return trimmed;
|
|
11
|
+
}
|
|
12
|
+
export async function gitCurrentBranch(cwd) {
|
|
13
|
+
try {
|
|
14
|
+
const { stdout } = await execFileAsync("git", ["symbolic-ref", "--short", "HEAD"], {
|
|
15
|
+
cwd,
|
|
16
|
+
env: gitEnv(),
|
|
17
|
+
});
|
|
18
|
+
const trimmed = stdout.trim();
|
|
19
|
+
if (trimmed)
|
|
20
|
+
return trimmed;
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
// fall through
|
|
24
|
+
}
|
|
25
|
+
const { stdout } = await execFileAsync("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
|
|
26
|
+
cwd,
|
|
27
|
+
env: gitEnv(),
|
|
28
|
+
});
|
|
29
|
+
const trimmed = stdout.trim();
|
|
30
|
+
if (!trimmed || trimmed === "HEAD")
|
|
31
|
+
throw new Error("Failed to resolve git branch");
|
|
32
|
+
return trimmed;
|
|
33
|
+
}
|
|
34
|
+
export async function gitBranchExists(cwd, branch) {
|
|
35
|
+
try {
|
|
36
|
+
await execFileAsync("git", ["show-ref", "--verify", "--quiet", `refs/heads/${branch}`], {
|
|
37
|
+
cwd,
|
|
38
|
+
env: gitEnv(),
|
|
39
|
+
});
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
const code = err?.code;
|
|
44
|
+
if (code === 1)
|
|
45
|
+
return false;
|
|
46
|
+
throw err;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
export async function gitListBranches(cwd) {
|
|
50
|
+
const { stdout } = await execFileAsync("git", ["branch", "--format=%(refname:short)"], {
|
|
51
|
+
cwd,
|
|
52
|
+
env: gitEnv(),
|
|
53
|
+
});
|
|
54
|
+
return stdout
|
|
55
|
+
.split("\n")
|
|
56
|
+
.map((line) => line.trim())
|
|
57
|
+
.filter((line) => line.length > 0);
|
|
58
|
+
}
|
|
59
|
+
export async function gitStagedPaths(cwd) {
|
|
60
|
+
const { stdout } = await execFileAsync("git", ["diff", "--cached", "--name-only"], {
|
|
61
|
+
cwd,
|
|
62
|
+
env: gitEnv(),
|
|
63
|
+
});
|
|
64
|
+
return stdout
|
|
65
|
+
.split("\n")
|
|
66
|
+
.map((line) => line.trim())
|
|
67
|
+
.filter((line) => line.length > 0);
|
|
68
|
+
}
|
|
69
|
+
export async function gitAddPaths(cwd, paths) {
|
|
70
|
+
if (paths.length === 0)
|
|
71
|
+
return;
|
|
72
|
+
await execFileAsync("git", ["add", "--", ...paths], { cwd, env: gitEnv() });
|
|
73
|
+
}
|
|
74
|
+
export async function gitCommit(cwd, message, opts) {
|
|
75
|
+
const args = ["commit", "-m", message];
|
|
76
|
+
if (opts?.skipHooks)
|
|
77
|
+
args.push("--no-verify");
|
|
78
|
+
const env = opts?.env ? { ...gitEnv(), ...opts.env } : gitEnv();
|
|
79
|
+
await execFileAsync("git", args, { cwd, env });
|
|
80
|
+
}
|
|
81
|
+
export async function gitInitRepo(cwd, branch) {
|
|
82
|
+
try {
|
|
83
|
+
await execFileAsync("git", ["init", "-q", "-b", branch], { cwd, env: gitEnv() });
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
await execFileAsync("git", ["init", "-q"], { cwd, env: gitEnv() });
|
|
88
|
+
}
|
|
89
|
+
try {
|
|
90
|
+
const current = await gitCurrentBranch(cwd);
|
|
91
|
+
if (current !== branch) {
|
|
92
|
+
await execFileAsync("git", ["checkout", "-q", "-b", branch], { cwd, env: gitEnv() });
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
await execFileAsync("git", ["checkout", "-q", "-b", branch], { cwd, env: gitEnv() });
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
export async function resolveInitBaseBranch(gitRoot, fallback) {
|
|
100
|
+
let current = null;
|
|
101
|
+
try {
|
|
102
|
+
current = await gitCurrentBranch(gitRoot);
|
|
103
|
+
}
|
|
104
|
+
catch {
|
|
105
|
+
current = null;
|
|
106
|
+
}
|
|
107
|
+
const branches = await gitListBranches(gitRoot);
|
|
108
|
+
if (current)
|
|
109
|
+
return current;
|
|
110
|
+
if (branches.includes(fallback))
|
|
111
|
+
return fallback;
|
|
112
|
+
if (branches.length > 0) {
|
|
113
|
+
const first = branches[0];
|
|
114
|
+
if (first)
|
|
115
|
+
return first;
|
|
116
|
+
}
|
|
117
|
+
return fallback;
|
|
118
|
+
}
|
|
119
|
+
export async function promptInitBaseBranch(opts) {
|
|
120
|
+
const branches = await gitListBranches(opts.gitRoot);
|
|
121
|
+
let current = null;
|
|
122
|
+
try {
|
|
123
|
+
current = await gitCurrentBranch(opts.gitRoot);
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
current = null;
|
|
127
|
+
}
|
|
128
|
+
const promptNewBranch = async (hasBranches) => {
|
|
129
|
+
const raw = await promptInput(`Enter new base branch name (default ${opts.fallback}): `);
|
|
130
|
+
const candidate = raw.trim() || opts.fallback;
|
|
131
|
+
if (!candidate) {
|
|
132
|
+
throw new CliError({
|
|
133
|
+
exitCode: 2,
|
|
134
|
+
code: "E_USAGE",
|
|
135
|
+
message: "Base branch name cannot be empty",
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
if (await gitBranchExists(opts.gitRoot, candidate))
|
|
139
|
+
return candidate;
|
|
140
|
+
try {
|
|
141
|
+
await execFileAsync("git", hasBranches ? ["branch", candidate] : ["checkout", "-q", "-b", candidate], { cwd: opts.gitRoot, env: gitEnv() });
|
|
142
|
+
}
|
|
143
|
+
catch (err) {
|
|
144
|
+
const message = err instanceof Error ? err.message : `Failed to create branch ${candidate}`;
|
|
145
|
+
throw new CliError({ exitCode: 5, code: "E_GIT", message });
|
|
146
|
+
}
|
|
147
|
+
return candidate;
|
|
148
|
+
};
|
|
149
|
+
if (branches.length === 0) {
|
|
150
|
+
return await promptNewBranch(false);
|
|
151
|
+
}
|
|
152
|
+
const createLabel = "Create new branch";
|
|
153
|
+
const defaultChoice = current && branches.includes(current) ? current : (branches[0] ?? opts.fallback);
|
|
154
|
+
const choice = await promptChoice("Select base branch", [...branches, createLabel], defaultChoice);
|
|
155
|
+
if (choice === createLabel) {
|
|
156
|
+
return await promptNewBranch(true);
|
|
157
|
+
}
|
|
158
|
+
return choice;
|
|
159
|
+
}
|
|
160
|
+
export async function ensureInitCommit(opts) {
|
|
161
|
+
const stagedBefore = await gitStagedPaths(opts.gitRoot);
|
|
162
|
+
if (stagedBefore.length > 0) {
|
|
163
|
+
throw new CliError({
|
|
164
|
+
exitCode: 5,
|
|
165
|
+
code: "E_GIT",
|
|
166
|
+
message: "Git index has staged changes; commit or unstage them before running agentplane init.",
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
await setPinnedBaseBranch({
|
|
170
|
+
cwd: opts.gitRoot,
|
|
171
|
+
rootOverride: opts.gitRoot,
|
|
172
|
+
value: opts.baseBranch,
|
|
173
|
+
});
|
|
174
|
+
const dedupedPaths = [...new Set(opts.installPaths)].filter((entry) => entry.length > 0);
|
|
175
|
+
await gitAddPaths(opts.gitRoot, dedupedPaths);
|
|
176
|
+
const staged = await gitStagedPaths(opts.gitRoot);
|
|
177
|
+
if (staged.length === 0)
|
|
178
|
+
return;
|
|
179
|
+
const message = `chore: install agentplane ${opts.version}`;
|
|
180
|
+
await gitCommit(opts.gitRoot, message, { skipHooks: opts.skipHooks });
|
|
181
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare function listWorktrees(cwd: string): Promise<{
|
|
2
|
+
path: string;
|
|
3
|
+
branch: string | null;
|
|
4
|
+
}[]>;
|
|
5
|
+
export declare function findWorktreeForBranch(cwd: string, branch: string): Promise<string | null>;
|
|
6
|
+
export declare function parseTaskIdFromBranch(prefix: string, branch: string): string | null;
|
|
7
|
+
export declare function gitListTaskBranches(cwd: string, prefix: string): Promise<string[]>;
|
|
8
|
+
//# sourceMappingURL=git-worktree.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-worktree.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/git-worktree.ts"],"names":[],"mappings":"AAEA,wBAAsB,aAAa,CACjC,GAAG,EAAE,MAAM,GACV,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,EAAE,CAAC,CAoBpD;AAED,wBAAsB,qBAAqB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAQ/F;AAMD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMnF;AAED,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAUxF"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { execFileAsync, gitEnv } from "./git.js";
|
|
2
|
+
export async function listWorktrees(cwd) {
|
|
3
|
+
const { stdout } = await execFileAsync("git", ["worktree", "list", "--porcelain"], {
|
|
4
|
+
cwd,
|
|
5
|
+
env: gitEnv(),
|
|
6
|
+
});
|
|
7
|
+
const worktrees = [];
|
|
8
|
+
const lines = stdout.split("\n");
|
|
9
|
+
let current = null;
|
|
10
|
+
for (const line of lines) {
|
|
11
|
+
if (line.startsWith("worktree ")) {
|
|
12
|
+
if (current)
|
|
13
|
+
worktrees.push(current);
|
|
14
|
+
current = { path: line.slice("worktree ".length).trim(), branch: null };
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
if (line.startsWith("branch ") && current) {
|
|
18
|
+
current.branch = line.slice("branch ".length).trim();
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if (current)
|
|
22
|
+
worktrees.push(current);
|
|
23
|
+
return worktrees;
|
|
24
|
+
}
|
|
25
|
+
export async function findWorktreeForBranch(cwd, branch) {
|
|
26
|
+
const target = branch.startsWith("refs/heads/") ? branch : `refs/heads/${branch}`;
|
|
27
|
+
const worktrees = await listWorktrees(cwd);
|
|
28
|
+
const match = worktrees.find((entry) => entry.branch === branch || entry.branch === target || entry.branch === `refs/heads/${branch}`);
|
|
29
|
+
return match ? match.path : null;
|
|
30
|
+
}
|
|
31
|
+
function stripBranchRef(branch) {
|
|
32
|
+
return branch.startsWith("refs/heads/") ? branch.slice("refs/heads/".length) : branch;
|
|
33
|
+
}
|
|
34
|
+
export function parseTaskIdFromBranch(prefix, branch) {
|
|
35
|
+
const normalized = stripBranchRef(branch);
|
|
36
|
+
if (!normalized.startsWith(`${prefix}/`))
|
|
37
|
+
return null;
|
|
38
|
+
const rest = normalized.slice(prefix.length + 1);
|
|
39
|
+
const taskId = rest.split("/", 1)[0];
|
|
40
|
+
return taskId ? taskId.trim() : null;
|
|
41
|
+
}
|
|
42
|
+
export async function gitListTaskBranches(cwd, prefix) {
|
|
43
|
+
const { stdout } = await execFileAsync("git", ["for-each-ref", "--format=%(refname:short)", `refs/heads/${prefix}`], { cwd, env: gitEnv() });
|
|
44
|
+
return stdout
|
|
45
|
+
.split("\n")
|
|
46
|
+
.map((line) => line.trim())
|
|
47
|
+
.filter((line) => line.length > 0);
|
|
48
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAG9C,eAAO,MAAM,aAAa,+BAAsB,CAAC;AAGjD,wBAAgB,MAAM,IAAI,MAAM,CAAC,UAAU,CAS1C"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { promisify } from "node:util";
|
|
3
|
+
export const execFileAsync = promisify(execFile);
|
|
4
|
+
// Avoid leaking worktree-index overrides into git subprocesses.
|
|
5
|
+
export function gitEnv() {
|
|
6
|
+
const env = { ...process.env };
|
|
7
|
+
delete env.GIT_DIR;
|
|
8
|
+
delete env.GIT_WORK_TREE;
|
|
9
|
+
delete env.GIT_COMMON_DIR;
|
|
10
|
+
delete env.GIT_INDEX_FILE;
|
|
11
|
+
delete env.GIT_OBJECT_DIRECTORY;
|
|
12
|
+
delete env.GIT_ALTERNATE_OBJECT_DIRECTORIES;
|
|
13
|
+
return env;
|
|
14
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/path.ts"],"names":[],"mappings":"AAGA,wBAAsB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAM3E;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAGvE"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { realpath } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
export async function resolvePathFallback(filePath) {
|
|
4
|
+
try {
|
|
5
|
+
return await realpath(filePath);
|
|
6
|
+
}
|
|
7
|
+
catch {
|
|
8
|
+
return path.resolve(filePath);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export function isPathWithin(parent, candidate) {
|
|
12
|
+
const rel = path.relative(parent, candidate);
|
|
13
|
+
return rel === "" || (!rel.startsWith("..") && !path.isAbsolute(rel));
|
|
14
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type PrMeta = {
|
|
2
|
+
schema_version: 1;
|
|
3
|
+
task_id: string;
|
|
4
|
+
branch?: string;
|
|
5
|
+
created_at: string;
|
|
6
|
+
updated_at: string;
|
|
7
|
+
last_verified_sha: string | null;
|
|
8
|
+
last_verified_at: string | null;
|
|
9
|
+
verify?: {
|
|
10
|
+
status?: "pass" | "fail" | "skipped";
|
|
11
|
+
command?: string;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
export declare function parsePrMeta(raw: string, taskId: string): PrMeta;
|
|
15
|
+
export declare function extractLastVerifiedSha(logText: string): string | null;
|
|
16
|
+
export declare function appendVerifyLog(logPath: string, header: string, content: string): Promise<void>;
|
|
17
|
+
export declare function runShellCommand(command: string, cwd: string): Promise<{
|
|
18
|
+
code: number;
|
|
19
|
+
output: string;
|
|
20
|
+
}>;
|
|
21
|
+
//# sourceMappingURL=pr-meta.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pr-meta.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/pr-meta.ts"],"names":[],"mappings":"AAaA,MAAM,MAAM,MAAM,GAAG;IACnB,cAAc,EAAE,CAAC,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,MAAM,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACrE,CAAC;AAEF,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAc/D;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQrE;AAED,wBAAsB,eAAe,CACnC,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAMf;AAED,wBAAsB,eAAe,CACnC,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,GACV,OAAO,CAAC;IACT,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC,CAoBD"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { mkdir, writeFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { execFileAsync } from "./git.js";
|
|
4
|
+
function isRecord(value) {
|
|
5
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
6
|
+
}
|
|
7
|
+
function isIsoDate(value) {
|
|
8
|
+
return typeof value === "string" && !Number.isNaN(Date.parse(value));
|
|
9
|
+
}
|
|
10
|
+
export function parsePrMeta(raw, taskId) {
|
|
11
|
+
let parsed;
|
|
12
|
+
try {
|
|
13
|
+
parsed = JSON.parse(raw);
|
|
14
|
+
}
|
|
15
|
+
catch (err) {
|
|
16
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
17
|
+
throw new Error(`JSON Parse error: ${message}`);
|
|
18
|
+
}
|
|
19
|
+
if (!isRecord(parsed))
|
|
20
|
+
throw new Error("pr/meta.json must be an object");
|
|
21
|
+
if (parsed.schema_version !== 1)
|
|
22
|
+
throw new Error("pr/meta.json schema_version must be 1");
|
|
23
|
+
if (parsed.task_id !== taskId)
|
|
24
|
+
throw new Error("pr/meta.json task_id mismatch");
|
|
25
|
+
if (!isIsoDate(parsed.created_at))
|
|
26
|
+
throw new Error("pr/meta.json created_at must be ISO");
|
|
27
|
+
if (!isIsoDate(parsed.updated_at))
|
|
28
|
+
throw new Error("pr/meta.json updated_at must be ISO");
|
|
29
|
+
return parsed;
|
|
30
|
+
}
|
|
31
|
+
export function extractLastVerifiedSha(logText) {
|
|
32
|
+
const regex = /verified_sha=([0-9a-f]{7,40})/gi;
|
|
33
|
+
let match = null;
|
|
34
|
+
let last = null;
|
|
35
|
+
while ((match = regex.exec(logText))) {
|
|
36
|
+
last = match[1] ?? null;
|
|
37
|
+
}
|
|
38
|
+
return last;
|
|
39
|
+
}
|
|
40
|
+
export async function appendVerifyLog(logPath, header, content) {
|
|
41
|
+
await mkdir(path.dirname(logPath), { recursive: true });
|
|
42
|
+
const lines = [header.trimEnd()];
|
|
43
|
+
if (content)
|
|
44
|
+
lines.push(content.trimEnd());
|
|
45
|
+
lines.push("");
|
|
46
|
+
await writeFile(logPath, `${lines.join("\n")}\n`, { flag: "a" });
|
|
47
|
+
}
|
|
48
|
+
export async function runShellCommand(command, cwd) {
|
|
49
|
+
try {
|
|
50
|
+
const { stdout, stderr } = await execFileAsync("sh", ["-lc", command], {
|
|
51
|
+
cwd,
|
|
52
|
+
env: process.env,
|
|
53
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
54
|
+
});
|
|
55
|
+
let output = "";
|
|
56
|
+
if (stdout)
|
|
57
|
+
output += stdout;
|
|
58
|
+
if (stderr)
|
|
59
|
+
output += (output && !output.endsWith("\n") ? "\n" : "") + stderr;
|
|
60
|
+
return { code: 0, output };
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
const error = err;
|
|
64
|
+
let output = "";
|
|
65
|
+
if (error.stdout)
|
|
66
|
+
output += String(error.stdout);
|
|
67
|
+
if (error.stderr)
|
|
68
|
+
output += (output && !output.endsWith("\n") ? "\n" : "") + String(error.stderr);
|
|
69
|
+
const code = typeof error.code === "number" ? error.code : 1;
|
|
70
|
+
return { code, output };
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { loadTaskBackend, type TaskData } from "../../backends/task-backend.js";
|
|
2
|
+
export declare function resolveDocUpdatedBy(task: TaskData, author?: string): string;
|
|
3
|
+
export declare function taskDataToFrontmatter(task: TaskData): Record<string, unknown>;
|
|
4
|
+
export declare function loadBackendTask(opts: {
|
|
5
|
+
cwd: string;
|
|
6
|
+
rootOverride?: string | null;
|
|
7
|
+
taskId: string;
|
|
8
|
+
}): Promise<{
|
|
9
|
+
backend: Awaited<ReturnType<typeof loadTaskBackend>>["backend"];
|
|
10
|
+
backendId: string;
|
|
11
|
+
resolved: Awaited<ReturnType<typeof loadTaskBackend>>["resolved"];
|
|
12
|
+
config: Awaited<ReturnType<typeof loadTaskBackend>>["config"];
|
|
13
|
+
task: TaskData;
|
|
14
|
+
}>;
|
|
15
|
+
//# sourceMappingURL=task-backend.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-backend.d.ts","sourceRoot":"","sources":["../../../src/commands/shared/task-backend.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,KAAK,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAShF,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAQ3E;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAiB7E;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,OAAO,CAAC;IACV,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAChE,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;IAClE,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAC9D,IAAI,EAAE,QAAQ,CAAC;CAChB,CAAC,CAgBD"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { CliError } from "../../shared/errors.js";
|
|
3
|
+
import { loadTaskBackend } from "../../backends/task-backend.js";
|
|
4
|
+
function normalizeDocUpdatedBy(value) {
|
|
5
|
+
const trimmed = value?.trim() ?? "";
|
|
6
|
+
if (!trimmed)
|
|
7
|
+
return "";
|
|
8
|
+
if (trimmed.toLowerCase() === "agentplane")
|
|
9
|
+
return "";
|
|
10
|
+
return trimmed;
|
|
11
|
+
}
|
|
12
|
+
export function resolveDocUpdatedBy(task, author) {
|
|
13
|
+
const fromAuthor = normalizeDocUpdatedBy(author);
|
|
14
|
+
if (fromAuthor)
|
|
15
|
+
return fromAuthor;
|
|
16
|
+
const fromTask = normalizeDocUpdatedBy(typeof task.doc_updated_by === "string" ? task.doc_updated_by : undefined);
|
|
17
|
+
if (fromTask)
|
|
18
|
+
return fromTask;
|
|
19
|
+
return normalizeDocUpdatedBy(typeof task.owner === "string" ? task.owner : undefined);
|
|
20
|
+
}
|
|
21
|
+
export function taskDataToFrontmatter(task) {
|
|
22
|
+
return {
|
|
23
|
+
id: task.id,
|
|
24
|
+
title: task.title,
|
|
25
|
+
status: task.status,
|
|
26
|
+
priority: task.priority,
|
|
27
|
+
owner: task.owner,
|
|
28
|
+
depends_on: task.depends_on ?? [],
|
|
29
|
+
tags: task.tags ?? [],
|
|
30
|
+
verify: task.verify ?? [],
|
|
31
|
+
commit: task.commit ?? null,
|
|
32
|
+
comments: task.comments ?? [],
|
|
33
|
+
doc_version: task.doc_version,
|
|
34
|
+
doc_updated_at: task.doc_updated_at,
|
|
35
|
+
doc_updated_by: task.doc_updated_by,
|
|
36
|
+
description: task.description ?? "",
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export async function loadBackendTask(opts) {
|
|
40
|
+
const { backend, backendId, resolved, config } = await loadTaskBackend({
|
|
41
|
+
cwd: opts.cwd,
|
|
42
|
+
rootOverride: opts.rootOverride ?? null,
|
|
43
|
+
});
|
|
44
|
+
const task = await backend.getTask(opts.taskId);
|
|
45
|
+
if (!task) {
|
|
46
|
+
const tasksDir = path.join(resolved.gitRoot, config.paths.workflow_dir);
|
|
47
|
+
const readmePath = path.join(tasksDir, opts.taskId, "README.md");
|
|
48
|
+
throw new CliError({
|
|
49
|
+
exitCode: 4,
|
|
50
|
+
code: "E_IO",
|
|
51
|
+
message: `ENOENT: no such file or directory, open '${readmePath}'`,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
return { backend, backendId, resolved, config, task };
|
|
55
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const TASK_ADD_USAGE = "Usage: agentplane task add <task-id> [<task-id> ...] --title <text> --description <text> --priority <low|normal|med|high> --owner <id> --tag <tag> [--tag <tag>...]";
|
|
2
|
+
export declare const TASK_ADD_USAGE_EXAMPLE = "agentplane task add 202602030608-F1Q8AB --title \"...\" --description \"...\" --priority med --owner CODER --tag cli";
|
|
3
|
+
export declare function cmdTaskAdd(opts: {
|
|
4
|
+
cwd: string;
|
|
5
|
+
rootOverride?: string;
|
|
6
|
+
args: string[];
|
|
7
|
+
}): Promise<number>;
|
|
8
|
+
//# sourceMappingURL=add.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../../src/commands/task/add.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,cAAc,wKAC4I,CAAC;AACxK,eAAO,MAAM,sBAAsB,yHACiF,CAAC;AAgGrH,wBAAsB,UAAU,CAAC,IAAI,EAAE;IACrC,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CAgFlB"}
|