agentplane 0.2.26 → 0.3.1
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/README.md +3 -1
- package/assets/AGENTS.md +123 -526
- package/assets/agents/UPGRADER.json +10 -9
- package/assets/framework.manifest.json +112 -7
- package/assets/policy/check-routing.mjs +180 -0
- package/assets/policy/dod.code.md +25 -0
- package/assets/policy/dod.core.md +32 -0
- package/assets/policy/dod.docs.md +32 -0
- package/assets/policy/examples/migration-note.md +6 -0
- package/assets/policy/examples/pr-note.md +16 -0
- package/assets/policy/examples/unit-test-pattern.md +19 -0
- package/assets/policy/governance.md +37 -0
- package/assets/policy/incidents.md +36 -0
- package/assets/policy/security.must.md +7 -0
- package/assets/policy/workflow.branch_pr.md +34 -0
- package/assets/policy/workflow.direct.md +46 -0
- package/assets/policy/workflow.md +9 -0
- package/assets/policy/workflow.release.md +31 -0
- package/assets/policy/workflow.upgrade.md +20 -0
- package/bin/agentplane.js +41 -88
- package/bin/dist-guard.js +124 -0
- package/dist/.build-manifest.json +5 -5
- package/dist/agents/agents-template.d.ts +7 -0
- package/dist/agents/agents-template.d.ts.map +1 -1
- package/dist/agents/agents-template.js +41 -2
- package/dist/cli/command-guide.d.ts.map +1 -1
- package/dist/cli/command-guide.js +18 -9
- package/dist/cli/command-snippets.d.ts +1 -1
- package/dist/cli/command-snippets.js +1 -1
- package/dist/cli/run-cli/commands/core.js +2 -2
- package/dist/cli/run-cli/commands/ide.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/ide.js +8 -3
- package/dist/cli/run-cli/commands/init/ui.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/init/ui.js +1 -2
- package/dist/cli/run-cli/commands/init/write-agents.d.ts +2 -0
- package/dist/cli/run-cli/commands/init/write-agents.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/init/write-agents.js +24 -5
- package/dist/cli/run-cli/commands/init/write-workflow.d.ts +5 -0
- package/dist/cli/run-cli/commands/init/write-workflow.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/init/write-workflow.js +6 -0
- package/dist/cli/run-cli/commands/init.d.ts +2 -0
- package/dist/cli/run-cli/commands/init.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/init.js +47 -19
- package/dist/cli/run-cli.d.ts.map +1 -1
- package/dist/cli/run-cli.js +125 -7
- package/dist/commands/doctor.run.d.ts.map +1 -1
- package/dist/commands/doctor.run.js +11 -6
- package/dist/commands/release/apply.command.d.ts.map +1 -1
- package/dist/commands/release/apply.command.js +9 -4
- package/dist/commands/release/plan.command.d.ts.map +1 -1
- package/dist/commands/release/plan.command.js +9 -3
- package/dist/commands/task/add.d.ts.map +1 -1
- package/dist/commands/task/add.js +32 -0
- package/dist/commands/task/doc.command.d.ts.map +1 -1
- package/dist/commands/task/doc.command.js +1 -0
- package/dist/commands/task/finish.d.ts.map +1 -1
- package/dist/commands/task/finish.js +9 -1
- package/dist/commands/task/new.d.ts.map +1 -1
- package/dist/commands/task/new.js +41 -4
- package/dist/commands/task/plan.d.ts.map +1 -1
- package/dist/commands/task/plan.js +7 -1
- package/dist/commands/task/shared.d.ts +7 -0
- package/dist/commands/task/shared.d.ts.map +1 -1
- package/dist/commands/task/shared.js +37 -0
- package/dist/commands/task/start-ready.js +1 -1
- package/dist/commands/upgrade.command.d.ts.map +1 -1
- package/dist/commands/upgrade.command.js +2 -2
- package/dist/commands/upgrade.d.ts.map +1 -1
- package/dist/commands/upgrade.js +263 -294
- package/dist/commands/workflow-build.command.d.ts.map +1 -1
- package/dist/commands/workflow-build.command.js +7 -0
- package/dist/commands/workflow-playbook.command.d.ts.map +1 -1
- package/dist/commands/workflow-playbook.command.js +0 -1
- package/dist/shared/policy-gateway.d.ts +15 -0
- package/dist/shared/policy-gateway.d.ts.map +1 -0
- package/dist/shared/policy-gateway.js +49 -0
- package/dist/shared/protected-paths.d.ts.map +1 -1
- package/dist/shared/protected-paths.js +1 -0
- package/dist/shared/runtime-artifacts.d.ts +2 -2
- package/dist/shared/runtime-artifacts.d.ts.map +1 -1
- package/dist/shared/runtime-artifacts.js +4 -0
- package/dist/workflow-runtime/build.d.ts +1 -1
- package/dist/workflow-runtime/build.d.ts.map +1 -1
- package/dist/workflow-runtime/build.js +14 -2
- package/package.json +2 -2
|
@@ -26,12 +26,11 @@ export function renderInitWelcome() {
|
|
|
26
26
|
"░█▀█░█░█░█▀▀░█░█░░█░░▄▀░░█▀▀░█░░░█▀█░█░█░█▀▀",
|
|
27
27
|
"░▀░▀░▀▀▀░▀▀▀░▀░▀░░▀░░▀░░░▀░░░▀▀▀░▀░▀░▀░▀░▀▀▀",
|
|
28
28
|
].map((line) => color(line, "36"));
|
|
29
|
-
const subtitle = color("agent/plane", "36");
|
|
30
29
|
const intro = [
|
|
31
30
|
color("Bootstrap an agent-first workflow in this repository.", "1"),
|
|
32
31
|
"This interactive setup runs once; daily work is executed by agents.",
|
|
33
32
|
];
|
|
34
|
-
return `${logo.join("\n")}\n
|
|
33
|
+
return `${logo.join("\n")}\n\n${box(intro)}\n\n`;
|
|
35
34
|
}
|
|
36
35
|
export function renderInitSection(title, description) {
|
|
37
36
|
const header = color(`[${title}]`, "33");
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import type { WorkflowMode } from "../../../../agents/agents-template.js";
|
|
2
|
+
import { type PolicyGatewayFlavor } from "../../../../shared/policy-gateway.js";
|
|
2
3
|
export declare function ensureAgentsFiles(opts: {
|
|
3
4
|
gitRoot: string;
|
|
4
5
|
agentplaneDir: string;
|
|
5
6
|
workflow: WorkflowMode;
|
|
7
|
+
policyGateway: PolicyGatewayFlavor;
|
|
6
8
|
configPathAbs: string;
|
|
7
9
|
backendPathAbs: string;
|
|
8
10
|
}): Promise<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write-agents.d.ts","sourceRoot":"","sources":["../../../../../src/cli/run-cli/commands/init/write-agents.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;
|
|
1
|
+
{"version":3,"file":"write-agents.d.ts","sourceRoot":"","sources":["../../../../../src/cli/run-cli/commands/init/write-agents.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uCAAuC,CAAC;AAQ1E,OAAO,EAGL,KAAK,mBAAmB,EACzB,MAAM,sCAAsC,CAAC;AA6B9C,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,YAAY,CAAC;IACvB,aAAa,EAAE,mBAAmB,CAAC;IACnC,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;CACxB,GAAG,OAAO,CAAC;IAAE,YAAY,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAwDtC"}
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { mkdir, readFile } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { atomicWriteFile } from "@agentplaneorg/core";
|
|
4
|
-
import { filterAgentsByWorkflow, loadAgentTemplates, loadAgentsTemplate, } from "../../../../agents/agents-template.js";
|
|
4
|
+
import { filterAgentsByWorkflow, loadAgentTemplates, loadAgentsTemplate, loadPolicyTemplates, } from "../../../../agents/agents-template.js";
|
|
5
5
|
import { fileExists } from "../../../fs-utils.js";
|
|
6
|
+
import { policyGatewayFileName, renderPolicyGatewayTemplateText, } from "../../../../shared/policy-gateway.js";
|
|
6
7
|
function toUpgradeBaselineKey(repoRelativePath) {
|
|
7
8
|
if (repoRelativePath === "AGENTS.md")
|
|
8
9
|
return "AGENTS.md";
|
|
10
|
+
if (repoRelativePath === "CLAUDE.md")
|
|
11
|
+
return "CLAUDE.md";
|
|
9
12
|
if (repoRelativePath.startsWith(".agentplane/")) {
|
|
10
13
|
return repoRelativePath.slice(".agentplane/".length);
|
|
11
14
|
}
|
|
@@ -26,7 +29,9 @@ async function seedUpgradeBaselineForInstalledFiles(opts) {
|
|
|
26
29
|
}
|
|
27
30
|
}
|
|
28
31
|
export async function ensureAgentsFiles(opts) {
|
|
29
|
-
const
|
|
32
|
+
const gatewayFileName = policyGatewayFileName(opts.policyGateway);
|
|
33
|
+
const renderGatewayText = (text) => renderPolicyGatewayTemplateText(text, gatewayFileName);
|
|
34
|
+
const agentsPath = path.join(opts.gitRoot, gatewayFileName);
|
|
30
35
|
const installPaths = [
|
|
31
36
|
path.relative(opts.gitRoot, opts.configPathAbs),
|
|
32
37
|
path.relative(opts.gitRoot, opts.backendPathAbs),
|
|
@@ -38,20 +43,34 @@ export async function ensureAgentsFiles(opts) {
|
|
|
38
43
|
}
|
|
39
44
|
else {
|
|
40
45
|
const template = await loadAgentsTemplate();
|
|
41
|
-
const filtered = filterAgentsByWorkflow(template, opts.workflow);
|
|
46
|
+
const filtered = filterAgentsByWorkflow(renderGatewayText(template), opts.workflow);
|
|
42
47
|
await atomicWriteFile(agentsPath, filtered, "utf8");
|
|
43
48
|
wroteAgents = true;
|
|
44
49
|
}
|
|
45
50
|
if (wroteAgents) {
|
|
46
51
|
installPaths.push(path.relative(opts.gitRoot, agentsPath));
|
|
47
|
-
installedManagedPaths.push(
|
|
52
|
+
installedManagedPaths.push(gatewayFileName);
|
|
48
53
|
}
|
|
49
54
|
const agentTemplates = await loadAgentTemplates();
|
|
50
55
|
for (const agent of agentTemplates) {
|
|
51
56
|
const targetPath = path.join(opts.agentplaneDir, "agents", agent.fileName);
|
|
52
57
|
if (await fileExists(targetPath))
|
|
53
58
|
continue;
|
|
54
|
-
await atomicWriteFile(targetPath, agent.contents, "utf8");
|
|
59
|
+
await atomicWriteFile(targetPath, renderGatewayText(agent.contents), "utf8");
|
|
60
|
+
const relPath = path.relative(opts.gitRoot, targetPath);
|
|
61
|
+
installPaths.push(relPath);
|
|
62
|
+
installedManagedPaths.push(relPath);
|
|
63
|
+
}
|
|
64
|
+
const policyTemplates = await loadPolicyTemplates();
|
|
65
|
+
for (const policy of policyTemplates) {
|
|
66
|
+
const targetPath = path.join(opts.agentplaneDir, "policy", policy.relativePath);
|
|
67
|
+
if (await fileExists(targetPath))
|
|
68
|
+
continue;
|
|
69
|
+
const rendered = policy.relativePath.endsWith(".md")
|
|
70
|
+
? renderGatewayText(policy.contents)
|
|
71
|
+
: policy.contents;
|
|
72
|
+
await mkdir(path.dirname(targetPath), { recursive: true });
|
|
73
|
+
await atomicWriteFile(targetPath, rendered, "utf8");
|
|
55
74
|
const relPath = path.relative(opts.gitRoot, targetPath);
|
|
56
75
|
installPaths.push(relPath);
|
|
57
76
|
installedManagedPaths.push(relPath);
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
export declare function ensureInitWorkflow(opts: {
|
|
2
2
|
gitRoot: string;
|
|
3
3
|
workflowMode: "direct" | "branch_pr";
|
|
4
|
+
approvals: {
|
|
5
|
+
requirePlanApproval: boolean;
|
|
6
|
+
requireVerifyApproval: boolean;
|
|
7
|
+
requireNetworkApproval: boolean;
|
|
8
|
+
};
|
|
4
9
|
}): Promise<{
|
|
5
10
|
installPaths: string[];
|
|
6
11
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write-workflow.d.ts","sourceRoot":"","sources":["../../../../../src/cli/run-cli/commands/init/write-workflow.ts"],"names":[],"mappings":"AASA,wBAAsB,kBAAkB,CAAC,IAAI,EAAE;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,QAAQ,GAAG,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"write-workflow.d.ts","sourceRoot":"","sources":["../../../../../src/cli/run-cli/commands/init/write-workflow.ts"],"names":[],"mappings":"AASA,wBAAsB,kBAAkB,CAAC,IAAI,EAAE;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,QAAQ,GAAG,WAAW,CAAC;IACrC,SAAS,EAAE;QACT,mBAAmB,EAAE,OAAO,CAAC;QAC7B,qBAAqB,EAAE,OAAO,CAAC;QAC/B,sBAAsB,EAAE,OAAO,CAAC;KACjC,CAAC;CACH,GAAG,OAAO,CAAC;IAAE,YAAY,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CA2DtC"}
|
|
@@ -7,8 +7,14 @@ export async function ensureInitWorkflow(opts) {
|
|
|
7
7
|
workflow: {
|
|
8
8
|
mode: opts.workflowMode,
|
|
9
9
|
version: 1,
|
|
10
|
+
approvals: {
|
|
11
|
+
require_plan: opts.approvals.requirePlanApproval,
|
|
12
|
+
require_verify: opts.approvals.requireVerifyApproval,
|
|
13
|
+
require_network: opts.approvals.requireNetworkApproval,
|
|
14
|
+
},
|
|
10
15
|
},
|
|
11
16
|
runtime: {
|
|
17
|
+
repo_name: opts.gitRoot.split(/[/\\\\]/).findLast((segment) => segment.length > 0) ?? "repo",
|
|
12
18
|
repo_root: opts.gitRoot,
|
|
13
19
|
timestamp: new Date().toISOString(),
|
|
14
20
|
},
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { CommandHandler, CommandSpec } from "../../spec/spec.js";
|
|
2
2
|
import { type ExecutionProfile } from "@agentplaneorg/core";
|
|
3
|
+
import type { PolicyGatewayFlavor } from "../../../shared/policy-gateway.js";
|
|
3
4
|
type InitFlags = {
|
|
4
5
|
setupProfile?: SetupProfilePreset;
|
|
6
|
+
policyGateway?: PolicyGatewayFlavor;
|
|
5
7
|
ide?: "codex" | "cursor" | "windsurf";
|
|
6
8
|
workflow?: "direct" | "branch_pr";
|
|
7
9
|
backend?: "local" | "redmine";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../../src/cli/run-cli/commands/init.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAItE,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../../src/cli/run-cli/commands/init.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAItE,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,qBAAqB,CAAC;AAc7B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAG7E,KAAK,SAAS,GAAG;IACf,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAClC,aAAa,CAAC,EAAE,mBAAmB,CAAC;IACpC,GAAG,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,UAAU,CAAC;IACtC,QAAQ,CAAC,EAAE,QAAQ,GAAG,WAAW,CAAC;IAClC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,OAAO,CAAC;CACd,CAAC;AAEF,KAAK,kBAAkB,GAAG,OAAO,GAAG,QAAQ,GAAG,cAAc,CAAC;AAoF9D,KAAK,UAAU,GAAG,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,GAAG;IAAE,GAAG,EAAE,OAAO,CAAA;CAAE,CAAC;AAE5D,eAAO,MAAM,QAAQ,EAAE,WAAW,CAAC,UAAU,CAyM5C,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,cAAc,CAAC,UAAU,CACmB,CAAC"}
|
|
@@ -20,11 +20,12 @@ import { ensureInitGitignore } from "./init/write-gitignore.js";
|
|
|
20
20
|
import { ensureInitRedmineEnvTemplate } from "./init/write-env.js";
|
|
21
21
|
import { renderInitSection, renderInitWelcome } from "./init/ui.js";
|
|
22
22
|
import { fileExists } from "../../fs-utils.js";
|
|
23
|
+
import { policyGatewayFileName } from "../../../shared/policy-gateway.js";
|
|
23
24
|
const setupProfilePresets = {
|
|
24
25
|
light: {
|
|
25
26
|
mode: "compact",
|
|
26
|
-
description: "Light profile (maximum flexibility, minimal enforcement, hooks
|
|
27
|
-
defaultHooks:
|
|
27
|
+
description: "Light profile (maximum flexibility, minimal enforcement, hooks disabled).",
|
|
28
|
+
defaultHooks: false,
|
|
28
29
|
defaultStrictUnsafeConfirm: false,
|
|
29
30
|
defaultRequirePlanApproval: false,
|
|
30
31
|
defaultRequireNetworkApproval: false,
|
|
@@ -34,7 +35,7 @@ const setupProfilePresets = {
|
|
|
34
35
|
},
|
|
35
36
|
normal: {
|
|
36
37
|
mode: "compact",
|
|
37
|
-
description: "Normal profile (balanced defaults and approvals enabled for standard team workflows).",
|
|
38
|
+
description: "Normal profile (balanced defaults and approvals enabled for standard team workflows; hooks enabled).",
|
|
38
39
|
defaultHooks: true,
|
|
39
40
|
defaultStrictUnsafeConfirm: false,
|
|
40
41
|
defaultRequirePlanApproval: true,
|
|
@@ -45,7 +46,7 @@ const setupProfilePresets = {
|
|
|
45
46
|
},
|
|
46
47
|
"full-harness": {
|
|
47
48
|
mode: "full",
|
|
48
|
-
description: "Full Harness profile (strict guardrails, explicit confirmations, conservative execution).",
|
|
49
|
+
description: "Full Harness profile (strict guardrails, explicit confirmations, conservative execution; hooks enabled).",
|
|
49
50
|
defaultHooks: true,
|
|
50
51
|
defaultStrictUnsafeConfirm: true,
|
|
51
52
|
defaultRequirePlanApproval: true,
|
|
@@ -113,6 +114,14 @@ export const initSpec = {
|
|
|
113
114
|
],
|
|
114
115
|
description: "Setup profile preset. Preferred values: light, normal, full-harness.",
|
|
115
116
|
},
|
|
117
|
+
{
|
|
118
|
+
kind: "string",
|
|
119
|
+
name: "policy-gateway",
|
|
120
|
+
valueHint: "<codex|claude>",
|
|
121
|
+
choices: ["codex", "claude"],
|
|
122
|
+
coerce: (raw) => raw.trim().toLowerCase(),
|
|
123
|
+
description: "Policy gateway file to install (codex -> AGENTS.md, claude -> CLAUDE.md).",
|
|
124
|
+
},
|
|
116
125
|
{
|
|
117
126
|
kind: "string",
|
|
118
127
|
name: "ide",
|
|
@@ -140,7 +149,7 @@ export const initSpec = {
|
|
|
140
149
|
kind: "string",
|
|
141
150
|
name: "hooks",
|
|
142
151
|
valueHint: "<true|false>",
|
|
143
|
-
description: "
|
|
152
|
+
description: "Install managed git hooks (default by setup profile: light=false, normal/full-harness=true).",
|
|
144
153
|
},
|
|
145
154
|
{
|
|
146
155
|
kind: "string",
|
|
@@ -201,7 +210,7 @@ export const initSpec = {
|
|
|
201
210
|
kind: "boolean",
|
|
202
211
|
name: "gitignore-agents",
|
|
203
212
|
default: false,
|
|
204
|
-
description: "Add agent files (AGENTS.md and .agentplane/agents/) to .gitignore and skip the initial install commit.",
|
|
213
|
+
description: "Add gateway/agent files (AGENTS.md or CLAUDE.md and .agentplane/agents/) to .gitignore and skip the initial install commit.",
|
|
205
214
|
},
|
|
206
215
|
],
|
|
207
216
|
examples: [
|
|
@@ -240,6 +249,7 @@ export const initSpec = {
|
|
|
240
249
|
const recipesRaw = raw.opts.recipes;
|
|
241
250
|
return {
|
|
242
251
|
setupProfile: normalizeSetupProfile(raw.opts["setup-profile"]),
|
|
252
|
+
policyGateway: raw.opts["policy-gateway"],
|
|
243
253
|
ide: raw.opts.ide,
|
|
244
254
|
workflow: raw.opts.workflow,
|
|
245
255
|
backend: raw.opts.backend,
|
|
@@ -272,22 +282,17 @@ export const initSpec = {
|
|
|
272
282
|
message: "Use either --force or --backup (not both).",
|
|
273
283
|
});
|
|
274
284
|
}
|
|
275
|
-
if (p.hooks === false) {
|
|
276
|
-
throw usageError({
|
|
277
|
-
spec: initSpec,
|
|
278
|
-
command: "init",
|
|
279
|
-
message: "Hooks installation is mandatory. Use --hooks true (or omit the flag).",
|
|
280
|
-
});
|
|
281
|
-
}
|
|
282
285
|
},
|
|
283
286
|
};
|
|
284
287
|
export const runInit = (ctx, flags) => cmdInit({ cwd: ctx.cwd, rootOverride: ctx.rootOverride, flags });
|
|
285
288
|
async function cmdInit(opts) {
|
|
286
289
|
const flags = opts.flags;
|
|
287
290
|
const defaults = {
|
|
291
|
+
policyGateway: "codex",
|
|
288
292
|
ide: "codex",
|
|
289
293
|
workflow: "direct",
|
|
290
294
|
backend: "local",
|
|
295
|
+
hooks: true,
|
|
291
296
|
recipes: [],
|
|
292
297
|
requirePlanApproval: true,
|
|
293
298
|
requireNetworkApproval: true,
|
|
@@ -296,8 +301,10 @@ async function cmdInit(opts) {
|
|
|
296
301
|
strictUnsafeConfirm: false,
|
|
297
302
|
};
|
|
298
303
|
let ide = flags.ide ?? defaults.ide;
|
|
304
|
+
let policyGateway = flags.policyGateway ?? defaults.policyGateway;
|
|
299
305
|
let workflow = flags.workflow ?? defaults.workflow;
|
|
300
306
|
let backend = flags.backend ?? defaults.backend;
|
|
307
|
+
let hooks = flags.hooks ?? defaults.hooks;
|
|
301
308
|
let recipes = flags.recipes ?? defaults.recipes;
|
|
302
309
|
let requirePlanApproval = flags.requirePlanApproval ?? defaults.requirePlanApproval;
|
|
303
310
|
let requireNetworkApproval = flags.requireNetworkApproval ?? defaults.requireNetworkApproval;
|
|
@@ -350,6 +357,14 @@ async function cmdInit(opts) {
|
|
|
350
357
|
}
|
|
351
358
|
const selectedPreset = setupProfilePresets[setupProfilePreset];
|
|
352
359
|
setupProfile = selectedPreset.mode;
|
|
360
|
+
hooks = flags.hooks ?? selectedPreset.defaultHooks;
|
|
361
|
+
if (flags.policyGateway) {
|
|
362
|
+
policyGateway = flags.policyGateway;
|
|
363
|
+
}
|
|
364
|
+
else {
|
|
365
|
+
process.stdout.write(renderInitSection("Policy Gateway", "Choose which root policy gateway file to install for your primary agent runtime."));
|
|
366
|
+
policyGateway = (await askChoice("Policy gateway", ["codex", "claude"], policyGateway));
|
|
367
|
+
}
|
|
353
368
|
if (flags.strictUnsafeConfirm === undefined) {
|
|
354
369
|
strictUnsafeConfirm = selectedPreset.defaultStrictUnsafeConfirm;
|
|
355
370
|
}
|
|
@@ -381,7 +396,9 @@ async function cmdInit(opts) {
|
|
|
381
396
|
backend = choice === "redmine" ? "redmine" : "local";
|
|
382
397
|
}
|
|
383
398
|
if (setupProfile === "full") {
|
|
384
|
-
process.stdout.write(renderInitSection("Hooks",
|
|
399
|
+
process.stdout.write(renderInitSection("Hooks", hooks
|
|
400
|
+
? "Managed git hooks are enabled and will be installed automatically."
|
|
401
|
+
: "Managed git hooks are disabled by profile/flag and will not be installed."));
|
|
385
402
|
process.stdout.write(renderInitSection("Execution Profile", "Set default autonomy/effort for agents. You can change this later in config."));
|
|
386
403
|
if (!flags.executionProfile) {
|
|
387
404
|
executionProfile = (await askChoice("Execution profile", ["conservative", "balanced", "aggressive"], executionProfile));
|
|
@@ -430,14 +447,16 @@ async function cmdInit(opts) {
|
|
|
430
447
|
flags.requireVerifyApproval ?? selectedPreset.defaultRequireVerifyApproval;
|
|
431
448
|
executionProfile = flags.executionProfile ?? selectedPreset.defaultExecutionProfile;
|
|
432
449
|
strictUnsafeConfirm = flags.strictUnsafeConfirm ?? selectedPreset.defaultStrictUnsafeConfirm;
|
|
433
|
-
process.stdout.write(renderInitSection("Defaults Applied", `Using compact ${setupProfilePreset} defaults for approvals, execution profile, and recipes. Hooks
|
|
450
|
+
process.stdout.write(renderInitSection("Defaults Applied", `Using compact ${setupProfilePreset} defaults for approvals, execution profile, and recipes. Hooks: ${hooks ? "enabled" : "disabled"}.`));
|
|
434
451
|
}
|
|
435
452
|
}
|
|
436
453
|
if (flags.yes) {
|
|
437
454
|
const yesPreset = setupProfilePresets[setupProfilePreset];
|
|
438
455
|
ide = flags.ide ?? defaults.ide;
|
|
456
|
+
policyGateway = flags.policyGateway ?? defaults.policyGateway;
|
|
439
457
|
workflow = flags.workflow ?? defaults.workflow;
|
|
440
458
|
backend = flags.backend ?? defaults.backend;
|
|
459
|
+
hooks = flags.hooks ?? yesPreset.defaultHooks;
|
|
441
460
|
recipes = flags.recipes ?? yesPreset.defaultRecipes;
|
|
442
461
|
requirePlanApproval = flags.requirePlanApproval ?? yesPreset.defaultRequirePlanApproval;
|
|
443
462
|
requireNetworkApproval =
|
|
@@ -473,8 +492,8 @@ async function cmdInit(opts) {
|
|
|
473
492
|
];
|
|
474
493
|
const initFiles = [configPath, backendPath];
|
|
475
494
|
const conflicts = await collectInitConflicts({ initDirs, initFiles });
|
|
476
|
-
const
|
|
477
|
-
const agentsMissing = !(await fileExists(
|
|
495
|
+
const gatewayPath = path.join(resolved.gitRoot, policyGatewayFileName(policyGateway));
|
|
496
|
+
const agentsMissing = !(await fileExists(gatewayPath));
|
|
478
497
|
if (conflicts.length > 0 && agentsMissing) {
|
|
479
498
|
// Recovery path: if a repo already contains conflicting .agentplane config/backend files,
|
|
480
499
|
// still materialize missing policy/agent templates before reporting conflicts.
|
|
@@ -483,6 +502,7 @@ async function cmdInit(opts) {
|
|
|
483
502
|
gitRoot: resolved.gitRoot,
|
|
484
503
|
agentplaneDir: resolved.agentplaneDir,
|
|
485
504
|
workflow,
|
|
505
|
+
policyGateway,
|
|
486
506
|
configPathAbs: configPath,
|
|
487
507
|
backendPathAbs: backendPath,
|
|
488
508
|
});
|
|
@@ -513,6 +533,7 @@ async function cmdInit(opts) {
|
|
|
513
533
|
gitRoot: resolved.gitRoot,
|
|
514
534
|
agentplaneDir: resolved.agentplaneDir,
|
|
515
535
|
workflow,
|
|
536
|
+
policyGateway,
|
|
516
537
|
configPathAbs: configPath,
|
|
517
538
|
backendPathAbs: backendPath,
|
|
518
539
|
});
|
|
@@ -527,6 +548,11 @@ async function cmdInit(opts) {
|
|
|
527
548
|
const workflowInit = await ensureInitWorkflow({
|
|
528
549
|
gitRoot: resolved.gitRoot,
|
|
529
550
|
workflowMode: workflow,
|
|
551
|
+
approvals: {
|
|
552
|
+
requirePlanApproval,
|
|
553
|
+
requireVerifyApproval,
|
|
554
|
+
requireNetworkApproval,
|
|
555
|
+
},
|
|
530
556
|
});
|
|
531
557
|
for (const abs of workflowInit.installPaths) {
|
|
532
558
|
installPaths.push(path.relative(resolved.gitRoot, abs));
|
|
@@ -538,8 +564,10 @@ async function cmdInit(opts) {
|
|
|
538
564
|
value: initBaseBranch,
|
|
539
565
|
});
|
|
540
566
|
}
|
|
541
|
-
|
|
542
|
-
|
|
567
|
+
if (hooks) {
|
|
568
|
+
await cmdHooksInstall({ cwd: opts.cwd, rootOverride: opts.rootOverride, quiet: true });
|
|
569
|
+
installPaths.push(".agentplane/bin/agentplane");
|
|
570
|
+
}
|
|
543
571
|
const ideRes = await maybeSyncIde({
|
|
544
572
|
cwd: opts.cwd,
|
|
545
573
|
rootOverride: opts.rootOverride,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-cli.d.ts","sourceRoot":"","sources":["../../src/cli/run-cli.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"run-cli.d.ts","sourceRoot":"","sources":["../../src/cli/run-cli.ts"],"names":[],"mappings":"AA0lBA,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA6N5D"}
|
package/dist/cli/run-cli.js
CHANGED
|
@@ -22,6 +22,7 @@ const GLOBAL_FLAGS = [
|
|
|
22
22
|
{ key: "noUpdateCheck", forms: ["--no-update-check"], takesValue: false, scoped: false },
|
|
23
23
|
{ key: "allowNetwork", forms: ["--allow-network"], takesValue: false, scoped: true },
|
|
24
24
|
{ key: "jsonErrors", forms: ["--json-errors"], takesValue: false, scoped: true },
|
|
25
|
+
{ key: "outputMode", forms: ["--output"], takesValue: true, scoped: false },
|
|
25
26
|
{ key: "root", forms: ["--root"], takesValue: true, scoped: false },
|
|
26
27
|
];
|
|
27
28
|
const GLOBAL_FLAG_FORMS = new Map(GLOBAL_FLAGS.flatMap((def) => def.forms.map((form) => [form, def])));
|
|
@@ -56,6 +57,7 @@ function parseGlobalArgs(argv) {
|
|
|
56
57
|
let jsonErrors = false;
|
|
57
58
|
let root;
|
|
58
59
|
let allowNetwork = false;
|
|
60
|
+
let outputMode;
|
|
59
61
|
const rest = [];
|
|
60
62
|
for (let i = 0; i < argv.length; i++) {
|
|
61
63
|
const arg = argv[i];
|
|
@@ -105,6 +107,27 @@ function parseGlobalArgs(argv) {
|
|
|
105
107
|
i++;
|
|
106
108
|
break;
|
|
107
109
|
}
|
|
110
|
+
case "outputMode": {
|
|
111
|
+
const next = argv[i + 1];
|
|
112
|
+
if (!next) {
|
|
113
|
+
throw new CliError({
|
|
114
|
+
exitCode: 2,
|
|
115
|
+
code: "E_USAGE",
|
|
116
|
+
message: "Missing value after --output (expected text|json)",
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
const normalized = next.trim().toLowerCase();
|
|
120
|
+
if (normalized !== "text" && normalized !== "json") {
|
|
121
|
+
throw new CliError({
|
|
122
|
+
exitCode: 2,
|
|
123
|
+
code: "E_USAGE",
|
|
124
|
+
message: `Invalid value for --output: ${next} (expected text|json)`,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
outputMode = normalized;
|
|
128
|
+
i++;
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
108
131
|
default: {
|
|
109
132
|
// Exhaustive by construction; keep a defensive fallback.
|
|
110
133
|
rest.push(arg);
|
|
@@ -112,7 +135,85 @@ function parseGlobalArgs(argv) {
|
|
|
112
135
|
}
|
|
113
136
|
}
|
|
114
137
|
}
|
|
115
|
-
return {
|
|
138
|
+
return {
|
|
139
|
+
globals: { help, version, noUpdateCheck, root, jsonErrors, allowNetwork, outputMode },
|
|
140
|
+
rest,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
const OUTPUT_MODE_ENV = "AGENTPLANE_OUTPUT";
|
|
144
|
+
function resolveOutputMode(modeFromFlag) {
|
|
145
|
+
if (modeFromFlag)
|
|
146
|
+
return modeFromFlag;
|
|
147
|
+
const fromEnv = process.env[OUTPUT_MODE_ENV]?.trim().toLowerCase();
|
|
148
|
+
if (!fromEnv || fromEnv === "text")
|
|
149
|
+
return "text";
|
|
150
|
+
if (fromEnv === "json")
|
|
151
|
+
return "json";
|
|
152
|
+
throw new CliError({
|
|
153
|
+
exitCode: 2,
|
|
154
|
+
code: "E_USAGE",
|
|
155
|
+
message: `Invalid ${OUTPUT_MODE_ENV}: ${fromEnv} (expected text|json)`,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
function chunkToString(chunk, encoding) {
|
|
159
|
+
if (typeof chunk === "string")
|
|
160
|
+
return chunk;
|
|
161
|
+
if (chunk instanceof Uint8Array)
|
|
162
|
+
return Buffer.from(chunk).toString(encoding);
|
|
163
|
+
return String(chunk);
|
|
164
|
+
}
|
|
165
|
+
async function runWithOutputMode(opts) {
|
|
166
|
+
if (opts.mode === "text")
|
|
167
|
+
return await opts.run();
|
|
168
|
+
const stdoutWrite = process.stdout.write.bind(process.stdout);
|
|
169
|
+
const stderrWrite = process.stderr.write.bind(process.stderr);
|
|
170
|
+
let stdout = "";
|
|
171
|
+
let stderr = "";
|
|
172
|
+
process.stdout.write = ((chunk, ...rest) => {
|
|
173
|
+
const encoding = typeof rest[0] === "string" ? rest[0] : undefined;
|
|
174
|
+
stdout += chunkToString(chunk, encoding);
|
|
175
|
+
const callback = rest.find((item) => typeof item === "function");
|
|
176
|
+
callback?.(null);
|
|
177
|
+
return true;
|
|
178
|
+
});
|
|
179
|
+
process.stderr.write = ((chunk, ...rest) => {
|
|
180
|
+
const encoding = typeof rest[0] === "string" ? rest[0] : undefined;
|
|
181
|
+
stderr += chunkToString(chunk, encoding);
|
|
182
|
+
const callback = rest.find((item) => typeof item === "function");
|
|
183
|
+
callback?.(null);
|
|
184
|
+
return true;
|
|
185
|
+
});
|
|
186
|
+
try {
|
|
187
|
+
const exitCode = await opts.run();
|
|
188
|
+
let parsed;
|
|
189
|
+
const trimmedStdout = stdout.trim();
|
|
190
|
+
if (trimmedStdout.length > 0) {
|
|
191
|
+
try {
|
|
192
|
+
parsed = JSON.parse(trimmedStdout);
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
parsed = undefined;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
const payload = {
|
|
199
|
+
schema_version: 1,
|
|
200
|
+
mode: "agent_json_v1",
|
|
201
|
+
command: opts.command,
|
|
202
|
+
ok: exitCode === 0,
|
|
203
|
+
exit_code: exitCode,
|
|
204
|
+
stdout: trimmedStdout,
|
|
205
|
+
stderr: stderr.trim(),
|
|
206
|
+
};
|
|
207
|
+
if (parsed !== undefined) {
|
|
208
|
+
payload.data = parsed;
|
|
209
|
+
}
|
|
210
|
+
stdoutWrite(`${JSON.stringify(payload, null, 2)}\n`);
|
|
211
|
+
return exitCode;
|
|
212
|
+
}
|
|
213
|
+
finally {
|
|
214
|
+
process.stdout.write = stdoutWrite;
|
|
215
|
+
process.stderr.write = stderrWrite;
|
|
216
|
+
}
|
|
116
217
|
}
|
|
117
218
|
function matchCommandCatalog(tokens) {
|
|
118
219
|
let best = null;
|
|
@@ -406,10 +507,17 @@ export async function runCli(argv) {
|
|
|
406
507
|
let jsonErrors = prescanJsonErrors(argv);
|
|
407
508
|
try {
|
|
408
509
|
const { globals, rest } = parseGlobalArgs(argv);
|
|
409
|
-
|
|
510
|
+
const outputMode = resolveOutputMode(globals.outputMode);
|
|
511
|
+
jsonErrors = globals.jsonErrors || outputMode === "json";
|
|
410
512
|
if (globals.version) {
|
|
411
|
-
|
|
412
|
-
|
|
513
|
+
return await runWithOutputMode({
|
|
514
|
+
mode: outputMode,
|
|
515
|
+
command: "version",
|
|
516
|
+
run: () => {
|
|
517
|
+
process.stdout.write(`${getVersion()}\n`);
|
|
518
|
+
return Promise.resolve(0);
|
|
519
|
+
},
|
|
520
|
+
});
|
|
413
521
|
}
|
|
414
522
|
const runCli2HelpFast = async (helpArgv) => {
|
|
415
523
|
const { buildRegistry } = await import("./run-cli/registry.run.js");
|
|
@@ -429,7 +537,13 @@ export async function runCli(argv) {
|
|
|
429
537
|
}
|
|
430
538
|
const tail = helpArgv.slice(match.consumed);
|
|
431
539
|
const parsed = parseCommandArgv(match.spec, tail).parsed;
|
|
432
|
-
return await
|
|
540
|
+
return await runWithOutputMode({
|
|
541
|
+
mode: outputMode,
|
|
542
|
+
command: match.spec.id.join(" "),
|
|
543
|
+
run: async () => {
|
|
544
|
+
return await match.handler({ cwd: process.cwd(), rootOverride: globals.root }, parsed);
|
|
545
|
+
},
|
|
546
|
+
});
|
|
433
547
|
};
|
|
434
548
|
// `--help` is treated as an alias for `help` and supports per-command help:
|
|
435
549
|
// - agentplane --help
|
|
@@ -520,7 +634,7 @@ export async function runCli(argv) {
|
|
|
520
634
|
await maybeWarnOnUpdate({
|
|
521
635
|
currentVersion: getVersion(),
|
|
522
636
|
skip: globals.noUpdateCheck || skipUpdateCheckForPolicy || matched?.entry.needsConfig === false,
|
|
523
|
-
jsonErrors
|
|
637
|
+
jsonErrors,
|
|
524
638
|
});
|
|
525
639
|
let ctxPromise = null;
|
|
526
640
|
const getCtx = async (commandForErrorContext) => {
|
|
@@ -562,7 +676,11 @@ export async function runCli(argv) {
|
|
|
562
676
|
if (match) {
|
|
563
677
|
const tail = rest.slice(match.consumed);
|
|
564
678
|
const parsed = parseCommandArgv(match.spec, tail).parsed;
|
|
565
|
-
return await
|
|
679
|
+
return await runWithOutputMode({
|
|
680
|
+
mode: outputMode,
|
|
681
|
+
command: match.spec.id.join(" "),
|
|
682
|
+
run: async () => await match.handler({ cwd, rootOverride: globals.root }, parsed),
|
|
683
|
+
});
|
|
566
684
|
}
|
|
567
685
|
const input = rest.join(" ");
|
|
568
686
|
const fullCandidates = registry.list().map((e) => e.spec.id.join(" "));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.run.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.run.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"doctor.run.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.run.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAM1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAyUrD,eAAO,MAAM,SAAS,EAAE,cAAc,CAAC,YAAY,CAmDlD,CAAC"}
|
|
@@ -3,6 +3,7 @@ import path from "node:path";
|
|
|
3
3
|
import { resolveProject } from "@agentplaneorg/core";
|
|
4
4
|
import { warnMessage, successMessage } from "../cli/output.js";
|
|
5
5
|
import { RUNTIME_GITIGNORE_LINES } from "../shared/runtime-artifacts.js";
|
|
6
|
+
import { resolvePolicyGatewayForRepo } from "../shared/policy-gateway.js";
|
|
6
7
|
import { execFileAsync, gitEnv } from "./shared/git.js";
|
|
7
8
|
import { loadCommandContext } from "./shared/task-backend.js";
|
|
8
9
|
import { emitWorkflowEvent, isWorkflowEnforcementDisabled, resolveWorkflowPaths, safeAutofixWorkflowText, validateWorkflowAtPath, workflowEnforcementEnvHint, } from "../workflow-runtime/index.js";
|
|
@@ -58,15 +59,19 @@ async function isDirectory(absPath) {
|
|
|
58
59
|
}
|
|
59
60
|
async function checkWorkspace(repoRoot) {
|
|
60
61
|
const problems = [];
|
|
61
|
-
const requiredFiles = [
|
|
62
|
-
path.join(repoRoot, "AGENTS.md"),
|
|
63
|
-
path.join(repoRoot, ".agentplane", "config.json"),
|
|
64
|
-
];
|
|
62
|
+
const requiredFiles = [path.join(repoRoot, ".agentplane", "config.json")];
|
|
65
63
|
for (const filePath of requiredFiles) {
|
|
66
64
|
if (!(await pathExists(filePath))) {
|
|
67
65
|
problems.push(`Missing required file: ${path.relative(repoRoot, filePath)}`);
|
|
68
66
|
}
|
|
69
67
|
}
|
|
68
|
+
const gateway = await resolvePolicyGatewayForRepo({
|
|
69
|
+
gitRoot: repoRoot,
|
|
70
|
+
fallbackFlavor: "codex",
|
|
71
|
+
});
|
|
72
|
+
if (!(await pathExists(gateway.absPath))) {
|
|
73
|
+
problems.push("Missing required policy gateway file: AGENTS.md or CLAUDE.md");
|
|
74
|
+
}
|
|
70
75
|
const agentsDir = path.join(repoRoot, ".agentplane", "agents");
|
|
71
76
|
if (!(await isDirectory(agentsDir))) {
|
|
72
77
|
problems.push("Missing required directory: .agentplane/agents");
|
|
@@ -286,11 +291,11 @@ async function checkDoneTaskCommitInvariants(repoRoot) {
|
|
|
286
291
|
continue;
|
|
287
292
|
const subject = subjectByHash.get(hash) ?? "";
|
|
288
293
|
if (!subject) {
|
|
289
|
-
problems.push(`DONE task references unknown commit hash: ${id} -> ${hash}`);
|
|
294
|
+
problems.push(`[WARN] DONE task references unknown commit hash: ${id} -> ${hash}`);
|
|
290
295
|
continue;
|
|
291
296
|
}
|
|
292
297
|
if (/\bclose:/iu.test(subject)) {
|
|
293
|
-
problems.push(`DONE task implementation commit points to a close commit: ${id} -> ${hash} (${subject})`);
|
|
298
|
+
problems.push(`[WARN] DONE task implementation commit points to a close commit: ${id} -> ${hash} (${subject})`);
|
|
294
299
|
}
|
|
295
300
|
}
|
|
296
301
|
return problems;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apply.command.d.ts","sourceRoot":"","sources":["../../../src/commands/release/apply.command.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAU1E,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,OAAO,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"apply.command.d.ts","sourceRoot":"","sources":["../../../src/commands/release/apply.command.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAU1E,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,OAAO,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,iBAAiB,CAAC;AA4VnD,eAAO,MAAM,gBAAgB,EAAE,WAAW,CAAC,kBAAkB,CAiF5D,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,cAAc,CAAC,kBAAkB,CAoL9D,CAAC"}
|
|
@@ -136,7 +136,7 @@ function cleanHookEnv() {
|
|
|
136
136
|
delete env.AGENTPLANE_AGENT_ID;
|
|
137
137
|
return env;
|
|
138
138
|
}
|
|
139
|
-
async function validateReleaseNotes(notesPath) {
|
|
139
|
+
async function validateReleaseNotes(notesPath, minBullets) {
|
|
140
140
|
const content = await readFile(notesPath, "utf8");
|
|
141
141
|
if (!/release\s+notes/i.test(content)) {
|
|
142
142
|
throw new CliError({
|
|
@@ -146,11 +146,11 @@ async function validateReleaseNotes(notesPath) {
|
|
|
146
146
|
});
|
|
147
147
|
}
|
|
148
148
|
const bulletCount = content.split(/\r?\n/u).filter((line) => /^\s*[-*]\s+\S+/u.test(line)).length;
|
|
149
|
-
if (bulletCount <
|
|
149
|
+
if (bulletCount < minBullets) {
|
|
150
150
|
throw new CliError({
|
|
151
151
|
exitCode: exitCodeForError("E_VALIDATION"),
|
|
152
152
|
code: "E_VALIDATION",
|
|
153
|
-
message: `Release notes must include at least
|
|
153
|
+
message: `Release notes must include at least ${minBullets} bullet points in ${notesPath}.`,
|
|
154
154
|
});
|
|
155
155
|
}
|
|
156
156
|
if (/[\u0400-\u04FF]/u.test(content)) {
|
|
@@ -383,6 +383,11 @@ export const runReleaseApply = async (ctx, flags) => {
|
|
|
383
383
|
});
|
|
384
384
|
}
|
|
385
385
|
const plan = parseVersionPlan(await readJsonFile(versionJsonPath));
|
|
386
|
+
const changesJsonPath = path.join(planDir, "changes.json");
|
|
387
|
+
const changes = (await fileExists(changesJsonPath))
|
|
388
|
+
? await readJsonFile(changesJsonPath)
|
|
389
|
+
: [];
|
|
390
|
+
const minBullets = Math.max(1, Array.isArray(changes) ? changes.length : 0);
|
|
386
391
|
if ((plan.bump === "minor" || plan.bump === "major") && flags.yes !== true) {
|
|
387
392
|
throw usageError({
|
|
388
393
|
spec: releaseApplySpec,
|
|
@@ -406,7 +411,7 @@ export const runReleaseApply = async (ctx, flags) => {
|
|
|
406
411
|
"Write this file using a DOCS agent before applying the release.",
|
|
407
412
|
});
|
|
408
413
|
}
|
|
409
|
-
await validateReleaseNotes(notesPath);
|
|
414
|
+
await validateReleaseNotes(notesPath, minBullets);
|
|
410
415
|
const corePkgPath = path.join(gitRoot, "packages", "core", "package.json");
|
|
411
416
|
const agentplanePkgPath = path.join(gitRoot, "packages", "agentplane", "package.json");
|
|
412
417
|
const [coreVersion, agentplaneVersion, coreDependencyVersion] = await Promise.all([
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plan.command.d.ts","sourceRoot":"","sources":["../../../src/commands/release/plan.command.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAM1E,KAAK,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AAE5C,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,OAAO,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"plan.command.d.ts","sourceRoot":"","sources":["../../../src/commands/release/plan.command.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAM1E,KAAK,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AAE5C,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,QAAQ,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,OAAO,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,gBAAgB,CAAC;AA4IjD,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,iBAAiB,CA4E1D,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,cAAc,CAAC,iBAAiB,CAqE5D,CAAC"}
|