@aperant/framework 0.13.0 → 0.15.0

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 (241) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/README.md +1 -1
  3. package/agents/apt-pr-review-i18n.md +190 -0
  4. package/agents/apt-pr-review-xplatform.md +189 -0
  5. package/dist/cli/commands/audit-branch-current.d.mts +27 -5
  6. package/dist/cli/commands/audit-branch-current.d.mts.map +1 -1
  7. package/dist/cli/commands/audit-branch-current.mjs +3 -3
  8. package/dist/cli/commands/audit-branch-current.mjs.map +1 -1
  9. package/dist/cli/commands/event.d.mts.map +1 -1
  10. package/dist/cli/commands/event.mjs +6 -4
  11. package/dist/cli/commands/event.mjs.map +1 -1
  12. package/dist/cli/commands/fan-out.d.mts.map +1 -1
  13. package/dist/cli/commands/fan-out.mjs +3 -1
  14. package/dist/cli/commands/fan-out.mjs.map +1 -1
  15. package/dist/cli/commands/features-audit.d.mts.map +1 -1
  16. package/dist/cli/commands/features-audit.mjs +6 -1
  17. package/dist/cli/commands/features-audit.mjs.map +1 -1
  18. package/dist/cli/commands/followups.d.mts +5 -0
  19. package/dist/cli/commands/followups.d.mts.map +1 -0
  20. package/dist/cli/commands/followups.mjs +266 -0
  21. package/dist/cli/commands/followups.mjs.map +1 -0
  22. package/dist/cli/commands/health-check.d.mts.map +1 -1
  23. package/dist/cli/commands/health-check.mjs +3 -1
  24. package/dist/cli/commands/health-check.mjs.map +1 -1
  25. package/dist/cli/commands/merge-detect.d.mts +29 -0
  26. package/dist/cli/commands/merge-detect.d.mts.map +1 -0
  27. package/dist/cli/commands/merge-detect.mjs +196 -0
  28. package/dist/cli/commands/merge-detect.mjs.map +1 -0
  29. package/dist/cli/commands/merge-integrate.d.mts +28 -0
  30. package/dist/cli/commands/merge-integrate.d.mts.map +1 -0
  31. package/dist/cli/commands/merge-integrate.mjs +383 -0
  32. package/dist/cli/commands/merge-integrate.mjs.map +1 -0
  33. package/dist/cli/commands/pr-review/detect-specialists.d.mts +58 -0
  34. package/dist/cli/commands/pr-review/detect-specialists.d.mts.map +1 -0
  35. package/dist/cli/commands/pr-review/detect-specialists.mjs +980 -0
  36. package/dist/cli/commands/pr-review/detect-specialists.mjs.map +1 -0
  37. package/dist/cli/commands/pr-review.d.mts.map +1 -1
  38. package/dist/cli/commands/pr-review.mjs +11 -2
  39. package/dist/cli/commands/pr-review.mjs.map +1 -1
  40. package/dist/cli/commands/precompact-hook.d.mts.map +1 -1
  41. package/dist/cli/commands/precompact-hook.mjs +10 -6
  42. package/dist/cli/commands/precompact-hook.mjs.map +1 -1
  43. package/dist/cli/commands/roadmap.d.mts.map +1 -1
  44. package/dist/cli/commands/roadmap.mjs +24 -11
  45. package/dist/cli/commands/roadmap.mjs.map +1 -1
  46. package/dist/cli/commands/seed.d.mts.map +1 -1
  47. package/dist/cli/commands/seed.mjs +3 -1
  48. package/dist/cli/commands/seed.mjs.map +1 -1
  49. package/dist/cli/commands/state.d.mts.map +1 -1
  50. package/dist/cli/commands/state.mjs +9 -3
  51. package/dist/cli/commands/state.mjs.map +1 -1
  52. package/dist/cli/commands/statusline.d.mts.map +1 -1
  53. package/dist/cli/commands/statusline.mjs +5 -1
  54. package/dist/cli/commands/statusline.mjs.map +1 -1
  55. package/dist/cli/commands/task.d.mts.map +1 -1
  56. package/dist/cli/commands/task.mjs +126 -23
  57. package/dist/cli/commands/task.mjs.map +1 -1
  58. package/dist/cli/commands/worktree.d.mts +1 -1
  59. package/dist/cli/commands/worktree.d.mts.map +1 -1
  60. package/dist/cli/commands/worktree.mjs +282 -83
  61. package/dist/cli/commands/worktree.mjs.map +1 -1
  62. package/dist/cli/config/post-merge-sweep.d.mts.map +1 -1
  63. package/dist/cli/config/post-merge-sweep.mjs +3 -2
  64. package/dist/cli/config/post-merge-sweep.mjs.map +1 -1
  65. package/dist/cli/config/share-policy.d.mts +3 -1
  66. package/dist/cli/config/share-policy.d.mts.map +1 -1
  67. package/dist/cli/config/share-policy.mjs +16 -3
  68. package/dist/cli/config/share-policy.mjs.map +1 -1
  69. package/dist/cli/config/upgrade-gitignore.d.mts.map +1 -1
  70. package/dist/cli/config/upgrade-gitignore.mjs +27 -5
  71. package/dist/cli/config/upgrade-gitignore.mjs.map +1 -1
  72. package/dist/cli/consistency/parse-qa.mjs +12 -1
  73. package/dist/cli/consistency/parse-qa.mjs.map +1 -1
  74. package/dist/cli/consistency/parse-review.d.mts +23 -0
  75. package/dist/cli/consistency/parse-review.d.mts.map +1 -1
  76. package/dist/cli/consistency/parse-review.mjs +36 -0
  77. package/dist/cli/consistency/parse-review.mjs.map +1 -1
  78. package/dist/cli/consistency/parse-spec.d.mts +16 -0
  79. package/dist/cli/consistency/parse-spec.d.mts.map +1 -1
  80. package/dist/cli/consistency/parse-spec.mjs +44 -0
  81. package/dist/cli/consistency/parse-spec.mjs.map +1 -1
  82. package/dist/cli/coordination/agent-identity.d.mts +5 -2
  83. package/dist/cli/coordination/agent-identity.d.mts.map +1 -1
  84. package/dist/cli/coordination/agent-identity.mjs +6 -4
  85. package/dist/cli/coordination/agent-identity.mjs.map +1 -1
  86. package/dist/cli/coordination/store.d.mts +1 -1
  87. package/dist/cli/dispatch.d.mts.map +1 -1
  88. package/dist/cli/dispatch.mjs +4 -0
  89. package/dist/cli/dispatch.mjs.map +1 -1
  90. package/dist/cli/followups/derive.d.mts +63 -0
  91. package/dist/cli/followups/derive.d.mts.map +1 -0
  92. package/dist/cli/followups/derive.mjs +115 -0
  93. package/dist/cli/followups/derive.mjs.map +1 -0
  94. package/dist/cli/followups/schema.d.mts +165 -0
  95. package/dist/cli/followups/schema.d.mts.map +1 -0
  96. package/dist/cli/followups/schema.mjs +251 -0
  97. package/dist/cli/followups/schema.mjs.map +1 -0
  98. package/dist/cli/gate/context.d.mts +1 -1
  99. package/dist/cli/gate/gates/followups-adjudicated.d.mts +69 -0
  100. package/dist/cli/gate/gates/followups-adjudicated.d.mts.map +1 -0
  101. package/dist/cli/gate/gates/followups-adjudicated.mjs +141 -0
  102. package/dist/cli/gate/gates/followups-adjudicated.mjs.map +1 -0
  103. package/dist/cli/gate/gates/index.mjs +1 -0
  104. package/dist/cli/gate/gates/index.mjs.map +1 -1
  105. package/dist/cli/git/materialize-env.d.mts +39 -0
  106. package/dist/cli/git/materialize-env.d.mts.map +1 -0
  107. package/dist/cli/git/materialize-env.mjs +217 -0
  108. package/dist/cli/git/materialize-env.mjs.map +1 -0
  109. package/dist/cli/help.d.mts.map +1 -1
  110. package/dist/cli/help.mjs +9 -1
  111. package/dist/cli/help.mjs.map +1 -1
  112. package/dist/cli/install/legacy-paths.d.mts.map +1 -1
  113. package/dist/cli/install/legacy-paths.mjs +4 -0
  114. package/dist/cli/install/legacy-paths.mjs.map +1 -1
  115. package/dist/cli/roadmap/lifecycle.d.mts.map +1 -1
  116. package/dist/cli/roadmap/lifecycle.mjs +4 -1
  117. package/dist/cli/roadmap/lifecycle.mjs.map +1 -1
  118. package/dist/cli/task/ids.d.mts +9 -0
  119. package/dist/cli/task/ids.d.mts.map +1 -1
  120. package/dist/cli/task/ids.mjs +9 -0
  121. package/dist/cli/task/ids.mjs.map +1 -1
  122. package/dist/cli/task/index-md.d.mts +5 -0
  123. package/dist/cli/task/index-md.d.mts.map +1 -1
  124. package/dist/cli/task/index-md.mjs +12 -4
  125. package/dist/cli/task/index-md.mjs.map +1 -1
  126. package/dist/cli/util/io.d.mts +6 -0
  127. package/dist/cli/util/io.d.mts.map +1 -1
  128. package/dist/cli/util/io.mjs +16 -1
  129. package/dist/cli/util/io.mjs.map +1 -1
  130. package/dist/cli/util/project.d.mts +7 -2
  131. package/dist/cli/util/project.d.mts.map +1 -1
  132. package/dist/cli/util/project.mjs +11 -14
  133. package/dist/cli/util/project.mjs.map +1 -1
  134. package/dist/cli/util/state-paths.d.mts +19 -0
  135. package/dist/cli/util/state-paths.d.mts.map +1 -0
  136. package/dist/cli/util/state-paths.mjs +45 -0
  137. package/dist/cli/util/state-paths.mjs.map +1 -0
  138. package/dist/plugin/.claude-plugin/plugin.json +4 -1
  139. package/dist/plugin/agents/apt-pr-review-i18n.md +190 -0
  140. package/dist/plugin/agents/apt-pr-review-xplatform.md +189 -0
  141. package/dist/plugin/skills/apt/SKILL.md +9 -3
  142. package/dist/plugin/skills/apt-close-task/SKILL.md +48 -0
  143. package/dist/plugin/skills/apt-debug/SKILL.md +19 -9
  144. package/dist/plugin/skills/apt-execute/SKILL.md +3 -1
  145. package/dist/plugin/skills/apt-fan-out/SKILL.md +65 -1
  146. package/dist/plugin/skills/apt-merge-conflict-resolution/SKILL.md +227 -0
  147. package/dist/plugin/skills/apt-pr-review/SCHEMA.md +4 -2
  148. package/dist/plugin/skills/apt-pr-review/SKILL.md +117 -29
  149. package/dist/plugin/skills/apt-quick/SKILL.md +24 -1
  150. package/dist/plugin/skills/apt-review/SKILL.md +6 -0
  151. package/dist/plugin/skills/apt-run/SKILL.md +1 -1
  152. package/dist/plugin/skills/apt-setup/SKILL.md +21 -3
  153. package/dist/plugin/skills/apt-ship/SKILL.md +32 -11
  154. package/dist/plugin/skills/apt-terminal/SKILL.md +8 -0
  155. package/dist/plugin/skills/apt-triage/SKILL.md +4 -0
  156. package/dist/plugin/skills/apt-verify/SKILL.md +24 -0
  157. package/dist/plugin/skills/apt-watch-ci/SKILL.md +3 -1
  158. package/dist/types/config.d.ts +33 -0
  159. package/dist/types/config.d.ts.map +1 -1
  160. package/package.json +1 -1
  161. package/prompts/conductor-framework-context.md +1 -1
  162. package/prompts/github/pr_i18n_agent.md +279 -0
  163. package/prompts/github/pr_xplatform_agent.md +283 -0
  164. package/prompts/inbox-clarification.md +18 -11
  165. package/skills/apt/SKILL.md +9 -3
  166. package/skills/apt-close-task/SKILL.md +48 -0
  167. package/skills/apt-debug/SKILL.md +19 -9
  168. package/skills/apt-execute/SKILL.md +3 -1
  169. package/skills/apt-fan-out/SKILL.md +65 -1
  170. package/skills/apt-merge-conflict-resolution/SKILL.md +227 -0
  171. package/skills/apt-pr-review/SCHEMA.md +4 -2
  172. package/skills/apt-pr-review/SKILL.md +117 -29
  173. package/skills/apt-quick/SKILL.md +24 -1
  174. package/skills/apt-review/SKILL.md +6 -0
  175. package/skills/apt-run/SKILL.md +1 -1
  176. package/skills/apt-setup/SKILL.md +21 -3
  177. package/skills/apt-ship/SKILL.md +32 -11
  178. package/skills/apt-terminal/SKILL.md +8 -0
  179. package/skills/apt-triage/SKILL.md +4 -0
  180. package/skills/apt-verify/SKILL.md +24 -0
  181. package/skills/apt-watch-ci/SKILL.md +3 -1
  182. package/src/cli/commands/audit-branch-current.mjs +3 -3
  183. package/src/cli/commands/event.mjs +6 -4
  184. package/src/cli/commands/fan-out.mjs +3 -1
  185. package/src/cli/commands/features-audit.mjs +6 -1
  186. package/src/cli/commands/followups.mjs +303 -0
  187. package/src/cli/commands/health-check.mjs +3 -1
  188. package/src/cli/commands/merge-detect.mjs +203 -0
  189. package/src/cli/commands/merge-integrate.mjs +392 -0
  190. package/src/cli/commands/pr-review/__fixtures__/android-strings/app/src/main/res/values-fr/strings.xml +3 -0
  191. package/src/cli/commands/pr-review/__fixtures__/babel-js/package.json +4 -0
  192. package/src/cli/commands/pr-review/__fixtures__/c-ifdef/src/main.c +4 -0
  193. package/src/cli/commands/pr-review/__fixtures__/ci-matrix/.github/workflows/ci.yml +10 -0
  194. package/src/cli/commands/pr-review/__fixtures__/cmake-win/CMakeLists.txt +5 -0
  195. package/src/cli/commands/pr-review/__fixtures__/diffs/add-arb.patch +9 -0
  196. package/src/cli/commands/pr-review/__fixtures__/diffs/ci-single-os-dep.patch +13 -0
  197. package/src/cli/commands/pr-review/__fixtures__/diffs/ci-single-os-list-item-dep.patch +17 -0
  198. package/src/cli/commands/pr-review/__fixtures__/diffs/lone-weak-t.patch +8 -0
  199. package/src/cli/commands/pr-review/__fixtures__/diffs/monorepo-b.patch +7 -0
  200. package/src/cli/commands/pr-review/__fixtures__/diffs/two-weak-xpl.patch +12 -0
  201. package/src/cli/commands/pr-review/__fixtures__/dropped-underscore/src/app.js +2 -0
  202. package/src/cli/commands/pr-review/__fixtures__/electron-app/package.json +4 -0
  203. package/src/cli/commands/pr-review/__fixtures__/i18n-locale-file/src/locales/fr.json +1 -0
  204. package/src/cli/commands/pr-review/__fixtures__/monorepo/packages/a/locales/fr.json +1 -0
  205. package/src/cli/commands/pr-review/__fixtures__/monorepo/packages/b/src/index.ts +1 -0
  206. package/src/cli/commands/pr-review/__fixtures__/py-babel/pyproject.toml +3 -0
  207. package/src/cli/commands/pr-review/__fixtures__/qt-i18n-dir/i18n/app_fr.ts +11 -0
  208. package/src/cli/commands/pr-review/__fixtures__/rust-cli/Cargo.toml +7 -0
  209. package/src/cli/commands/pr-review/__fixtures__/rust-cli/src/main.rs +1 -0
  210. package/src/cli/commands/pr-review/__fixtures__/ts-dir/ts/foo.ts +3 -0
  211. package/src/cli/commands/pr-review/detect-specialists.mjs +1023 -0
  212. package/src/cli/commands/pr-review.mjs +12 -2
  213. package/src/cli/commands/precompact-hook.mjs +10 -6
  214. package/src/cli/commands/roadmap.mjs +24 -11
  215. package/src/cli/commands/seed.mjs +3 -1
  216. package/src/cli/commands/state.mjs +9 -3
  217. package/src/cli/commands/statusline.mjs +5 -1
  218. package/src/cli/commands/task.mjs +135 -23
  219. package/src/cli/commands/worktree.mjs +298 -81
  220. package/src/cli/config/post-merge-sweep.mjs +3 -2
  221. package/src/cli/config/share-policy.mjs +16 -3
  222. package/src/cli/config/upgrade-gitignore.mjs +27 -5
  223. package/src/cli/consistency/parse-qa.mjs +11 -1
  224. package/src/cli/consistency/parse-review.mjs +36 -0
  225. package/src/cli/consistency/parse-spec.mjs +43 -0
  226. package/src/cli/coordination/agent-identity.mjs +6 -4
  227. package/src/cli/dispatch.mjs +4 -0
  228. package/src/cli/followups/derive.mjs +123 -0
  229. package/src/cli/followups/schema.mjs +264 -0
  230. package/src/cli/gate/gates/followups-adjudicated.mjs +158 -0
  231. package/src/cli/gate/gates/index.mjs +1 -0
  232. package/src/cli/git/materialize-env.mjs +212 -0
  233. package/src/cli/help.mjs +9 -1
  234. package/src/cli/install/legacy-paths.mjs +4 -0
  235. package/src/cli/roadmap/lifecycle.mjs +4 -1
  236. package/src/cli/task/ids.mjs +9 -0
  237. package/src/cli/task/index-md.mjs +12 -4
  238. package/src/cli/util/io.mjs +15 -1
  239. package/src/cli/util/project.mjs +11 -14
  240. package/src/cli/util/state-paths.mjs +45 -0
  241. package/prompts/followup_planner.md +0 -399
@@ -0,0 +1,196 @@
1
+ /**
2
+ * commands/merge-detect.mjs — conflict envelope + on-disk marker reader for
3
+ * apt:merge-conflict-resolution.
4
+ *
5
+ * Two read-only subcommands, both pure git inspection — NO history rewrite,
6
+ * NO `git merge`, NO `git rebase`, NO index mutation. The SKILL.md prose owns
7
+ * every state change; this primitive only OBSERVES.
8
+ *
9
+ * apt-tools merge detect <project-dir> [--base <ref>] [--head <ref>]
10
+ * Trial-merge probe via `git merge-tree --write-tree --no-messages`.
11
+ * Reuses the EXACT detection from audit-branch-current.mjs (`gitTry`,
12
+ * `parseConflictPaths`, `isGitVersionTooOld`) — no reinvented detection.
13
+ * --base defaults to `origin/main`; --head defaults to `HEAD`. Returns
14
+ * { mergeable, conflicts_preview?, audit_warning? }. `mergeable: null`
15
+ * on an unprobeable git (too old / invocation error) so the caller can
16
+ * fall back gracefully rather than asserting clean.
17
+ *
18
+ * apt-tools merge markers <project-dir>
19
+ * Lists files that carry on-disk conflict markers (the state AFTER a
20
+ * real `git merge`/`git rebase` left the worktree conflicted) and reads
21
+ * each file's full content so the executing agent can resolve the
22
+ * markers inline. Source of truth for "is the merge conflicted" is
23
+ * `git diff --name-only --diff-filter=U` (unmerged paths). Returns
24
+ * { conflicted, files: [{ path, content }] }. Empty `conflicted` means
25
+ * a clean tree — nothing to resolve.
26
+ *
27
+ * Why agent-inline (not a programmatic resolver): the framework CLI is
28
+ * self-contained ESM and MUST NOT import @aperant/core (it declares no such
29
+ * dep — see runtime-capabilities.mjs:5). The LLM driving the CLI reads the
30
+ * markers this command surfaces and resolves them, then re-probes via
31
+ * `detect`. See GitHub issue #390 for the architecture decision.
32
+ *
33
+ * @internal
34
+ */
35
+ import { readFileSync } from 'node:fs';
36
+ import { join, resolve } from 'node:path';
37
+ import { err, ok } from '../util/result.mjs';
38
+ import { gitTry, isGitVersionTooOld, parseConflictPaths } from './audit-branch-current.mjs';
39
+ import { mergeIntegrate } from './merge-integrate.mjs';
40
+ /**
41
+ * Parse `--<name> <value>` (or `--<name>=<value>`) from extraArgs.
42
+ *
43
+ * @param {string[]} extraArgs
44
+ * @param {string} name
45
+ * @param {string} fallback
46
+ * @returns {string}
47
+ */
48
+ function parseFlag(extraArgs, name, fallback) {
49
+ const long = `--${name}`;
50
+ const eq = `--${name}=`;
51
+ for (let i = 0; i < extraArgs.length; i++) {
52
+ const a = extraArgs[i];
53
+ if (a === long && i + 1 < extraArgs.length)
54
+ return extraArgs[i + 1];
55
+ if (a.startsWith(eq))
56
+ return a.slice(eq.length);
57
+ }
58
+ return fallback;
59
+ }
60
+ /**
61
+ * `apt-tools merge detect` — trial-merge mergeability probe.
62
+ *
63
+ * @param {string} targetDir
64
+ * @param {string[]} extraArgs
65
+ * @returns {import('../util/result.mjs').CommandResult}
66
+ */
67
+ function mergeDetect(targetDir, extraArgs) {
68
+ const base = parseFlag(extraArgs, 'base', 'origin/main');
69
+ const head = parseFlag(extraArgs, 'head', 'HEAD');
70
+ const probe = gitTry(targetDir, ['merge-tree', '--write-tree', '--no-messages', head, base]);
71
+ /** @type {boolean | null} */
72
+ let mergeable;
73
+ /** @type {string[] | undefined} */
74
+ let conflictsPreview;
75
+ /** @type {string | undefined} */
76
+ let auditWarning;
77
+ if (probe.ok) {
78
+ // Documented merge-tree exit-code semantics: 0 = clean.
79
+ mergeable = true;
80
+ }
81
+ else if (probe.code === 1 && probe.stdout.trim().length > 0) {
82
+ // 1 = conflict, BUT only when stdout carried the conflict report
83
+ // (the tree-OID line + per-stage paths). A bad ref also exits 1 with
84
+ // EMPTY stdout and the error on stderr (e.g. "<ref> - not something we
85
+ // can merge") — that is a probe failure, not a clean-merge conflict, so
86
+ // we fall through to the merge-tree-probe-failed branch below.
87
+ mergeable = false;
88
+ conflictsPreview = parseConflictPaths(probe.stdout);
89
+ }
90
+ else if (isGitVersionTooOld(probe.stderr)) {
91
+ mergeable = null;
92
+ auditWarning = 'git-version-too-old';
93
+ }
94
+ else {
95
+ // Other = invocation error (bad ref, not a repo, etc.).
96
+ mergeable = null;
97
+ auditWarning = 'merge-tree-probe-failed';
98
+ }
99
+ const envelope = {
100
+ status: 'ok',
101
+ command: 'merge-detect',
102
+ projectDir: targetDir,
103
+ base,
104
+ head,
105
+ mergeable,
106
+ };
107
+ if (conflictsPreview && conflictsPreview.length > 0) {
108
+ envelope.conflicts_preview = conflictsPreview;
109
+ }
110
+ if (auditWarning) {
111
+ envelope.audit_warning = auditWarning;
112
+ if (probe.stderr.trim()) {
113
+ envelope.warnings = [probe.stderr.trim().slice(0, 200)];
114
+ }
115
+ }
116
+ return ok(envelope);
117
+ }
118
+ /**
119
+ * `apt-tools merge markers` — read on-disk conflict markers from the unmerged
120
+ * worktree so the agent can resolve them inline.
121
+ *
122
+ * @param {string} targetDir
123
+ * @returns {import('../util/result.mjs').CommandResult}
124
+ */
125
+ function mergeMarkers(targetDir) {
126
+ // Unmerged paths (stage > 0) are the authoritative "conflicted file" set.
127
+ const unmerged = gitTry(targetDir, ['diff', '--name-only', '--diff-filter=U']);
128
+ if (!unmerged.ok) {
129
+ return ok({
130
+ status: 'ok',
131
+ command: 'merge-markers',
132
+ projectDir: targetDir,
133
+ conflicted: [],
134
+ files: [],
135
+ warnings: [`git diff failed: ${unmerged.stderr.trim().slice(0, 200) || 'unknown error'}`],
136
+ });
137
+ }
138
+ const conflicted = unmerged.stdout
139
+ .split('\n')
140
+ .map((l) => l.trim())
141
+ .filter((l) => l.length > 0);
142
+ const files = [];
143
+ const warnings = [];
144
+ for (const path of conflicted) {
145
+ try {
146
+ const content = readFileSync(join(targetDir, path), 'utf-8');
147
+ files.push({ path, content });
148
+ }
149
+ catch (e) {
150
+ warnings.push(`could not read ${path}: ${e?.message ?? String(e)}`);
151
+ }
152
+ }
153
+ const envelope = {
154
+ status: 'ok',
155
+ command: 'merge-markers',
156
+ projectDir: targetDir,
157
+ conflicted,
158
+ files,
159
+ };
160
+ if (warnings.length > 0)
161
+ envelope.warnings = warnings;
162
+ return ok(envelope);
163
+ }
164
+ /**
165
+ * Dispatch an `apt-tools merge <subcommand>` call.
166
+ *
167
+ * @param {string} subcommand
168
+ * @param {string} projectDir
169
+ * @param {string[]} [extraArgs]
170
+ * @returns {import('../util/result.mjs').CommandResult}
171
+ *
172
+ * @internal
173
+ */
174
+ export function cmdMerge(subcommand, projectDir, extraArgs = []) {
175
+ if (!subcommand) {
176
+ return err('Usage: apt-tools merge <detect|markers|integrate> <project-dir> [flags]');
177
+ }
178
+ if (!projectDir) {
179
+ return err(`Usage: apt-tools merge ${subcommand} <project-dir> [flags]`);
180
+ }
181
+ const targetDir = resolve(projectDir);
182
+ switch (subcommand) {
183
+ case 'detect':
184
+ return mergeDetect(targetDir, extraArgs);
185
+ case 'markers':
186
+ return mergeMarkers(targetDir);
187
+ case 'integrate':
188
+ return mergeIntegrate(targetDir, extraArgs);
189
+ default:
190
+ return err(`Unknown merge subcommand: ${subcommand}. Expected 'detect', 'markers', or 'integrate'.`);
191
+ }
192
+ }
193
+ // Test-only exports for unit-level coverage (not part of the public CLI
194
+ // contract).
195
+ export { mergeDetect as __mergeDetectForTests, mergeMarkers as __mergeMarkersForTests };
196
+ //# sourceMappingURL=merge-detect.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge-detect.mjs","sourceRoot":"","sources":["../../../src/cli/commands/merge-detect.mjs"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * `apt-tools merge integrate` — serialize a fan-out batch into base.
3
+ *
4
+ * @param {string} targetDir
5
+ * @param {string[]} extraArgs
6
+ * @returns {import('../util/result.mjs').CommandResult}
7
+ */
8
+ export function mergeIntegrate(targetDir: string, extraArgs: string[]): import("../util/result.mjs").CommandResult;
9
+ export { orderTasks as __orderTasksForTests };
10
+ /**
11
+ * Order the batch's task ids. Topological (Kahn) over the batch SUBSET when any
12
+ * member has a `depends_on` edge to another member, else a stable alphabetical
13
+ * sort by task id (deterministic). A dependency cycle (or any unresolvable
14
+ * ordering) falls back to the stable order with a warning rather than throwing.
15
+ *
16
+ * Reuses `buildDependsOnMap` so the edge normalization matches the rest of the
17
+ * framework's graph handling exactly.
18
+ *
19
+ * @param {string[]} taskIds
20
+ * @param {object | null} state
21
+ * @returns {{ order: string[], strategy: 'topological' | 'stable', warnings: string[] }}
22
+ */
23
+ declare function orderTasks(taskIds: string[], state: object | null): {
24
+ order: string[];
25
+ strategy: "topological" | "stable";
26
+ warnings: string[];
27
+ };
28
+ //# sourceMappingURL=merge-integrate.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge-integrate.d.mts","sourceRoot":"","sources":["../../../src/cli/commands/merge-integrate.mjs"],"names":[],"mappings":"AAqOA;;;;;;GAMG;AACH,0CAJW,MAAM,aACN,MAAM,EAAE,GACN,OAAO,oBAAoB,EAAE,aAAa,CA0JtD;;AAzQD;;;;;;;;;;;;GAYG;AACH,qCAJW,MAAM,EAAE,SACR,MAAM,GAAG,IAAI,GACX;IAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,aAAa,GAAG,QAAQ,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CAuEvF"}
@@ -0,0 +1,383 @@
1
+ /**
2
+ * commands/merge-integrate.mjs — `apt-tools merge integrate` (GitHub issue #397).
3
+ *
4
+ * The fan-out PR-integration phase. After a fan-out run, N workers each opened
5
+ * an independent PR against the same base; nothing ordered or reconciled them.
6
+ * This command SERIALIZES that batch: it resolves the task → branch/PR set,
7
+ * computes a deterministic merge order (topological when `depends_on` edges
8
+ * exist, else stable by task id), and probes each branch's mergeability against
9
+ * the CURRENT base via the EXACT same `git merge-tree` detection the `detect`
10
+ * subcommand uses (#395). It emits a structured integration report the
11
+ * conductor renders and the `apt:merge-conflict-resolution` flow consumes for
12
+ * any conflicted branch.
13
+ *
14
+ * READ-ONLY, like `detect`/`markers`: NO `git merge`, NO `git rebase`, NO index
15
+ * mutation, NO `gh pr merge`. The SKILL.md prose owns every state change; this
16
+ * primitive only OBSERVES and ORDERS. Conflict resolution stays agent-inline —
17
+ * the framework CLI is self-contained ESM and MUST NOT import @aperant/core
18
+ * (see GitHub issue #390 for the architecture decision). When a branch probes
19
+ * `mergeable: false`, this command surfaces the conflict envelope (the worker's
20
+ * worktree + base ref + conflicts_preview) and the agent resolves it inline via
21
+ * `/apt:merge-conflict-resolution`, then re-runs `integrate` to re-probe.
22
+ *
23
+ * Reuse, not reinvent (#397):
24
+ * - detection → `gitTry` / `parseConflictPaths` / `isGitVersionTooOld`
25
+ * promoted in audit-branch-current.mjs (#395).
26
+ * - batch resolution → the same `--tasks`/`--batch` shape fan-out.mjs uses;
27
+ * task records read from the shared `.aperant/state.json`
28
+ * board (resolveMainRepoRoot — state-fork-fix).
29
+ * - dependency graph → `buildDependsOnMap` (graph/depends-on.mjs), which
30
+ * already normalizes `depends_on` edges to bare ids.
31
+ *
32
+ * apt-tools merge integrate <project-dir> --tasks <id,id,...> [--base <ref>]
33
+ * apt-tools merge integrate <project-dir> --batch <batch-id> [--base <ref>]
34
+ *
35
+ * --tasks Explicit canonical task-id list (what `fan-out resolve` returns and
36
+ * the conductor already holds). Primary form.
37
+ * --batch Recover the task-id list from the batch's worker rows
38
+ * `.aperant/team-status/fanout-<batch>-<task>.json` (the agent-id
39
+ * format fan-out.mjs spawns workers with: `fanout-${batch}-${task}`).
40
+ * --base Override the base ref every branch is probed against. When omitted,
41
+ * each task is probed against `origin/<its base_branch>` (falling back
42
+ * to `origin/main` when the record carries no base_branch).
43
+ *
44
+ * @internal
45
+ */
46
+ import { existsSync, readdirSync, readFileSync } from 'node:fs';
47
+ import { join, resolve } from 'node:path';
48
+ import { buildDependsOnMap } from '../graph/depends-on.mjs';
49
+ import { parseFlags } from '../util/args.mjs';
50
+ import { err, ok } from '../util/result.mjs';
51
+ import { resolveMainRepoRoot } from '../util/state-paths.mjs';
52
+ import { gitTry, isGitVersionTooOld, parseConflictPaths } from './audit-branch-current.mjs';
53
+ /**
54
+ * Parse a PR number from a `pr_url` string (full GitHub URL or `#123` short
55
+ * form). Returns null if not parseable. Incidental metadata for the report —
56
+ * the integration order/probe never depends on it.
57
+ *
58
+ * @param {unknown} url
59
+ * @returns {number | null}
60
+ */
61
+ function extractPrNumber(url) {
62
+ if (typeof url !== 'string')
63
+ return null;
64
+ const m1 = url.match(/\/pull\/(\d+)(?:[?#/]|$)/);
65
+ if (m1)
66
+ return Number.parseInt(m1[1], 10);
67
+ const m2 = url.match(/#(\d+)$/);
68
+ if (m2)
69
+ return Number.parseInt(m2[1], 10);
70
+ const m3 = url.match(/^(\d+)$/);
71
+ if (m3)
72
+ return Number.parseInt(m3[1], 10);
73
+ return null;
74
+ }
75
+ /**
76
+ * Read the shared ephemeral board (`state.json`). Anchors to the MAIN repo so
77
+ * it resolves identically from any worktree (state-fork-fix), matching how
78
+ * fan-out.mjs reads it.
79
+ *
80
+ * @param {string} targetDir
81
+ * @returns {object | null}
82
+ */
83
+ function readState(targetDir) {
84
+ const statePath = join(resolveMainRepoRoot(targetDir), '.aperant', 'state.json');
85
+ if (!existsSync(statePath))
86
+ return null;
87
+ try {
88
+ return JSON.parse(readFileSync(statePath, 'utf-8'));
89
+ }
90
+ catch {
91
+ return null;
92
+ }
93
+ }
94
+ /**
95
+ * Recover a batch's task-id list from its worker rows. Fan-out spawns each
96
+ * worker with `APT_AGENT_ID=fanout-<batch>-<task>`, which materializes one
97
+ * `.aperant/team-status/fanout-<batch>-<task>.json` per worker. We list that
98
+ * directory and strip the shared prefix to recover the task ids.
99
+ *
100
+ * @param {string} targetDir
101
+ * @param {string} batchId
102
+ * @returns {string[]}
103
+ */
104
+ function recoverBatchTaskIds(targetDir, batchId) {
105
+ const statusDir = join(resolveMainRepoRoot(targetDir), '.aperant', 'team-status');
106
+ if (!existsSync(statusDir))
107
+ return [];
108
+ const prefix = `fanout-${batchId}-`;
109
+ const ids = [];
110
+ let entries;
111
+ try {
112
+ entries = readdirSync(statusDir);
113
+ }
114
+ catch {
115
+ return [];
116
+ }
117
+ for (const name of entries) {
118
+ if (!name.endsWith('.json'))
119
+ continue;
120
+ const base = name.slice(0, -'.json'.length);
121
+ if (base.startsWith(prefix)) {
122
+ const taskId = base.slice(prefix.length);
123
+ if (taskId)
124
+ ids.push(taskId);
125
+ }
126
+ }
127
+ return ids;
128
+ }
129
+ /**
130
+ * Order the batch's task ids. Topological (Kahn) over the batch SUBSET when any
131
+ * member has a `depends_on` edge to another member, else a stable alphabetical
132
+ * sort by task id (deterministic). A dependency cycle (or any unresolvable
133
+ * ordering) falls back to the stable order with a warning rather than throwing.
134
+ *
135
+ * Reuses `buildDependsOnMap` so the edge normalization matches the rest of the
136
+ * framework's graph handling exactly.
137
+ *
138
+ * @param {string[]} taskIds
139
+ * @param {object | null} state
140
+ * @returns {{ order: string[], strategy: 'topological' | 'stable', warnings: string[] }}
141
+ */
142
+ function orderTasks(taskIds, state) {
143
+ const stable = [...taskIds].sort();
144
+ const inBatch = new Set(taskIds);
145
+ const warnings = [];
146
+ const depMap = buildDependsOnMap(state || {});
147
+ // Restrict edges to within-batch dependencies — cross-batch deps don't gate
148
+ // the integration order (those PRs aren't part of this serialization).
149
+ const deps = new Map();
150
+ let edgeCount = 0;
151
+ for (const id of taskIds) {
152
+ // buildDependsOnMap already normalizes deps to bare task_ids, so the
153
+ // entries are consumed directly (no re-parse — a re-parse would split a
154
+ // colon-bearing id and drop the constraint). De-dupe so a task that lists
155
+ // the same dependency twice doesn't overcount its Kahn indegree (which
156
+ // would strand it below zero-indegree and mis-flag a valid graph as a
157
+ // cycle).
158
+ const within = [];
159
+ const seen = new Set();
160
+ for (const depId of depMap.get(id) || []) {
161
+ if (inBatch.has(depId) && depId !== id && !seen.has(depId)) {
162
+ seen.add(depId);
163
+ within.push(depId);
164
+ edgeCount++;
165
+ }
166
+ }
167
+ deps.set(id, within);
168
+ }
169
+ if (edgeCount === 0) {
170
+ return { order: stable, strategy: 'stable', warnings };
171
+ }
172
+ // Kahn's algorithm — a task lands AFTER its dependencies (deps merge first).
173
+ const indegree = new Map(taskIds.map((id) => [id, 0]));
174
+ for (const id of taskIds) {
175
+ for (const _dep of deps.get(id) || []) {
176
+ indegree.set(id, (indegree.get(id) || 0) + 1);
177
+ }
178
+ }
179
+ // Ready = zero remaining unmet deps. Process in stable order for determinism.
180
+ const ready = taskIds.filter((id) => (indegree.get(id) || 0) === 0).sort();
181
+ const order = [];
182
+ while (ready.length > 0) {
183
+ const id = ready.shift();
184
+ order.push(id);
185
+ // Decrement indegree of every task that depends on `id`.
186
+ const newlyReady = [];
187
+ for (const other of taskIds) {
188
+ if ((deps.get(other) || []).includes(id)) {
189
+ const d = (indegree.get(other) || 0) - 1;
190
+ indegree.set(other, d);
191
+ if (d === 0)
192
+ newlyReady.push(other);
193
+ }
194
+ }
195
+ for (const r of newlyReady)
196
+ ready.push(r);
197
+ // Re-sort the whole queue (not just the newly-ready tail) so ties across
198
+ // rounds resolve in strict alphabetical order — fully deterministic.
199
+ ready.sort();
200
+ }
201
+ if (order.length !== taskIds.length) {
202
+ // Cycle or unresolvable ordering — fall back to stable, deterministic.
203
+ warnings.push('dependency cycle detected among batch tasks — falling back to stable task-id order');
204
+ return { order: stable, strategy: 'stable', warnings };
205
+ }
206
+ return { order, strategy: 'topological', warnings };
207
+ }
208
+ /**
209
+ * Probe one task's branch against the base. Mirrors the `detect` subcommand's
210
+ * merge-tree semantics exactly (#395) — same gitTry call, same exit-code
211
+ * branching — so the integrate report and a standalone `merge detect` agree.
212
+ *
213
+ * @param {string} worktreeDir
214
+ * @param {string} base
215
+ * @param {string} head
216
+ * @returns {{ mergeable: boolean | null, conflicts_preview?: string[], audit_warning?: string }}
217
+ */
218
+ function probeBranch(worktreeDir, base, head) {
219
+ const probe = gitTry(worktreeDir, ['merge-tree', '--write-tree', '--no-messages', head, base]);
220
+ if (probe.ok)
221
+ return { mergeable: true };
222
+ if (probe.code === 1 && probe.stdout.trim().length > 0) {
223
+ return { mergeable: false, conflicts_preview: parseConflictPaths(probe.stdout) };
224
+ }
225
+ if (isGitVersionTooOld(probe.stderr)) {
226
+ return { mergeable: null, audit_warning: 'git-version-too-old' };
227
+ }
228
+ return { mergeable: null, audit_warning: 'merge-tree-probe-failed' };
229
+ }
230
+ /**
231
+ * `apt-tools merge integrate` — serialize a fan-out batch into base.
232
+ *
233
+ * @param {string} targetDir
234
+ * @param {string[]} extraArgs
235
+ * @returns {import('../util/result.mjs').CommandResult}
236
+ */
237
+ export function mergeIntegrate(targetDir, extraArgs) {
238
+ const flags = parseFlags(extraArgs);
239
+ const hasTasks = flags.has('tasks');
240
+ const hasBatch = flags.has('batch');
241
+ if (!hasTasks && !hasBatch) {
242
+ return err('One of --tasks <id,id,...> or --batch <batch-id> is required for merge integrate');
243
+ }
244
+ if (hasTasks && hasBatch) {
245
+ return err('Pass only one of --tasks or --batch to merge integrate');
246
+ }
247
+ const state = readState(targetDir);
248
+ let taskIds = [];
249
+ let source = '';
250
+ if (hasTasks) {
251
+ taskIds = String(flags.get('tasks') || '')
252
+ .split(',')
253
+ .map((s) => s.trim())
254
+ .filter(Boolean);
255
+ source = 'tasks';
256
+ if (taskIds.length === 0) {
257
+ return err('--tasks resolved to an empty list');
258
+ }
259
+ }
260
+ else {
261
+ const batchId = String(flags.get('batch') || '').trim();
262
+ if (!batchId)
263
+ return err('--batch requires a batch id');
264
+ taskIds = recoverBatchTaskIds(targetDir, batchId);
265
+ source = 'batch';
266
+ if (taskIds.length === 0) {
267
+ return err(`No worker rows found for batch "${batchId}" — nothing to integrate`);
268
+ }
269
+ }
270
+ // parseFlags yields `true` for a bare `--base` with no following value; reject
271
+ // it rather than silently probing against the ref literal "true".
272
+ let baseOverride = null;
273
+ if (flags.has('base')) {
274
+ const raw = flags.get('base');
275
+ if (raw === true || String(raw).trim() === '') {
276
+ return err('--base requires a ref value (e.g. --base origin/main)');
277
+ }
278
+ baseOverride = String(raw).trim();
279
+ }
280
+ const { order, strategy, warnings } = orderTasks(taskIds, state);
281
+ const tasks = [];
282
+ let merged = 0;
283
+ let conflicted = 0;
284
+ let needsHuman = 0;
285
+ for (const id of order) {
286
+ const task = state?.active_tasks?.[id] || null;
287
+ // Tasks with no shipped branch can't be integrated — record them so the
288
+ // conductor sees why, but never block the rest of the batch.
289
+ if (!task) {
290
+ needsHuman++;
291
+ tasks.push({ task_id: id, status: 'unknown', reason: 'task not found in state.json' });
292
+ continue;
293
+ }
294
+ const branch = typeof task.branch === 'string' ? task.branch : null;
295
+ const prUrl = typeof task.pr_url === 'string' ? task.pr_url : null;
296
+ const worktree = typeof task.worktree_path === 'string' && existsSync(task.worktree_path)
297
+ ? resolve(task.worktree_path)
298
+ : null;
299
+ if (!prUrl) {
300
+ needsHuman++;
301
+ tasks.push({
302
+ task_id: id,
303
+ branch,
304
+ status: 'skipped',
305
+ reason: 'no pr_url on task record (not shipped) — nothing to integrate',
306
+ });
307
+ continue;
308
+ }
309
+ if (!worktree) {
310
+ needsHuman++;
311
+ tasks.push({
312
+ task_id: id,
313
+ branch,
314
+ pr_url: prUrl,
315
+ pr_number: extractPrNumber(prUrl),
316
+ status: 'needs-human',
317
+ reason: 'worktree_path missing or no longer on disk — cannot probe mergeability',
318
+ });
319
+ continue;
320
+ }
321
+ const taskBaseBranch = typeof task.base_branch === 'string' && task.base_branch ? task.base_branch : 'main';
322
+ const base = baseOverride || `origin/${taskBaseBranch}`;
323
+ const probe = probeBranch(worktree, base, 'HEAD');
324
+ const entry = {
325
+ task_id: id,
326
+ branch,
327
+ pr_url: prUrl,
328
+ pr_number: extractPrNumber(prUrl),
329
+ worktree_path: worktree,
330
+ base,
331
+ mergeable: probe.mergeable,
332
+ };
333
+ if (probe.conflicts_preview && probe.conflicts_preview.length > 0) {
334
+ entry.conflicts_preview = probe.conflicts_preview;
335
+ }
336
+ if (probe.audit_warning)
337
+ entry.audit_warning = probe.audit_warning;
338
+ if (probe.mergeable === true) {
339
+ merged++;
340
+ entry.status = 'mergeable';
341
+ entry.action = 'advance';
342
+ }
343
+ else if (probe.mergeable === false) {
344
+ conflicted++;
345
+ entry.status = 'conflicted';
346
+ // Hand-off envelope for /apt:merge-conflict-resolution — the agent
347
+ // resolves these markers inline then re-runs `integrate` to re-probe.
348
+ entry.action = 'resolve-conflict';
349
+ entry.resolution = {
350
+ skill: 'apt:merge-conflict-resolution',
351
+ worktree_path: worktree,
352
+ base,
353
+ };
354
+ }
355
+ else {
356
+ needsHuman++;
357
+ entry.status = 'needs-human';
358
+ entry.action = 'probe-failed';
359
+ }
360
+ tasks.push(entry);
361
+ }
362
+ const envelope = {
363
+ status: 'ok',
364
+ command: 'merge-integrate',
365
+ projectDir: targetDir,
366
+ source,
367
+ order_strategy: strategy,
368
+ order,
369
+ summary: {
370
+ total: tasks.length,
371
+ mergeable: merged,
372
+ conflicted,
373
+ needs_human: needsHuman,
374
+ },
375
+ tasks,
376
+ };
377
+ if (warnings.length > 0)
378
+ envelope.warnings = warnings;
379
+ return ok(envelope);
380
+ }
381
+ // Test-only export for unit-level coverage of the ordering core.
382
+ export { orderTasks as __orderTasksForTests };
383
+ //# sourceMappingURL=merge-integrate.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge-integrate.mjs","sourceRoot":"","sources":["../../../src/cli/commands/merge-integrate.mjs"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAEH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAC/D,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAA;AAC3D,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAA;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAA;AAC7D,OAAO,EAAE,MAAM,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAA;AAE3F;;;;;;;GAOG;AACH,SAAS,eAAe,CAAC,GAAG;IAC3B,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAA;IACxC,MAAM,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAA;IAChD,IAAI,EAAE;QAAE,OAAO,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IACzC,MAAM,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;IAC/B,IAAI,EAAE;QAAE,OAAO,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IACzC,MAAM,EAAE,GAAG,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;IAC/B,IAAI,EAAE;QAAE,OAAO,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;IACzC,OAAO,IAAI,CAAA;AACZ,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,SAAS,CAAC,SAAS;IAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,mBAAmB,CAAC,SAAS,CAAC,EAAE,UAAU,EAAE,YAAY,CAAC,CAAA;IAChF,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAA;IACvC,IAAI,CAAC;QACJ,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAA;IACpD,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,IAAI,CAAA;IACZ,CAAC;AACF,CAAC;AAED;;;;;;;;;GASG;AACH,SAAS,mBAAmB,CAAC,SAAS,EAAE,OAAO;IAC9C,MAAM,SAAS,GAAG,IAAI,CAAC,mBAAmB,CAAC,SAAS,CAAC,EAAE,UAAU,EAAE,aAAa,CAAC,CAAA;IACjF,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,EAAE,CAAA;IACrC,MAAM,MAAM,GAAG,UAAU,OAAO,GAAG,CAAA;IACnC,MAAM,GAAG,GAAG,EAAE,CAAA;IACd,IAAI,OAAO,CAAA;IACX,IAAI,CAAC;QACJ,OAAO,GAAG,WAAW,CAAC,SAAS,CAAC,CAAA;IACjC,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,EAAE,CAAA;IACV,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;YAAE,SAAQ;QACrC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;QAC3C,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YAC7B,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;YACxC,IAAI,MAAM;gBAAE,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAC7B,CAAC;IACF,CAAC;IACD,OAAO,GAAG,CAAA;AACX,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,SAAS,UAAU,CAAC,OAAO,EAAE,KAAK;IACjC,MAAM,MAAM,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,EAAE,CAAA;IAClC,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAA;IAChC,MAAM,QAAQ,GAAG,EAAE,CAAA;IAEnB,MAAM,MAAM,GAAG,iBAAiB,CAAC,KAAK,IAAI,EAAE,CAAC,CAAA;IAC7C,4EAA4E;IAC5E,uEAAuE;IACvE,MAAM,IAAI,GAAG,IAAI,GAAG,EAAE,CAAA;IACtB,IAAI,SAAS,GAAG,CAAC,CAAA;IACjB,KAAK,MAAM,EAAE,IAAI,OAAO,EAAE,CAAC;QAC1B,qEAAqE;QACrE,wEAAwE;QACxE,0EAA0E;QAC1E,uEAAuE;QACvE,sEAAsE;QACtE,UAAU;QACV,MAAM,MAAM,GAAG,EAAE,CAAA;QACjB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAE,CAAA;QACtB,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC;YAC1C,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,KAAK,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC5D,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;gBACf,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;gBAClB,SAAS,EAAE,CAAA;YACZ,CAAC;QACF,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,MAAM,CAAC,CAAA;IACrB,CAAC;IAED,IAAI,SAAS,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAA;IACvD,CAAC;IAED,6EAA6E;IAC7E,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;IACtD,KAAK,MAAM,EAAE,IAAI,OAAO,EAAE,CAAC;QAC1B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC;YACvC,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;QAC9C,CAAC;IACF,CAAC;IACD,8EAA8E;IAC9E,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;IAC1E,MAAM,KAAK,GAAG,EAAE,CAAA;IAChB,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,MAAM,EAAE,GAAG,KAAK,CAAC,KAAK,EAAE,CAAA;QACxB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QACd,yDAAyD;QACzD,MAAM,UAAU,GAAG,EAAE,CAAA;QACrB,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC7B,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;gBAC1C,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAA;gBACxC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAA;gBACtB,IAAI,CAAC,KAAK,CAAC;oBAAE,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YACpC,CAAC;QACF,CAAC;QACD,KAAK,MAAM,CAAC,IAAI,UAAU;YAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACzC,yEAAyE;QACzE,qEAAqE;QACrE,KAAK,CAAC,IAAI,EAAE,CAAA;IACb,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC;QACrC,uEAAuE;QACvE,QAAQ,CAAC,IAAI,CACZ,oFAAoF,CACpF,CAAA;QACD,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAA;IACvD,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAA;AACpD,CAAC;AAED;;;;;;;;;GASG;AACH,SAAS,WAAW,CAAC,WAAW,EAAE,IAAI,EAAE,IAAI;IAC3C,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAA;IAC9F,IAAI,KAAK,CAAC,EAAE;QAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,CAAA;IACxC,IAAI,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxD,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,iBAAiB,EAAE,kBAAkB,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAA;IACjF,CAAC;IACD,IAAI,kBAAkB,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;QACtC,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,aAAa,EAAE,qBAAqB,EAAE,CAAA;IACjE,CAAC;IACD,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,aAAa,EAAE,yBAAyB,EAAE,CAAA;AACrE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAC,SAAS,EAAE,SAAS;IAClD,MAAM,KAAK,GAAG,UAAU,CAAC,SAAS,CAAC,CAAA;IACnC,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IACnC,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;IAEnC,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC5B,OAAO,GAAG,CAAC,kFAAkF,CAAC,CAAA;IAC/F,CAAC;IACD,IAAI,QAAQ,IAAI,QAAQ,EAAE,CAAC;QAC1B,OAAO,GAAG,CAAC,wDAAwD,CAAC,CAAA;IACrE,CAAC;IAED,MAAM,KAAK,GAAG,SAAS,CAAC,SAAS,CAAC,CAAA;IAElC,IAAI,OAAO,GAAG,EAAE,CAAA;IAChB,IAAI,MAAM,GAAG,EAAE,CAAA;IACf,IAAI,QAAQ,EAAE,CAAC;QACd,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;aACxC,KAAK,CAAC,GAAG,CAAC;aACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;aACpB,MAAM,CAAC,OAAO,CAAC,CAAA;QACjB,MAAM,GAAG,OAAO,CAAA;QAChB,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,GAAG,CAAC,mCAAmC,CAAC,CAAA;QAChD,CAAC;IACF,CAAC;SAAM,CAAC;QACP,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;QACvD,IAAI,CAAC,OAAO;YAAE,OAAO,GAAG,CAAC,6BAA6B,CAAC,CAAA;QACvD,OAAO,GAAG,mBAAmB,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;QACjD,MAAM,GAAG,OAAO,CAAA;QAChB,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,GAAG,CAAC,mCAAmC,OAAO,0BAA0B,CAAC,CAAA;QACjF,CAAC;IACF,CAAC;IAED,+EAA+E;IAC/E,kEAAkE;IAClE,IAAI,YAAY,GAAG,IAAI,CAAA;IACvB,IAAI,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;QAC7B,IAAI,GAAG,KAAK,IAAI,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;YAC/C,OAAO,GAAG,CAAC,uDAAuD,CAAC,CAAA;QACpE,CAAC;QACD,YAAY,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAA;IAClC,CAAC;IAED,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;IAEhE,MAAM,KAAK,GAAG,EAAE,CAAA;IAChB,IAAI,MAAM,GAAG,CAAC,CAAA;IACd,IAAI,UAAU,GAAG,CAAC,CAAA;IAClB,IAAI,UAAU,GAAG,CAAC,CAAA;IAElB,KAAK,MAAM,EAAE,IAAI,KAAK,EAAE,CAAC;QACxB,MAAM,IAAI,GAAG,KAAK,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC,IAAI,IAAI,CAAA;QAE9C,wEAAwE;QACxE,6DAA6D;QAC7D,IAAI,CAAC,IAAI,EAAE,CAAC;YACX,UAAU,EAAE,CAAA;YACZ,KAAK,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,8BAA8B,EAAE,CAAC,CAAA;YACtF,SAAQ;QACT,CAAC;QACD,MAAM,MAAM,GAAG,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAA;QACnE,MAAM,KAAK,GAAG,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAA;QAClE,MAAM,QAAQ,GACb,OAAO,IAAI,CAAC,aAAa,KAAK,QAAQ,IAAI,UAAU,CAAC,IAAI,CAAC,aAAa,CAAC;YACvE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC;YAC7B,CAAC,CAAC,IAAI,CAAA;QAER,IAAI,CAAC,KAAK,EAAE,CAAC;YACZ,UAAU,EAAE,CAAA;YACZ,KAAK,CAAC,IAAI,CAAC;gBACV,OAAO,EAAE,EAAE;gBACX,MAAM;gBACN,MAAM,EAAE,SAAS;gBACjB,MAAM,EAAE,+DAA+D;aACvE,CAAC,CAAA;YACF,SAAQ;QACT,CAAC;QACD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACf,UAAU,EAAE,CAAA;YACZ,KAAK,CAAC,IAAI,CAAC;gBACV,OAAO,EAAE,EAAE;gBACX,MAAM;gBACN,MAAM,EAAE,KAAK;gBACb,SAAS,EAAE,eAAe,CAAC,KAAK,CAAC;gBACjC,MAAM,EAAE,aAAa;gBACrB,MAAM,EAAE,wEAAwE;aAChF,CAAC,CAAA;YACF,SAAQ;QACT,CAAC;QAED,MAAM,cAAc,GACnB,OAAO,IAAI,CAAC,WAAW,KAAK,QAAQ,IAAI,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAA;QACrF,MAAM,IAAI,GAAG,YAAY,IAAI,UAAU,cAAc,EAAE,CAAA;QACvD,MAAM,KAAK,GAAG,WAAW,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;QAEjD,MAAM,KAAK,GAAG;YACb,OAAO,EAAE,EAAE;YACX,MAAM;YACN,MAAM,EAAE,KAAK;YACb,SAAS,EAAE,eAAe,CAAC,KAAK,CAAC;YACjC,aAAa,EAAE,QAAQ;YACvB,IAAI;YACJ,SAAS,EAAE,KAAK,CAAC,SAAS;SAC1B,CAAA;QACD,IAAI,KAAK,CAAC,iBAAiB,IAAI,KAAK,CAAC,iBAAiB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnE,KAAK,CAAC,iBAAiB,GAAG,KAAK,CAAC,iBAAiB,CAAA;QAClD,CAAC;QACD,IAAI,KAAK,CAAC,aAAa;YAAE,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC,aAAa,CAAA;QAElE,IAAI,KAAK,CAAC,SAAS,KAAK,IAAI,EAAE,CAAC;YAC9B,MAAM,EAAE,CAAA;YACR,KAAK,CAAC,MAAM,GAAG,WAAW,CAAA;YAC1B,KAAK,CAAC,MAAM,GAAG,SAAS,CAAA;QACzB,CAAC;aAAM,IAAI,KAAK,CAAC,SAAS,KAAK,KAAK,EAAE,CAAC;YACtC,UAAU,EAAE,CAAA;YACZ,KAAK,CAAC,MAAM,GAAG,YAAY,CAAA;YAC3B,mEAAmE;YACnE,sEAAsE;YACtE,KAAK,CAAC,MAAM,GAAG,kBAAkB,CAAA;YACjC,KAAK,CAAC,UAAU,GAAG;gBAClB,KAAK,EAAE,+BAA+B;gBACtC,aAAa,EAAE,QAAQ;gBACvB,IAAI;aACJ,CAAA;QACF,CAAC;aAAM,CAAC;YACP,UAAU,EAAE,CAAA;YACZ,KAAK,CAAC,MAAM,GAAG,aAAa,CAAA;YAC5B,KAAK,CAAC,MAAM,GAAG,cAAc,CAAA;QAC9B,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAClB,CAAC;IAED,MAAM,QAAQ,GAAG;QAChB,MAAM,EAAE,IAAI;QACZ,OAAO,EAAE,iBAAiB;QAC1B,UAAU,EAAE,SAAS;QACrB,MAAM;QACN,cAAc,EAAE,QAAQ;QACxB,KAAK;QACL,OAAO,EAAE;YACR,KAAK,EAAE,KAAK,CAAC,MAAM;YACnB,SAAS,EAAE,MAAM;YACjB,UAAU;YACV,WAAW,EAAE,UAAU;SACvB;QACD,KAAK;KACL,CAAA;IACD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;QAAE,QAAQ,CAAC,QAAQ,GAAG,QAAQ,CAAA;IACrD,OAAO,EAAE,CAAC,QAAQ,CAAC,CAAA;AACpB,CAAC;AAED,iEAAiE;AACjE,OAAO,EAAE,UAAU,IAAI,oBAAoB,EAAE,CAAA"}