fg-tracker-mcp 0.4.0 → 0.6.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.
@@ -0,0 +1,437 @@
1
+ /**
2
+ * Plano e arquivos do PR de transferência de controle (plano-infraestrutura.md §7):
3
+ * remove os stacks do app CDK e do deploy do CI (via patch), separa o deploy de código,
4
+ * adiciona o guard do CI, `infra/fg-tracker.lock.json` e a documentação. Só escreve
5
+ * arquivos locais; nunca executa git, gh nem chamadas AWS de escrita.
6
+ */
7
+ import { mkdir, writeFile, access } from 'node:fs/promises';
8
+ import { dirname, join, posix } from 'node:path';
9
+ import { splitLines, unifiedDiff } from './diff.js';
10
+ import { readText } from './files.js';
11
+ export const LOCK_PATH = 'infra/fg-tracker.lock.json';
12
+ export const GUARD_PATH = 'scripts/fg-tracker-guard.mjs';
13
+ export const DOC_PATH = 'docs/fg-tracker-handover.md';
14
+ export const HANDOVER_DIR = 'infra/_handover';
15
+ export const PATCH_PATH = `${HANDOVER_DIR}/fg-tracker-handover.patch`;
16
+ export const HANDOVER_README = `${HANDOVER_DIR}/README.md`;
17
+ export const CODE_DEPLOY_COMMAND = 'npx fg-tracker-release deploy --release <sha>';
18
+ function escapeRe(s) {
19
+ return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
20
+ }
21
+ function indentOf(line) {
22
+ return /^\s*/.exec(line)?.[0] ?? '';
23
+ }
24
+ /** Edições no arquivo de entrada do app CDK: remove `new XStack(app, 'Name')`, dependências e imports órfãos. */
25
+ function entryFileEdits(file, content, stacks, remaining, warnings, changes) {
26
+ const { lines } = splitLines(content);
27
+ const edits = [];
28
+ const removed = new Set();
29
+ for (const s of stacks) {
30
+ if (!s.entryLines)
31
+ continue;
32
+ if (!s.standalone) {
33
+ warnings.push(`${file}:${s.entryLines[0]}: \`${s.name}\` não está em um statement isolado — remova manualmente.`);
34
+ changes.push({ path: file, kind: 'manual', description: `remover a instanciação de ${s.name} (expressão composta)`, lines: s.entryLines });
35
+ continue;
36
+ }
37
+ const [a, b] = s.entryLines;
38
+ for (let i = a - 1; i < b; i++)
39
+ removed.add(i);
40
+ edits.push({ start: a - 1, deleteCount: b - a + 1, insert: [`${indentOf(lines[a - 1] ?? '')}// FG Tracker: stack "${s.name}" transferido ao FG Tracker (${LOCK_PATH}); código arquivado em ${HANDOVER_DIR}/.`] });
41
+ changes.push({ path: file, kind: 'patch', description: `remove \`new ${s.className ?? 'Stack'}(…, '${s.constructId}')\` (${s.name})`, lines: [a, b] });
42
+ if (s.variable) {
43
+ const v = escapeRe(s.variable);
44
+ lines.forEach((ln, i) => {
45
+ const code = ln.replace(/(['"`])(?:\\.|(?!\1).)*\1/g, "''").replace(/\/\/.*$/, '');
46
+ if (removed.has(i) || /^\s*import\s/.test(ln) || !new RegExp(`\\b${v}\\b`).test(code))
47
+ return;
48
+ if (/^\s*[\w$.]+\.addDependency\([\w$.]+\);?\s*$/.test(ln)) {
49
+ removed.add(i);
50
+ edits.push({ start: i, deleteCount: 1, insert: [] });
51
+ changes.push({ path: file, kind: 'patch', description: `remove dependência com ${s.name}: \`${ln.trim()}\``, lines: [i + 1, i + 1] });
52
+ }
53
+ else {
54
+ warnings.push(`${file}:${i + 1}: \`${s.variable}\` (${s.name}) ainda é usado — troque por \`Fn.importValue\`/SSM ou referência por nome: \`${ln.trim().slice(0, 120)}\``);
55
+ changes.push({ path: file, kind: 'manual', description: `substituir referência a ${s.variable} (stack transferido)`, lines: [i + 1, i + 1] });
56
+ }
57
+ });
58
+ }
59
+ }
60
+ // Imports de classes que deixaram de ser usadas neste arquivo.
61
+ const classes = new Set(stacks.map((s) => s.className).filter((c) => Boolean(c) && c !== 'Stack'));
62
+ for (const cls of classes) {
63
+ if (remaining.some((r) => r.entryFile === file && r.className === cls))
64
+ continue;
65
+ const re = new RegExp(`\\b${escapeRe(cls)}\\b`);
66
+ const importIdx = lines.findIndex((ln) => /^\s*import\s/.test(ln) && re.test(ln));
67
+ const stillUsed = lines.some((ln, i) => i !== importIdx && !removed.has(i) && re.test(ln));
68
+ if (importIdx < 0 || stillUsed || removed.has(importIdx))
69
+ continue;
70
+ const ln = lines[importIdx] ?? '';
71
+ const named = /^(\s*import\s*\{)([^}]*)(\}\s*from\s*['"][^'"]+['"];?\s*)$/.exec(ln);
72
+ if (named) {
73
+ const names = (named[2] ?? '').split(',').map((x) => x.trim()).filter(Boolean);
74
+ const rest = names.filter((x) => x.split(/\s+as\s+/)[0] !== cls && x.split(/\s+as\s+/)[1] !== cls);
75
+ edits.push({ start: importIdx, deleteCount: 1, insert: rest.length ? [`${named[1]} ${rest.join(', ')} ${named[3]}`] : [] });
76
+ }
77
+ else if (/^\s*import\s+[\w$]+\s+from\s/.test(ln)) {
78
+ edits.push({ start: importIdx, deleteCount: 1, insert: [] });
79
+ }
80
+ else
81
+ continue;
82
+ removed.add(importIdx);
83
+ changes.push({ path: file, kind: 'patch', description: `remove import de ${cls}`, lines: [importIdx + 1, importIdx + 1] });
84
+ }
85
+ return edits;
86
+ }
87
+ function guardInvocation(file) {
88
+ const depth = posix.dirname(file) === '.' || file.startsWith('.github/') ? 0 : posix.dirname(file).split('/').length;
89
+ return `node ${depth ? '../'.repeat(depth) : ''}${GUARD_PATH}`;
90
+ }
91
+ /** Edições nos arquivos de CI/scripts: tira os stacks transferidos do `cdk deploy` e adiciona o guard. */
92
+ function ciEdits(file, content, commands, names, changes) {
93
+ const { lines } = splitLines(content);
94
+ const edits = [];
95
+ for (const cmd of commands.filter((c) => c.tool === 'cdk')) {
96
+ const idx = cmd.line - 1;
97
+ let line = lines[idx] ?? '';
98
+ if (line.includes(GUARD_PATH))
99
+ continue;
100
+ const explicit = cmd.stacks.filter((s) => s !== '*');
101
+ const drop = explicit.filter((s) => names.has(s.replace(/^['"]|['"]$/g, '')));
102
+ if (drop.length) {
103
+ for (const d of drop)
104
+ line = line.replace(new RegExp(`\\s+['"]?${escapeRe(d)}['"]?(?=\\s|$|&|;|\\|)`), '');
105
+ changes.push({ path: file, kind: 'patch', description: `remove ${drop.join(', ')} do \`cdk deploy\``, lines: [cmd.line, cmd.line] });
106
+ if (explicit.length === drop.length) {
107
+ // Nenhum stack restante neste comando.
108
+ const run = /^(\s*-?\s*run:\s*)(.*)$/.exec(line);
109
+ if (run)
110
+ edits.push({ start: idx, deleteCount: 1, insert: [`${run[1]}echo "Stacks transferidos ao FG Tracker: deploy de infra desativado (${LOCK_PATH})."`] });
111
+ else
112
+ edits.push({ start: idx, deleteCount: 1, insert: [`${indentOf(line)}# FG Tracker: ${drop.join(', ')} transferido(s) ao FG Tracker (${LOCK_PATH}).`] });
113
+ continue;
114
+ }
115
+ }
116
+ const guard = guardInvocation(file);
117
+ const run = /^(\s*-?\s*run:\s*)(?![|>])(.+)$/.exec(line);
118
+ if (file.endsWith('package.json')) {
119
+ const m = /^(\s*"[^"]+"\s*:\s*")(.*)$/.exec(line);
120
+ if (m)
121
+ line = `${m[1]}${guard} && ${m[2]}`;
122
+ edits.push({ start: idx, deleteCount: 1, insert: [line] });
123
+ }
124
+ else if (run) {
125
+ edits.push({ start: idx, deleteCount: 1, insert: [`${run[1]}${guard} && ${run[2]}`] });
126
+ }
127
+ else {
128
+ edits.push({ start: idx, deleteCount: 1, insert: [`${indentOf(line)}${guard}`, line] });
129
+ }
130
+ changes.push({ path: file, kind: 'patch', description: `executa o guard do FG Tracker antes do \`cdk deploy\``, lines: [cmd.line, cmd.line] });
131
+ }
132
+ return edits;
133
+ }
134
+ export async function buildHandoverEdits(root, analysis, stackNames) {
135
+ const wanted = new Set(stackNames);
136
+ const warnings = [];
137
+ const changes = [];
138
+ const matched = analysis.stacks.filter((s) => wanted.has(s.name) || (s.constructId !== null && wanted.has(s.constructId)));
139
+ const unsupported = matched.filter((s) => s.handover === 'unsupported-terraform');
140
+ const usable = matched.filter((s) => s.handover !== 'unsupported-terraform');
141
+ const found = new Set(matched.flatMap((s) => [s.name, s.constructId ?? '']));
142
+ const missing = stackNames.filter((n) => !found.has(n));
143
+ const names = new Set([...usable.map((s) => s.name), ...usable.map((s) => s.constructId ?? '').filter(Boolean)]);
144
+ const remaining = analysis.stacks.filter((s) => !usable.includes(s));
145
+ const patches = [];
146
+ // App CDK.
147
+ const byEntry = new Map();
148
+ for (const s of usable.filter((x) => x.tool === 'cdk' && x.entryFile))
149
+ byEntry.set(s.entryFile, [...(byEntry.get(s.entryFile) ?? []), s]);
150
+ for (const [file, stacks] of byEntry) {
151
+ const content = await readText(join(root, file));
152
+ if (content === null)
153
+ continue;
154
+ const edits = entryFileEdits(file, content, stacks, remaining, warnings, changes);
155
+ const diff = unifiedDiff(file, content, edits);
156
+ if (diff)
157
+ patches.push(diff);
158
+ }
159
+ // SAM / Serverless / CloudFormation: não há app a editar; o deploy sai do CI.
160
+ for (const s of usable.filter((x) => x.tool !== 'cdk')) {
161
+ changes.push({ path: s.entryFile ?? s.appDir, kind: 'manual', description: `${s.tool}: parar de implantar ${s.name} por \`${s.tool === 'sam' ? 'sam deploy' : s.tool === 'serverless' ? 'serverless deploy' : 'aws cloudformation deploy'}\`; manter só o build de artefatos` });
162
+ }
163
+ // CI.
164
+ const byFile = new Map();
165
+ for (const c of analysis.deployCommands)
166
+ byFile.set(c.file, [...(byFile.get(c.file) ?? []), c]);
167
+ for (const [file, commands] of byFile) {
168
+ const nonCdk = commands.filter((c) => c.tool === 'sam' || c.tool === 'serverless');
169
+ for (const c of nonCdk)
170
+ if (usable.some((s) => s.tool === c.tool))
171
+ changes.push({ path: file, kind: 'manual', description: `remover/ajustar \`${c.text}\` (stack transferido)`, lines: [c.line, c.line] });
172
+ if (!commands.some((c) => c.tool === 'cdk') || !usable.some((s) => s.tool === 'cdk'))
173
+ continue;
174
+ const content = await readText(join(root, file));
175
+ if (content === null)
176
+ continue;
177
+ const diff = unifiedDiff(file, content, ciEdits(file, content, commands, names, changes));
178
+ if (diff)
179
+ patches.push(diff);
180
+ }
181
+ if (!analysis.deployCommands.length && usable.length)
182
+ warnings.push('Nenhum `cdk deploy` encontrado no CI: adicione o guard (`node scripts/fg-tracker-guard.mjs`) onde o deploy acontece.');
183
+ // README de infra.
184
+ const readmePath = (await readText(join(root, 'infra/README.md'))) !== null ? 'infra/README.md' : (await readText(join(root, 'README.md'))) !== null ? 'README.md' : 'infra/README.md';
185
+ const readme = await readText(join(root, readmePath));
186
+ const section = [
187
+ '',
188
+ '## Infraestrutura controlada pelo FG Tracker',
189
+ '',
190
+ `Os stacks ${usable.map((s) => `\`${s.name}\``).join(', ')} são controlados pelo FG Tracker (\`${LOCK_PATH}\`).`,
191
+ '',
192
+ '- Mudanças de infraestrutura desses stacks: pelo diagrama do FG Tracker, com aprovação na tela.',
193
+ `- Deploy de código: o CI constrói os artefatos e chama \`${CODE_DEPLOY_COMMAND}\`.`,
194
+ `- O CI roda \`node ${GUARD_PATH}\` e falha se algum stack transferido voltar ao app CDK.`,
195
+ `- Emergência (FG Tracker fora do ar) e ejeção: veja \`${DOC_PATH}\`.`,
196
+ ];
197
+ if (readme === null)
198
+ patches.push(unifiedDiff(readmePath, null, [{ start: 0, deleteCount: 0, insert: ['# Infraestrutura', ...section] }]));
199
+ else if (!readme.includes('Infraestrutura controlada pelo FG Tracker'))
200
+ patches.push(unifiedDiff(readmePath, readme, [{ start: splitLines(readme).lines.length, deleteCount: 0, insert: section }]));
201
+ changes.push({ path: readmePath, kind: 'patch', description: 'seção "Infraestrutura controlada pelo FG Tracker"' });
202
+ // Arquivamento das classes de stack usadas só pelos stacks transferidos.
203
+ const moves = [];
204
+ for (const s of usable.filter((x) => x.tool === 'cdk')) {
205
+ const classFile = s.sourceFiles.find((f) => f !== s.entryFile);
206
+ if (!classFile || moves.some((m) => m.from === classFile))
207
+ continue;
208
+ if (remaining.some((r) => r.sourceFiles.includes(classFile))) {
209
+ warnings.push(`${classFile} também é usado por stacks que continuam no repositório — não será arquivado.`);
210
+ continue;
211
+ }
212
+ moves.push({ from: classFile, to: `${HANDOVER_DIR}/${classFile}` });
213
+ changes.push({ path: classFile, kind: 'move', description: `arquivar em ${HANDOVER_DIR}/${classFile} (\`git mv\`; exclua ${HANDOVER_DIR} do tsconfig)` });
214
+ }
215
+ for (const s of usable.filter((x) => x.handover === 'needs-code-deploy-split')) {
216
+ changes.push({ path: '.github/workflows', kind: 'manual', description: `${s.name}: construir artefatos (${uniqKinds(s)}) no CI e publicar com \`${CODE_DEPLOY_COMMAND}\`` });
217
+ }
218
+ changes.push({ path: LOCK_PATH, kind: 'create', description: 'registro de projeto, conta, ambiente e stacks transferidos' }, { path: GUARD_PATH, kind: 'create', description: 'guard do CI (falha se stack transferido ou com fg-tracker:owner=true for implantado)' }, { path: DOC_PATH, kind: 'create', description: 'explicação do PR, passos do CI e procedimento de emergência (corpo do PR)' }, { path: HANDOVER_README, kind: 'create', description: 'instruções de aplicação do patch e arquivamento' }, { path: PATCH_PATH, kind: 'create', description: 'patch unificado com as edições acima' });
219
+ return { matched, missing, unsupported, changes, patch: patches.filter(Boolean).join(''), moves, warnings };
220
+ }
221
+ function uniqKinds(s) {
222
+ return [...new Set(s.assets.map((a) => a.kind))].join(', ');
223
+ }
224
+ export function formatChanges(edits) {
225
+ const lines = [];
226
+ const order = ['patch', 'move', 'manual', 'create'];
227
+ const label = { patch: 'editar (patch)', move: 'mover', manual: 'ajuste manual', create: 'criar' };
228
+ for (const kind of order) {
229
+ const items = edits.changes.filter((c) => c.kind === kind);
230
+ if (!items.length)
231
+ continue;
232
+ lines.push(`### ${label[kind]}`);
233
+ for (const c of items)
234
+ lines.push(`- \`${c.path}${c.lines ? `:${c.lines[0]}${c.lines[1] !== c.lines[0] ? `-${c.lines[1]}` : ''}` : ''}\` — ${c.description}`);
235
+ }
236
+ return lines.join('\n');
237
+ }
238
+ /* ---------------- arquivos gerados ---------------- */
239
+ export function lockFile(ctx, analysis, edits) {
240
+ const stacks = edits.matched.filter((s) => s.handover !== 'unsupported-terraform');
241
+ return JSON.stringify({
242
+ version: 1,
243
+ generatedBy: `fg-tracker-mcp@${ctx.version}`,
244
+ generatedAt: new Date().toISOString(),
245
+ status: 'pending-merge',
246
+ project: { id: ctx.projectId, slug: ctx.projectSlug, name: ctx.projectName, url: ctx.endpoint },
247
+ accountId: ctx.accountId,
248
+ environment: ctx.environment,
249
+ regions: ctx.regions,
250
+ stacks: stacks.map((s) => ({ name: s.name, constructId: s.constructId, region: ctx.stackRegions[s.name] ?? ctx.regions[0] ?? null, owner: 'fg-tracker', tool: s.tool, sourceFiles: s.sourceFiles, codeDeploy: s.handover === 'needs-code-deploy-split' })),
251
+ cdkApps: analysis.cdkApps.map((a) => ({ dir: a.dir, cdkJson: a.cdkJson, entryFiles: a.entryFiles })),
252
+ codeDeploy: { command: CODE_DEPLOY_COMMAND },
253
+ guard: { script: GUARD_PATH, tag: 'fg-tracker:owner=true' },
254
+ }, null, 2) + '\n';
255
+ }
256
+ export const GUARD_SCRIPT = `#!/usr/bin/env node
257
+ // Guard do FG Tracker (gerado por fg-tracker-mcp). Falha o CI se um stack transferido ao FG Tracker
258
+ // (infra/fg-tracker.lock.json) ou marcado com fg-tracker:owner=true for sintetizado/implantado pelo repositório.
259
+ // Uso: node scripts/fg-tracker-guard.mjs [--cdk-out <dir>] [--lock <arquivo>] [--aws] [-- <stacks do cdk deploy>]
260
+ // --aws consulta as tags dos stacks sintetizados com \`aws cloudformation describe-stacks\` (somente leitura).
261
+ import { existsSync, readFileSync } from 'node:fs';
262
+ import { spawnSync } from 'node:child_process';
263
+ import { dirname, join, resolve } from 'node:path';
264
+ import { fileURLToPath } from 'node:url';
265
+
266
+ const root = resolve(dirname(fileURLToPath(import.meta.url)), '..');
267
+ const args = process.argv.slice(2);
268
+ const flag = (name) => { const i = args.indexOf(name); return i >= 0 ? args[i + 1] : undefined; };
269
+ const sep = args.indexOf('--');
270
+ const deployArgs = sep >= 0 ? args.slice(sep + 1).filter((a) => !a.startsWith('-')) : [];
271
+ const lockPath = resolve(root, flag('--lock') ?? 'infra/fg-tracker.lock.json');
272
+
273
+ if (!existsSync(lockPath)) {
274
+ console.log('[fg-tracker-guard] sem ' + lockPath + ': nada a verificar.');
275
+ process.exit(0);
276
+ }
277
+ const lock = JSON.parse(readFileSync(lockPath, 'utf8'));
278
+ const owned = new Set((lock.stacks ?? []).flatMap((s) => [s.name, s.constructId].filter(Boolean)));
279
+ const violations = [];
280
+
281
+ // 1) Stacks passados ao cdk deploy.
282
+ for (const name of deployArgs) if (owned.has(name)) violations.push('cdk deploy recebeu o stack transferido "' + name + '"');
283
+
284
+ // 2) Assembly sintetizado (cdk.out/manifest.json).
285
+ const outDirs = new Set([flag('--cdk-out'), process.env.CDK_OUT, ...(lock.cdkApps ?? []).map((a) => join(a.dir, 'cdk.out'))].filter(Boolean).map((d) => resolve(root, d)));
286
+ const synthesized = [];
287
+ for (const dir of outDirs) {
288
+ const manifestPath = join(dir, 'manifest.json');
289
+ if (!existsSync(manifestPath)) continue;
290
+ const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
291
+ for (const [id, artifact] of Object.entries(manifest.artifacts ?? {})) {
292
+ if (artifact.type !== 'aws:cloudformation:stack') continue;
293
+ const name = artifact.properties?.stackName ?? id;
294
+ const tags = artifact.properties?.tags ?? {};
295
+ synthesized.push({ name, region: artifact.environment?.split('/').pop() });
296
+ if (owned.has(name) || owned.has(id)) violations.push('stack transferido "' + name + '" está no app CDK (' + manifestPath + ')');
297
+ else if (tags['fg-tracker:owner'] === 'true') violations.push('stack "' + name + '" tem a tag fg-tracker:owner=true');
298
+ }
299
+ }
300
+
301
+ // 3) Código-fonte do app: reintrodução de new XStack(app, 'Nome').
302
+ for (const app of lock.cdkApps ?? []) {
303
+ for (const file of app.entryFiles ?? []) {
304
+ const path = resolve(root, file);
305
+ if (!existsSync(path)) continue;
306
+ const src = readFileSync(path, 'utf8');
307
+ for (const name of owned) {
308
+ const esc = name.replace(/[.*+?^\${}()|[\\]\\\\]/g, '\\\\$&');
309
+ if (new RegExp("new\\\\s+[\\\\w$.]+\\\\s*\\\\(\\\\s*[\\\\w$.]+\\\\s*,\\\\s*['\\"\`]" + esc + "['\\"\`]").test(src) || new RegExp("stackName\\\\s*:\\\\s*['\\"\`]" + esc + "['\\"\`]").test(src)) {
310
+ violations.push('stack transferido "' + name + '" voltou a ser instanciado em ' + file);
311
+ }
312
+ }
313
+ }
314
+ }
315
+
316
+ // 4) Opcional: tags dos stacks implantados (somente leitura).
317
+ if (args.includes('--aws')) {
318
+ for (const s of synthesized) {
319
+ const r = spawnSync('aws', ['cloudformation', 'describe-stacks', '--stack-name', s.name, ...(s.region && s.region !== 'unknown-region' ? ['--region', s.region] : []), '--query', 'Stacks[0].Tags', '--output', 'json'], { encoding: 'utf8' });
320
+ if (r.status !== 0) continue;
321
+ const tags = JSON.parse(r.stdout || '[]') ?? [];
322
+ if (tags.some((t) => t.Key === 'fg-tracker:owner' && t.Value === 'true')) violations.push('stack implantado "' + s.name + '" é controlado pelo FG Tracker (tag fg-tracker:owner=true)');
323
+ }
324
+ }
325
+
326
+ if (violations.length) {
327
+ console.error('[fg-tracker-guard] deploy bloqueado:');
328
+ for (const v of [...new Set(violations)]) console.error(' - ' + v);
329
+ console.error('Esses stacks são controlados pelo FG Tracker (' + (lock.project?.url ?? '') + '). Altere a infra pelo diagrama ou faça a ejeção antes de implantá-los pelo repositório.');
330
+ process.exit(1);
331
+ }
332
+ console.log('[fg-tracker-guard] ok: nenhum stack do FG Tracker no deploy (' + owned.size + ' transferido(s)).');
333
+ `;
334
+ export function handoverDoc(ctx, edits, branch) {
335
+ const stacks = edits.matched.filter((s) => s.handover !== 'unsupported-terraform');
336
+ const split = stacks.filter((s) => s.handover === 'needs-code-deploy-split');
337
+ return [
338
+ `# Transferência de controle ao FG Tracker — ${ctx.projectName}`,
339
+ '',
340
+ `Este PR transfere ao FG Tracker o controle dos stacks CloudFormation abaixo. Os stacks mantêm nome e recursos físicos; muda só quem gera e aplica o template. O merge é a confirmação humana; depois dele o FG Tracker marca os stacks com \`fg-tracker:owner=true\`, aplica a stack policy e roda um change set de verificação que precisa sair vazio.`,
341
+ '',
342
+ '| stack | região | ferramenta | código implantado junto |',
343
+ '|---|---|---|---|',
344
+ ...stacks.map((s) => `| \`${s.name}\` | ${ctx.stackRegions[s.name] ?? ctx.regions[0] ?? '—'} | ${s.tool} | ${s.handover === 'needs-code-deploy-split' ? `sim (${uniqKinds(s)})` : 'não'} |`),
345
+ '',
346
+ `Projeto: \`${ctx.projectSlug}\` · conta: \`${ctx.accountId ?? '—'}\` · ambiente: ${ctx.environment ?? '—'} · branch: \`${branch}\`.`,
347
+ '',
348
+ '## O que muda',
349
+ '',
350
+ `- **App CDK e CI**: os stacks saem do app e do \`cdk deploy\` (patch \`${PATCH_PATH}\`); o código das classes vai para \`${HANDOVER_DIR}/\`.`,
351
+ `- **Deploy de código separado**: o CI só constrói artefatos (zip no S3, imagem no ECR) e chama \`${CODE_DEPLOY_COMMAND}\`.`,
352
+ `- **Guard no CI**: \`node ${GUARD_PATH}\` falha se um stack transferido (ou com \`fg-tracker:owner=true\`) voltar ao deploy.`,
353
+ `- **Registro**: \`${LOCK_PATH}\` com projeto, conta, ambiente e stacks.`,
354
+ '',
355
+ '## Passos do GitHub Actions',
356
+ '',
357
+ '```yaml',
358
+ ' - name: Guard FG Tracker',
359
+ ` run: node ${GUARD_PATH}`,
360
+ ...(split.length
361
+ ? [
362
+ ' # Build dos artefatos que antes eram assets do CDK (ajuste ao projeto):',
363
+ ...split.flatMap((s) => s.assets.slice(0, 5).map((a) => ` # ${s.name}: ${a.kind} em ${a.file}:${a.line}${a.detail ? ` (${a.detail})` : ''}`)),
364
+ ' - name: Build dos artefatos',
365
+ ' run: pnpm install --frozen-lockfile && pnpm build',
366
+ ]
367
+ : []),
368
+ ' - name: Deploy de código pelo FG Tracker',
369
+ ' run: npx fg-tracker-release deploy --release ${{ github.sha }}',
370
+ ' env:',
371
+ ` FG_TRACKER_URL: ${ctx.endpoint}`,
372
+ ' FG_TRACKER_KEY: ${{ secrets.FG_TRACKER_KEY }}',
373
+ '```',
374
+ '',
375
+ '## Emergência (FG Tracker indisponível)',
376
+ '',
377
+ 'O último template de cada stack fica no bucket S3 de break glass da sua conta (criado pelo stack de conexão). Para operar sem o FG Tracker:',
378
+ '',
379
+ '```bash',
380
+ 'aws cloudformation create-change-set --stack-name <stack> --change-set-name break-glass \\',
381
+ ' --template-url https://<bucket-break-glass>.s3.amazonaws.com/<stack>/latest.json --capabilities CAPABILITY_NAMED_IAM',
382
+ 'aws cloudformation describe-change-set --stack-name <stack> --change-set-name break-glass # revise',
383
+ 'aws cloudformation execute-change-set --stack-name <stack> --change-set-name break-glass',
384
+ '```',
385
+ '',
386
+ '## Ejeção',
387
+ '',
388
+ 'A qualquer momento, "Ejetar" no FG Tracker (`POST /infra/handover/:id/eject`) exporta o estado desejado como app CDK + template e abre um PR que devolve o controle ao repositório; remova a entrada do lock e o guard deixa de bloquear.',
389
+ '',
390
+ ...(edits.warnings.length ? ['## Pendências', '', ...edits.warnings.map((w) => `- ${w}`), ''] : []),
391
+ ].join('\n');
392
+ }
393
+ export function handoverReadme(edits) {
394
+ return [
395
+ '# Arquivo da transferência ao FG Tracker',
396
+ '',
397
+ 'Gerado por `infra_open_handover_pr` (fg-tracker-mcp). Nada foi removido automaticamente.',
398
+ '',
399
+ '1. Aplique as edições do app CDK, do CI e do README:',
400
+ ' ```bash',
401
+ ` git apply --check ${PATCH_PATH} && git apply ${PATCH_PATH}`,
402
+ ' ```',
403
+ '2. Arquive o código das classes de stack transferidas (sem apagar):',
404
+ ' ```bash',
405
+ ...(edits.moves.length ? edits.moves.map((m) => ` mkdir -p ${posix.dirname(m.to)} && git mv ${m.from} ${m.to}`) : [' # nenhuma classe exclusiva dos stacks transferidos']),
406
+ ' ```',
407
+ ` Exclua \`${HANDOVER_DIR}\` da compilação (\`"exclude": ["${HANDOVER_DIR}"]\` no tsconfig do app CDK).`,
408
+ '3. Confira: `npx cdk ls` não lista os stacks transferidos e `node scripts/fg-tracker-guard.mjs` passa.',
409
+ '4. Resolva as pendências manuais listadas em `docs/fg-tracker-handover.md`.',
410
+ '5. Após o merge, conclua no FG Tracker (tool `infra_complete_handover` ou botão na tela).',
411
+ '',
412
+ 'Stacks:',
413
+ ...edits.matched.map((s) => `- ${s.name} (${s.tool}) — ${s.sourceFiles.join(', ')}`),
414
+ '',
415
+ ].join('\n');
416
+ }
417
+ async function exists(path) {
418
+ try {
419
+ await access(path);
420
+ return true;
421
+ }
422
+ catch {
423
+ return false;
424
+ }
425
+ }
426
+ export async function writeHandoverFiles(root, files) {
427
+ const out = [];
428
+ for (const [rel, content] of Object.entries(files)) {
429
+ const abs = join(root, rel);
430
+ const overwritten = await exists(abs);
431
+ await mkdir(dirname(abs), { recursive: true });
432
+ await writeFile(abs, content, rel.endsWith('.mjs') ? { encoding: 'utf8', mode: 0o755 } : 'utf8');
433
+ out.push({ path: rel, overwritten });
434
+ }
435
+ return out;
436
+ }
437
+ //# sourceMappingURL=handover.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handover.js","sourceRoot":"","sources":["../../src/infra/handover.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ export type IacTool = 'cdk' | 'sam' | 'serverless' | 'terraform' | 'cloudformation';
2
+ export type HandoverFeasibility = 'ok' | 'needs-code-deploy-split' | 'unsupported-terraform';
3
+ export interface IacAsset {
4
+ kind: string;
5
+ file: string;
6
+ line: number;
7
+ detail: string;
8
+ }
9
+ export interface IacStack {
10
+ /** Nome do stack no CloudFormation (stackName explícito ou id do construct). */
11
+ name: string;
12
+ constructId: string | null;
13
+ className: string | null;
14
+ tool: IacTool;
15
+ appDir: string;
16
+ /** Arquivo onde o stack é instanciado (`new XStack(app, 'Name')`) ou o template. */
17
+ entryFile: string | null;
18
+ /** Linhas (1-based, inclusivas) do statement de instanciação. */
19
+ entryLines: [number, number] | null;
20
+ variable: string | null;
21
+ /** O statement ocupa linhas inteiras (pode ser removido do app sem quebrar a sintaxe). */
22
+ standalone: boolean;
23
+ sourceFiles: string[];
24
+ env: string | null;
25
+ constructs: string[];
26
+ assets: IacAsset[];
27
+ resourceTypes: string[];
28
+ handover: HandoverFeasibility;
29
+ notes: string[];
30
+ }
31
+ export interface DeployCommand {
32
+ file: string;
33
+ line: number;
34
+ tool: 'cdk' | 'sam' | 'serverless' | 'terraform';
35
+ text: string;
36
+ /** Stacks explícitos no comando; `['*']` para `--all`; vazio = padrão do app. */
37
+ stacks: string[];
38
+ }
39
+ export interface CdkApp {
40
+ dir: string;
41
+ cdkJson: string;
42
+ appCommand: string | null;
43
+ entryFiles: string[];
44
+ contextKeys: string[];
45
+ }
46
+ export interface IacAnalysis {
47
+ root: string;
48
+ tools: IacTool[];
49
+ cdkApps: CdkApp[];
50
+ stacks: IacStack[];
51
+ deployCommands: DeployCommand[];
52
+ warnings: string[];
53
+ filesScanned: number;
54
+ }
55
+ export declare function analyzeIac(root: string): Promise<IacAnalysis>;
56
+ export declare function formatIac(a: IacAnalysis): string;