@groundnuty/macf 0.2.0-rc.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 (124) hide show
  1. package/dist/.build-info.json +4 -0
  2. package/dist/cli/build-info.d.ts +38 -0
  3. package/dist/cli/build-info.d.ts.map +1 -0
  4. package/dist/cli/build-info.js +119 -0
  5. package/dist/cli/build-info.js.map +1 -0
  6. package/dist/cli/claude-sh.d.ts +42 -0
  7. package/dist/cli/claude-sh.d.ts.map +1 -0
  8. package/dist/cli/claude-sh.js +247 -0
  9. package/dist/cli/claude-sh.js.map +1 -0
  10. package/dist/cli/commands/cd.d.ts +6 -0
  11. package/dist/cli/commands/cd.d.ts.map +1 -0
  12. package/dist/cli/commands/cd.js +17 -0
  13. package/dist/cli/commands/cd.js.map +1 -0
  14. package/dist/cli/commands/certs.d.ts +33 -0
  15. package/dist/cli/commands/certs.d.ts.map +1 -0
  16. package/dist/cli/commands/certs.js +233 -0
  17. package/dist/cli/commands/certs.js.map +1 -0
  18. package/dist/cli/commands/doctor.d.ts +91 -0
  19. package/dist/cli/commands/doctor.d.ts.map +1 -0
  20. package/dist/cli/commands/doctor.js +235 -0
  21. package/dist/cli/commands/doctor.js.map +1 -0
  22. package/dist/cli/commands/init.d.ts +37 -0
  23. package/dist/cli/commands/init.d.ts.map +1 -0
  24. package/dist/cli/commands/init.js +279 -0
  25. package/dist/cli/commands/init.js.map +1 -0
  26. package/dist/cli/commands/list.d.ts +5 -0
  27. package/dist/cli/commands/list.d.ts.map +1 -0
  28. package/dist/cli/commands/list.js +21 -0
  29. package/dist/cli/commands/list.js.map +1 -0
  30. package/dist/cli/commands/migrate-ca-key.d.ts +36 -0
  31. package/dist/cli/commands/migrate-ca-key.d.ts.map +1 -0
  32. package/dist/cli/commands/migrate-ca-key.js +92 -0
  33. package/dist/cli/commands/migrate-ca-key.js.map +1 -0
  34. package/dist/cli/commands/peers.d.ts +8 -0
  35. package/dist/cli/commands/peers.d.ts.map +1 -0
  36. package/dist/cli/commands/peers.js +45 -0
  37. package/dist/cli/commands/peers.js.map +1 -0
  38. package/dist/cli/commands/repo-init.d.ts +43 -0
  39. package/dist/cli/commands/repo-init.d.ts.map +1 -0
  40. package/dist/cli/commands/repo-init.js +304 -0
  41. package/dist/cli/commands/repo-init.js.map +1 -0
  42. package/dist/cli/commands/rules-refresh.d.ts +14 -0
  43. package/dist/cli/commands/rules-refresh.d.ts.map +1 -0
  44. package/dist/cli/commands/rules-refresh.js +67 -0
  45. package/dist/cli/commands/rules-refresh.js.map +1 -0
  46. package/dist/cli/commands/self-update.d.ts +14 -0
  47. package/dist/cli/commands/self-update.d.ts.map +1 -0
  48. package/dist/cli/commands/self-update.js +112 -0
  49. package/dist/cli/commands/self-update.js.map +1 -0
  50. package/dist/cli/commands/status.d.ts +9 -0
  51. package/dist/cli/commands/status.d.ts.map +1 -0
  52. package/dist/cli/commands/status.js +90 -0
  53. package/dist/cli/commands/status.js.map +1 -0
  54. package/dist/cli/commands/update.d.ts +25 -0
  55. package/dist/cli/commands/update.d.ts.map +1 -0
  56. package/dist/cli/commands/update.js +316 -0
  57. package/dist/cli/commands/update.js.map +1 -0
  58. package/dist/cli/config.d.ts +103 -0
  59. package/dist/cli/config.d.ts.map +1 -0
  60. package/dist/cli/config.js +224 -0
  61. package/dist/cli/config.js.map +1 -0
  62. package/dist/cli/index.d.ts +3 -0
  63. package/dist/cli/index.d.ts.map +1 -0
  64. package/dist/cli/index.js +245 -0
  65. package/dist/cli/index.js.map +1 -0
  66. package/dist/cli/plugin-fetcher.d.ts +20 -0
  67. package/dist/cli/plugin-fetcher.d.ts.map +1 -0
  68. package/dist/cli/plugin-fetcher.js +83 -0
  69. package/dist/cli/plugin-fetcher.js.map +1 -0
  70. package/dist/cli/prompt.d.ts +17 -0
  71. package/dist/cli/prompt.d.ts.map +1 -0
  72. package/dist/cli/prompt.js +109 -0
  73. package/dist/cli/prompt.js.map +1 -0
  74. package/dist/cli/registry-helper.d.ts +11 -0
  75. package/dist/cli/registry-helper.d.ts.map +1 -0
  76. package/dist/cli/registry-helper.js +18 -0
  77. package/dist/cli/registry-helper.js.map +1 -0
  78. package/dist/cli/rules.d.ts +39 -0
  79. package/dist/cli/rules.d.ts.map +1 -0
  80. package/dist/cli/rules.js +112 -0
  81. package/dist/cli/rules.js.map +1 -0
  82. package/dist/cli/settings-writer.d.ts +97 -0
  83. package/dist/cli/settings-writer.d.ts.map +1 -0
  84. package/dist/cli/settings-writer.js +270 -0
  85. package/dist/cli/settings-writer.js.map +1 -0
  86. package/dist/cli/version-resolver.d.ts +73 -0
  87. package/dist/cli/version-resolver.d.ts.map +1 -0
  88. package/dist/cli/version-resolver.js +238 -0
  89. package/dist/cli/version-resolver.js.map +1 -0
  90. package/dist/index.d.ts +19 -0
  91. package/dist/index.d.ts.map +1 -0
  92. package/dist/index.js +22 -0
  93. package/dist/index.js.map +1 -0
  94. package/dist/plugin/bin/macf-plugin-cli.d.ts +13 -0
  95. package/dist/plugin/bin/macf-plugin-cli.d.ts.map +1 -0
  96. package/dist/plugin/bin/macf-plugin-cli.js +127 -0
  97. package/dist/plugin/bin/macf-plugin-cli.js.map +1 -0
  98. package/dist/plugin/lib/format.d.ts +40 -0
  99. package/dist/plugin/lib/format.d.ts.map +1 -0
  100. package/dist/plugin/lib/format.js +137 -0
  101. package/dist/plugin/lib/format.js.map +1 -0
  102. package/dist/plugin/lib/health.d.ts +2 -0
  103. package/dist/plugin/lib/health.d.ts.map +1 -0
  104. package/dist/plugin/lib/health.js +6 -0
  105. package/dist/plugin/lib/health.js.map +1 -0
  106. package/dist/plugin/lib/index.d.ts +7 -0
  107. package/dist/plugin/lib/index.d.ts.map +1 -0
  108. package/dist/plugin/lib/index.js +5 -0
  109. package/dist/plugin/lib/index.js.map +1 -0
  110. package/dist/plugin/lib/registry.d.ts +18 -0
  111. package/dist/plugin/lib/registry.d.ts.map +1 -0
  112. package/dist/plugin/lib/registry.js +17 -0
  113. package/dist/plugin/lib/registry.js.map +1 -0
  114. package/dist/plugin/lib/work.d.ts +13 -0
  115. package/dist/plugin/lib/work.d.ts.map +1 -0
  116. package/dist/plugin/lib/work.js +27 -0
  117. package/dist/plugin/lib/work.js.map +1 -0
  118. package/package.json +43 -0
  119. package/plugin/rules/coordination.md +224 -0
  120. package/scripts/check-gh-token.sh +102 -0
  121. package/scripts/macf-gh-token.sh +130 -0
  122. package/scripts/macf-whoami.sh +51 -0
  123. package/scripts/tmux-send-to-claude.sh +51 -0
  124. package/scripts/write-build-info.mjs +48 -0
@@ -0,0 +1,279 @@
1
+ import { execFileSync } from 'node:child_process';
2
+ import { mkdirSync, writeFileSync, readFileSync, existsSync, appendFileSync } from 'node:fs';
3
+ import { join, resolve } from 'node:path';
4
+ import { projectMacfDir, writeAgentConfig, addToAgentsIndex, agentCertPath, agentKeyPath, caCertPath as caCertPathFor, caKeyPath as caKeyPathFor, isValidProjectName, } from '../config.js';
5
+ import { loadCA } from '@groundnuty/macf-core';
6
+ import { generateAgentCert } from '@groundnuty/macf-core';
7
+ import { copyCanonicalRules, copyCanonicalScripts } from '../rules.js';
8
+ import { installGhTokenHook, installPluginSkillPermissions, installSandboxFdAllowRead } from '../settings-writer.js';
9
+ import { fetchPluginToWorkspace } from '../plugin-fetcher.js';
10
+ import { writeClaudeSh } from '../claude-sh.js';
11
+ import { resolveLatestVersions, isValidSemver, isValidActionsRef, FALLBACK_VERSIONS, statusMessage, } from '../version-resolver.js';
12
+ /**
13
+ * Resolve version pins: explicit flags > network-fetched latest > hardcoded fallback.
14
+ * Validates any explicit flag against format pattern.
15
+ */
16
+ async function resolveVersions(opts) {
17
+ if (opts.cliVersion && !isValidSemver(opts.cliVersion)) {
18
+ throw new Error(`--cli-version must be semver (e.g., 0.1.0), got "${opts.cliVersion}"`);
19
+ }
20
+ if (opts.pluginVersion && !isValidSemver(opts.pluginVersion)) {
21
+ throw new Error(`--plugin-version must be semver (e.g., 0.1.0), got "${opts.pluginVersion}"`);
22
+ }
23
+ if (opts.actionsVersion && !isValidActionsRef(opts.actionsVersion)) {
24
+ throw new Error(`--actions-version must be a tag ref (v1, v1.0, v1.0.0), got "${opts.actionsVersion}"`);
25
+ }
26
+ // Skip the network fetch if all three flags are explicitly set
27
+ const allSet = opts.cliVersion && opts.pluginVersion && opts.actionsVersion;
28
+ if (allSet) {
29
+ return {
30
+ cli: opts.cliVersion,
31
+ plugin: opts.pluginVersion,
32
+ actions: opts.actionsVersion,
33
+ };
34
+ }
35
+ let resolved;
36
+ try {
37
+ resolved = await resolveLatestVersions();
38
+ // Print one targeted message per non-ok component so the user sees the
39
+ // actual reason (no release, network down, malformed response) instead
40
+ // of a single vague "network fetch failed".
41
+ const notOk = Object.entries(resolved.sources)
42
+ .filter(([, status]) => status !== 'ok');
43
+ if (notOk.length > 0) {
44
+ process.stderr.write('Warning: using default versions for some components:\n');
45
+ for (const [component, status] of notOk) {
46
+ process.stderr.write(` - ${statusMessage(component, status)}\n`);
47
+ }
48
+ }
49
+ }
50
+ catch {
51
+ process.stderr.write('Warning: version resolution failed entirely, using hardcoded fallbacks\n');
52
+ resolved = {
53
+ versions: FALLBACK_VERSIONS,
54
+ sources: {
55
+ cli: 'network_error',
56
+ plugin: 'network_error',
57
+ actions: 'network_error',
58
+ },
59
+ };
60
+ }
61
+ return {
62
+ cli: opts.cliVersion ?? resolved.versions.cli,
63
+ plugin: opts.pluginVersion ?? resolved.versions.plugin,
64
+ actions: opts.actionsVersion ?? resolved.versions.actions,
65
+ };
66
+ }
67
+ /**
68
+ * Validate fields that end up embedded verbatim in `claude.sh` via a
69
+ * shell double-quoted template literal (`export APP_ID="${appId}"`,
70
+ * etc.). Reject inputs containing characters that would break quoting
71
+ * or trigger shell expansion. Runs before any workspace state is
72
+ * written so bad inputs fail early, not after partial init. (#105)
73
+ */
74
+ function validateInitOpts(opts) {
75
+ if (!isValidProjectName(opts.project)) {
76
+ throw new Error(`project "${opts.project}" must match [a-zA-Z0-9_-]+`);
77
+ }
78
+ // role + name are interpolated into claude.sh shell exports the same
79
+ // way project is. Without this check, `--name 'foo"$(evil)'` would
80
+ // produce an injection-vulnerable launcher. Apply the same allowlist
81
+ // as project — per ultrareview finding C2.
82
+ if (!isValidProjectName(opts.role)) {
83
+ throw new Error(`role "${opts.role}" must match [a-zA-Z0-9_-]+`);
84
+ }
85
+ if (opts.name !== undefined && !isValidProjectName(opts.name)) {
86
+ throw new Error(`name "${opts.name}" must match [a-zA-Z0-9_-]+`);
87
+ }
88
+ if (!/^\d+$/.test(opts.appId)) {
89
+ throw new Error(`appId "${opts.appId}" must be numeric (GitHub App IDs are digits only)`);
90
+ }
91
+ if (!/^\d+$/.test(opts.installId)) {
92
+ throw new Error(`installId "${opts.installId}" must be numeric (GitHub installation IDs are digits only)`);
93
+ }
94
+ // Shell-dangerous chars inside double-quoted context. `\` escapes in
95
+ // double quotes; include it to avoid any sub-expansion surprise.
96
+ if (/["$`\\\n\r]/.test(opts.keyPath)) {
97
+ throw new Error(`keyPath "${opts.keyPath}" contains a shell-unsafe character (", $, backtick, backslash, or newline)`);
98
+ }
99
+ }
100
+ /**
101
+ * Set up a project directory for an agent.
102
+ */
103
+ export async function initAgent(projectDir, opts) {
104
+ validateInitOpts(opts);
105
+ const absDir = resolve(projectDir);
106
+ const macfDir = projectMacfDir(absDir);
107
+ const agentName = opts.name ?? opts.role;
108
+ // Create directory structure
109
+ mkdirSync(join(macfDir, 'certs'), { recursive: true });
110
+ mkdirSync(join(macfDir, 'logs'), { recursive: true });
111
+ mkdirSync(join(macfDir, 'plugin'), { recursive: true });
112
+ // Build registry config
113
+ let registry;
114
+ const regType = opts.registryType ?? 'repo';
115
+ switch (regType) {
116
+ case 'org':
117
+ if (!opts.registryOrg)
118
+ throw new Error('--registry-org required for org registry');
119
+ registry = { type: 'org', org: opts.registryOrg };
120
+ break;
121
+ case 'profile':
122
+ if (!opts.registryUser)
123
+ throw new Error('--registry-user required for profile registry');
124
+ registry = { type: 'profile', user: opts.registryUser };
125
+ break;
126
+ case 'repo': {
127
+ const repo = opts.registryRepo ?? detectRepoFromGit(absDir);
128
+ if (!repo)
129
+ throw new Error('--registry-repo required (or run from a git repo with a GitHub remote)');
130
+ const parts = repo.split('/');
131
+ if (parts.length !== 2 || !parts[0] || !parts[1]) {
132
+ throw new Error(`Invalid repo format: "${repo}". Expected "owner/repo".`);
133
+ }
134
+ registry = { type: 'repo', owner: parts[0], repo: parts[1] };
135
+ break;
136
+ }
137
+ default:
138
+ throw new Error(`Unknown registry type: "${regType}"`);
139
+ }
140
+ // Resolve version pins (explicit flags > network-fetched latest > fallback)
141
+ const versions = await resolveVersions(opts);
142
+ // Write agent config
143
+ const config = {
144
+ project: opts.project,
145
+ agent_name: agentName,
146
+ agent_role: opts.role,
147
+ agent_type: (opts.type ?? 'permanent'),
148
+ registry,
149
+ github_app: {
150
+ app_id: opts.appId,
151
+ install_id: opts.installId,
152
+ key_path: opts.keyPath,
153
+ },
154
+ ...(opts.advertiseHost !== undefined ? { advertise_host: opts.advertiseHost } : {}),
155
+ ...(opts.tmuxSession !== undefined ? { tmux_session: opts.tmuxSession } : {}),
156
+ ...(opts.tmuxWindow !== undefined ? { tmux_window: opts.tmuxWindow } : {}),
157
+ versions,
158
+ };
159
+ writeAgentConfig(absDir, config);
160
+ // Generate claude.sh launcher.
161
+ const claudeShPath = writeClaudeSh(absDir, config);
162
+ // Add .macf/ to .gitignore
163
+ updateGitignore(absDir);
164
+ // Register in global index
165
+ addToAgentsIndex(absDir);
166
+ // Copy canonical coordination rules into <workspace>/.claude/rules/
167
+ // (single source of truth shipped with the CLI; refreshed by `macf update`)
168
+ const copiedRules = copyCanonicalRules(absDir);
169
+ if (copiedRules.length > 0) {
170
+ console.log(` Rules: copied ${copiedRules.length} canonical rule file(s) to .claude/rules/`);
171
+ }
172
+ // Copy canonical helper scripts (e.g., tmux-send-to-claude.sh) into
173
+ // <workspace>/.claude/scripts/. Hooks in settings.local.json.example
174
+ // call these by relative path.
175
+ const copiedScripts = copyCanonicalScripts(absDir);
176
+ if (copiedScripts.length > 0) {
177
+ console.log(` Scripts: copied ${copiedScripts.length} helper script(s) to .claude/scripts/`);
178
+ }
179
+ // Install the attribution-trap PreToolUse hook entry in
180
+ // .claude/settings.json (merge-preserving). Per #140, structurally
181
+ // blocks gh / git push calls when GH_TOKEN isn't a ghs_ bot token —
182
+ // behavioral controls recurred the trap 5 times in a single day.
183
+ installGhTokenHook(absDir);
184
+ console.log(` Hooks: installed gh-token guard in .claude/settings.json`);
185
+ // Pre-approve the 4 macf-agent plugin skills so first-turn
186
+ // invocations (/macf-status, /macf-issues, etc.) don't block on
187
+ // interactive approval dialogs — essential for SessionStart
188
+ // auto-pickup + general agent autonomy. Operator opted into the
189
+ // plugin deliberately via `macf init`; trusting its own skills is
190
+ // a safe default. Non-macf permissions.allow entries preserved.
191
+ // See macf#189 sub-item 2.
192
+ installPluginSkillPermissions(absDir);
193
+ console.log(` Permissions: pre-approved macf-agent plugin skills`);
194
+ // Add `/proc/self/fd/**` to sandbox.filesystem.allowRead so Claude
195
+ // Code's Bash-tool harness can pass command-input fds to spawned
196
+ // shells without hitting zsh permission-denied. Every MACF agent
197
+ // pre-#200 silently failed every Bash call; this fixes on init.
198
+ installSandboxFdAllowRead(absDir);
199
+ console.log(` Sandbox: allowRead for /proc/self/fd/** installed`);
200
+ // Fetch the macf-agent plugin at the pinned version and place it at
201
+ // .macf/plugin/ so claude.sh can use --plugin-dir (per DR-013).
202
+ // Network failures here don't abort init — the workspace is usable
203
+ // without the plugin (degrades to rules-only mode), and the user can
204
+ // re-try with `macf update` once connectivity is back.
205
+ try {
206
+ fetchPluginToWorkspace(absDir, versions.plugin);
207
+ console.log(` Plugin: fetched macf-agent@v${versions.plugin} to .macf/plugin/`);
208
+ }
209
+ catch (err) {
210
+ const msg = err instanceof Error ? err.message : String(err);
211
+ console.warn(` Warning: plugin fetch failed: ${msg}`);
212
+ console.warn(` You can retry later with \`macf update\` once the issue is resolved.`);
213
+ }
214
+ // Generate agent cert if CA key is available locally (per-project)
215
+ const caCertFile = caCertPathFor(opts.project);
216
+ const caKeyFile = caKeyPathFor(opts.project);
217
+ if (existsSync(caCertFile) && existsSync(caKeyFile)) {
218
+ try {
219
+ const ca = loadCA(caCertFile, caKeyFile);
220
+ await generateAgentCert({
221
+ agentName,
222
+ caCertPem: ca.certPem,
223
+ caKeyPem: ca.keyPem,
224
+ ...(opts.advertiseHost !== undefined ? { advertiseHost: opts.advertiseHost } : {}),
225
+ certPath: agentCertPath(absDir),
226
+ keyPath: agentKeyPath(absDir),
227
+ });
228
+ console.log(`Agent "${agentName}" initialized in ${absDir}`);
229
+ console.log(` Config: ${join(macfDir, 'macf-agent.json')}`);
230
+ console.log(` Cert: ${agentCertPath(absDir)}`);
231
+ console.log(` Launcher: ${claudeShPath}`);
232
+ }
233
+ catch (err) {
234
+ console.warn(` Warning: cert generation failed: ${err instanceof Error ? err.message : String(err)}`);
235
+ console.log(`Agent "${agentName}" initialized in ${absDir} (no cert — run macf certs rotate)`);
236
+ }
237
+ }
238
+ else {
239
+ console.log(`Agent "${agentName}" initialized in ${absDir}`);
240
+ console.log(` Config: ${join(macfDir, 'macf-agent.json')}`);
241
+ console.log(` Launcher: ${claudeShPath}`);
242
+ console.log(`\n No CA found locally. To generate agent cert:`);
243
+ console.log(` macf certs init (if first agent — creates CA)`);
244
+ console.log(` macf certs rotate (if CA already exists)`);
245
+ }
246
+ }
247
+ function updateGitignore(projectDir) {
248
+ const gitignorePath = join(projectDir, '.gitignore');
249
+ const entry = '.macf/';
250
+ if (existsSync(gitignorePath)) {
251
+ const content = readFileSync(gitignorePath, 'utf-8');
252
+ if (!content.includes(entry)) {
253
+ appendFileSync(gitignorePath, `\n# MACF agent data\n${entry}\n`);
254
+ }
255
+ }
256
+ else {
257
+ writeFileSync(gitignorePath, `# MACF agent data\n${entry}\n`);
258
+ }
259
+ }
260
+ /**
261
+ * Detect owner/repo from git remote. Uses execFileSync (safe — no shell injection).
262
+ */
263
+ function detectRepoFromGit(dir) {
264
+ try {
265
+ const remote = execFileSync('git', ['remote', 'get-url', 'origin'], {
266
+ cwd: dir,
267
+ encoding: 'utf-8',
268
+ stdio: ['pipe', 'pipe', 'pipe'],
269
+ }).trim();
270
+ const match = /github\.com[/:]([\w.-]+)\/([\w.-]+?)(?:\.git)?$/.exec(remote);
271
+ if (match)
272
+ return `${match[1]}/${match[2]}`;
273
+ return null;
274
+ }
275
+ catch {
276
+ return null;
277
+ }
278
+ }
279
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Default command: list all agents registered on this machine.
3
+ */
4
+ export declare function listAgents(): void;
5
+ //# sourceMappingURL=list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/list.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,wBAAgB,UAAU,IAAI,IAAI,CAmBjC"}
@@ -0,0 +1,21 @@
1
+ import { loadAllAgents, readAgentsIndex } from '../config.js';
2
+ /**
3
+ * Default command: list all agents registered on this machine.
4
+ */
5
+ export function listAgents() {
6
+ const index = readAgentsIndex();
7
+ if (index.agents.length === 0) {
8
+ console.log('No agents registered. Run `macf init` in a project directory to set up an agent.');
9
+ return;
10
+ }
11
+ const agents = loadAllAgents();
12
+ if (agents.length === 0) {
13
+ console.log('Agent index has entries but no valid configs found.');
14
+ return;
15
+ }
16
+ console.log('macf agents:\n');
17
+ for (const { path, config } of agents) {
18
+ console.log(` ${config.agent_name.padEnd(20)} ${config.agent_role.padEnd(15)} ${config.project.padEnd(10)} ${path}`);
19
+ }
20
+ }
21
+ //# sourceMappingURL=list.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list.js","sourceRoot":"","sources":["../../../src/cli/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE9D;;GAEG;AACH,MAAM,UAAU,UAAU;IACxB,MAAM,KAAK,GAAG,eAAe,EAAE,CAAC;IAEhC,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,CAAC,GAAG,CAAC,kFAAkF,CAAC,CAAC;QAChG,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;IAE/B,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAC;QACnE,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAC9B,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,MAAM,EAAE,CAAC;QACtC,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IACxH,CAAC;AACH,CAAC"}
@@ -0,0 +1,36 @@
1
+ import type { GitHubVariablesClient } from '@groundnuty/macf-core';
2
+ export type MigrationResult = {
3
+ readonly status: 'no_variable';
4
+ } | {
5
+ readonly status: 'already_v2';
6
+ } | {
7
+ readonly status: 'migrated';
8
+ } | {
9
+ readonly status: 'wrong_passphrase';
10
+ } | {
11
+ readonly status: 'error';
12
+ readonly message: string;
13
+ };
14
+ /**
15
+ * Check if a registry-stored value is the legacy v1 (raw base64)
16
+ * shape. v2 envelopes always start with `{` (JSON object); base64
17
+ * alphabet excludes `{`, so this dispatch is safe by construction.
18
+ */
19
+ export declare function isV1Blob(value: string): boolean;
20
+ /**
21
+ * Run the migration for one project. Returns a result tag for the
22
+ * caller to render to the operator. Does NOT log directly — the
23
+ * caller owns stdout/stderr presentation so this is testable without
24
+ * capturing output.
25
+ */
26
+ export declare function migrateCaKeyToV2(opts: {
27
+ readonly project: string;
28
+ readonly client: GitHubVariablesClient;
29
+ readonly prompt: (message: string) => Promise<string>;
30
+ }): Promise<MigrationResult>;
31
+ /**
32
+ * Render a MigrationResult to the operator. Kept out of
33
+ * `migrateCaKeyToV2` so tests don't need stdout capture.
34
+ */
35
+ export declare function formatMigrationResult(result: MigrationResult, project: string): string;
36
+ //# sourceMappingURL=migrate-ca-key.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate-ca-key.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/migrate-ca-key.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAEnE,MAAM,MAAM,eAAe,GACvB;IAAE,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAA;CAAE,GAClC;IAAE,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAA;CAAE,GACjC;IAAE,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAA;CAAE,GAC/B;IAAE,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAA;CAAE,GACvC;IAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3D;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAE/C;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAC3C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;CACvD,GAAG,OAAO,CAAC,eAAe,CAAC,CA6C3B;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAatF"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * macf update auto-migrate for CA key encryption (DR-011 rev2, #115).
3
+ *
4
+ * Detects legacy v1-shaped `{PROJECT}_CA_KEY_ENCRYPTED` blobs in the
5
+ * registry and upgrades them in place to v2 (JSON envelope at 600k
6
+ * iters). One-time per project — subsequent `macf update` runs see
7
+ * the v2 blob and no-op silently.
8
+ *
9
+ * Idempotent: re-running on a v2 blob is a no-op. Atomic: if the
10
+ * passphrase is wrong or re-encryption fails, the v1 blob in the
11
+ * registry is untouched — the only state change is the prompt. The
12
+ * operator can retry.
13
+ *
14
+ * Isolation: this module has no hard dependency on the `macf update`
15
+ * command shape. Callers provide the registry client + prompt
16
+ * function, enabling headless tests and future `--passphrase-file`
17
+ * extension (Future Work in DR-011 rev2).
18
+ */
19
+ import { encryptCAKey, decryptCAKey, CaError } from '@groundnuty/macf-core';
20
+ import { toVariableSegment } from '@groundnuty/macf-core';
21
+ /**
22
+ * Check if a registry-stored value is the legacy v1 (raw base64)
23
+ * shape. v2 envelopes always start with `{` (JSON object); base64
24
+ * alphabet excludes `{`, so this dispatch is safe by construction.
25
+ */
26
+ export function isV1Blob(value) {
27
+ return !value.trimStart().startsWith('{');
28
+ }
29
+ /**
30
+ * Run the migration for one project. Returns a result tag for the
31
+ * caller to render to the operator. Does NOT log directly — the
32
+ * caller owns stdout/stderr presentation so this is testable without
33
+ * capturing output.
34
+ */
35
+ export async function migrateCaKeyToV2(opts) {
36
+ const { project, client, prompt } = opts;
37
+ const varName = `${toVariableSegment(project)}_CA_KEY_ENCRYPTED`;
38
+ const current = await client.readVariable(varName);
39
+ if (current === null) {
40
+ return { status: 'no_variable' };
41
+ }
42
+ if (!isV1Blob(current)) {
43
+ // Already v2 (or v3+ future) — nothing to do. Silent no-op.
44
+ return { status: 'already_v2' };
45
+ }
46
+ // DR-011 rev2 canonical prompt text. Keep verbatim — matches the
47
+ // operator-facing doctrine in design/decisions/DR-011-ca-key-backup.md.
48
+ const passphrase = await prompt(`Migrating CA key encryption: v1/iter=10000 → v2/iter=600000 for project ${project}.\n` +
49
+ `This is a one-time passphrase prompt for this project; subsequent \`macf update\`\n` +
50
+ `runs in this or any other workspace for the same project won't re-prompt.\n` +
51
+ `Enter CA key passphrase: `);
52
+ let keyPem;
53
+ try {
54
+ keyPem = decryptCAKey(current, passphrase);
55
+ }
56
+ catch (err) {
57
+ if (err instanceof CaError) {
58
+ return { status: 'wrong_passphrase' };
59
+ }
60
+ throw err;
61
+ }
62
+ const v2Value = encryptCAKey(keyPem, passphrase);
63
+ try {
64
+ await client.writeVariable(varName, v2Value);
65
+ }
66
+ catch (err) {
67
+ return {
68
+ status: 'error',
69
+ message: err instanceof Error ? err.message : String(err),
70
+ };
71
+ }
72
+ return { status: 'migrated' };
73
+ }
74
+ /**
75
+ * Render a MigrationResult to the operator. Kept out of
76
+ * `migrateCaKeyToV2` so tests don't need stdout capture.
77
+ */
78
+ export function formatMigrationResult(result, project) {
79
+ switch (result.status) {
80
+ case 'no_variable':
81
+ return ''; // No backup exists; silent no-op.
82
+ case 'already_v2':
83
+ return ''; // Already migrated; silent no-op.
84
+ case 'migrated':
85
+ return `Migration complete: ${toVariableSegment(project)}_CA_KEY_ENCRYPTED is now v2/600k.`;
86
+ case 'wrong_passphrase':
87
+ return `Migration aborted: wrong passphrase. Your v1 backup is untouched; re-run \`macf update\` to retry.`;
88
+ case 'error':
89
+ return `Migration failed: ${result.message}. Your v1 backup is untouched; re-run \`macf update\` to retry.`;
90
+ }
91
+ }
92
+ //# sourceMappingURL=migrate-ca-key.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate-ca-key.js","sourceRoot":"","sources":["../../../src/cli/commands/migrate-ca-key.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAC5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAU1D;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAa;IACpC,OAAO,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;AAC5C,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAItC;IACC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACzC,MAAM,OAAO,GAAG,GAAG,iBAAiB,CAAC,OAAO,CAAC,mBAAmB,CAAC;IAEjE,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;IACnD,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACrB,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC;IACnC,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACvB,4DAA4D;QAC5D,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;IAClC,CAAC;IAED,iEAAiE;IACjE,wEAAwE;IACxE,MAAM,UAAU,GAAG,MAAM,MAAM,CAC7B,2EAA2E,OAAO,KAAK;QACvF,qFAAqF;QACrF,6EAA6E;QAC7E,2BAA2B,CAC5B,CAAC;IAEF,IAAI,MAAc,CAAC;IACnB,IAAI,CAAC;QACH,MAAM,GAAG,YAAY,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAC7C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,OAAO,EAAE,CAAC;YAC3B,OAAO,EAAE,MAAM,EAAE,kBAAkB,EAAE,CAAC;QACxC,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;IAED,MAAM,OAAO,GAAG,YAAY,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAEjD,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC/C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,MAAM,EAAE,OAAO;YACf,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;SAC1D,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;AAChC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAAuB,EAAE,OAAe;IAC5E,QAAQ,MAAM,CAAC,MAAM,EAAE,CAAC;QACtB,KAAK,aAAa;YAChB,OAAO,EAAE,CAAC,CAAC,kCAAkC;QAC/C,KAAK,YAAY;YACf,OAAO,EAAE,CAAC,CAAC,kCAAkC;QAC/C,KAAK,UAAU;YACb,OAAO,uBAAuB,iBAAiB,CAAC,OAAO,CAAC,mCAAmC,CAAC;QAC9F,KAAK,kBAAkB;YACrB,OAAO,oGAAoG,CAAC;QAC9G,KAAK,OAAO;YACV,OAAO,qBAAqB,MAAM,CAAC,OAAO,iEAAiE,CAAC;IAChH,CAAC;AACH,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * List peers from the registry.
3
+ *
4
+ * If projectDir is given, uses that project's config for registry access.
5
+ * Otherwise uses the first agent from the global index.
6
+ */
7
+ export declare function listPeers(projectDir?: string): Promise<void>;
8
+ //# sourceMappingURL=peers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"peers.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/peers.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH,wBAAsB,SAAS,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAwClE"}
@@ -0,0 +1,45 @@
1
+ import { loadAllAgents, readAgentConfig, tokenSourceFromConfig } from '../config.js';
2
+ import { createRegistryFromConfig } from '@groundnuty/macf-core';
3
+ import { generateToken } from '@groundnuty/macf-core';
4
+ /**
5
+ * List peers from the registry.
6
+ *
7
+ * If projectDir is given, uses that project's config for registry access.
8
+ * Otherwise uses the first agent from the global index.
9
+ */
10
+ export async function listPeers(projectDir) {
11
+ let driverConfig;
12
+ let driverPath;
13
+ if (projectDir) {
14
+ const c = readAgentConfig(projectDir);
15
+ if (!c) {
16
+ console.error(`Could not read agent config at ${projectDir}/.macf/macf-agent.json`);
17
+ return;
18
+ }
19
+ driverConfig = c;
20
+ driverPath = projectDir;
21
+ }
22
+ else {
23
+ const agents = loadAllAgents();
24
+ if (agents.length === 0) {
25
+ console.log('No agents configured. Run `macf init` first.');
26
+ return;
27
+ }
28
+ driverConfig = agents[0].config;
29
+ driverPath = agents[0].path;
30
+ }
31
+ const token = await generateToken(tokenSourceFromConfig(driverPath, driverConfig));
32
+ const registry = createRegistryFromConfig(driverConfig.registry, driverConfig.project, token);
33
+ const peers = await registry.list('');
34
+ if (peers.length === 0) {
35
+ console.log('No peers registered in the registry.');
36
+ return;
37
+ }
38
+ console.log('macf peers:\n');
39
+ console.log(` ${'NAME'.padEnd(25)} ${'HOST'.padEnd(20)} ${'PORT'.padEnd(8)} ${'TYPE'.padEnd(12)} STARTED`);
40
+ console.log(` ${'─'.repeat(25)} ${'─'.repeat(20)} ${'─'.repeat(8)} ${'─'.repeat(12)} ${'─'.repeat(24)}`);
41
+ for (const peer of peers) {
42
+ console.log(` ${peer.name.padEnd(25)} ${peer.info.host.padEnd(20)} ${String(peer.info.port).padEnd(8)} ${peer.info.type.padEnd(12)} ${peer.info.started}`);
43
+ }
44
+ }
45
+ //# sourceMappingURL=peers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"peers.js","sourceRoot":"","sources":["../../../src/cli/commands/peers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACrF,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,UAAmB;IACjD,IAAI,YAAY,CAAC;IACjB,IAAI,UAAkB,CAAC;IACvB,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,CAAC,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;QACtC,IAAI,CAAC,CAAC,EAAE,CAAC;YACP,OAAO,CAAC,KAAK,CAAC,kCAAkC,UAAU,wBAAwB,CAAC,CAAC;YACpF,OAAO;QACT,CAAC;QACD,YAAY,GAAG,CAAC,CAAC;QACjB,UAAU,GAAG,UAAU,CAAC;IAC1B,CAAC;SAAM,CAAC;QACN,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;QAC/B,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxB,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;YAC5D,OAAO;QACT,CAAC;QACD,YAAY,GAAG,MAAM,CAAC,CAAC,CAAE,CAAC,MAAM,CAAC;QACjC,UAAU,GAAG,MAAM,CAAC,CAAC,CAAE,CAAC,IAAI,CAAC;IAC/B,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,qBAAqB,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC,CAAC;IACnF,MAAM,QAAQ,GAAG,wBAAwB,CAAC,YAAY,CAAC,QAAQ,EAAE,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAE9F,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEtC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,sCAAsC,CAAC,CAAC;QACpD,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAC7B,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC;IAC5G,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IAE1G,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CACT,KAAK,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAC/I,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,43 @@
1
+ export interface RepoInitOptions {
2
+ readonly repo?: string;
3
+ readonly actionsVersion: string;
4
+ readonly agents?: string;
5
+ readonly force: boolean;
6
+ /**
7
+ * Optional shared tmux session name. When provided alongside 2+ agents,
8
+ * all agents share this session and each is given a `tmux_window` equal
9
+ * to the agent name. Omit or combine with a single agent to get the
10
+ * legacy "session per agent, no window" layout.
11
+ */
12
+ readonly sessionName?: string;
13
+ }
14
+ interface LabelSpec {
15
+ readonly name: string;
16
+ readonly color: string;
17
+ readonly description: string;
18
+ }
19
+ export declare function generateWorkflow(actionsVersion: string): string;
20
+ /**
21
+ * Options passed to generate/patch helpers so they can compute sensible
22
+ * default values for new entries. Owner/repo come from `--repo`; ssh_user
23
+ * defaults to 'ubuntu' matching the other template defaults.
24
+ */
25
+ export interface AgentEntryDefaults {
26
+ readonly owner: string;
27
+ readonly repo: string;
28
+ }
29
+ export declare function generateAgentConfig(agents: readonly string[], sessionName?: string, defaults?: AgentEntryDefaults): string;
30
+ /**
31
+ * Merge-preserving regenerate for #76: update only tmux_session/tmux_window
32
+ * fields from user input, preserve app_name/host/ssh_key_secret/ssh_user
33
+ * /tmux_bin/unknown-fields, preserve top-level label_to_status and extras.
34
+ * Agents not in the --agents list are left alone.
35
+ */
36
+ export declare function patchAgentConfig(existingJson: string, agents: readonly string[], sessionName?: string, defaults?: AgentEntryDefaults): string;
37
+ export declare function createLabel(owner: string, repo: string, token: string, spec: LabelSpec): Promise<'created' | 'exists' | 'failed'>;
38
+ /**
39
+ * Bootstrap a repo for MACF routing.
40
+ */
41
+ export declare function repoInit(projectDir: string, opts: RepoInitOptions): Promise<void>;
42
+ export {};
43
+ //# sourceMappingURL=repo-init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repo-init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/repo-init.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB;;;;;OAKG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,UAAU,SAAS;IACjB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AA4CD,wBAAgB,gBAAgB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAkB/D;AA8BD;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAuCD,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,WAAW,CAAC,EAAE,MAAM,EACpB,QAAQ,CAAC,EAAE,kBAAkB,GAC5B,MAAM,CA4BR;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,WAAW,CAAC,EAAE,MAAM,EACpB,QAAQ,CAAC,EAAE,kBAAkB,GAC5B,MAAM,CA0CR;AAED,wBAAsB,WAAW,CAC/B,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,SAAS,GACd,OAAO,CAAC,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC,CAmB1C;AAYD;;GAEG;AACH,wBAAsB,QAAQ,CAC5B,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,eAAe,GACpB,OAAO,CAAC,IAAI,CAAC,CA8Ff"}