agentplane 0.2.24 → 0.2.25
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/commands/block.spec.d.ts.map +1 -1
- package/dist/commands/block.spec.js +23 -2
- package/dist/commands/commit.spec.d.ts.map +1 -1
- package/dist/commands/commit.spec.js +18 -6
- package/dist/commands/finish.spec.d.ts.map +1 -1
- package/dist/commands/finish.spec.js +53 -4
- package/dist/commands/guard/commit.command.d.ts.map +1 -1
- package/dist/commands/guard/commit.command.js +26 -20
- package/dist/commands/guard/impl/allow.d.ts.map +1 -1
- package/dist/commands/guard/impl/allow.js +8 -1
- package/dist/commands/guard/impl/commands.d.ts.map +1 -1
- package/dist/commands/guard/impl/commands.js +7 -15
- package/dist/commands/guard/impl/comment-commit.d.ts.map +1 -1
- package/dist/commands/guard/impl/comment-commit.js +8 -17
- package/dist/commands/start.spec.d.ts.map +1 -1
- package/dist/commands/start.spec.js +23 -2
- package/dist/commands/task/finish.d.ts.map +1 -1
- package/dist/commands/task/finish.js +32 -10
- package/dist/commands/task/set-status.command.d.ts.map +1 -1
- package/dist/commands/task/set-status.command.js +22 -2
- package/dist/policy/rules/allowlist.d.ts.map +1 -1
- package/dist/policy/rules/allowlist.js +9 -0
- package/dist/shared/allow-prefix-policy.d.ts +3 -0
- package/dist/shared/allow-prefix-policy.d.ts.map +1 -0
- package/dist/shared/allow-prefix-policy.js +8 -0
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"block.spec.d.ts","sourceRoot":"","sources":["../../src/commands/block.spec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"block.spec.d.ts","sourceRoot":"","sources":["../../src/commands/block.spec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AASvD,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB,EAAE,OAAO,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,eAAe,EAAE,OAAO,CAAC;IACzB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,mBAAmB,EAAE,OAAO,CAAC;IAC7B,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,EAAE,OAAO,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,WAAW,CAAC,WAAW,CA8I9C,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { usageError } from "../cli/spec/errors.js";
|
|
2
|
+
import { findRepoWideAllowPrefixes, repoWideAllowPrefixMessage, } from "../shared/allow-prefix-policy.js";
|
|
2
3
|
import { toStringList } from "../cli/spec/parse-utils.js";
|
|
3
4
|
export const blockSpec = {
|
|
4
5
|
id: ["block"],
|
|
@@ -44,13 +45,14 @@ export const blockSpec = {
|
|
|
44
45
|
name: "commit-allow",
|
|
45
46
|
valueHint: "<path-prefix>",
|
|
46
47
|
repeatable: true,
|
|
47
|
-
description: "Repeatable. Allowlist path prefixes to stage for the status commit (used with --commit-from-comment).",
|
|
48
|
+
description: "Repeatable. Allowlist path prefixes to stage for the status commit (used with --commit-from-comment). Use minimal prefixes; '.' is rejected.",
|
|
48
49
|
},
|
|
49
50
|
{
|
|
50
51
|
kind: "boolean",
|
|
51
52
|
name: "commit-auto-allow",
|
|
52
53
|
default: false,
|
|
53
|
-
description: "
|
|
54
|
+
description: "Deprecated. Disabled for safety; pass explicit --commit-allow prefixes.",
|
|
55
|
+
deprecated: "disabled",
|
|
54
56
|
},
|
|
55
57
|
{
|
|
56
58
|
kind: "boolean",
|
|
@@ -99,10 +101,29 @@ export const blockSpec = {
|
|
|
99
101
|
validateRaw: (raw) => {
|
|
100
102
|
const author = typeof raw.opts.author === "string" ? raw.opts.author.trim() : "";
|
|
101
103
|
const body = typeof raw.opts.body === "string" ? raw.opts.body.trim() : "";
|
|
104
|
+
const commitAllow = toStringList(raw.opts["commit-allow"]);
|
|
102
105
|
if (!author)
|
|
103
106
|
throw usageError({ spec: blockSpec, message: "Invalid value for --author: empty." });
|
|
104
107
|
if (!body)
|
|
105
108
|
throw usageError({ spec: blockSpec, message: "Invalid value for --body: empty." });
|
|
109
|
+
if (findRepoWideAllowPrefixes(commitAllow).length > 0) {
|
|
110
|
+
throw usageError({
|
|
111
|
+
spec: blockSpec,
|
|
112
|
+
message: repoWideAllowPrefixMessage("--commit-allow"),
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
if (raw.opts["commit-auto-allow"] === true) {
|
|
116
|
+
throw usageError({
|
|
117
|
+
spec: blockSpec,
|
|
118
|
+
message: "--commit-auto-allow is disabled; pass explicit --commit-allow <path-prefix>.",
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
if (raw.opts["commit-from-comment"] === true && commitAllow.length === 0) {
|
|
122
|
+
throw usageError({
|
|
123
|
+
spec: blockSpec,
|
|
124
|
+
message: "--commit-from-comment requires --commit-allow <path-prefix> (tip: `agentplane guard suggest-allow --format args`).",
|
|
125
|
+
});
|
|
126
|
+
}
|
|
106
127
|
},
|
|
107
128
|
parse: (raw) => ({
|
|
108
129
|
taskId: typeof raw.args["task-id"] === "string" ? raw.args["task-id"] : "",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commit.spec.d.ts","sourceRoot":"","sources":["../../src/commands/commit.spec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"commit.spec.d.ts","sourceRoot":"","sources":["../../src/commands/commit.spec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAOvD,MAAM,MAAM,YAAY,GAAG;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,OAAO,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;IACf,kBAAkB,EAAE,OAAO,CAAC;IAC5B,cAAc,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,WAAW,CAAC,YAAY,CA8JhD,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { usageError } from "../cli/spec/errors.js";
|
|
2
|
+
import { findRepoWideAllowPrefixes, repoWideAllowPrefixMessage, } from "../shared/allow-prefix-policy.js";
|
|
2
3
|
export const commitSpec = {
|
|
3
4
|
id: ["commit"],
|
|
4
5
|
group: "Guard",
|
|
@@ -35,13 +36,14 @@ export const commitSpec = {
|
|
|
35
36
|
name: "allow",
|
|
36
37
|
valueHint: "<path-prefix>",
|
|
37
38
|
repeatable: true,
|
|
38
|
-
description: "Repeatable. Allowed path prefix (git-path).",
|
|
39
|
+
description: "Repeatable. Allowed path prefix (git-path). Use minimal prefixes; repo-wide '.' is rejected (tip: `agentplane guard suggest-allow --format args`).",
|
|
39
40
|
},
|
|
40
41
|
{
|
|
41
42
|
kind: "boolean",
|
|
42
43
|
name: "auto-allow",
|
|
43
44
|
default: false,
|
|
44
|
-
description: "
|
|
45
|
+
description: "Deprecated. Disabled for safety; pass explicit --allow prefixes.",
|
|
46
|
+
deprecated: "disabled",
|
|
45
47
|
},
|
|
46
48
|
{
|
|
47
49
|
kind: "boolean",
|
|
@@ -77,10 +79,6 @@ export const commitSpec = {
|
|
|
77
79
|
cmd: 'agentplane commit 202602030608-F1Q8AB -m "✨ F1Q8AB task: implement allowlist guard" --allow packages/agentplane',
|
|
78
80
|
why: "Create a commit after validating allowlist and subject policy.",
|
|
79
81
|
},
|
|
80
|
-
{
|
|
81
|
-
cmd: 'agentplane commit 202602030608-F1Q8AB -m "✨ F1Q8AB task: implement allowlist guard" --auto-allow',
|
|
82
|
-
why: "Infer allowlist prefixes from staged paths.",
|
|
83
|
-
},
|
|
84
82
|
{
|
|
85
83
|
cmd: "agentplane commit 202602030608-F1Q8AB --close",
|
|
86
84
|
why: "Create a close commit for the task README using a deterministic message builder.",
|
|
@@ -120,6 +118,20 @@ export const commitSpec = {
|
|
|
120
118
|
if (Array.isArray(allow) && allow.some((s) => typeof s === "string" && s.trim() === "")) {
|
|
121
119
|
throw usageError({ spec: commitSpec, message: "Invalid value for --allow: empty." });
|
|
122
120
|
}
|
|
121
|
+
const allowList = Array.isArray(allow)
|
|
122
|
+
? allow
|
|
123
|
+
: typeof allow === "string"
|
|
124
|
+
? [allow]
|
|
125
|
+
: [];
|
|
126
|
+
if (findRepoWideAllowPrefixes(allowList).length > 0) {
|
|
127
|
+
throw usageError({ spec: commitSpec, message: repoWideAllowPrefixMessage("--allow") });
|
|
128
|
+
}
|
|
129
|
+
if (raw.opts["auto-allow"] === true) {
|
|
130
|
+
throw usageError({
|
|
131
|
+
spec: commitSpec,
|
|
132
|
+
message: "--auto-allow is disabled; pass explicit --allow <path-prefix>.",
|
|
133
|
+
});
|
|
134
|
+
}
|
|
123
135
|
},
|
|
124
136
|
parse: (raw) => ({
|
|
125
137
|
taskId: String(raw.args["task-id"]),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"finish.spec.d.ts","sourceRoot":"","sources":["../../src/commands/finish.spec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"finish.spec.d.ts","sourceRoot":"","sources":["../../src/commands/finish.spec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AASvD,MAAM,MAAM,YAAY,GAAG;IACzB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;IAC9B,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,EAAE,OAAO,CAAC;IACb,iBAAiB,EAAE,OAAO,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,eAAe,EAAE,OAAO,CAAC;IACzB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,YAAY,EAAE,OAAO,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,wBAAwB,EAAE,OAAO,CAAC;IAClC,mBAAmB,EAAE,OAAO,CAAC;IAC7B,WAAW,EAAE,OAAO,CAAC;IACrB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,WAAW,CAAC,YAAY,CAsShD,CAAC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { usageError } from "../cli/spec/errors.js";
|
|
2
2
|
import { toStringList } from "../cli/spec/parse-utils.js";
|
|
3
|
+
import { findRepoWideAllowPrefixes, repoWideAllowPrefixMessage, } from "../shared/allow-prefix-policy.js";
|
|
3
4
|
export const finishSpec = {
|
|
4
5
|
id: ["finish"],
|
|
5
6
|
group: "Lifecycle",
|
|
@@ -77,13 +78,14 @@ export const finishSpec = {
|
|
|
77
78
|
name: "commit-allow",
|
|
78
79
|
valueHint: "<path-prefix>",
|
|
79
80
|
repeatable: true,
|
|
80
|
-
description: "Repeatable. Allowlist path prefixes to stage for the commit (used with --commit-from-comment).",
|
|
81
|
+
description: "Repeatable. Allowlist path prefixes to stage for the commit (used with --commit-from-comment). Use minimal prefixes; '.' is rejected.",
|
|
81
82
|
},
|
|
82
83
|
{
|
|
83
84
|
kind: "boolean",
|
|
84
85
|
name: "commit-auto-allow",
|
|
85
86
|
default: false,
|
|
86
|
-
description: "
|
|
87
|
+
description: "Deprecated. Disabled for safety; pass explicit --commit-allow prefixes.",
|
|
88
|
+
deprecated: "disabled",
|
|
87
89
|
},
|
|
88
90
|
{
|
|
89
91
|
kind: "boolean",
|
|
@@ -116,13 +118,14 @@ export const finishSpec = {
|
|
|
116
118
|
name: "status-commit-allow",
|
|
117
119
|
valueHint: "<path-prefix>",
|
|
118
120
|
repeatable: true,
|
|
119
|
-
description: "Repeatable. Allowlist path prefixes to stage for the status commit (used with --status-commit).",
|
|
121
|
+
description: "Repeatable. Allowlist path prefixes to stage for the status commit (used with --status-commit). Use minimal prefixes; '.' is rejected.",
|
|
120
122
|
},
|
|
121
123
|
{
|
|
122
124
|
kind: "boolean",
|
|
123
125
|
name: "status-commit-auto-allow",
|
|
124
126
|
default: false,
|
|
125
|
-
description: "
|
|
127
|
+
description: "Deprecated. Disabled for safety; pass explicit --status-commit-allow prefixes.",
|
|
128
|
+
deprecated: "disabled",
|
|
126
129
|
},
|
|
127
130
|
{
|
|
128
131
|
kind: "boolean",
|
|
@@ -165,6 +168,38 @@ export const finishSpec = {
|
|
|
165
168
|
const taskIds = Array.isArray(ids) ? ids : [];
|
|
166
169
|
const commitFromComment = raw.opts["commit-from-comment"] === true;
|
|
167
170
|
const statusCommit = raw.opts["status-commit"] === true;
|
|
171
|
+
const commitAllow = toStringList(raw.opts["commit-allow"]);
|
|
172
|
+
const statusCommitAllow = toStringList(raw.opts["status-commit-allow"]);
|
|
173
|
+
const commitAutoAllow = raw.opts["commit-auto-allow"] === true;
|
|
174
|
+
const statusCommitAutoAllow = raw.opts["status-commit-auto-allow"] === true;
|
|
175
|
+
if (findRepoWideAllowPrefixes(commitAllow).length > 0) {
|
|
176
|
+
throw usageError({
|
|
177
|
+
spec: finishSpec,
|
|
178
|
+
command: "finish",
|
|
179
|
+
message: repoWideAllowPrefixMessage("--commit-allow"),
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
if (findRepoWideAllowPrefixes(statusCommitAllow).length > 0) {
|
|
183
|
+
throw usageError({
|
|
184
|
+
spec: finishSpec,
|
|
185
|
+
command: "finish",
|
|
186
|
+
message: repoWideAllowPrefixMessage("--status-commit-allow"),
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
if (commitAutoAllow) {
|
|
190
|
+
throw usageError({
|
|
191
|
+
spec: finishSpec,
|
|
192
|
+
command: "finish",
|
|
193
|
+
message: "--commit-auto-allow is disabled; pass explicit --commit-allow <path-prefix>.",
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
if (statusCommitAutoAllow) {
|
|
197
|
+
throw usageError({
|
|
198
|
+
spec: finishSpec,
|
|
199
|
+
command: "finish",
|
|
200
|
+
message: "--status-commit-auto-allow is disabled; pass explicit --status-commit-allow <path-prefix>.",
|
|
201
|
+
});
|
|
202
|
+
}
|
|
168
203
|
if ((commitFromComment || statusCommit) && taskIds.length !== 1) {
|
|
169
204
|
throw usageError({
|
|
170
205
|
spec: finishSpec,
|
|
@@ -172,6 +207,20 @@ export const finishSpec = {
|
|
|
172
207
|
message: "--commit-from-comment/--status-commit requires exactly one task id",
|
|
173
208
|
});
|
|
174
209
|
}
|
|
210
|
+
if (commitFromComment && commitAllow.length === 0) {
|
|
211
|
+
throw usageError({
|
|
212
|
+
spec: finishSpec,
|
|
213
|
+
command: "finish",
|
|
214
|
+
message: "--commit-from-comment requires --commit-allow <path-prefix> (tip: `agentplane guard suggest-allow --format args`).",
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
if (statusCommit && statusCommitAllow.length === 0) {
|
|
218
|
+
throw usageError({
|
|
219
|
+
spec: finishSpec,
|
|
220
|
+
command: "finish",
|
|
221
|
+
message: "--status-commit requires --status-commit-allow <path-prefix> (tip: `agentplane guard suggest-allow --format args`).",
|
|
222
|
+
});
|
|
223
|
+
}
|
|
175
224
|
if (raw.opts["close-commit"] === true && taskIds.length !== 1) {
|
|
176
225
|
throw usageError({
|
|
177
226
|
spec: finishSpec,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commit.command.d.ts","sourceRoot":"","sources":["../../../src/commands/guard/commit.command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"commit.command.d.ts","sourceRoot":"","sources":["../../../src/commands/guard/commit.command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAOtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAIhE,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,OAAO,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,iBAAiB,CA0G1D,CAAC;AAEF,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,IAC1E,KAAK,UAAU,EAAE,GAAG,iBAAiB,KAAG,OAAO,CAAC,MAAM,CAAC,CA2BtE"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { usageError } from "../../cli/spec/errors.js";
|
|
2
2
|
import { CliError } from "../../shared/errors.js";
|
|
3
|
-
import {
|
|
3
|
+
import { findRepoWideAllowPrefixes, repoWideAllowPrefixMessage, } from "../../shared/allow-prefix-policy.js";
|
|
4
|
+
import { cmdGuardCommit } from "./index.js";
|
|
4
5
|
export const guardCommitSpec = {
|
|
5
6
|
id: ["guard", "commit"],
|
|
6
7
|
group: "Guard",
|
|
@@ -20,13 +21,14 @@ export const guardCommitSpec = {
|
|
|
20
21
|
name: "allow",
|
|
21
22
|
valueHint: "<path-prefix>",
|
|
22
23
|
repeatable: true,
|
|
23
|
-
description: "Repeatable. Allowed path prefix (git-path).",
|
|
24
|
+
description: "Repeatable. Allowed path prefix (git-path). Use minimal prefixes; repo-wide '.' is rejected (tip: `agentplane guard suggest-allow --format args`).",
|
|
24
25
|
},
|
|
25
26
|
{
|
|
26
27
|
kind: "boolean",
|
|
27
28
|
name: "auto-allow",
|
|
28
29
|
default: false,
|
|
29
|
-
description: "
|
|
30
|
+
description: "Deprecated. Disabled for safety; pass explicit --allow prefixes.",
|
|
31
|
+
deprecated: "disabled",
|
|
30
32
|
},
|
|
31
33
|
{
|
|
32
34
|
kind: "boolean",
|
|
@@ -62,10 +64,6 @@ export const guardCommitSpec = {
|
|
|
62
64
|
cmd: 'agentplane guard commit 202602030608-F1Q8AB -m "✨ F1Q8AB task: implement allowlist guard" --allow packages/agentplane',
|
|
63
65
|
why: "Validate staged changes are covered by allowlist and policy.",
|
|
64
66
|
},
|
|
65
|
-
{
|
|
66
|
-
cmd: 'agentplane guard commit 202602030608-F1Q8AB -m "✨ F1Q8AB task: implement allowlist guard" --auto-allow',
|
|
67
|
-
why: "Infer allowlist prefixes from staged paths.",
|
|
68
|
-
},
|
|
69
67
|
],
|
|
70
68
|
validateRaw: (raw) => {
|
|
71
69
|
const msg = typeof raw.opts.message === "string" ? raw.opts.message.trim() : "";
|
|
@@ -76,6 +74,20 @@ export const guardCommitSpec = {
|
|
|
76
74
|
if (Array.isArray(allow) && allow.some((s) => typeof s === "string" && s.trim() === "")) {
|
|
77
75
|
throw usageError({ spec: guardCommitSpec, message: "Invalid value for --allow: empty." });
|
|
78
76
|
}
|
|
77
|
+
const allowList = Array.isArray(allow)
|
|
78
|
+
? allow
|
|
79
|
+
: typeof allow === "string"
|
|
80
|
+
? [allow]
|
|
81
|
+
: [];
|
|
82
|
+
if (findRepoWideAllowPrefixes(allowList).length > 0) {
|
|
83
|
+
throw usageError({ spec: guardCommitSpec, message: repoWideAllowPrefixMessage("--allow") });
|
|
84
|
+
}
|
|
85
|
+
if (raw.opts["auto-allow"] === true) {
|
|
86
|
+
throw usageError({
|
|
87
|
+
spec: guardCommitSpec,
|
|
88
|
+
message: "--auto-allow is disabled; pass explicit --allow <path-prefix>.",
|
|
89
|
+
});
|
|
90
|
+
}
|
|
79
91
|
},
|
|
80
92
|
parse: (raw) => ({
|
|
81
93
|
taskId: String(raw.args["task-id"]),
|
|
@@ -99,18 +111,12 @@ export const guardCommitSpec = {
|
|
|
99
111
|
export function makeRunGuardCommitHandler(getCtx) {
|
|
100
112
|
return async (ctx, p) => {
|
|
101
113
|
const cmdCtx = await getCtx("guard commit");
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
exitCode: 5,
|
|
109
|
-
code: "E_GIT",
|
|
110
|
-
message: "No staged files (git index empty)",
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
allow = prefixes;
|
|
114
|
+
if (p.autoAllow) {
|
|
115
|
+
throw new CliError({
|
|
116
|
+
exitCode: 2,
|
|
117
|
+
code: "E_USAGE",
|
|
118
|
+
message: "--auto-allow is disabled; pass explicit --allow <path-prefix>.",
|
|
119
|
+
});
|
|
114
120
|
}
|
|
115
121
|
return await cmdGuardCommit({
|
|
116
122
|
ctx: cmdCtx,
|
|
@@ -118,7 +124,7 @@ export function makeRunGuardCommitHandler(getCtx) {
|
|
|
118
124
|
rootOverride: ctx.rootOverride,
|
|
119
125
|
taskId: p.taskId,
|
|
120
126
|
message: p.message,
|
|
121
|
-
allow,
|
|
127
|
+
allow: p.allow,
|
|
122
128
|
allowBase: p.allowBase,
|
|
123
129
|
allowTasks: p.allowTasks,
|
|
124
130
|
allowPolicy: p.allowPolicy,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"allow.d.ts","sourceRoot":"","sources":["../../../../src/commands/guard/impl/allow.ts"],"names":[],"mappings":"AAMA,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAkBvF,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAe9D;AAED,wBAAsB,qBAAqB,CAAC,IAAI,EAAE;IAChD,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAOpB;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE;IACzC,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqBhB;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE;IACzC,GAAG,EAAE,cAAc,CAAC;IACpB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"allow.d.ts","sourceRoot":"","sources":["../../../../src/commands/guard/impl/allow.ts"],"names":[],"mappings":"AAMA,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAkBvF,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAe9D;AAED,wBAAsB,qBAAqB,CAAC,IAAI,EAAE;IAChD,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAOpB;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE;IACzC,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqBhB;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE;IACzC,GAAG,EAAE,cAAc,CAAC;IACpB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAkDpB"}
|
|
@@ -82,6 +82,13 @@ export async function stageAllowlist(opts) {
|
|
|
82
82
|
message: "Provide at least one allowed prefix",
|
|
83
83
|
});
|
|
84
84
|
}
|
|
85
|
+
if (allow.includes(".")) {
|
|
86
|
+
throw new CliError({
|
|
87
|
+
exitCode: 2,
|
|
88
|
+
code: "E_USAGE",
|
|
89
|
+
message: "Repo-wide allowlist ('.') is not allowed; choose minimal prefixes (tip: `agentplane guard suggest-allow --format args`).",
|
|
90
|
+
});
|
|
91
|
+
}
|
|
85
92
|
const denied = new Set();
|
|
86
93
|
if (!opts.allowTasks)
|
|
87
94
|
denied.add(opts.tasksPath);
|
|
@@ -98,7 +105,7 @@ export async function stageAllowlist(opts) {
|
|
|
98
105
|
throw new CliError({
|
|
99
106
|
exitCode: 2,
|
|
100
107
|
code: "E_USAGE",
|
|
101
|
-
message: "No changes matched allowed prefixes (
|
|
108
|
+
message: "No changes matched allowed prefixes (update --commit-allow)",
|
|
102
109
|
});
|
|
103
110
|
}
|
|
104
111
|
// `git add <pathspec>` is not reliable for staging deletes/renames across versions/configs.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../../../src/commands/guard/impl/commands.ts"],"names":[],"mappings":"AAGA,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAOvF,OAAO,EAAoB,KAAK,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAyDxE,wBAAsB,aAAa,CAAC,IAAI,EAAE;IACxC,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CAsBlB;AAED,wBAAsB,oBAAoB,CAAC,IAAI,EAAE;IAC/C,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC;CAC1B,GAAG,OAAO,CAAC,MAAM,CAAC,CAyBlB;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CAS9E;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE;IACpC,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,OAAO,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;IACf,kBAAkB,EAAE,OAAO,CAAC;IAC5B,cAAc,EAAE,OAAO,CAAC;CACzB,GAAG,OAAO,CAAC,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../../../src/commands/guard/impl/commands.ts"],"names":[],"mappings":"AAGA,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAOvF,OAAO,EAAoB,KAAK,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAyDxE,wBAAsB,aAAa,CAAC,IAAI,EAAE;IACxC,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CAsBlB;AAED,wBAAsB,oBAAoB,CAAC,IAAI,EAAE;IAC/C,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC;CAC1B,GAAG,OAAO,CAAC,MAAM,CAAC,CAyBlB;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,MAAM,CAAC,CAS9E;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE;IACpC,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,OAAO,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;IACf,kBAAkB,EAAE,OAAO,CAAC;IAC5B,cAAc,EAAE,OAAO,CAAC;CACzB,GAAG,OAAO,CAAC,MAAM,CAAC,CAgJlB"}
|
|
@@ -201,20 +201,12 @@ export async function cmdCommit(opts) {
|
|
|
201
201
|
}
|
|
202
202
|
return 0;
|
|
203
203
|
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
if (prefixes.length === 0) {
|
|
211
|
-
throw new CliError({
|
|
212
|
-
exitCode: 5,
|
|
213
|
-
code: "E_GIT",
|
|
214
|
-
message: "No staged files (git index empty)",
|
|
215
|
-
});
|
|
216
|
-
}
|
|
217
|
-
allow = prefixes;
|
|
204
|
+
if (opts.autoAllow) {
|
|
205
|
+
throw new CliError({
|
|
206
|
+
exitCode: 2,
|
|
207
|
+
code: "E_USAGE",
|
|
208
|
+
message: "--auto-allow is disabled; pass explicit --allow <path-prefix>.",
|
|
209
|
+
});
|
|
218
210
|
}
|
|
219
211
|
await guardCommitCheck({
|
|
220
212
|
ctx: opts.ctx,
|
|
@@ -222,7 +214,7 @@ export async function cmdCommit(opts) {
|
|
|
222
214
|
rootOverride: opts.rootOverride,
|
|
223
215
|
taskId: opts.taskId,
|
|
224
216
|
message: opts.message,
|
|
225
|
-
allow,
|
|
217
|
+
allow: opts.allow,
|
|
226
218
|
allowBase: opts.allowBase,
|
|
227
219
|
allowTasks: opts.allowTasks,
|
|
228
220
|
allowPolicy: opts.allowPolicy,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"comment-commit.d.ts","sourceRoot":"","sources":["../../../../src/commands/guard/impl/comment-commit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"comment-commit.d.ts","sourceRoot":"","sources":["../../../../src/commands/guard/impl/comment-commit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAQ/E,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAiEvF,wBAAsB,iBAAiB,CAAC,IAAI,EAAE;IAC5C,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;IACtB,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,gBAAgB,CAAC;CAC1B,GAAG,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAyF/D"}
|
|
@@ -2,10 +2,9 @@ import { extractTaskSuffix } from "@agentplaneorg/core";
|
|
|
2
2
|
import { invalidValueMessage, successMessage } from "../../../cli/output.js";
|
|
3
3
|
import { CliError } from "../../../shared/errors.js";
|
|
4
4
|
import { formatCommentBodyForCommit, normalizeCommentBodyForCommit, } from "../../../shared/comment-format.js";
|
|
5
|
-
import { protectedPathKindForFile } from "../../../shared/protected-paths.js";
|
|
6
5
|
import { loadCommandContext } from "../../shared/task-backend.js";
|
|
7
6
|
import { buildGitCommitEnv } from "./env.js";
|
|
8
|
-
import { stageAllowlist
|
|
7
|
+
import { stageAllowlist } from "./allow.js";
|
|
9
8
|
import { guardCommitCheck } from "./policy.js";
|
|
10
9
|
function deriveCommitMessageFromComment(opts) {
|
|
11
10
|
const prefix = opts.emoji.trim();
|
|
@@ -49,27 +48,19 @@ function deriveCommitBodyFromComment(opts) {
|
|
|
49
48
|
export async function commitFromComment(opts) {
|
|
50
49
|
const ctx = opts.ctx ??
|
|
51
50
|
(await loadCommandContext({ cwd: opts.cwd, rootOverride: opts.rootOverride ?? null }));
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
// broaden into policy/config/CI changes (those require explicit intent).
|
|
58
|
-
const eligible = changed.filter((filePath) => {
|
|
59
|
-
const kind = protectedPathKindForFile({ filePath, tasksPath });
|
|
60
|
-
if (!kind)
|
|
61
|
-
return true;
|
|
62
|
-
if (kind === "tasks")
|
|
63
|
-
return opts.allowTasks;
|
|
64
|
-
return false;
|
|
51
|
+
if (opts.autoAllow) {
|
|
52
|
+
throw new CliError({
|
|
53
|
+
exitCode: 2,
|
|
54
|
+
code: "E_USAGE",
|
|
55
|
+
message: "--commit-auto-allow is disabled; pass explicit --commit-allow <path-prefix>.",
|
|
65
56
|
});
|
|
66
|
-
allowPrefixes = suggestAllowPrefixes(eligible);
|
|
67
57
|
}
|
|
58
|
+
let allowPrefixes = opts.allow.map((prefix) => prefix.trim()).filter(Boolean);
|
|
68
59
|
if (allowPrefixes.length === 0) {
|
|
69
60
|
throw new CliError({
|
|
70
61
|
exitCode: 2,
|
|
71
62
|
code: "E_USAGE",
|
|
72
|
-
message: "Provide at least one --commit-allow prefix
|
|
63
|
+
message: "Provide at least one --commit-allow prefix",
|
|
73
64
|
});
|
|
74
65
|
}
|
|
75
66
|
const staged = await stageAllowlist({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"start.spec.d.ts","sourceRoot":"","sources":["../../src/commands/start.spec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"start.spec.d.ts","sourceRoot":"","sources":["../../src/commands/start.spec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AASvD,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,iBAAiB,EAAE,OAAO,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,eAAe,EAAE,OAAO,CAAC;IACzB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,mBAAmB,EAAE,OAAO,CAAC;IAC7B,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,EAAE,OAAO,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,WAAW,CAAC,WAAW,CA8I9C,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { usageError } from "../cli/spec/errors.js";
|
|
2
|
+
import { findRepoWideAllowPrefixes, repoWideAllowPrefixMessage, } from "../shared/allow-prefix-policy.js";
|
|
2
3
|
import { toStringList } from "../cli/spec/parse-utils.js";
|
|
3
4
|
export const startSpec = {
|
|
4
5
|
id: ["start"],
|
|
@@ -44,13 +45,14 @@ export const startSpec = {
|
|
|
44
45
|
name: "commit-allow",
|
|
45
46
|
valueHint: "<path-prefix>",
|
|
46
47
|
repeatable: true,
|
|
47
|
-
description: "Repeatable. Allowlist path prefixes to stage for the status commit (used with --commit-from-comment).",
|
|
48
|
+
description: "Repeatable. Allowlist path prefixes to stage for the status commit (used with --commit-from-comment). Use minimal prefixes; '.' is rejected.",
|
|
48
49
|
},
|
|
49
50
|
{
|
|
50
51
|
kind: "boolean",
|
|
51
52
|
name: "commit-auto-allow",
|
|
52
53
|
default: false,
|
|
53
|
-
description: "
|
|
54
|
+
description: "Deprecated. Disabled for safety; pass explicit --commit-allow prefixes.",
|
|
55
|
+
deprecated: "disabled",
|
|
54
56
|
},
|
|
55
57
|
{
|
|
56
58
|
kind: "boolean",
|
|
@@ -99,10 +101,29 @@ export const startSpec = {
|
|
|
99
101
|
validateRaw: (raw) => {
|
|
100
102
|
const author = typeof raw.opts.author === "string" ? raw.opts.author.trim() : "";
|
|
101
103
|
const body = typeof raw.opts.body === "string" ? raw.opts.body.trim() : "";
|
|
104
|
+
const commitAllow = toStringList(raw.opts["commit-allow"]);
|
|
102
105
|
if (!author)
|
|
103
106
|
throw usageError({ spec: startSpec, message: "Invalid value for --author: empty." });
|
|
104
107
|
if (!body)
|
|
105
108
|
throw usageError({ spec: startSpec, message: "Invalid value for --body: empty." });
|
|
109
|
+
if (findRepoWideAllowPrefixes(commitAllow).length > 0) {
|
|
110
|
+
throw usageError({
|
|
111
|
+
spec: startSpec,
|
|
112
|
+
message: repoWideAllowPrefixMessage("--commit-allow"),
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
if (raw.opts["commit-auto-allow"] === true) {
|
|
116
|
+
throw usageError({
|
|
117
|
+
spec: startSpec,
|
|
118
|
+
message: "--commit-auto-allow is disabled; pass explicit --commit-allow <path-prefix>.",
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
if (raw.opts["commit-from-comment"] === true && commitAllow.length === 0) {
|
|
122
|
+
throw usageError({
|
|
123
|
+
spec: startSpec,
|
|
124
|
+
message: "--commit-from-comment requires --commit-allow <path-prefix> (tip: `agentplane guard suggest-allow --format args`).",
|
|
125
|
+
});
|
|
126
|
+
}
|
|
106
127
|
},
|
|
107
128
|
parse: (raw) => ({
|
|
108
129
|
taskId: typeof raw.args["task-id"] === "string" ? raw.args["task-id"] : "",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"finish.d.ts","sourceRoot":"","sources":["../../../src/commands/task/finish.ts"],"names":[],"mappings":"AAUA,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,2BAA2B,CAAC;AAmCnC,wBAAsB,SAAS,CAAC,IAAI,EAAE;IACpC,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;IAC9B,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,iBAAiB,EAAE,OAAO,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,eAAe,EAAE,OAAO,CAAC;IACzB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,YAAY,EAAE,OAAO,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,wBAAwB,EAAE,OAAO,CAAC;IAClC,mBAAmB,EAAE,OAAO,CAAC;IAC7B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"finish.d.ts","sourceRoot":"","sources":["../../../src/commands/task/finish.ts"],"names":[],"mappings":"AAUA,OAAO,EAGL,KAAK,cAAc,EACpB,MAAM,2BAA2B,CAAC;AAmCnC,wBAAsB,SAAS,CAAC,IAAI,EAAE;IACpC,GAAG,CAAC,EAAE,cAAc,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;IAC9B,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,iBAAiB,EAAE,OAAO,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,eAAe,EAAE,OAAO,CAAC;IACzB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,YAAY,EAAE,OAAO,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,wBAAwB,EAAE,OAAO,CAAC;IAClC,mBAAmB,EAAE,OAAO,CAAC;IAC7B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,MAAM,CAAC,CA2VlB"}
|
|
@@ -40,13 +40,7 @@ export async function cmdFinish(opts) {
|
|
|
40
40
|
}
|
|
41
41
|
const { prefix, min_chars: minChars } = ctx.config.tasks.comments.verified;
|
|
42
42
|
requireStructuredComment(opts.body, prefix, minChars);
|
|
43
|
-
const
|
|
44
|
-
ctx.config.commit_automation === "finish_only") &&
|
|
45
|
-
!opts.commitFromComment &&
|
|
46
|
-
!opts.statusCommit &&
|
|
47
|
-
opts.closeCommit !== true &&
|
|
48
|
-
opts.taskIds.length === 1;
|
|
49
|
-
const statusCommitRequested = opts.statusCommit || autoStatusCommit;
|
|
43
|
+
const statusCommitRequested = opts.statusCommit;
|
|
50
44
|
if ((opts.commitFromComment || statusCommitRequested) && opts.taskIds.length !== 1) {
|
|
51
45
|
throw new CliError({
|
|
52
46
|
exitCode: 2,
|
|
@@ -76,6 +70,34 @@ export async function cmdFinish(opts) {
|
|
|
76
70
|
message: "--commit-from-comment/--status-commit requires exactly one task id",
|
|
77
71
|
});
|
|
78
72
|
}
|
|
73
|
+
if (opts.commitAutoAllow) {
|
|
74
|
+
throw new CliError({
|
|
75
|
+
exitCode: 2,
|
|
76
|
+
code: "E_USAGE",
|
|
77
|
+
message: "--commit-auto-allow is disabled; pass explicit --commit-allow <path-prefix>.",
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
if (opts.statusCommitAutoAllow) {
|
|
81
|
+
throw new CliError({
|
|
82
|
+
exitCode: 2,
|
|
83
|
+
code: "E_USAGE",
|
|
84
|
+
message: "--status-commit-auto-allow is disabled; pass explicit --status-commit-allow <path-prefix>.",
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
if (opts.commitFromComment && opts.commitAllow.length === 0) {
|
|
88
|
+
throw new CliError({
|
|
89
|
+
exitCode: 2,
|
|
90
|
+
code: "E_USAGE",
|
|
91
|
+
message: "--commit-from-comment requires --commit-allow <path-prefix>",
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
if (statusCommitRequested && opts.statusCommitAllow.length === 0) {
|
|
95
|
+
throw new CliError({
|
|
96
|
+
exitCode: 2,
|
|
97
|
+
code: "E_USAGE",
|
|
98
|
+
message: "--status-commit requires --status-commit-allow <path-prefix>",
|
|
99
|
+
});
|
|
100
|
+
}
|
|
79
101
|
const gitRoot = ctx.resolvedProject.gitRoot;
|
|
80
102
|
const commitInfo = opts.commit
|
|
81
103
|
? await readCommitInfo(gitRoot, opts.commit)
|
|
@@ -168,7 +190,7 @@ export async function cmdFinish(opts) {
|
|
|
168
190
|
enforceStatusCommitPolicy({
|
|
169
191
|
policy: ctx.config.status_commit_policy,
|
|
170
192
|
action: "finish",
|
|
171
|
-
confirmed: opts.confirmStatusCommit
|
|
193
|
+
confirmed: opts.confirmStatusCommit,
|
|
172
194
|
quiet: opts.quiet,
|
|
173
195
|
statusFrom: primaryStatusFrom ?? "UNKNOWN",
|
|
174
196
|
statusTo: "DONE",
|
|
@@ -208,7 +230,7 @@ export async function cmdFinish(opts) {
|
|
|
208
230
|
formattedComment: formatCommentBodyForCommit(opts.body, ctx.config),
|
|
209
231
|
emoji: opts.commitEmoji ?? defaultCommitEmojiForStatus("DONE"),
|
|
210
232
|
allow: opts.commitAllow,
|
|
211
|
-
autoAllow:
|
|
233
|
+
autoAllow: false,
|
|
212
234
|
allowTasks: opts.commitAllowTasks,
|
|
213
235
|
requireClean: opts.commitRequireClean,
|
|
214
236
|
quiet: opts.quiet,
|
|
@@ -269,7 +291,7 @@ export async function cmdFinish(opts) {
|
|
|
269
291
|
formattedComment: formatCommentBodyForCommit(opts.body, ctx.config),
|
|
270
292
|
emoji: opts.statusCommitEmoji ?? defaultCommitEmojiForStatus("DONE"),
|
|
271
293
|
allow: opts.statusCommitAllow,
|
|
272
|
-
autoAllow:
|
|
294
|
+
autoAllow: false,
|
|
273
295
|
allowTasks: true,
|
|
274
296
|
requireClean: opts.statusCommitRequireClean,
|
|
275
297
|
quiet: opts.quiet,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"set-status.command.d.ts","sourceRoot":"","sources":["../../../src/commands/task/set-status.command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"set-status.command.d.ts","sourceRoot":"","sources":["../../../src/commands/task/set-status.command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAOtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAIhE,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,EAAE,OAAO,CAAC;IACb,iBAAiB,EAAE,OAAO,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,eAAe,EAAE,OAAO,CAAC;IACzB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,mBAAmB,EAAE,OAAO,CAAC;IAC7B,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,WAAW,CAAC,mBAAmB,CAyK9D,CAAC;AAEF,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,cAAc,CAAC,IAC5E,KAAK,UAAU,EAAE,GAAG,mBAAmB,KAAG,OAAO,CAAC,MAAM,CAAC,CAsBxE"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { usageError } from "../../cli/spec/errors.js";
|
|
2
2
|
import { toStringList } from "../../cli/spec/parse-utils.js";
|
|
3
|
+
import { findRepoWideAllowPrefixes, repoWideAllowPrefixMessage, } from "../../shared/allow-prefix-policy.js";
|
|
3
4
|
import { cmdTaskSetStatus } from "./set-status.js";
|
|
4
5
|
export const taskSetStatusSpec = {
|
|
5
6
|
id: ["task", "set-status"],
|
|
@@ -57,13 +58,14 @@ export const taskSetStatusSpec = {
|
|
|
57
58
|
name: "commit-allow",
|
|
58
59
|
valueHint: "<path-prefix>",
|
|
59
60
|
repeatable: true,
|
|
60
|
-
description: "Repeatable. Allowlist prefix for commit-from-comment staging.",
|
|
61
|
+
description: "Repeatable. Allowlist prefix for commit-from-comment staging. Use minimal prefixes; '.' is rejected.",
|
|
61
62
|
},
|
|
62
63
|
{
|
|
63
64
|
kind: "boolean",
|
|
64
65
|
name: "commit-auto-allow",
|
|
65
66
|
default: false,
|
|
66
|
-
description: "
|
|
67
|
+
description: "Deprecated. Disabled for safety; pass explicit --commit-allow prefixes.",
|
|
68
|
+
deprecated: "disabled",
|
|
67
69
|
},
|
|
68
70
|
{
|
|
69
71
|
kind: "boolean",
|
|
@@ -125,6 +127,24 @@ export const taskSetStatusSpec = {
|
|
|
125
127
|
message: "Invalid value for --commit-allow: empty.",
|
|
126
128
|
});
|
|
127
129
|
}
|
|
130
|
+
if (findRepoWideAllowPrefixes(allow).length > 0) {
|
|
131
|
+
throw usageError({
|
|
132
|
+
spec: taskSetStatusSpec,
|
|
133
|
+
message: repoWideAllowPrefixMessage("--commit-allow"),
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
if (raw.opts["commit-auto-allow"] === true) {
|
|
137
|
+
throw usageError({
|
|
138
|
+
spec: taskSetStatusSpec,
|
|
139
|
+
message: "--commit-auto-allow is disabled; pass explicit --commit-allow <path-prefix>.",
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
if (raw.opts["commit-from-comment"] === true && allow.length === 0) {
|
|
143
|
+
throw usageError({
|
|
144
|
+
spec: taskSetStatusSpec,
|
|
145
|
+
message: "--commit-from-comment requires --commit-allow <path-prefix> (tip: `agentplane guard suggest-allow --format args`).",
|
|
146
|
+
});
|
|
147
|
+
}
|
|
128
148
|
},
|
|
129
149
|
parse: (raw) => {
|
|
130
150
|
const commitAllow = toStringList(raw.opts["commit-allow"]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"allowlist.d.ts","sourceRoot":"","sources":["../../../src/policy/rules/allowlist.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE/D,wBAAgB,aAAa,CAAC,GAAG,EAAE,aAAa,GAAG,YAAY,
|
|
1
|
+
{"version":3,"file":"allowlist.d.ts","sourceRoot":"","sources":["../../../src/policy/rules/allowlist.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE/D,wBAAgB,aAAa,CAAC,GAAG,EAAE,aAAa,GAAG,YAAY,CA0C9D"}
|
|
@@ -17,6 +17,15 @@ export function allowlistRule(ctx) {
|
|
|
17
17
|
};
|
|
18
18
|
}
|
|
19
19
|
const allow = allowRaw.map((p) => normalizeGitPathPrefix(p));
|
|
20
|
+
if (allow.includes(".")) {
|
|
21
|
+
return {
|
|
22
|
+
ok: false,
|
|
23
|
+
errors: [
|
|
24
|
+
gitError("Repo-wide allowlist ('.') is not allowed; choose minimal prefixes (tip: `agentplane guard suggest-allow --format args`)."),
|
|
25
|
+
],
|
|
26
|
+
warnings: [],
|
|
27
|
+
};
|
|
28
|
+
}
|
|
20
29
|
const errors = [];
|
|
21
30
|
for (const filePath of staged) {
|
|
22
31
|
if (!allow.some((prefix) => gitPathIsUnderPrefix(filePath, prefix))) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"allow-prefix-policy.d.ts","sourceRoot":"","sources":["../../src/shared/allow-prefix-policy.ts"],"names":[],"mappings":"AAEA,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAEtE;AAED,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAKnE"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { normalizeGitPathPrefix } from "./git-path.js";
|
|
2
|
+
export function findRepoWideAllowPrefixes(prefixes) {
|
|
3
|
+
return prefixes.filter((prefix) => normalizeGitPathPrefix(prefix) === ".");
|
|
4
|
+
}
|
|
5
|
+
export function repoWideAllowPrefixMessage(flagName) {
|
|
6
|
+
return (`${flagName} cannot be repo-wide ('.'). ` +
|
|
7
|
+
"Choose minimal path prefixes; tip: `agentplane guard suggest-allow --format args`.");
|
|
8
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentplane",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.25",
|
|
4
4
|
"description": "Agent Plane CLI for task workflows, recipes, and project automation.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agentplane",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"prepublishOnly": "node ../../scripts/enforce-github-publish.mjs && npm run prepack"
|
|
56
56
|
},
|
|
57
57
|
"dependencies": {
|
|
58
|
-
"@agentplaneorg/core": "0.2.
|
|
58
|
+
"@agentplaneorg/core": "0.2.25",
|
|
59
59
|
"yauzl": "^2.10.0"
|
|
60
60
|
},
|
|
61
61
|
"devDependencies": {
|