agentplane 0.3.1 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/AGENTS.md +5 -4
- package/assets/agents/CODER.json +4 -3
- package/assets/agents/DOCS.json +1 -1
- package/assets/agents/INTEGRATOR.json +1 -1
- package/assets/agents/ORCHESTRATOR.json +1 -0
- package/assets/agents/PLANNER.json +1 -0
- package/assets/agents/TESTER.json +3 -1
- package/assets/policy/dod.code.md +2 -2
- package/assets/policy/dod.core.md +16 -2
- package/assets/policy/dod.docs.md +2 -2
- package/assets/policy/incidents.md +44 -1
- package/assets/policy/workflow.direct.md +10 -5
- package/bin/agentplane.js +116 -18
- package/bin/dist-guard.js +78 -10
- package/bin/runtime-context.d.ts +23 -0
- package/bin/runtime-context.js +94 -0
- package/bin/runtime-watch.d.ts +26 -0
- package/bin/runtime-watch.js +116 -0
- package/bin/stale-dist-policy.d.ts +6 -0
- package/bin/stale-dist-policy.js +44 -0
- package/dist/.build-manifest.json +2480 -5
- package/dist/backends/task-backend/local-backend.d.ts.map +1 -1
- package/dist/backends/task-backend/local-backend.js +9 -12
- package/dist/backends/task-backend/redmine-backend.d.ts.map +1 -1
- package/dist/backends/task-backend/redmine-backend.js +23 -18
- package/dist/backends/task-backend/shared/constants.d.ts +1 -0
- package/dist/backends/task-backend/shared/constants.d.ts.map +1 -1
- package/dist/backends/task-backend/shared/constants.js +1 -0
- package/dist/backends/task-backend/shared/doc.d.ts +1 -0
- package/dist/backends/task-backend/shared/doc.d.ts.map +1 -1
- package/dist/backends/task-backend/shared/doc.js +4 -1
- package/dist/backends/task-backend/shared/export.js +3 -3
- package/dist/cli/bootstrap-guide.d.ts +16 -0
- package/dist/cli/bootstrap-guide.d.ts.map +1 -0
- package/dist/cli/bootstrap-guide.js +112 -0
- package/dist/cli/command-guide.d.ts.map +1 -1
- package/dist/cli/command-guide.js +62 -203
- package/dist/cli/command-snippets.d.ts +2 -2
- package/dist/cli/command-snippets.js +2 -2
- package/dist/cli/run-cli/catalog.d.ts +7 -0
- package/dist/cli/run-cli/catalog.d.ts.map +1 -0
- package/dist/cli/run-cli/catalog.js +22 -0
- 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 +11 -0
- package/dist/cli/run-cli/commands/core.js +1 -1
- package/dist/cli/run-cli/commands/init/write-config.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/init/write-config.js +2 -0
- package/dist/cli/run-cli/commands/init.js +5 -14
- package/dist/cli/run-cli/error-guidance.d.ts +9 -0
- package/dist/cli/run-cli/error-guidance.d.ts.map +1 -0
- package/dist/cli/run-cli/error-guidance.js +180 -0
- package/dist/cli/run-cli/globals.d.ts +22 -0
- package/dist/cli/run-cli/globals.d.ts.map +1 -0
- package/dist/cli/run-cli/globals.js +197 -0
- package/dist/cli/run-cli/update-warning.d.ts +6 -0
- package/dist/cli/run-cli/update-warning.d.ts.map +1 -0
- package/dist/cli/run-cli/update-warning.js +64 -0
- package/dist/cli/run-cli.d.ts.map +1 -1
- package/dist/cli/run-cli.js +5 -476
- package/dist/cli/spec/docs-render.d.ts.map +1 -1
- package/dist/cli/spec/docs-render.js +14 -1
- package/dist/commands/doctor/archive.d.ts +4 -0
- package/dist/commands/doctor/archive.d.ts.map +1 -0
- package/dist/commands/doctor/archive.js +211 -0
- package/dist/commands/doctor/fixes.d.ts +9 -0
- package/dist/commands/doctor/fixes.d.ts.map +1 -0
- package/dist/commands/doctor/fixes.js +40 -0
- package/dist/commands/doctor/layering.d.ts +2 -0
- package/dist/commands/doctor/layering.d.ts.map +1 -0
- package/dist/commands/doctor/layering.js +87 -0
- package/dist/commands/doctor/runtime.d.ts +4 -0
- package/dist/commands/doctor/runtime.d.ts.map +1 -0
- package/dist/commands/doctor/runtime.js +56 -0
- package/dist/commands/doctor/workflow.d.ts +6 -0
- package/dist/commands/doctor/workflow.d.ts.map +1 -0
- package/dist/commands/doctor/workflow.js +62 -0
- package/dist/commands/doctor/workspace.d.ts +2 -0
- package/dist/commands/doctor/workspace.d.ts.map +1 -0
- package/dist/commands/doctor/workspace.js +165 -0
- package/dist/commands/doctor.run.d.ts.map +1 -1
- package/dist/commands/doctor.run.js +16 -305
- package/dist/commands/doctor.spec.d.ts +1 -0
- package/dist/commands/doctor.spec.d.ts.map +1 -1
- package/dist/commands/doctor.spec.js +15 -1
- package/dist/commands/finish.run.d.ts.map +1 -1
- package/dist/commands/finish.run.js +1 -0
- package/dist/commands/finish.spec.d.ts +1 -0
- package/dist/commands/finish.spec.d.ts.map +1 -1
- package/dist/commands/finish.spec.js +23 -2
- package/dist/commands/guard/impl/commands.d.ts.map +1 -1
- package/dist/commands/guard/impl/commands.js +19 -0
- package/dist/commands/release/apply.command.d.ts +2 -7
- package/dist/commands/release/apply.command.d.ts.map +1 -1
- package/dist/commands/release/apply.command.js +159 -382
- package/dist/commands/release/apply.mutation.d.ts +7 -0
- package/dist/commands/release/apply.mutation.d.ts.map +1 -0
- package/dist/commands/release/apply.mutation.js +107 -0
- package/dist/commands/release/apply.preflight.d.ts +25 -0
- package/dist/commands/release/apply.preflight.d.ts.map +1 -0
- package/dist/commands/release/apply.preflight.js +338 -0
- package/dist/commands/release/apply.reporting.d.ts +4 -0
- package/dist/commands/release/apply.reporting.d.ts.map +1 -0
- package/dist/commands/release/apply.reporting.js +24 -0
- package/dist/commands/release/apply.types.d.ts +46 -0
- package/dist/commands/release/apply.types.d.ts.map +1 -0
- package/dist/commands/release/apply.types.js +1 -0
- package/dist/commands/runtime.command.d.ts +28 -0
- package/dist/commands/runtime.command.d.ts.map +1 -0
- package/dist/commands/runtime.command.js +169 -0
- package/dist/commands/shared/task-store.d.ts.map +1 -1
- package/dist/commands/shared/task-store.js +7 -3
- package/dist/commands/task/add.d.ts.map +1 -1
- package/dist/commands/task/add.js +3 -33
- package/dist/commands/task/block.d.ts.map +1 -1
- package/dist/commands/task/block.js +2 -2
- package/dist/commands/task/close-duplicate.d.ts.map +1 -1
- package/dist/commands/task/close-duplicate.js +2 -2
- package/dist/commands/task/close-noop.d.ts.map +1 -1
- package/dist/commands/task/close-noop.js +2 -2
- package/dist/commands/task/comment.js +2 -2
- package/dist/commands/task/derive.d.ts.map +1 -1
- package/dist/commands/task/derive.js +3 -3
- package/dist/commands/task/doc-template.d.ts +10 -0
- package/dist/commands/task/doc-template.d.ts.map +1 -0
- package/dist/commands/task/doc-template.js +104 -0
- package/dist/commands/task/doc.d.ts.map +1 -1
- package/dist/commands/task/doc.js +36 -1
- package/dist/commands/task/finish.d.ts +1 -0
- package/dist/commands/task/finish.d.ts.map +1 -1
- package/dist/commands/task/finish.js +26 -10
- package/dist/commands/task/migrate-doc.command.d.ts.map +1 -1
- package/dist/commands/task/migrate-doc.command.js +5 -1
- package/dist/commands/task/migrate-doc.d.ts.map +1 -1
- package/dist/commands/task/migrate-doc.js +136 -2
- package/dist/commands/task/new.d.ts.map +1 -1
- package/dist/commands/task/new.js +4 -110
- package/dist/commands/task/new.spec.js +3 -3
- package/dist/commands/task/plan.d.ts.map +1 -1
- package/dist/commands/task/plan.js +5 -4
- package/dist/commands/task/scaffold.d.ts.map +1 -1
- package/dist/commands/task/scaffold.js +7 -52
- package/dist/commands/task/set-status.d.ts.map +1 -1
- package/dist/commands/task/set-status.js +2 -2
- package/dist/commands/task/shared/dependencies.d.ts +15 -0
- package/dist/commands/task/shared/dependencies.d.ts.map +1 -0
- package/dist/commands/task/shared/dependencies.js +143 -0
- package/dist/commands/task/shared/docs.d.ts +21 -0
- package/dist/commands/task/shared/docs.d.ts.map +1 -0
- package/dist/commands/task/shared/docs.js +121 -0
- package/dist/commands/task/shared/listing.d.ts +20 -0
- package/dist/commands/task/shared/listing.d.ts.map +1 -0
- package/dist/commands/task/shared/listing.js +127 -0
- package/dist/commands/task/shared/tags.d.ts +24 -0
- package/dist/commands/task/shared/tags.d.ts.map +1 -0
- package/dist/commands/task/shared/tags.js +177 -0
- package/dist/commands/task/shared/transitions.d.ts +42 -0
- package/dist/commands/task/shared/transitions.d.ts.map +1 -0
- package/dist/commands/task/shared/transitions.js +175 -0
- package/dist/commands/task/shared.d.ts +5 -106
- package/dist/commands/task/shared.d.ts.map +1 -1
- package/dist/commands/task/shared.js +5 -681
- package/dist/commands/task/start.d.ts.map +1 -1
- package/dist/commands/task/start.js +7 -5
- package/dist/commands/task/verify-record.d.ts.map +1 -1
- package/dist/commands/task/verify-record.js +9 -25
- package/dist/commands/task/verify-show.command.d.ts.map +1 -1
- package/dist/commands/task/verify-show.command.js +5 -1
- package/dist/commands/upgrade/apply.d.ts +44 -0
- package/dist/commands/upgrade/apply.d.ts.map +1 -0
- package/dist/commands/upgrade/apply.js +180 -0
- package/dist/commands/upgrade/report.d.ts +21 -0
- package/dist/commands/upgrade/report.d.ts.map +1 -0
- package/dist/commands/upgrade/report.js +81 -0
- package/dist/commands/upgrade/source.d.ts +35 -0
- package/dist/commands/upgrade/source.d.ts.map +1 -0
- package/dist/commands/upgrade/source.js +109 -0
- package/dist/commands/upgrade/types.d.ts +31 -0
- package/dist/commands/upgrade/types.d.ts.map +1 -0
- package/dist/commands/upgrade/types.js +1 -0
- package/dist/commands/upgrade.command.d.ts.map +1 -1
- package/dist/commands/upgrade.command.js +11 -7
- package/dist/commands/upgrade.d.ts +1 -35
- package/dist/commands/upgrade.d.ts.map +1 -1
- package/dist/commands/upgrade.js +54 -320
- package/dist/shared/diagnostics.d.ts +23 -0
- package/dist/shared/diagnostics.d.ts.map +1 -0
- package/dist/shared/diagnostics.js +57 -0
- package/dist/shared/errors.d.ts +2 -0
- package/dist/shared/errors.d.ts.map +1 -1
- package/dist/shared/errors.js +2 -0
- package/dist/shared/repo-cli-version.d.ts +13 -0
- package/dist/shared/repo-cli-version.d.ts.map +1 -0
- package/dist/shared/repo-cli-version.js +63 -0
- package/dist/shared/runtime-source.d.ts +33 -0
- package/dist/shared/runtime-source.d.ts.map +1 -0
- package/dist/shared/runtime-source.js +156 -0
- package/dist/shared/version-compare.d.ts +7 -0
- package/dist/shared/version-compare.d.ts.map +1 -0
- package/dist/shared/version-compare.js +30 -0
- package/package.json +2 -2
|
@@ -1,289 +1,168 @@
|
|
|
1
|
-
import { readFile, writeFile, readdir, mkdir } from "node:fs/promises";
|
|
2
1
|
import path from "node:path";
|
|
3
|
-
import {
|
|
4
|
-
import { usageError } from "../../cli/spec/errors.js";
|
|
2
|
+
import { loadConfig, resolveProject } from "@agentplaneorg/core";
|
|
5
3
|
import { exitCodeForError } from "../../cli/exit-codes.js";
|
|
4
|
+
import { usageError } from "../../cli/spec/errors.js";
|
|
5
|
+
import { withDiagnosticContext } from "../../shared/diagnostics.js";
|
|
6
6
|
import { CliError } from "../../shared/errors.js";
|
|
7
7
|
import { execFileAsync, gitEnv } from "../shared/git.js";
|
|
8
8
|
import { GitContext } from "../shared/git-context.js";
|
|
9
9
|
import { ensureNetworkApproved } from "../shared/network-approval.js";
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
async function readJsonFile(p) {
|
|
20
|
-
return JSON.parse(await readFile(p, "utf8"));
|
|
21
|
-
}
|
|
22
|
-
function assertNonEmptyString(value, label) {
|
|
23
|
-
if (typeof value !== "string" || !value.trim()) {
|
|
24
|
-
throw new CliError({
|
|
25
|
-
exitCode: exitCodeForError("E_VALIDATION"),
|
|
26
|
-
code: "E_VALIDATION",
|
|
27
|
-
message: `Invalid ${label} (expected non-empty string).`,
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
return value.trim();
|
|
31
|
-
}
|
|
32
|
-
function parseVersionPlan(raw) {
|
|
33
|
-
if (!raw || typeof raw !== "object") {
|
|
34
|
-
throw new CliError({
|
|
35
|
-
exitCode: exitCodeForError("E_VALIDATION"),
|
|
36
|
-
code: "E_VALIDATION",
|
|
37
|
-
message: "Invalid version.json (expected object).",
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
const obj = raw;
|
|
41
|
-
const bumpRaw = assertNonEmptyString(obj.bump, "bump");
|
|
42
|
-
if (bumpRaw !== "patch" && bumpRaw !== "minor" && bumpRaw !== "major") {
|
|
10
|
+
import { cleanHookEnv, maybePersistExpectedCliVersion, maybeRefreshGeneratedReference, maybeUpdateBunLockfile, replaceAgentplanePackageMetadata, replacePackageVersionInFile, } from "./apply.mutation.js";
|
|
11
|
+
import { ensureCleanTrackedTree, ensureNpmVersionsAvailable, ensureRemoteExists, ensureRemoteTagDoesNotExist, ensureTagDoesNotExist, fileExists, loadReleasePlan, readCoreDependencyVersion, readPackageVersion, runReleasePrepublishGate, validateReleaseNotes, } from "./apply.preflight.js";
|
|
12
|
+
import { pushReleaseRefs, writeReleaseApplyReport } from "./apply.reporting.js";
|
|
13
|
+
async function resolveReleasePlanInputs(opts) {
|
|
14
|
+
const { planDir, plan, minBullets } = await loadReleasePlan({
|
|
15
|
+
gitRoot: opts.gitRoot,
|
|
16
|
+
planOverride: opts.planOverride,
|
|
17
|
+
});
|
|
18
|
+
if (!/^v\d+\.\d+\.\d+$/u.test(plan.nextTag)) {
|
|
43
19
|
throw new CliError({
|
|
44
20
|
exitCode: exitCodeForError("E_VALIDATION"),
|
|
45
21
|
code: "E_VALIDATION",
|
|
46
|
-
message: `Invalid
|
|
22
|
+
message: `Invalid nextTag in version.json (expected vX.Y.Z): ${plan.nextTag}`,
|
|
47
23
|
});
|
|
48
24
|
}
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
const prevVersion = assertNonEmptyString(obj.prevVersion, "prevVersion");
|
|
52
|
-
const nextTag = assertNonEmptyString(obj.nextTag, "nextTag");
|
|
53
|
-
const nextVersion = assertNonEmptyString(obj.nextVersion, "nextVersion");
|
|
54
|
-
return { prevTag, prevVersion, nextTag, nextVersion, bump: bumpRaw };
|
|
55
|
-
}
|
|
56
|
-
async function findLatestPlanDir(gitRoot) {
|
|
57
|
-
const base = path.join(gitRoot, ".agentplane", ".release", "plan");
|
|
58
|
-
const runNames = await readdir(base);
|
|
59
|
-
const runs = runNames
|
|
60
|
-
.map((s) => s.trim())
|
|
61
|
-
.filter(Boolean)
|
|
62
|
-
.toSorted();
|
|
63
|
-
const latest = runs.at(-1);
|
|
64
|
-
if (!latest) {
|
|
25
|
+
const notesPath = path.join(opts.gitRoot, "docs", "releases", `${plan.nextTag}.md`);
|
|
26
|
+
if (!(await fileExists(notesPath))) {
|
|
65
27
|
throw new CliError({
|
|
66
28
|
exitCode: exitCodeForError("E_IO"),
|
|
67
29
|
code: "E_IO",
|
|
68
|
-
message:
|
|
69
|
-
|
|
70
|
-
}
|
|
71
|
-
return path.join(base, latest);
|
|
72
|
-
}
|
|
73
|
-
async function readPackageVersion(pkgJsonPath) {
|
|
74
|
-
const raw = JSON.parse(await readFile(pkgJsonPath, "utf8"));
|
|
75
|
-
const version = typeof raw.version === "string" ? raw.version.trim() : "";
|
|
76
|
-
if (!version) {
|
|
77
|
-
throw new CliError({
|
|
78
|
-
exitCode: exitCodeForError("E_VALIDATION"),
|
|
79
|
-
code: "E_VALIDATION",
|
|
80
|
-
message: `Missing package.json version: ${pkgJsonPath}`,
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
return version;
|
|
84
|
-
}
|
|
85
|
-
async function readCoreDependencyVersion(pkgJsonPath) {
|
|
86
|
-
const raw = JSON.parse(await readFile(pkgJsonPath, "utf8"));
|
|
87
|
-
const value = raw.dependencies?.["@agentplaneorg/core"];
|
|
88
|
-
const version = typeof value === "string" ? value.trim() : "";
|
|
89
|
-
if (!version) {
|
|
90
|
-
throw new CliError({
|
|
91
|
-
exitCode: exitCodeForError("E_VALIDATION"),
|
|
92
|
-
code: "E_VALIDATION",
|
|
93
|
-
message: `Missing dependency @agentplaneorg/core in ${pkgJsonPath}. ` +
|
|
94
|
-
"Release parity requires packages/agentplane to pin @agentplaneorg/core to the same version.",
|
|
30
|
+
message: `Missing release notes: ${path.relative(opts.gitRoot, notesPath)}\n` +
|
|
31
|
+
"Write this file using a DOCS agent before applying the release.",
|
|
95
32
|
});
|
|
96
33
|
}
|
|
97
|
-
|
|
34
|
+
await validateReleaseNotes(notesPath, minBullets);
|
|
35
|
+
return { planDir, plan, notesPath, minBullets };
|
|
98
36
|
}
|
|
99
|
-
async function
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
37
|
+
async function ensureReleasePlanMatchesRepoState(opts) {
|
|
38
|
+
const [coreVersion, agentplaneVersion, coreDependencyVersion] = await Promise.all([
|
|
39
|
+
readPackageVersion(opts.corePkgPath),
|
|
40
|
+
readPackageVersion(opts.agentplanePkgPath),
|
|
41
|
+
readCoreDependencyVersion(opts.agentplanePkgPath),
|
|
42
|
+
]);
|
|
43
|
+
if (coreVersion !== agentplaneVersion) {
|
|
103
44
|
throw new CliError({
|
|
104
45
|
exitCode: exitCodeForError("E_VALIDATION"),
|
|
105
46
|
code: "E_VALIDATION",
|
|
106
|
-
message: `
|
|
47
|
+
message: `Package versions must match before applying a release. ` +
|
|
48
|
+
`packages/core=${coreVersion} packages/agentplane=${agentplaneVersion}`,
|
|
107
49
|
});
|
|
108
50
|
}
|
|
109
|
-
|
|
110
|
-
}
|
|
111
|
-
async function replaceAgentplanePackageMetadata(pkgJsonPath, nextVersion) {
|
|
112
|
-
const text = await readFile(pkgJsonPath, "utf8");
|
|
113
|
-
const withVersion = text.replace(/"version"\s*:\s*"[^"]*"/u, `"version": "${nextVersion}"`);
|
|
114
|
-
if (withVersion === text) {
|
|
51
|
+
if (coreDependencyVersion !== coreVersion) {
|
|
115
52
|
throw new CliError({
|
|
116
53
|
exitCode: exitCodeForError("E_VALIDATION"),
|
|
117
54
|
code: "E_VALIDATION",
|
|
118
|
-
message:
|
|
55
|
+
message: "Release dependency parity check failed before apply. " +
|
|
56
|
+
`packages/agentplane dependency @agentplaneorg/core=${coreDependencyVersion} ` +
|
|
57
|
+
`must match packages/core version ${coreVersion}.`,
|
|
119
58
|
});
|
|
120
59
|
}
|
|
121
|
-
|
|
122
|
-
|
|
60
|
+
await ensureCleanTrackedTree(opts.gitRoot);
|
|
61
|
+
await ensureTagDoesNotExist(opts.gitRoot, opts.plan.nextTag);
|
|
62
|
+
if (coreVersion !== opts.plan.prevVersion) {
|
|
123
63
|
throw new CliError({
|
|
124
64
|
exitCode: exitCodeForError("E_VALIDATION"),
|
|
125
65
|
code: "E_VALIDATION",
|
|
126
|
-
message: `
|
|
127
|
-
|
|
66
|
+
message: `Current version does not match the release-plan baseline. ` +
|
|
67
|
+
`current=${coreVersion} expected_prev=${opts.plan.prevVersion} expected_next=${opts.plan.nextVersion}\n` +
|
|
68
|
+
"Re-run `agentplane release plan` to generate a fresh plan for this repo state.",
|
|
69
|
+
context: withDiagnosticContext({ command: "release apply" }, {
|
|
70
|
+
state: "the repository version no longer matches the prepared release-plan baseline",
|
|
71
|
+
likelyCause: "package versions changed after the plan was generated, so continuing would apply the release over a partially drifted local state",
|
|
72
|
+
nextAction: {
|
|
73
|
+
command: "agentplane release plan",
|
|
74
|
+
reason: "generate a fresh release plan from the current repository state before applying the release",
|
|
75
|
+
reasonCode: "release_plan_drifted",
|
|
76
|
+
},
|
|
77
|
+
}),
|
|
128
78
|
});
|
|
129
79
|
}
|
|
130
|
-
await writeFile(pkgJsonPath, withDependency, "utf8");
|
|
131
80
|
}
|
|
132
|
-
function
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
81
|
+
async function runPushPreflight(opts) {
|
|
82
|
+
const loaded = await loadConfig(opts.agentplaneDir);
|
|
83
|
+
await ensureNetworkApproved({
|
|
84
|
+
config: loaded.config,
|
|
85
|
+
yes: opts.yes,
|
|
86
|
+
reason: "release apply --push validates npm version availability and pushes over network",
|
|
87
|
+
interactive: Boolean(process.stdin.isTTY),
|
|
88
|
+
});
|
|
89
|
+
await ensureRemoteExists(opts.gitRoot, opts.remote);
|
|
90
|
+
await ensureRemoteTagDoesNotExist(opts.gitRoot, opts.remote, opts.nextTag);
|
|
91
|
+
await ensureNpmVersionsAvailable(opts.gitRoot, opts.nextVersion);
|
|
92
|
+
await runReleasePrepublishGate(opts.gitRoot);
|
|
93
|
+
return true;
|
|
138
94
|
}
|
|
139
|
-
async function
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
95
|
+
async function applyReleaseMutation(opts) {
|
|
96
|
+
let releaseCommit = null;
|
|
97
|
+
await Promise.all([
|
|
98
|
+
replacePackageVersionInFile(opts.corePkgPath, opts.nextVersion),
|
|
99
|
+
replaceAgentplanePackageMetadata(opts.agentplanePkgPath, opts.nextVersion),
|
|
100
|
+
]);
|
|
101
|
+
const expectedCliVersionPersisted = await maybePersistExpectedCliVersion(opts.agentplaneDir, opts.nextVersion);
|
|
102
|
+
await maybeUpdateBunLockfile(opts.gitRoot, fileExists);
|
|
103
|
+
const generatedReferenceExists = await maybeRefreshGeneratedReference(opts.gitRoot, fileExists);
|
|
104
|
+
const stagePaths = [
|
|
105
|
+
"packages/core/package.json",
|
|
106
|
+
"packages/agentplane/package.json",
|
|
107
|
+
path.relative(opts.gitRoot, opts.notesPath),
|
|
108
|
+
];
|
|
109
|
+
if (expectedCliVersionPersisted) {
|
|
110
|
+
stagePaths.push(".agentplane/config.json");
|
|
155
111
|
}
|
|
156
|
-
if (
|
|
157
|
-
|
|
158
|
-
exitCode: exitCodeForError("E_VALIDATION"),
|
|
159
|
-
code: "E_VALIDATION",
|
|
160
|
-
message: `Release notes must be written in English (no Cyrillic) in ${notesPath}.`,
|
|
161
|
-
});
|
|
112
|
+
if (generatedReferenceExists) {
|
|
113
|
+
stagePaths.push("docs/reference/generated-reference.mdx");
|
|
162
114
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
// GitHub publish uses `bun install --frozen-lockfile`, which will fail if the lockfile
|
|
166
|
-
// needs regeneration after bumping workspace package versions.
|
|
167
|
-
const bunLockPath = path.join(gitRoot, "bun.lock");
|
|
168
|
-
const rootPkgPath = path.join(gitRoot, "package.json");
|
|
169
|
-
if (!(await fileExists(bunLockPath)))
|
|
170
|
-
return;
|
|
171
|
-
if (!(await fileExists(rootPkgPath)))
|
|
172
|
-
return;
|
|
173
|
-
try {
|
|
174
|
-
await execFileAsync("bun", ["install", "--ignore-scripts"], {
|
|
175
|
-
cwd: gitRoot,
|
|
176
|
-
env: process.env,
|
|
177
|
-
maxBuffer: 50 * 1024 * 1024,
|
|
178
|
-
});
|
|
115
|
+
if (await fileExists(path.join(opts.gitRoot, "bun.lock"))) {
|
|
116
|
+
stagePaths.push("bun.lock");
|
|
179
117
|
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
message: "Failed to update bun.lock via `bun install --ignore-scripts`.\n" +
|
|
186
|
-
"Fix:\n" +
|
|
187
|
-
" 1) Run `bun install --ignore-scripts` manually\n" +
|
|
188
|
-
" 2) Re-run `agentplane release apply`\n" +
|
|
189
|
-
(e?.message ? `\nDetails:\n${e.message}` : ""),
|
|
190
|
-
});
|
|
118
|
+
await opts.git.stage(stagePaths);
|
|
119
|
+
const staged = await opts.git.statusStagedPaths();
|
|
120
|
+
if (staged.length === 0) {
|
|
121
|
+
process.stdout.write("No changes to commit.\n");
|
|
122
|
+
return { releaseCommit };
|
|
191
123
|
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
const { stdout } = await execFileAsync("git", ["
|
|
195
|
-
cwd: gitRoot,
|
|
124
|
+
const subject = `✨ release: ${opts.nextTag}`;
|
|
125
|
+
await opts.git.commit({ message: subject, env: cleanHookEnv() });
|
|
126
|
+
const { stdout: headHash } = await execFileAsync("git", ["rev-parse", "HEAD"], {
|
|
127
|
+
cwd: opts.gitRoot,
|
|
196
128
|
env: gitEnv(),
|
|
197
|
-
maxBuffer: 10 * 1024 * 1024,
|
|
198
|
-
});
|
|
199
|
-
const dirty = String(stdout ?? "")
|
|
200
|
-
.split(/\r?\n/u)
|
|
201
|
-
.map((line) => line.trimEnd())
|
|
202
|
-
.filter((line) => line.length > 0);
|
|
203
|
-
if (dirty.length === 0)
|
|
204
|
-
return;
|
|
205
|
-
throw new CliError({
|
|
206
|
-
exitCode: exitCodeForError("E_GIT"),
|
|
207
|
-
code: "E_GIT",
|
|
208
|
-
message: "Release apply requires a clean tracked working tree.\n" +
|
|
209
|
-
`Found tracked changes:\n${dirty.map((line) => ` ${line}`).join("\n")}`,
|
|
210
129
|
});
|
|
130
|
+
releaseCommit = { hash: String(headHash ?? "").trim(), subject };
|
|
131
|
+
return { releaseCommit };
|
|
211
132
|
}
|
|
212
|
-
async function
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
message: `Tag already exists: ${tag}`,
|
|
222
|
-
});
|
|
223
|
-
}
|
|
224
|
-
catch (err) {
|
|
225
|
-
const code = err?.code;
|
|
226
|
-
if (code !== 1)
|
|
227
|
-
throw err;
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
async function ensureNpmVersionsAvailable(gitRoot, version) {
|
|
231
|
-
const scriptPath = path.join(gitRoot, "scripts", "check-npm-version-availability.mjs");
|
|
232
|
-
try {
|
|
233
|
-
await execFileAsync("node", [scriptPath, "--version", version], {
|
|
234
|
-
cwd: gitRoot,
|
|
235
|
-
env: process.env,
|
|
236
|
-
maxBuffer: 10 * 1024 * 1024,
|
|
237
|
-
});
|
|
238
|
-
}
|
|
239
|
-
catch (err) {
|
|
240
|
-
const details = String(err?.stderr ?? "").trim();
|
|
241
|
-
throw new CliError({
|
|
242
|
-
exitCode: exitCodeForError("E_VALIDATION"),
|
|
243
|
-
code: "E_VALIDATION",
|
|
244
|
-
message: `Pre-publish npm check failed for version ${version}. ` +
|
|
245
|
-
"Ensure this version is not already published for @agentplaneorg/core and agentplane." +
|
|
246
|
-
(details ? `\n\n${details}` : ""),
|
|
247
|
-
});
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
async function runReleasePrepublishGate(gitRoot) {
|
|
251
|
-
try {
|
|
252
|
-
await execFileAsync("bun", ["run", "release:prepublish"], {
|
|
253
|
-
cwd: gitRoot,
|
|
254
|
-
env: {
|
|
255
|
-
...process.env,
|
|
256
|
-
GIT_AUTHOR_NAME: process.env.GIT_AUTHOR_NAME ?? "agentplane-release",
|
|
257
|
-
GIT_AUTHOR_EMAIL: process.env.GIT_AUTHOR_EMAIL ?? "agentplane-release@example.com",
|
|
258
|
-
GIT_COMMITTER_NAME: process.env.GIT_COMMITTER_NAME ?? "agentplane-release",
|
|
259
|
-
GIT_COMMITTER_EMAIL: process.env.GIT_COMMITTER_EMAIL ?? "agentplane-release@example.com",
|
|
260
|
-
},
|
|
261
|
-
maxBuffer: 200 * 1024 * 1024,
|
|
262
|
-
});
|
|
133
|
+
async function finalizeReleaseApply(opts) {
|
|
134
|
+
await execFileAsync("git", ["tag", opts.plan.nextTag], {
|
|
135
|
+
cwd: opts.gitRoot,
|
|
136
|
+
env: gitEnv(),
|
|
137
|
+
});
|
|
138
|
+
process.stdout.write(`Release tag created: ${opts.plan.nextTag}\n`);
|
|
139
|
+
if (opts.push) {
|
|
140
|
+
await pushReleaseRefs(opts.gitRoot, opts.remote, opts.plan.nextTag);
|
|
141
|
+
process.stdout.write(`Pushed: ${opts.remote} HEAD + ${opts.plan.nextTag}\n`);
|
|
263
142
|
}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
err?.stdout ??
|
|
267
|
-
err?.message ??
|
|
268
|
-
"").trim();
|
|
269
|
-
throw new CliError({
|
|
270
|
-
exitCode: exitCodeForError("E_VALIDATION"),
|
|
271
|
-
code: "E_VALIDATION",
|
|
272
|
-
message: "Release prepublish gate failed. `agentplane release apply --push` requires a successful local `bun run release:prepublish` run before pushing the release tag." +
|
|
273
|
-
(details ? `\n\n${details}` : ""),
|
|
274
|
-
});
|
|
143
|
+
else {
|
|
144
|
+
process.stdout.write(`Next: git push <remote> HEAD && git push <remote> ${opts.plan.nextTag}\n`);
|
|
275
145
|
}
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
146
|
+
const reportPath = await writeReleaseApplyReport(opts.gitRoot, {
|
|
147
|
+
applied_at: new Date().toISOString(),
|
|
148
|
+
plan_dir: path.relative(opts.gitRoot, opts.planDir),
|
|
149
|
+
notes_path: path.relative(opts.gitRoot, opts.notesPath),
|
|
150
|
+
prev_version: opts.plan.prevVersion,
|
|
151
|
+
next_version: opts.plan.nextVersion,
|
|
152
|
+
prev_tag: opts.plan.prevTag,
|
|
153
|
+
next_tag: opts.plan.nextTag,
|
|
154
|
+
bump: opts.plan.bump,
|
|
155
|
+
checks: {
|
|
156
|
+
clean_tracked_tree: true,
|
|
157
|
+
tag_absent: true,
|
|
158
|
+
notes_validated: true,
|
|
159
|
+
npm_version_available_checked: opts.npmVersionChecked,
|
|
160
|
+
},
|
|
161
|
+
commit: opts.releaseCommit,
|
|
162
|
+
push: { requested: opts.push, remote: opts.remote, performed: opts.push },
|
|
163
|
+
});
|
|
164
|
+
process.stdout.write(`Release report: ${path.relative(opts.gitRoot, reportPath)}\n`);
|
|
165
|
+
return 0;
|
|
287
166
|
}
|
|
288
167
|
export const releaseApplySpec = {
|
|
289
168
|
id: ["release", "apply"],
|
|
@@ -373,21 +252,10 @@ export const runReleaseApply = async (ctx, flags) => {
|
|
|
373
252
|
}
|
|
374
253
|
const resolved = await resolveProject({ cwd: ctx.cwd, rootOverride: ctx.rootOverride ?? null });
|
|
375
254
|
const gitRoot = resolved.gitRoot;
|
|
376
|
-
const planDir
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
exitCode: exitCodeForError("E_IO"),
|
|
381
|
-
code: "E_IO",
|
|
382
|
-
message: `Missing version.json in plan dir: ${path.relative(gitRoot, versionJsonPath)}`,
|
|
383
|
-
});
|
|
384
|
-
}
|
|
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);
|
|
255
|
+
const { planDir, plan, notesPath } = await resolveReleasePlanInputs({
|
|
256
|
+
gitRoot,
|
|
257
|
+
planOverride: flags.plan,
|
|
258
|
+
});
|
|
391
259
|
if ((plan.bump === "minor" || plan.bump === "major") && flags.yes !== true) {
|
|
392
260
|
throw usageError({
|
|
393
261
|
spec: releaseApplySpec,
|
|
@@ -395,136 +263,45 @@ export const runReleaseApply = async (ctx, flags) => {
|
|
|
395
263
|
message: `Bump '${plan.bump}' requires explicit approval. Re-run with --yes.`,
|
|
396
264
|
});
|
|
397
265
|
}
|
|
398
|
-
if (!/^v\d+\.\d+\.\d+$/u.test(plan.nextTag)) {
|
|
399
|
-
throw new CliError({
|
|
400
|
-
exitCode: exitCodeForError("E_VALIDATION"),
|
|
401
|
-
code: "E_VALIDATION",
|
|
402
|
-
message: `Invalid nextTag in version.json (expected vX.Y.Z): ${plan.nextTag}`,
|
|
403
|
-
});
|
|
404
|
-
}
|
|
405
|
-
const notesPath = path.join(gitRoot, "docs", "releases", `${plan.nextTag}.md`);
|
|
406
|
-
if (!(await fileExists(notesPath))) {
|
|
407
|
-
throw new CliError({
|
|
408
|
-
exitCode: exitCodeForError("E_IO"),
|
|
409
|
-
code: "E_IO",
|
|
410
|
-
message: `Missing release notes: ${path.relative(gitRoot, notesPath)}\n` +
|
|
411
|
-
"Write this file using a DOCS agent before applying the release.",
|
|
412
|
-
});
|
|
413
|
-
}
|
|
414
|
-
await validateReleaseNotes(notesPath, minBullets);
|
|
415
266
|
const corePkgPath = path.join(gitRoot, "packages", "core", "package.json");
|
|
416
267
|
const agentplanePkgPath = path.join(gitRoot, "packages", "agentplane", "package.json");
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
throw new CliError({
|
|
424
|
-
exitCode: exitCodeForError("E_VALIDATION"),
|
|
425
|
-
code: "E_VALIDATION",
|
|
426
|
-
message: `Package versions must match before applying a release. ` +
|
|
427
|
-
`packages/core=${coreVersion} packages/agentplane=${agentplaneVersion}`,
|
|
428
|
-
});
|
|
429
|
-
}
|
|
430
|
-
if (coreDependencyVersion !== coreVersion) {
|
|
431
|
-
throw new CliError({
|
|
432
|
-
exitCode: exitCodeForError("E_VALIDATION"),
|
|
433
|
-
code: "E_VALIDATION",
|
|
434
|
-
message: "Release dependency parity check failed before apply. " +
|
|
435
|
-
`packages/agentplane dependency @agentplaneorg/core=${coreDependencyVersion} ` +
|
|
436
|
-
`must match packages/core version ${coreVersion}.`,
|
|
437
|
-
});
|
|
438
|
-
}
|
|
439
|
-
const git = new GitContext({ gitRoot });
|
|
440
|
-
await ensureCleanTrackedTree(gitRoot);
|
|
441
|
-
await ensureTagDoesNotExist(gitRoot, plan.nextTag);
|
|
268
|
+
await ensureReleasePlanMatchesRepoState({
|
|
269
|
+
gitRoot,
|
|
270
|
+
plan,
|
|
271
|
+
corePkgPath,
|
|
272
|
+
agentplanePkgPath,
|
|
273
|
+
});
|
|
442
274
|
let npmVersionChecked = false;
|
|
443
275
|
if (flags.push) {
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
276
|
+
npmVersionChecked = await runPushPreflight({
|
|
277
|
+
agentplaneDir: resolved.agentplaneDir,
|
|
278
|
+
gitRoot,
|
|
279
|
+
remote: flags.remote,
|
|
280
|
+
nextTag: plan.nextTag,
|
|
281
|
+
nextVersion: plan.nextVersion,
|
|
447
282
|
yes: flags.yes,
|
|
448
|
-
reason: "release apply --push validates npm version availability and pushes over network",
|
|
449
|
-
interactive: Boolean(process.stdin.isTTY),
|
|
450
|
-
});
|
|
451
|
-
await runReleasePrepublishGate(gitRoot);
|
|
452
|
-
await ensureNpmVersionsAvailable(gitRoot, plan.nextVersion);
|
|
453
|
-
npmVersionChecked = true;
|
|
454
|
-
}
|
|
455
|
-
let releaseCommit = null;
|
|
456
|
-
if (coreVersion === plan.prevVersion) {
|
|
457
|
-
await Promise.all([
|
|
458
|
-
replacePackageVersionInFile(corePkgPath, plan.nextVersion),
|
|
459
|
-
replaceAgentplanePackageMetadata(agentplanePkgPath, plan.nextVersion),
|
|
460
|
-
]);
|
|
461
|
-
}
|
|
462
|
-
else if (coreVersion === plan.nextVersion) {
|
|
463
|
-
await replaceAgentplanePackageMetadata(agentplanePkgPath, plan.nextVersion);
|
|
464
|
-
}
|
|
465
|
-
else {
|
|
466
|
-
throw new CliError({
|
|
467
|
-
exitCode: exitCodeForError("E_VALIDATION"),
|
|
468
|
-
code: "E_VALIDATION",
|
|
469
|
-
message: `Current version does not match plan. ` +
|
|
470
|
-
`current=${coreVersion} expected_prev=${plan.prevVersion} expected_next=${plan.nextVersion}\n` +
|
|
471
|
-
"Re-run `agentplane release plan` to generate a fresh plan for this repo state.",
|
|
472
|
-
});
|
|
473
|
-
}
|
|
474
|
-
await maybeUpdateBunLockfile(gitRoot);
|
|
475
|
-
const stagePaths = [
|
|
476
|
-
"packages/core/package.json",
|
|
477
|
-
"packages/agentplane/package.json",
|
|
478
|
-
path.relative(gitRoot, notesPath),
|
|
479
|
-
];
|
|
480
|
-
if (await fileExists(path.join(gitRoot, "bun.lock"))) {
|
|
481
|
-
stagePaths.push("bun.lock");
|
|
482
|
-
}
|
|
483
|
-
await git.stage(stagePaths);
|
|
484
|
-
const staged = await git.statusStagedPaths();
|
|
485
|
-
if (staged.length === 0) {
|
|
486
|
-
process.stdout.write("No changes to commit.\n");
|
|
487
|
-
}
|
|
488
|
-
else {
|
|
489
|
-
const subject = `✨ release: ${plan.nextTag}`;
|
|
490
|
-
await git.commit({ message: subject, env: cleanHookEnv() });
|
|
491
|
-
const { stdout: headHash } = await execFileAsync("git", ["rev-parse", "HEAD"], {
|
|
492
|
-
cwd: gitRoot,
|
|
493
|
-
env: gitEnv(),
|
|
494
|
-
});
|
|
495
|
-
releaseCommit = { hash: String(headHash ?? "").trim(), subject };
|
|
496
|
-
}
|
|
497
|
-
await execFileAsync("git", ["tag", plan.nextTag], { cwd: gitRoot, env: gitEnv() });
|
|
498
|
-
process.stdout.write(`Release tag created: ${plan.nextTag}\n`);
|
|
499
|
-
if (flags.push) {
|
|
500
|
-
await execFileAsync("git", ["push", flags.remote, "HEAD"], { cwd: gitRoot, env: gitEnv() });
|
|
501
|
-
await execFileAsync("git", ["push", flags.remote, plan.nextTag], {
|
|
502
|
-
cwd: gitRoot,
|
|
503
|
-
env: gitEnv(),
|
|
504
283
|
});
|
|
505
|
-
process.stdout.write(`Pushed: ${flags.remote} HEAD + ${plan.nextTag}\n`);
|
|
506
284
|
}
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
285
|
+
const git = new GitContext({ gitRoot });
|
|
286
|
+
const { releaseCommit } = await applyReleaseMutation({
|
|
287
|
+
agentplaneDir: resolved.agentplaneDir,
|
|
288
|
+
gitRoot,
|
|
289
|
+
git,
|
|
290
|
+
notesPath,
|
|
291
|
+
corePkgPath,
|
|
292
|
+
agentplanePkgPath,
|
|
293
|
+
nextTag: plan.nextTag,
|
|
294
|
+
nextVersion: plan.nextVersion,
|
|
295
|
+
});
|
|
296
|
+
return await finalizeReleaseApply({
|
|
297
|
+
gitRoot,
|
|
298
|
+
planDir,
|
|
299
|
+
notesPath,
|
|
300
|
+
plan,
|
|
301
|
+
npmVersionChecked,
|
|
302
|
+
releaseCommit,
|
|
303
|
+
push: flags.push,
|
|
304
|
+
remote: flags.remote,
|
|
527
305
|
});
|
|
528
|
-
process.stdout.write(`Release report: ${path.relative(gitRoot, reportPath)}\n`);
|
|
529
|
-
return 0;
|
|
530
306
|
};
|
|
307
|
+
export { pushReleaseRefs } from "./apply.reporting.js";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export declare function replacePackageVersionInFile(pkgJsonPath: string, nextVersion: string): Promise<void>;
|
|
2
|
+
export declare function replaceAgentplanePackageMetadata(pkgJsonPath: string, nextVersion: string): Promise<void>;
|
|
3
|
+
export declare function maybeUpdateBunLockfile(gitRoot: string, fileExists: (p: string) => Promise<boolean>): Promise<void>;
|
|
4
|
+
export declare function maybeRefreshGeneratedReference(gitRoot: string, fileExists: (p: string) => Promise<boolean>): Promise<boolean>;
|
|
5
|
+
export declare function maybePersistExpectedCliVersion(agentplaneDir: string, nextVersion: string): Promise<boolean>;
|
|
6
|
+
export declare function cleanHookEnv(): NodeJS.ProcessEnv;
|
|
7
|
+
//# sourceMappingURL=apply.mutation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply.mutation.d.ts","sourceRoot":"","sources":["../../../src/commands/release/apply.mutation.ts"],"names":[],"mappings":"AASA,wBAAsB,2BAA2B,CAC/C,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CAWf;AAED,wBAAsB,gCAAgC,CACpD,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CAwBf;AAED,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,GAC1C,OAAO,CAAC,IAAI,CAAC,CAyBf;AAED,wBAAsB,8BAA8B,CAClD,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,GAC1C,OAAO,CAAC,OAAO,CAAC,CAyBlB;AAED,wBAAsB,8BAA8B,CAClD,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,OAAO,CAAC,CAQlB;AAED,wBAAgB,YAAY,IAAI,MAAM,CAAC,UAAU,CAMhD"}
|