agentplane 0.2.24 → 0.2.26
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/bin/agentplane.js +91 -54
- package/dist/.build-manifest.json +11 -0
- package/dist/backends/task-backend/local-backend.d.ts +2 -0
- package/dist/backends/task-backend/local-backend.d.ts.map +1 -1
- package/dist/backends/task-backend/local-backend.js +12 -1
- package/dist/backends/task-backend/redmine/mapping.d.ts.map +1 -1
- package/dist/backends/task-backend/redmine/mapping.js +26 -1
- package/dist/backends/task-backend/redmine-backend.d.ts +4 -0
- package/dist/backends/task-backend/redmine-backend.d.ts.map +1 -1
- package/dist/backends/task-backend/redmine-backend.js +92 -9
- package/dist/backends/task-backend/shared/types.d.ts +1 -0
- package/dist/backends/task-backend/shared/types.d.ts.map +1 -1
- package/dist/backends/task-index.d.ts.map +1 -1
- package/dist/backends/task-index.js +8 -1
- package/dist/cli/command-guide.d.ts.map +1 -1
- package/dist/cli/command-guide.js +21 -8
- package/dist/cli/command-snippets.d.ts +24 -0
- package/dist/cli/command-snippets.d.ts.map +1 -0
- package/dist/cli/command-snippets.js +23 -0
- package/dist/cli/reason-codes.d.ts +9 -0
- package/dist/cli/reason-codes.d.ts.map +1 -0
- package/dist/cli/reason-codes.js +79 -0
- package/dist/cli/recipes-bundled.d.ts +1 -0
- package/dist/cli/recipes-bundled.d.ts.map +1 -1
- package/dist/cli/recipes-bundled.js +4 -1
- package/dist/cli/run-cli/command-catalog.d.ts +1 -1
- package/dist/cli/run-cli/command-catalog.d.ts.map +1 -1
- package/dist/cli/run-cli/command-catalog.js +40 -1
- package/dist/cli/run-cli/commands/config.d.ts +5 -0
- package/dist/cli/run-cli/commands/config.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/config.js +86 -1
- package/dist/cli/run-cli/commands/core.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/core.js +55 -0
- package/dist/cli/run-cli/commands/init/recipes.d.ts +5 -1
- package/dist/cli/run-cli/commands/init/recipes.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/init/recipes.js +24 -4
- package/dist/cli/run-cli/commands/init/write-workflow.d.ts +7 -0
- package/dist/cli/run-cli/commands/init/write-workflow.d.ts.map +1 -0
- package/dist/cli/run-cli/commands/init/write-workflow.js +52 -0
- package/dist/cli/run-cli/commands/init.d.ts +2 -1
- package/dist/cli/run-cli/commands/init.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/init.js +104 -54
- package/dist/cli/run-cli.d.ts.map +1 -1
- package/dist/cli/run-cli.js +70 -1
- package/dist/commands/backend/sync.command.d.ts.map +1 -1
- package/dist/commands/backend/sync.command.js +7 -6
- package/dist/commands/backend.d.ts.map +1 -1
- package/dist/commands/backend.js +2 -0
- 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/doctor.run.d.ts.map +1 -1
- package/dist/commands/doctor.run.js +96 -10
- 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 +19 -21
- 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/recipes/impl/commands/install.d.ts.map +1 -1
- package/dist/commands/recipes/impl/commands/install.js +36 -13
- package/dist/commands/recipes/impl/scenario.d.ts.map +1 -1
- package/dist/commands/recipes/impl/scenario.js +25 -0
- package/dist/commands/recipes/impl/types.d.ts +4 -0
- package/dist/commands/recipes/impl/types.d.ts.map +1 -1
- package/dist/commands/scenario/impl/commands.d.ts.map +1 -1
- package/dist/commands/scenario/impl/commands.js +74 -3
- package/dist/commands/scenario/impl/report.d.ts +8 -0
- package/dist/commands/scenario/impl/report.d.ts.map +1 -1
- package/dist/commands/scenario/impl/report.js +1 -0
- package/dist/commands/shared/reconcile-check.d.ts +7 -0
- package/dist/commands/shared/reconcile-check.d.ts.map +1 -0
- package/dist/commands/shared/reconcile-check.js +60 -0
- package/dist/commands/start.spec.d.ts.map +1 -1
- package/dist/commands/start.spec.js +23 -2
- package/dist/commands/sync.command.d.ts.map +1 -1
- package/dist/commands/sync.command.js +9 -2
- package/dist/commands/task/finish.d.ts.map +1 -1
- package/dist/commands/task/finish.js +34 -10
- package/dist/commands/task/list.d.ts.map +1 -1
- package/dist/commands/task/list.js +2 -1
- package/dist/commands/task/list.spec.d.ts.map +1 -1
- package/dist/commands/task/list.spec.js +7 -0
- package/dist/commands/task/next.d.ts.map +1 -1
- package/dist/commands/task/next.js +2 -1
- package/dist/commands/task/next.spec.d.ts.map +1 -1
- package/dist/commands/task/next.spec.js +7 -0
- package/dist/commands/task/search.d.ts.map +1 -1
- package/dist/commands/task/search.js +2 -1
- package/dist/commands/task/search.spec.d.ts.map +1 -1
- package/dist/commands/task/search.spec.js +7 -0
- package/dist/commands/task/set-status.command.d.ts.map +1 -1
- package/dist/commands/task/set-status.command.js +22 -2
- 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 +21 -1
- package/dist/commands/task/verify-record.d.ts.map +1 -1
- package/dist/commands/task/verify-record.js +2 -0
- package/dist/commands/workflow-build.command.d.ts +8 -0
- package/dist/commands/workflow-build.command.d.ts.map +1 -0
- package/dist/commands/workflow-build.command.js +96 -0
- package/dist/commands/workflow-playbook.command.d.ts +10 -0
- package/dist/commands/workflow-playbook.command.d.ts.map +1 -0
- package/dist/commands/workflow-playbook.command.js +174 -0
- package/dist/commands/workflow-restore.command.d.ts +5 -0
- package/dist/commands/workflow-restore.command.d.ts.map +1 -0
- package/dist/commands/workflow-restore.command.js +30 -0
- package/dist/commands/workflow.command.d.ts +6 -0
- package/dist/commands/workflow.command.d.ts.map +1 -0
- package/dist/commands/workflow.command.js +36 -0
- package/dist/harness/dynamic-tool-contract.d.ts +29 -0
- package/dist/harness/dynamic-tool-contract.d.ts.map +1 -0
- package/dist/harness/dynamic-tool-contract.js +86 -0
- package/dist/harness/hooks-lifecycle.d.ts +27 -0
- package/dist/harness/hooks-lifecycle.d.ts.map +1 -0
- package/dist/harness/hooks-lifecycle.js +67 -0
- package/dist/harness/index.d.ts +9 -0
- package/dist/harness/index.d.ts.map +1 -0
- package/dist/harness/index.js +8 -0
- package/dist/harness/reconcile.d.ts +37 -0
- package/dist/harness/reconcile.d.ts.map +1 -0
- package/dist/harness/reconcile.js +42 -0
- package/dist/harness/retry-policy.d.ts +31 -0
- package/dist/harness/retry-policy.d.ts.map +1 -0
- package/dist/harness/retry-policy.js +33 -0
- package/dist/harness/scheduler.d.ts +18 -0
- package/dist/harness/scheduler.d.ts.map +1 -0
- package/dist/harness/scheduler.js +55 -0
- package/dist/harness/state-machine.d.ts +17 -0
- package/dist/harness/state-machine.d.ts.map +1 -0
- package/dist/harness/state-machine.js +70 -0
- package/dist/harness/token-accounting.d.ts +19 -0
- package/dist/harness/token-accounting.d.ts.map +1 -0
- package/dist/harness/token-accounting.js +77 -0
- package/dist/harness/workspace-safety.d.ts +14 -0
- package/dist/harness/workspace-safety.d.ts.map +1 -0
- package/dist/harness/workspace-safety.js +62 -0
- package/dist/policy/rules/allowlist.d.ts.map +1 -1
- package/dist/policy/rules/allowlist.js +9 -0
- package/dist/recipes/bundled-recipes.d.ts +4 -0
- package/dist/recipes/bundled-recipes.d.ts.map +1 -1
- package/dist/recipes/bundled-recipes.js +11 -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/dist/shared/errors.d.ts +6 -0
- package/dist/shared/errors.d.ts.map +1 -1
- package/dist/shared/errors.js +1 -0
- package/dist/workflow-runtime/build.d.ts +4 -0
- package/dist/workflow-runtime/build.d.ts.map +1 -0
- package/dist/workflow-runtime/build.js +114 -0
- package/dist/workflow-runtime/enforcement.d.ts +3 -0
- package/dist/workflow-runtime/enforcement.d.ts.map +1 -0
- package/dist/workflow-runtime/enforcement.js +10 -0
- package/dist/workflow-runtime/file-ops.d.ts +11 -0
- package/dist/workflow-runtime/file-ops.d.ts.map +1 -0
- package/dist/workflow-runtime/file-ops.js +248 -0
- package/dist/workflow-runtime/fix.d.ts +9 -0
- package/dist/workflow-runtime/fix.d.ts.map +1 -0
- package/dist/workflow-runtime/fix.js +107 -0
- package/dist/workflow-runtime/index.d.ts +11 -0
- package/dist/workflow-runtime/index.d.ts.map +1 -0
- package/dist/workflow-runtime/index.js +10 -0
- package/dist/workflow-runtime/markdown.d.ts +10 -0
- package/dist/workflow-runtime/markdown.d.ts.map +1 -0
- package/dist/workflow-runtime/markdown.js +147 -0
- package/dist/workflow-runtime/observability.d.ts +12 -0
- package/dist/workflow-runtime/observability.d.ts.map +1 -0
- package/dist/workflow-runtime/observability.js +14 -0
- package/dist/workflow-runtime/paths.d.ts +3 -0
- package/dist/workflow-runtime/paths.d.ts.map +1 -0
- package/dist/workflow-runtime/paths.js +11 -0
- package/dist/workflow-runtime/template.d.ts +7 -0
- package/dist/workflow-runtime/template.d.ts.map +1 -0
- package/dist/workflow-runtime/template.js +94 -0
- package/dist/workflow-runtime/types.d.ts +68 -0
- package/dist/workflow-runtime/types.d.ts.map +1 -0
- package/dist/workflow-runtime/types.js +1 -0
- package/dist/workflow-runtime/validate.d.ts +8 -0
- package/dist/workflow-runtime/validate.d.ts.map +1 -0
- package/dist/workflow-runtime/validate.js +331 -0
- package/package.json +3 -3
|
@@ -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":"doctor.run.d.ts","sourceRoot":"","sources":["../../src/commands/doctor.run.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAK1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,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;AAK1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAqUrD,eAAO,MAAM,SAAS,EAAE,cAAc,CAAC,YAAY,CAmDlD,CAAC"}
|
|
@@ -5,6 +5,7 @@ import { warnMessage, successMessage } from "../cli/output.js";
|
|
|
5
5
|
import { RUNTIME_GITIGNORE_LINES } from "../shared/runtime-artifacts.js";
|
|
6
6
|
import { execFileAsync, gitEnv } from "./shared/git.js";
|
|
7
7
|
import { loadCommandContext } from "./shared/task-backend.js";
|
|
8
|
+
import { emitWorkflowEvent, isWorkflowEnforcementDisabled, resolveWorkflowPaths, safeAutofixWorkflowText, validateWorkflowAtPath, workflowEnforcementEnvHint, } from "../workflow-runtime/index.js";
|
|
8
9
|
async function listTsFiles(rootDir) {
|
|
9
10
|
const out = [];
|
|
10
11
|
async function walk(absDir) {
|
|
@@ -160,6 +161,75 @@ async function safeFixTaskIndex(repoRoot) {
|
|
|
160
161
|
return { changed: false, note: "Skip: could not rebuild tasks index cache." };
|
|
161
162
|
}
|
|
162
163
|
}
|
|
164
|
+
async function checkWorkflowContract(repoRoot) {
|
|
165
|
+
const result = await validateWorkflowAtPath(repoRoot);
|
|
166
|
+
const findings = result.diagnostics.map((d) => `[${d.severity}] ${d.code} ${d.path}: ${d.message}`);
|
|
167
|
+
emitWorkflowEvent({
|
|
168
|
+
event: "workflow_doctor_check",
|
|
169
|
+
details: { ok: result.ok, findings: result.diagnostics.length },
|
|
170
|
+
});
|
|
171
|
+
return findings;
|
|
172
|
+
}
|
|
173
|
+
function findingSeverity(problem) {
|
|
174
|
+
const normalized = problem.trimStart();
|
|
175
|
+
if (normalized.startsWith("[WARN]"))
|
|
176
|
+
return "WARN";
|
|
177
|
+
if (normalized.startsWith("[INFO]"))
|
|
178
|
+
return "INFO";
|
|
179
|
+
if (normalized.startsWith("[ERROR]"))
|
|
180
|
+
return "ERROR";
|
|
181
|
+
return "ERROR";
|
|
182
|
+
}
|
|
183
|
+
async function safeFixWorkflow(repoRoot) {
|
|
184
|
+
const paths = resolveWorkflowPaths(repoRoot);
|
|
185
|
+
let current = "";
|
|
186
|
+
let sourcePath = paths.workflowPath;
|
|
187
|
+
try {
|
|
188
|
+
current = await fs.readFile(paths.workflowPath, "utf8");
|
|
189
|
+
}
|
|
190
|
+
catch {
|
|
191
|
+
try {
|
|
192
|
+
current = await fs.readFile(paths.legacyWorkflowPath, "utf8");
|
|
193
|
+
sourcePath = paths.legacyWorkflowPath;
|
|
194
|
+
}
|
|
195
|
+
catch {
|
|
196
|
+
return { changed: false, note: "Skip: workflow contract file not found." };
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
const fixed = safeAutofixWorkflowText(current);
|
|
200
|
+
if (fixed.diagnostics.some((d) => d.code === "WF_FIX_SKIPPED_UNSAFE")) {
|
|
201
|
+
const details = fixed.diagnostics.map((d) => `${d.path}`).join(", ");
|
|
202
|
+
return {
|
|
203
|
+
changed: false,
|
|
204
|
+
note: `Skip: unsafe workflow autofix required (unknown keys). Proposed manual review: ${details}`,
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
if (!fixed.changed) {
|
|
208
|
+
if (sourcePath === paths.workflowPath) {
|
|
209
|
+
return { changed: false, note: "OK: workflow contract already normalized." };
|
|
210
|
+
}
|
|
211
|
+
await fs.mkdir(path.dirname(paths.workflowPath), { recursive: true });
|
|
212
|
+
await fs.writeFile(paths.workflowPath, current, "utf8");
|
|
213
|
+
await fs.rm(paths.legacyWorkflowPath, { force: true });
|
|
214
|
+
await fs.mkdir(paths.workflowDir, { recursive: true });
|
|
215
|
+
await fs.copyFile(paths.workflowPath, paths.lastKnownGoodPath);
|
|
216
|
+
return {
|
|
217
|
+
changed: true,
|
|
218
|
+
note: "Fixed: moved legacy WORKFLOW.md into .agentplane and refreshed last-known-good.",
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
await fs.mkdir(path.dirname(paths.workflowPath), { recursive: true });
|
|
222
|
+
await fs.writeFile(paths.workflowPath, fixed.text, "utf8");
|
|
223
|
+
if (sourcePath === paths.legacyWorkflowPath) {
|
|
224
|
+
await fs.rm(paths.legacyWorkflowPath, { force: true });
|
|
225
|
+
}
|
|
226
|
+
await fs.mkdir(paths.workflowDir, { recursive: true });
|
|
227
|
+
await fs.copyFile(paths.workflowPath, paths.lastKnownGoodPath);
|
|
228
|
+
return {
|
|
229
|
+
changed: true,
|
|
230
|
+
note: "Fixed: normalized workflow contract and refreshed last-known-good.",
|
|
231
|
+
};
|
|
232
|
+
}
|
|
163
233
|
async function checkDoneTaskCommitInvariants(repoRoot) {
|
|
164
234
|
const tasksPath = path.join(repoRoot, ".agentplane", "tasks.json");
|
|
165
235
|
let raw = "";
|
|
@@ -228,22 +298,38 @@ async function checkDoneTaskCommitInvariants(repoRoot) {
|
|
|
228
298
|
export const runDoctor = async (ctx, p) => {
|
|
229
299
|
const resolved = await resolveProject({ cwd: ctx.cwd, rootOverride: ctx.rootOverride ?? null });
|
|
230
300
|
const repoRoot = resolved.gitRoot;
|
|
231
|
-
const
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
return
|
|
301
|
+
const runChecks = async () => {
|
|
302
|
+
const checks = await checkWorkspace(repoRoot);
|
|
303
|
+
checks.push(...(await checkDoneTaskCommitInvariants(repoRoot)));
|
|
304
|
+
if (!isWorkflowEnforcementDisabled()) {
|
|
305
|
+
checks.push(...(await checkWorkflowContract(repoRoot)));
|
|
306
|
+
}
|
|
307
|
+
if (p.dev) {
|
|
308
|
+
checks.push(...(await checkLayering(repoRoot)));
|
|
309
|
+
}
|
|
310
|
+
return checks;
|
|
311
|
+
};
|
|
312
|
+
if (isWorkflowEnforcementDisabled()) {
|
|
313
|
+
console.log(successMessage("doctor", undefined, `workflow contract checks disabled via ${workflowEnforcementEnvHint()}.`));
|
|
241
314
|
}
|
|
242
315
|
if (p.fix) {
|
|
243
316
|
const fix = await safeFixGitignore(repoRoot);
|
|
244
317
|
console.log(successMessage("doctor fix", undefined, fix.note));
|
|
245
318
|
const idx = await safeFixTaskIndex(repoRoot);
|
|
246
319
|
console.log(successMessage("doctor fix", undefined, idx.note));
|
|
320
|
+
const workflowFix = await safeFixWorkflow(repoRoot);
|
|
321
|
+
console.log(successMessage("doctor fix", undefined, workflowFix.note));
|
|
322
|
+
}
|
|
323
|
+
const problems = await runChecks();
|
|
324
|
+
const errors = problems.filter((problem) => findingSeverity(problem) === "ERROR");
|
|
325
|
+
if (problems.length > 0) {
|
|
326
|
+
const warningCount = problems.filter((problem) => findingSeverity(problem) === "WARN").length;
|
|
327
|
+
const infoCount = problems.filter((problem) => findingSeverity(problem) === "INFO").length;
|
|
328
|
+
console.error(warnMessage(`doctor findings: errors=${errors.length} warnings=${warningCount} info=${infoCount}`));
|
|
329
|
+
for (const prob of problems)
|
|
330
|
+
console.error(`- ${prob}`);
|
|
331
|
+
if (errors.length > 0)
|
|
332
|
+
return 1;
|
|
247
333
|
}
|
|
248
334
|
console.log(successMessage("doctor", undefined, "OK"));
|
|
249
335
|
return 0;
|
|
@@ -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;
|
|
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;AAQvF,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,CAa9E;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,CAmJlB"}
|
|
@@ -4,6 +4,7 @@ import { CliError } from "../../../shared/errors.js";
|
|
|
4
4
|
import { loadCommandContext } from "../../shared/task-backend.js";
|
|
5
5
|
import { loadTaskFromContext } from "../../shared/task-backend.js";
|
|
6
6
|
import { execFileAsync, gitEnv } from "../../shared/git.js";
|
|
7
|
+
import { ensureReconciledBeforeMutation } from "../../shared/reconcile-check.js";
|
|
7
8
|
import { suggestAllowPrefixes } from "./allow.js";
|
|
8
9
|
import { buildCloseCommitMessage, taskReadmePathForTask } from "./close-message.js";
|
|
9
10
|
import { buildGitCommitEnv } from "./env.js";
|
|
@@ -111,7 +112,10 @@ export async function cmdGuardSuggestAllow(opts) {
|
|
|
111
112
|
}
|
|
112
113
|
export async function cmdGuardCommit(opts) {
|
|
113
114
|
try {
|
|
114
|
-
|
|
115
|
+
const ctx = opts.ctx ??
|
|
116
|
+
(await loadCommandContext({ cwd: opts.cwd, rootOverride: opts.rootOverride ?? null }));
|
|
117
|
+
await ensureReconciledBeforeMutation({ ctx, command: "guard commit" });
|
|
118
|
+
await guardCommitCheck({ ...opts, ctx });
|
|
115
119
|
if (!opts.quiet)
|
|
116
120
|
process.stdout.write("OK\n");
|
|
117
121
|
return 0;
|
|
@@ -124,9 +128,12 @@ export async function cmdGuardCommit(opts) {
|
|
|
124
128
|
}
|
|
125
129
|
export async function cmdCommit(opts) {
|
|
126
130
|
try {
|
|
131
|
+
const ctx = opts.ctx ??
|
|
132
|
+
(await loadCommandContext({ cwd: opts.cwd, rootOverride: opts.rootOverride ?? null }));
|
|
127
133
|
if (opts.close) {
|
|
128
|
-
|
|
129
|
-
|
|
134
|
+
if (!opts.closeCheckOnly) {
|
|
135
|
+
await ensureReconciledBeforeMutation({ ctx, command: "commit" });
|
|
136
|
+
}
|
|
130
137
|
// Make the close commit deterministic: start from a clean index unless --unstage-others is used.
|
|
131
138
|
let staged = await ctx.git.statusStagedPaths();
|
|
132
139
|
if (staged.length > 0 && opts.closeUnstageOthers) {
|
|
@@ -201,28 +208,21 @@ export async function cmdCommit(opts) {
|
|
|
201
208
|
}
|
|
202
209
|
return 0;
|
|
203
210
|
}
|
|
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;
|
|
211
|
+
if (opts.autoAllow) {
|
|
212
|
+
throw new CliError({
|
|
213
|
+
exitCode: 2,
|
|
214
|
+
code: "E_USAGE",
|
|
215
|
+
message: "--auto-allow is disabled; pass explicit --allow <path-prefix>.",
|
|
216
|
+
});
|
|
218
217
|
}
|
|
218
|
+
await ensureReconciledBeforeMutation({ ctx, command: "commit" });
|
|
219
219
|
await guardCommitCheck({
|
|
220
|
-
ctx
|
|
220
|
+
ctx,
|
|
221
221
|
cwd: opts.cwd,
|
|
222
222
|
rootOverride: opts.rootOverride,
|
|
223
223
|
taskId: opts.taskId,
|
|
224
224
|
message: opts.message,
|
|
225
|
-
allow,
|
|
225
|
+
allow: opts.allow,
|
|
226
226
|
allowBase: opts.allowBase,
|
|
227
227
|
allowTasks: opts.allowTasks,
|
|
228
228
|
allowPolicy: opts.allowPolicy,
|
|
@@ -232,8 +232,6 @@ export async function cmdCommit(opts) {
|
|
|
232
232
|
requireClean: opts.requireClean,
|
|
233
233
|
quiet: opts.quiet,
|
|
234
234
|
});
|
|
235
|
-
const ctx = opts.ctx ??
|
|
236
|
-
(await loadCommandContext({ cwd: opts.cwd, rootOverride: opts.rootOverride ?? null }));
|
|
237
235
|
const env = buildGitCommitEnv({
|
|
238
236
|
taskId: opts.taskId,
|
|
239
237
|
allowTasks: opts.allowTasks,
|
|
@@ -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":"install.d.ts","sourceRoot":"","sources":["../../../../../src/commands/recipes/impl/commands/install.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../../../../src/commands/recipes/impl/commands/install.ts"],"names":[],"mappings":"AAkCA,OAAO,KAAK,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAM3E,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,mBAAmB,CAAC;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,kBAAkB,CAAC;IAC/B,GAAG,EAAE,OAAO,CAAC;CACd,GAAG,OAAO,CAAC,MAAM,CAAC,CA6NlB"}
|