agentplane 0.3.2 → 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.
Files changed (190) hide show
  1. package/assets/AGENTS.md +1 -1
  2. package/assets/agents/CODER.json +4 -3
  3. package/assets/agents/DOCS.json +1 -1
  4. package/assets/agents/INTEGRATOR.json +1 -1
  5. package/assets/agents/ORCHESTRATOR.json +1 -0
  6. package/assets/agents/PLANNER.json +1 -0
  7. package/assets/agents/TESTER.json +3 -1
  8. package/assets/policy/dod.code.md +2 -2
  9. package/assets/policy/dod.core.md +16 -2
  10. package/assets/policy/dod.docs.md +2 -2
  11. package/assets/policy/incidents.md +44 -1
  12. package/assets/policy/workflow.direct.md +8 -4
  13. package/bin/agentplane.js +59 -9
  14. package/bin/dist-guard.js +78 -10
  15. package/bin/runtime-context.d.ts +3 -0
  16. package/bin/runtime-context.js +13 -0
  17. package/bin/runtime-watch.d.ts +26 -0
  18. package/bin/runtime-watch.js +116 -0
  19. package/bin/stale-dist-policy.d.ts +6 -0
  20. package/bin/stale-dist-policy.js +44 -0
  21. package/dist/.build-manifest.json +2480 -5
  22. package/dist/backends/task-backend/local-backend.d.ts.map +1 -1
  23. package/dist/backends/task-backend/local-backend.js +9 -12
  24. package/dist/backends/task-backend/redmine-backend.d.ts.map +1 -1
  25. package/dist/backends/task-backend/redmine-backend.js +23 -18
  26. package/dist/backends/task-backend/shared/constants.d.ts +1 -0
  27. package/dist/backends/task-backend/shared/constants.d.ts.map +1 -1
  28. package/dist/backends/task-backend/shared/constants.js +1 -0
  29. package/dist/backends/task-backend/shared/doc.d.ts +1 -0
  30. package/dist/backends/task-backend/shared/doc.d.ts.map +1 -1
  31. package/dist/backends/task-backend/shared/doc.js +4 -1
  32. package/dist/backends/task-backend/shared/export.js +3 -3
  33. package/dist/cli/bootstrap-guide.d.ts +1 -3
  34. package/dist/cli/bootstrap-guide.d.ts.map +1 -1
  35. package/dist/cli/bootstrap-guide.js +13 -33
  36. package/dist/cli/command-guide.d.ts.map +1 -1
  37. package/dist/cli/command-guide.js +27 -34
  38. package/dist/cli/run-cli/catalog.d.ts +7 -0
  39. package/dist/cli/run-cli/catalog.d.ts.map +1 -0
  40. package/dist/cli/run-cli/catalog.js +22 -0
  41. package/dist/cli/run-cli/command-catalog.d.ts +1 -1
  42. package/dist/cli/run-cli/command-catalog.d.ts.map +1 -1
  43. package/dist/cli/run-cli/command-catalog.js +11 -0
  44. package/dist/cli/run-cli/commands/init/write-config.d.ts.map +1 -1
  45. package/dist/cli/run-cli/commands/init/write-config.js +2 -0
  46. package/dist/cli/run-cli/commands/init.js +5 -14
  47. package/dist/cli/run-cli/error-guidance.d.ts +9 -0
  48. package/dist/cli/run-cli/error-guidance.d.ts.map +1 -0
  49. package/dist/cli/run-cli/error-guidance.js +180 -0
  50. package/dist/cli/run-cli/globals.d.ts +22 -0
  51. package/dist/cli/run-cli/globals.d.ts.map +1 -0
  52. package/dist/cli/run-cli/globals.js +197 -0
  53. package/dist/cli/run-cli/update-warning.d.ts +6 -0
  54. package/dist/cli/run-cli/update-warning.d.ts.map +1 -0
  55. package/dist/cli/run-cli/update-warning.js +64 -0
  56. package/dist/cli/run-cli.d.ts.map +1 -1
  57. package/dist/cli/run-cli.js +5 -476
  58. package/dist/cli/spec/docs-render.d.ts.map +1 -1
  59. package/dist/cli/spec/docs-render.js +14 -1
  60. package/dist/commands/doctor/archive.d.ts +4 -0
  61. package/dist/commands/doctor/archive.d.ts.map +1 -0
  62. package/dist/commands/doctor/archive.js +211 -0
  63. package/dist/commands/doctor/fixes.d.ts +9 -0
  64. package/dist/commands/doctor/fixes.d.ts.map +1 -0
  65. package/dist/commands/doctor/fixes.js +40 -0
  66. package/dist/commands/doctor/layering.d.ts +2 -0
  67. package/dist/commands/doctor/layering.d.ts.map +1 -0
  68. package/dist/commands/doctor/layering.js +87 -0
  69. package/dist/commands/doctor/runtime.d.ts +4 -0
  70. package/dist/commands/doctor/runtime.d.ts.map +1 -0
  71. package/dist/commands/doctor/runtime.js +56 -0
  72. package/dist/commands/doctor/workflow.d.ts +6 -0
  73. package/dist/commands/doctor/workflow.d.ts.map +1 -0
  74. package/dist/commands/doctor/workflow.js +62 -0
  75. package/dist/commands/doctor/workspace.d.ts +2 -0
  76. package/dist/commands/doctor/workspace.d.ts.map +1 -0
  77. package/dist/commands/doctor/workspace.js +165 -0
  78. package/dist/commands/doctor.run.d.ts.map +1 -1
  79. package/dist/commands/doctor.run.js +16 -342
  80. package/dist/commands/doctor.spec.d.ts +1 -0
  81. package/dist/commands/doctor.spec.d.ts.map +1 -1
  82. package/dist/commands/doctor.spec.js +15 -1
  83. package/dist/commands/guard/impl/commands.d.ts.map +1 -1
  84. package/dist/commands/guard/impl/commands.js +19 -0
  85. package/dist/commands/release/apply.command.d.ts +2 -8
  86. package/dist/commands/release/apply.command.d.ts.map +1 -1
  87. package/dist/commands/release/apply.command.js +158 -387
  88. package/dist/commands/release/apply.mutation.d.ts +7 -0
  89. package/dist/commands/release/apply.mutation.d.ts.map +1 -0
  90. package/dist/commands/release/apply.mutation.js +107 -0
  91. package/dist/commands/release/apply.preflight.d.ts +25 -0
  92. package/dist/commands/release/apply.preflight.d.ts.map +1 -0
  93. package/dist/commands/release/apply.preflight.js +338 -0
  94. package/dist/commands/release/apply.reporting.d.ts +4 -0
  95. package/dist/commands/release/apply.reporting.d.ts.map +1 -0
  96. package/dist/commands/release/apply.reporting.js +24 -0
  97. package/dist/commands/release/apply.types.d.ts +46 -0
  98. package/dist/commands/release/apply.types.d.ts.map +1 -0
  99. package/dist/commands/release/apply.types.js +1 -0
  100. package/dist/commands/runtime.command.d.ts +28 -0
  101. package/dist/commands/runtime.command.d.ts.map +1 -0
  102. package/dist/commands/runtime.command.js +169 -0
  103. package/dist/commands/shared/task-store.d.ts.map +1 -1
  104. package/dist/commands/shared/task-store.js +7 -3
  105. package/dist/commands/task/add.d.ts.map +1 -1
  106. package/dist/commands/task/add.js +3 -33
  107. package/dist/commands/task/block.d.ts.map +1 -1
  108. package/dist/commands/task/block.js +2 -2
  109. package/dist/commands/task/close-duplicate.d.ts.map +1 -1
  110. package/dist/commands/task/close-duplicate.js +2 -2
  111. package/dist/commands/task/close-noop.d.ts.map +1 -1
  112. package/dist/commands/task/close-noop.js +2 -2
  113. package/dist/commands/task/comment.js +2 -2
  114. package/dist/commands/task/derive.d.ts.map +1 -1
  115. package/dist/commands/task/derive.js +3 -3
  116. package/dist/commands/task/doc-template.d.ts +10 -0
  117. package/dist/commands/task/doc-template.d.ts.map +1 -0
  118. package/dist/commands/task/doc-template.js +104 -0
  119. package/dist/commands/task/doc.d.ts.map +1 -1
  120. package/dist/commands/task/doc.js +36 -1
  121. package/dist/commands/task/finish.d.ts.map +1 -1
  122. package/dist/commands/task/finish.js +7 -4
  123. package/dist/commands/task/migrate-doc.command.d.ts.map +1 -1
  124. package/dist/commands/task/migrate-doc.command.js +5 -1
  125. package/dist/commands/task/migrate-doc.d.ts.map +1 -1
  126. package/dist/commands/task/migrate-doc.js +136 -2
  127. package/dist/commands/task/new.d.ts.map +1 -1
  128. package/dist/commands/task/new.js +4 -110
  129. package/dist/commands/task/new.spec.js +3 -3
  130. package/dist/commands/task/plan.d.ts.map +1 -1
  131. package/dist/commands/task/plan.js +5 -4
  132. package/dist/commands/task/scaffold.d.ts.map +1 -1
  133. package/dist/commands/task/scaffold.js +7 -52
  134. package/dist/commands/task/set-status.d.ts.map +1 -1
  135. package/dist/commands/task/set-status.js +2 -2
  136. package/dist/commands/task/shared/dependencies.d.ts +15 -0
  137. package/dist/commands/task/shared/dependencies.d.ts.map +1 -0
  138. package/dist/commands/task/shared/dependencies.js +143 -0
  139. package/dist/commands/task/shared/docs.d.ts +21 -0
  140. package/dist/commands/task/shared/docs.d.ts.map +1 -0
  141. package/dist/commands/task/shared/docs.js +121 -0
  142. package/dist/commands/task/shared/listing.d.ts +20 -0
  143. package/dist/commands/task/shared/listing.d.ts.map +1 -0
  144. package/dist/commands/task/shared/listing.js +127 -0
  145. package/dist/commands/task/shared/tags.d.ts +24 -0
  146. package/dist/commands/task/shared/tags.d.ts.map +1 -0
  147. package/dist/commands/task/shared/tags.js +177 -0
  148. package/dist/commands/task/shared/transitions.d.ts +42 -0
  149. package/dist/commands/task/shared/transitions.d.ts.map +1 -0
  150. package/dist/commands/task/shared/transitions.js +175 -0
  151. package/dist/commands/task/shared.d.ts +5 -106
  152. package/dist/commands/task/shared.d.ts.map +1 -1
  153. package/dist/commands/task/shared.js +5 -681
  154. package/dist/commands/task/start.d.ts.map +1 -1
  155. package/dist/commands/task/start.js +7 -5
  156. package/dist/commands/task/verify-record.d.ts.map +1 -1
  157. package/dist/commands/task/verify-record.js +9 -25
  158. package/dist/commands/task/verify-show.command.d.ts.map +1 -1
  159. package/dist/commands/task/verify-show.command.js +5 -1
  160. package/dist/commands/upgrade/apply.d.ts +44 -0
  161. package/dist/commands/upgrade/apply.d.ts.map +1 -0
  162. package/dist/commands/upgrade/apply.js +180 -0
  163. package/dist/commands/upgrade/report.d.ts +21 -0
  164. package/dist/commands/upgrade/report.d.ts.map +1 -0
  165. package/dist/commands/upgrade/report.js +81 -0
  166. package/dist/commands/upgrade/source.d.ts +35 -0
  167. package/dist/commands/upgrade/source.d.ts.map +1 -0
  168. package/dist/commands/upgrade/source.js +109 -0
  169. package/dist/commands/upgrade/types.d.ts +31 -0
  170. package/dist/commands/upgrade/types.d.ts.map +1 -0
  171. package/dist/commands/upgrade/types.js +1 -0
  172. package/dist/commands/upgrade.d.ts +1 -35
  173. package/dist/commands/upgrade.d.ts.map +1 -1
  174. package/dist/commands/upgrade.js +46 -331
  175. package/dist/shared/diagnostics.d.ts +23 -0
  176. package/dist/shared/diagnostics.d.ts.map +1 -0
  177. package/dist/shared/diagnostics.js +57 -0
  178. package/dist/shared/errors.d.ts +2 -0
  179. package/dist/shared/errors.d.ts.map +1 -1
  180. package/dist/shared/errors.js +2 -0
  181. package/dist/shared/repo-cli-version.d.ts +13 -0
  182. package/dist/shared/repo-cli-version.d.ts.map +1 -0
  183. package/dist/shared/repo-cli-version.js +63 -0
  184. package/dist/shared/runtime-source.d.ts +33 -0
  185. package/dist/shared/runtime-source.d.ts.map +1 -0
  186. package/dist/shared/runtime-source.js +156 -0
  187. package/dist/shared/version-compare.d.ts +7 -0
  188. package/dist/shared/version-compare.d.ts.map +1 -0
  189. package/dist/shared/version-compare.js +30 -0
  190. package/package.json +2 -2
@@ -0,0 +1,107 @@
1
+ import { readFile, writeFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { loadConfig, saveConfig, setByDottedKey } from "@agentplaneorg/core";
4
+ import { exitCodeForError } from "../../cli/exit-codes.js";
5
+ import { CliError } from "../../shared/errors.js";
6
+ import { execFileAsync, gitEnv } from "../shared/git.js";
7
+ export async function replacePackageVersionInFile(pkgJsonPath, nextVersion) {
8
+ const text = await readFile(pkgJsonPath, "utf8");
9
+ const replaced = text.replace(/"version"\s*:\s*"[^"]*"/u, `"version": "${nextVersion}"`);
10
+ if (replaced === text) {
11
+ throw new CliError({
12
+ exitCode: exitCodeForError("E_VALIDATION"),
13
+ code: "E_VALIDATION",
14
+ message: `Failed to update version in ${pkgJsonPath} (missing "version" field).`,
15
+ });
16
+ }
17
+ await writeFile(pkgJsonPath, replaced, "utf8");
18
+ }
19
+ export async function replaceAgentplanePackageMetadata(pkgJsonPath, nextVersion) {
20
+ const text = await readFile(pkgJsonPath, "utf8");
21
+ const withVersion = text.replace(/"version"\s*:\s*"[^"]*"/u, `"version": "${nextVersion}"`);
22
+ if (withVersion === text) {
23
+ throw new CliError({
24
+ exitCode: exitCodeForError("E_VALIDATION"),
25
+ code: "E_VALIDATION",
26
+ message: `Failed to update version in ${pkgJsonPath} (missing "version" field).`,
27
+ });
28
+ }
29
+ const withDependency = withVersion.replace(/("@agentplaneorg\/core"\s*:\s*")[^"]*(")/u, `$1${nextVersion}$2`);
30
+ if (withDependency === withVersion) {
31
+ throw new CliError({
32
+ exitCode: exitCodeForError("E_VALIDATION"),
33
+ code: "E_VALIDATION",
34
+ message: `Failed to update @agentplaneorg/core dependency in ${pkgJsonPath}. ` +
35
+ "Ensure packages/agentplane/package.json declares this dependency.",
36
+ });
37
+ }
38
+ await writeFile(pkgJsonPath, withDependency, "utf8");
39
+ }
40
+ export async function maybeUpdateBunLockfile(gitRoot, fileExists) {
41
+ const bunLockPath = path.join(gitRoot, "bun.lock");
42
+ const rootPkgPath = path.join(gitRoot, "package.json");
43
+ if (!(await fileExists(bunLockPath)))
44
+ return;
45
+ if (!(await fileExists(rootPkgPath)))
46
+ return;
47
+ try {
48
+ await execFileAsync("bun", ["install", "--ignore-scripts"], {
49
+ cwd: gitRoot,
50
+ env: process.env,
51
+ maxBuffer: 50 * 1024 * 1024,
52
+ });
53
+ }
54
+ catch (err) {
55
+ const e = err;
56
+ throw new CliError({
57
+ exitCode: exitCodeForError("E_IO"),
58
+ code: "E_IO",
59
+ message: "Failed to update bun.lock via `bun install --ignore-scripts`.\n" +
60
+ "Fix:\n" +
61
+ " 1) Run `bun install --ignore-scripts` manually\n" +
62
+ " 2) Re-run `agentplane release apply`\n" +
63
+ (e?.message ? `\nDetails:\n${e.message}` : ""),
64
+ });
65
+ }
66
+ }
67
+ export async function maybeRefreshGeneratedReference(gitRoot, fileExists) {
68
+ const scriptPath = path.join(gitRoot, "scripts", "generate-website-docs.mjs");
69
+ if (!(await fileExists(scriptPath)))
70
+ return false;
71
+ try {
72
+ await execFileAsync("node", [scriptPath], {
73
+ cwd: gitRoot,
74
+ env: process.env,
75
+ maxBuffer: 20 * 1024 * 1024,
76
+ });
77
+ }
78
+ catch (err) {
79
+ const e = err;
80
+ throw new CliError({
81
+ exitCode: exitCodeForError("E_IO"),
82
+ code: "E_IO",
83
+ message: "Failed to refresh docs/reference/generated-reference.mdx after bumping release versions.\n" +
84
+ "Fix:\n" +
85
+ " 1) Run `node scripts/generate-website-docs.mjs`\n" +
86
+ " 2) Re-run `agentplane release apply`\n" +
87
+ (e?.message ? `\nDetails:\n${e.message}` : ""),
88
+ });
89
+ }
90
+ return await fileExists(path.join(gitRoot, "docs", "reference", "generated-reference.mdx"));
91
+ }
92
+ export async function maybePersistExpectedCliVersion(agentplaneDir, nextVersion) {
93
+ const loaded = await loadConfig(agentplaneDir);
94
+ if (!loaded.exists)
95
+ return false;
96
+ const raw = { ...loaded.raw };
97
+ setByDottedKey(raw, "framework.cli.expected_version", nextVersion);
98
+ await saveConfig(agentplaneDir, raw);
99
+ return true;
100
+ }
101
+ export function cleanHookEnv() {
102
+ const env = { ...gitEnv() };
103
+ delete env.AGENTPLANE_TASK_ID;
104
+ delete env.AGENTPLANE_STATUS_TO;
105
+ delete env.AGENTPLANE_AGENT_ID;
106
+ return env;
107
+ }
@@ -0,0 +1,25 @@
1
+ import type { PlanChange, ReleaseVersionPlan } from "./apply.types.js";
2
+ export declare function fileExists(p: string): Promise<boolean>;
3
+ export declare function readJsonFile<T>(p: string): Promise<T>;
4
+ export declare function parseVersionPlan(raw: unknown): ReleaseVersionPlan;
5
+ export declare function findLatestPlanDir(gitRoot: string): Promise<string>;
6
+ export declare function readPackageVersion(pkgJsonPath: string): Promise<string>;
7
+ export declare function readCoreDependencyVersion(pkgJsonPath: string): Promise<string>;
8
+ export declare function validateReleaseNotes(notesPath: string, minBullets: number): Promise<void>;
9
+ export declare function ensureCleanTrackedTree(gitRoot: string): Promise<void>;
10
+ export declare function ensureTagDoesNotExist(gitRoot: string, tag: string): Promise<void>;
11
+ export declare function ensureRemoteExists(gitRoot: string, remote: string): Promise<void>;
12
+ export declare function ensureRemoteTagDoesNotExist(gitRoot: string, remote: string, tag: string): Promise<void>;
13
+ export declare function ensureNpmVersionsAvailable(gitRoot: string, version: string): Promise<void>;
14
+ export declare function runReleasePrepublishGate(gitRoot: string): Promise<void>;
15
+ export declare function loadReleasePlan(opts: {
16
+ gitRoot: string;
17
+ planOverride?: string;
18
+ }): Promise<{
19
+ planDir: string;
20
+ versionJsonPath: string;
21
+ plan: ReleaseVersionPlan;
22
+ changes: PlanChange[];
23
+ minBullets: number;
24
+ }>;
25
+ //# sourceMappingURL=apply.preflight.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apply.preflight.d.ts","sourceRoot":"","sources":["../../../src/commands/release/apply.preflight.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAEvE,wBAAsB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO5D;AAED,wBAAsB,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAE3D;AAaD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,kBAAkB,CAuBjE;AAED,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAiBxE;AAED,wBAAsB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAW7E;AAED,wBAAsB,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAgBpF;AAED,wBAAsB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAwB/F;AAED,wBAAsB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiC3E;AAED,wBAAsB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA6BvF;AAED,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA+BvF;AAED,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,IAAI,CAAC,CAyDf;AAED,wBAAsB,0BAA0B,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmChG;AAED,wBAAsB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0C7E;AAED,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC;IAC/F,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,IAAI,EAAE,kBAAkB,CAAC;IACzB,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC,CAwBD"}
@@ -0,0 +1,338 @@
1
+ import { readFile, readdir } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { exitCodeForError } from "../../cli/exit-codes.js";
4
+ import { withDiagnosticContext } from "../../shared/diagnostics.js";
5
+ import { CliError } from "../../shared/errors.js";
6
+ import { execFileAsync, gitEnv } from "../shared/git.js";
7
+ export async function fileExists(p) {
8
+ try {
9
+ await readFile(p, "utf8");
10
+ return true;
11
+ }
12
+ catch {
13
+ return false;
14
+ }
15
+ }
16
+ export async function readJsonFile(p) {
17
+ return JSON.parse(await readFile(p, "utf8"));
18
+ }
19
+ function assertNonEmptyString(value, label) {
20
+ if (typeof value !== "string" || !value.trim()) {
21
+ throw new CliError({
22
+ exitCode: exitCodeForError("E_VALIDATION"),
23
+ code: "E_VALIDATION",
24
+ message: `Invalid ${label} (expected non-empty string).`,
25
+ });
26
+ }
27
+ return value.trim();
28
+ }
29
+ export function parseVersionPlan(raw) {
30
+ if (!raw || typeof raw !== "object") {
31
+ throw new CliError({
32
+ exitCode: exitCodeForError("E_VALIDATION"),
33
+ code: "E_VALIDATION",
34
+ message: "Invalid version.json (expected object).",
35
+ });
36
+ }
37
+ const obj = raw;
38
+ const bumpRaw = assertNonEmptyString(obj.bump, "bump");
39
+ if (bumpRaw !== "patch" && bumpRaw !== "minor" && bumpRaw !== "major") {
40
+ throw new CliError({
41
+ exitCode: exitCodeForError("E_VALIDATION"),
42
+ code: "E_VALIDATION",
43
+ message: `Invalid bump in version.json: ${bumpRaw}`,
44
+ });
45
+ }
46
+ const prevTagVal = obj.prevTag;
47
+ const prevTag = prevTagVal === null ? null : typeof prevTagVal === "string" ? prevTagVal : null;
48
+ const prevVersion = assertNonEmptyString(obj.prevVersion, "prevVersion");
49
+ const nextTag = assertNonEmptyString(obj.nextTag, "nextTag");
50
+ const nextVersion = assertNonEmptyString(obj.nextVersion, "nextVersion");
51
+ return { prevTag, prevVersion, nextTag, nextVersion, bump: bumpRaw };
52
+ }
53
+ export async function findLatestPlanDir(gitRoot) {
54
+ const base = path.join(gitRoot, ".agentplane", ".release", "plan");
55
+ const runNames = await readdir(base);
56
+ const runs = runNames
57
+ .map((s) => s.trim())
58
+ .filter(Boolean)
59
+ .toSorted();
60
+ const latest = runs.at(-1);
61
+ if (!latest) {
62
+ throw new CliError({
63
+ exitCode: exitCodeForError("E_IO"),
64
+ code: "E_IO",
65
+ message: "No release plan runs found under .agentplane/.release/plan/. Run `agentplane release plan` first.",
66
+ });
67
+ }
68
+ return path.join(base, latest);
69
+ }
70
+ export async function readPackageVersion(pkgJsonPath) {
71
+ const raw = JSON.parse(await readFile(pkgJsonPath, "utf8"));
72
+ const version = typeof raw.version === "string" ? raw.version.trim() : "";
73
+ if (!version) {
74
+ throw new CliError({
75
+ exitCode: exitCodeForError("E_VALIDATION"),
76
+ code: "E_VALIDATION",
77
+ message: `Missing package.json version: ${pkgJsonPath}`,
78
+ });
79
+ }
80
+ return version;
81
+ }
82
+ export async function readCoreDependencyVersion(pkgJsonPath) {
83
+ const raw = JSON.parse(await readFile(pkgJsonPath, "utf8"));
84
+ const value = raw.dependencies?.["@agentplaneorg/core"];
85
+ const version = typeof value === "string" ? value.trim() : "";
86
+ if (!version) {
87
+ throw new CliError({
88
+ exitCode: exitCodeForError("E_VALIDATION"),
89
+ code: "E_VALIDATION",
90
+ message: `Missing dependency @agentplaneorg/core in ${pkgJsonPath}. ` +
91
+ "Release parity requires packages/agentplane to pin @agentplaneorg/core to the same version.",
92
+ });
93
+ }
94
+ return version;
95
+ }
96
+ export async function validateReleaseNotes(notesPath, minBullets) {
97
+ const content = await readFile(notesPath, "utf8");
98
+ if (!/release\s+notes/i.test(content)) {
99
+ throw new CliError({
100
+ exitCode: exitCodeForError("E_VALIDATION"),
101
+ code: "E_VALIDATION",
102
+ message: `Release notes must include a "Release Notes" heading in ${notesPath}.`,
103
+ });
104
+ }
105
+ const bulletCount = content.split(/\r?\n/u).filter((line) => /^\s*[-*]\s+\S+/u.test(line)).length;
106
+ if (bulletCount < minBullets) {
107
+ throw new CliError({
108
+ exitCode: exitCodeForError("E_VALIDATION"),
109
+ code: "E_VALIDATION",
110
+ message: `Release notes must include at least ${minBullets} bullet points in ${notesPath}.`,
111
+ });
112
+ }
113
+ if (/[\u0400-\u04FF]/u.test(content)) {
114
+ throw new CliError({
115
+ exitCode: exitCodeForError("E_VALIDATION"),
116
+ code: "E_VALIDATION",
117
+ message: `Release notes must be written in English (no Cyrillic) in ${notesPath}.`,
118
+ });
119
+ }
120
+ }
121
+ export async function ensureCleanTrackedTree(gitRoot) {
122
+ const { stdout } = await execFileAsync("git", ["status", "--short", "--untracked-files=no"], {
123
+ cwd: gitRoot,
124
+ env: gitEnv(),
125
+ maxBuffer: 10 * 1024 * 1024,
126
+ });
127
+ const dirty = String(stdout ?? "")
128
+ .split(/\r?\n/u)
129
+ .map((line) => line.trimEnd())
130
+ .filter((line) => line.length > 0);
131
+ if (dirty.length === 0)
132
+ return;
133
+ throw new CliError({
134
+ exitCode: exitCodeForError("E_GIT"),
135
+ code: "E_GIT",
136
+ message: "Release apply requires a clean tracked working tree.\n" +
137
+ `Found tracked changes:\n${dirty.map((line) => ` ${line}`).join("\n")}`,
138
+ context: withDiagnosticContext({ command: "release apply" }, {
139
+ state: "release apply cannot start from a dirty tracked tree",
140
+ likelyCause: "the release flow needs to create one deterministic version-bump commit and tag, but tracked edits already exist in the workspace",
141
+ nextAction: {
142
+ command: "git status --short --untracked-files=no",
143
+ reason: "inspect or clear tracked changes before rerunning `agentplane release apply --push --yes`",
144
+ reasonCode: "release_dirty_tree",
145
+ },
146
+ }),
147
+ });
148
+ }
149
+ export async function ensureTagDoesNotExist(gitRoot, tag) {
150
+ try {
151
+ await execFileAsync("git", ["rev-parse", "-q", "--verify", `refs/tags/${tag}`], {
152
+ cwd: gitRoot,
153
+ env: gitEnv(),
154
+ });
155
+ throw new CliError({
156
+ exitCode: exitCodeForError("E_GIT"),
157
+ code: "E_GIT",
158
+ message: `Tag already exists: ${tag}`,
159
+ context: withDiagnosticContext({ command: "release apply" }, {
160
+ state: "the target release tag already exists locally",
161
+ likelyCause: "the release version was already applied earlier, or a previous release attempt created the tag before failing later in the flow",
162
+ nextAction: {
163
+ command: `git show --stat --oneline ${tag}`,
164
+ reason: "inspect the existing tag before deciding whether to reuse it or plan a new version",
165
+ reasonCode: "release_tag_exists",
166
+ },
167
+ }),
168
+ });
169
+ }
170
+ catch (err) {
171
+ const code = err?.code;
172
+ if (code !== 1)
173
+ throw err;
174
+ }
175
+ }
176
+ export async function ensureRemoteExists(gitRoot, remote) {
177
+ try {
178
+ await execFileAsync("git", ["remote", "get-url", remote], {
179
+ cwd: gitRoot,
180
+ env: gitEnv(),
181
+ });
182
+ }
183
+ catch (err) {
184
+ const details = String(err?.stderr ??
185
+ err?.message ??
186
+ "").trim();
187
+ throw new CliError({
188
+ exitCode: exitCodeForError("E_GIT"),
189
+ code: "E_GIT",
190
+ message: `Git remote is not configured: ${remote}` + (details ? `\n\n${details}` : ""),
191
+ context: withDiagnosticContext({ command: "release apply" }, {
192
+ state: "the configured release remote does not exist locally",
193
+ likelyCause: "release apply was asked to push, but the selected git remote is missing or misconfigured in this checkout",
194
+ nextAction: {
195
+ command: "git remote -v",
196
+ reason: "inspect configured remotes before rerunning release apply with --push",
197
+ reasonCode: "release_remote_missing",
198
+ },
199
+ }),
200
+ });
201
+ }
202
+ }
203
+ export async function ensureRemoteTagDoesNotExist(gitRoot, remote, tag) {
204
+ let stdout = "";
205
+ try {
206
+ const out = await execFileAsync("git", ["ls-remote", "--tags", remote, `refs/tags/${tag}`], {
207
+ cwd: gitRoot,
208
+ env: gitEnv(),
209
+ });
210
+ stdout = String(out.stdout ?? "").trim();
211
+ }
212
+ catch (err) {
213
+ const details = String(err?.stderr ??
214
+ err?.message ??
215
+ "").trim();
216
+ throw new CliError({
217
+ exitCode: exitCodeForError("E_GIT"),
218
+ code: "E_GIT",
219
+ message: `Failed to inspect remote tag state for ${remote}/${tag}.` +
220
+ (details ? `\n\n${details}` : ""),
221
+ context: withDiagnosticContext({ command: "release apply" }, {
222
+ state: "release apply could not verify the remote tag state",
223
+ likelyCause: "the remote is configured, but git could not query it for the target release tag before the release started",
224
+ nextAction: {
225
+ command: `git ls-remote --tags ${remote} refs/tags/${tag}`,
226
+ reason: "inspect remote tag visibility before retrying the release push path",
227
+ reasonCode: "release_remote_tag_check_failed",
228
+ },
229
+ }),
230
+ });
231
+ }
232
+ if (!stdout)
233
+ return;
234
+ throw new CliError({
235
+ exitCode: exitCodeForError("E_GIT"),
236
+ code: "E_GIT",
237
+ message: `Remote tag already exists: ${remote}/${tag}`,
238
+ context: withDiagnosticContext({ command: "release apply" }, {
239
+ state: "the target release tag already exists on the remote",
240
+ likelyCause: "a previous release or partial push already published this tag upstream, so pushing the same version again would drift the local release state",
241
+ nextAction: {
242
+ command: `git ls-remote --tags ${remote} refs/tags/${tag}`,
243
+ reason: "inspect the existing remote tag before deciding whether to recover or bump to a new version",
244
+ reasonCode: "release_remote_tag_exists",
245
+ },
246
+ }),
247
+ });
248
+ }
249
+ export async function ensureNpmVersionsAvailable(gitRoot, version) {
250
+ const scriptPath = path.join(gitRoot, "scripts", "check-npm-version-availability.mjs");
251
+ try {
252
+ await execFileAsync("node", [scriptPath, "--version", version], {
253
+ cwd: gitRoot,
254
+ env: process.env,
255
+ maxBuffer: 10 * 1024 * 1024,
256
+ });
257
+ }
258
+ catch (err) {
259
+ const details = String(err?.stderr ?? "").trim();
260
+ throw new CliError({
261
+ exitCode: exitCodeForError("E_VALIDATION"),
262
+ code: "E_VALIDATION",
263
+ message: `Pre-publish npm check failed for version ${version}. ` +
264
+ "Ensure this version is not already published for @agentplaneorg/core and agentplane." +
265
+ (details ? `\n\n${details}` : ""),
266
+ context: withDiagnosticContext({ command: "release apply" }, {
267
+ state: "the target npm version is not publishable",
268
+ likelyCause: "that version is already burned in npm history for one of the published packages, even if it is no longer the current dist-tag",
269
+ nextAction: {
270
+ command: `node scripts/check-npm-version-availability.mjs --version ${version}`,
271
+ reason: "inspect which package already consumed the target version before choosing a new release number",
272
+ reasonCode: "release_npm_version_burned",
273
+ },
274
+ }),
275
+ });
276
+ }
277
+ }
278
+ export async function runReleasePrepublishGate(gitRoot) {
279
+ try {
280
+ await execFileAsync("bun", ["run", "release:prepublish"], {
281
+ cwd: gitRoot,
282
+ env: {
283
+ ...process.env,
284
+ GIT_AUTHOR_NAME: process.env.GIT_AUTHOR_NAME ?? "agentplane-release",
285
+ GIT_AUTHOR_EMAIL: process.env.GIT_AUTHOR_EMAIL ?? "agentplane-release@example.com",
286
+ GIT_COMMITTER_NAME: process.env.GIT_COMMITTER_NAME ?? "agentplane-release",
287
+ GIT_COMMITTER_EMAIL: process.env.GIT_COMMITTER_EMAIL ?? "agentplane-release@example.com",
288
+ },
289
+ maxBuffer: 200 * 1024 * 1024,
290
+ });
291
+ }
292
+ catch (err) {
293
+ const details = String(err?.stderr ??
294
+ err?.stdout ??
295
+ err?.message ??
296
+ "").trim();
297
+ throw new CliError({
298
+ exitCode: exitCodeForError("E_VALIDATION"),
299
+ code: "E_VALIDATION",
300
+ message: "Release prepublish gate failed. `agentplane release apply --push` requires a successful local `bun run release:prepublish` run before pushing the release tag." +
301
+ (details ? `\n\n${details}` : ""),
302
+ context: withDiagnosticContext({ command: "release apply" }, {
303
+ state: "release prepublish validation failed before pushing the release",
304
+ likelyCause: "one of the local publish gates rejected the current repository state, so the release cannot be pushed safely yet",
305
+ nextAction: {
306
+ command: "bun run release:prepublish",
307
+ reason: "rerun the exact local publish gate and fix the reported failure before retrying release apply",
308
+ reasonCode: "release_prepublish_failed",
309
+ },
310
+ }),
311
+ });
312
+ }
313
+ }
314
+ export async function loadReleasePlan(opts) {
315
+ const planDir = opts.planOverride
316
+ ? path.resolve(opts.gitRoot, opts.planOverride)
317
+ : await findLatestPlanDir(opts.gitRoot);
318
+ const versionJsonPath = path.join(planDir, "version.json");
319
+ if (!(await fileExists(versionJsonPath))) {
320
+ throw new CliError({
321
+ exitCode: exitCodeForError("E_IO"),
322
+ code: "E_IO",
323
+ message: `Missing version.json in plan dir: ${path.relative(opts.gitRoot, versionJsonPath)}`,
324
+ });
325
+ }
326
+ const plan = parseVersionPlan(await readJsonFile(versionJsonPath));
327
+ const changesJsonPath = path.join(planDir, "changes.json");
328
+ const changes = (await fileExists(changesJsonPath))
329
+ ? await readJsonFile(changesJsonPath)
330
+ : [];
331
+ return {
332
+ planDir,
333
+ versionJsonPath,
334
+ plan,
335
+ changes,
336
+ minBullets: Math.max(1, Array.isArray(changes) ? changes.length : 0),
337
+ };
338
+ }
@@ -0,0 +1,4 @@
1
+ import type { ReleaseApplyReport } from "./apply.types.js";
2
+ export declare function writeReleaseApplyReport(gitRoot: string, report: ReleaseApplyReport): Promise<string>;
3
+ export declare function pushReleaseRefs(gitRoot: string, remote: string, tag: string): Promise<void>;
4
+ //# sourceMappingURL=apply.reporting.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apply.reporting.d.ts","sourceRoot":"","sources":["../../../src/commands/release/apply.reporting.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAE3D,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,MAAM,CAAC,CAUjB;AAED,wBAAsB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CASjG"}
@@ -0,0 +1,24 @@
1
+ import { mkdir, writeFile } from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { execFileAsync, gitEnv } from "../shared/git.js";
4
+ export async function writeReleaseApplyReport(gitRoot, report) {
5
+ const runId = new Date().toISOString().replaceAll(":", "-").replaceAll(".", "-");
6
+ const dir = path.join(gitRoot, ".agentplane", ".release", "apply");
7
+ await mkdir(dir, { recursive: true });
8
+ const reportPath = path.join(dir, `${runId}.json`);
9
+ const latestPath = path.join(dir, "latest.json");
10
+ const text = `${JSON.stringify(report, null, 2)}\n`;
11
+ await writeFile(reportPath, text, "utf8");
12
+ await writeFile(latestPath, text, "utf8");
13
+ return reportPath;
14
+ }
15
+ export async function pushReleaseRefs(gitRoot, remote, tag) {
16
+ await execFileAsync("git", ["push", "--no-verify", remote, "HEAD"], {
17
+ cwd: gitRoot,
18
+ env: gitEnv(),
19
+ });
20
+ await execFileAsync("git", ["push", "--no-verify", remote, tag], {
21
+ cwd: gitRoot,
22
+ env: gitEnv(),
23
+ });
24
+ }
@@ -0,0 +1,46 @@
1
+ export type BumpKind = "patch" | "minor" | "major";
2
+ export type ReleaseApplyFlags = {
3
+ plan?: string;
4
+ yes: boolean;
5
+ push: boolean;
6
+ remote: string;
7
+ };
8
+ export type ReleaseApplyParsed = ReleaseApplyFlags;
9
+ export type ReleaseVersionPlan = {
10
+ prevTag: string | null;
11
+ prevVersion: string;
12
+ nextTag: string;
13
+ nextVersion: string;
14
+ bump: BumpKind;
15
+ };
16
+ export type PlanChange = {
17
+ hash: string;
18
+ authorDateIso: string;
19
+ subject: string;
20
+ };
21
+ export type ReleaseApplyReport = {
22
+ applied_at: string;
23
+ plan_dir: string;
24
+ notes_path: string;
25
+ prev_version: string;
26
+ next_version: string;
27
+ prev_tag: string | null;
28
+ next_tag: string;
29
+ bump: BumpKind;
30
+ checks: {
31
+ clean_tracked_tree: true;
32
+ tag_absent: true;
33
+ notes_validated: true;
34
+ npm_version_available_checked: boolean;
35
+ };
36
+ commit: {
37
+ hash: string;
38
+ subject: string;
39
+ } | null;
40
+ push: {
41
+ requested: boolean;
42
+ remote: string;
43
+ performed: boolean;
44
+ };
45
+ };
46
+ //# sourceMappingURL=apply.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apply.types.d.ts","sourceRoot":"","sources":["../../../src/commands/release/apply.types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AAEnD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,OAAO,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,iBAAiB,CAAC;AAEnD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,QAAQ,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE;QACN,kBAAkB,EAAE,IAAI,CAAC;QACzB,UAAU,EAAE,IAAI,CAAC;QACjB,eAAe,EAAE,IAAI,CAAC;QACtB,6BAA6B,EAAE,OAAO,CAAC;KACxC,CAAC;IACF,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACjD,IAAI,EAAE;QAAE,SAAS,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,OAAO,CAAA;KAAE,CAAC;CAClE,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,28 @@
1
+ import type { CommandHandler, CommandSpec } from "../cli/spec/spec.js";
2
+ import { type RepoCliVersionExpectation } from "../shared/repo-cli-version.js";
3
+ import { type RuntimeSourceInfo } from "../shared/runtime-source.js";
4
+ export type FrameworkDevWorkflow = {
5
+ available: boolean;
6
+ rebuildCommands: string[];
7
+ reinstallScript: string;
8
+ verifyCommand: string;
9
+ forceGlobalExample: string;
10
+ recommendation: string | null;
11
+ };
12
+ export type RuntimeExplainPayload = RuntimeSourceInfo & {
13
+ frameworkDev: FrameworkDevWorkflow;
14
+ repoCliExpectation: RepoCliVersionExpectation;
15
+ };
16
+ export type RuntimeGroupParsed = {
17
+ cmd: string[];
18
+ };
19
+ export type RuntimeExplainParsed = {
20
+ json: boolean;
21
+ };
22
+ export declare const runtimeSpec: CommandSpec<RuntimeGroupParsed>;
23
+ export declare const runtimeExplainSpec: CommandSpec<RuntimeExplainParsed>;
24
+ export declare function buildFrameworkDevWorkflow(report: RuntimeSourceInfo): FrameworkDevWorkflow;
25
+ export declare function renderRuntimeExplainText(report: RuntimeSourceInfo, repoCliExpectation: RepoCliVersionExpectation): string;
26
+ export declare const runRuntime: CommandHandler<RuntimeGroupParsed>;
27
+ export declare const runRuntimeExplain: CommandHandler<RuntimeExplainParsed>;
28
+ //# sourceMappingURL=runtime.command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.command.d.ts","sourceRoot":"","sources":["../../src/commands/runtime.command.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAGvE,OAAO,EAEL,KAAK,yBAAyB,EAC/B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAGL,KAAK,iBAAiB,EACvB,MAAM,6BAA6B,CAAC;AAErC,MAAM,MAAM,oBAAoB,GAAG;IACjC,SAAS,EAAE,OAAO,CAAC;IACnB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG,iBAAiB,GAAG;IACtD,YAAY,EAAE,oBAAoB,CAAC;IACnC,kBAAkB,EAAE,yBAAyB,CAAC;CAC/C,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAAE,GAAG,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AACnD,MAAM,MAAM,oBAAoB,GAAG;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AAErD,eAAO,MAAM,WAAW,EAAE,WAAW,CAAC,kBAAkB,CAQvD,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,WAAW,CAAC,oBAAoB,CAoBhE,CAAC;AAMF,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,iBAAiB,GAAG,oBAAoB,CAsCzF;AAgBD,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,iBAAiB,EACzB,kBAAkB,EAAE,yBAAyB,GAC5C,MAAM,CA2CR;AAyBD,eAAO,MAAM,UAAU,EAAE,cAAc,CAAC,kBAAkB,CAazD,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,cAAc,CAAC,oBAAoB,CAkBlE,CAAC"}