fg-tracker-mcp 0.4.0 → 0.5.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.
- package/CHANGELOG.md +6 -0
- package/README.md +2 -0
- package/dist/docs.d.ts +1 -1
- package/dist/docs.js +11 -1
- package/dist/docs.js.map +1 -1
- package/dist/infra/aws.d.ts +51 -0
- package/dist/infra/aws.js +393 -0
- package/dist/infra/aws.js.map +1 -0
- package/dist/infra/diff.d.ts +15 -0
- package/dist/infra/diff.js +108 -0
- package/dist/infra/diff.js.map +1 -0
- package/dist/infra/files.d.ts +16 -0
- package/dist/infra/files.js +115 -0
- package/dist/infra/files.js.map +1 -0
- package/dist/infra/handover.d.ts +47 -0
- package/dist/infra/handover.js +437 -0
- package/dist/infra/handover.js.map +1 -0
- package/dist/infra/iac.d.ts +56 -0
- package/dist/infra/iac.js +378 -0
- package/dist/infra/iac.js.map +1 -0
- package/dist/infra/instrument.d.ts +6 -0
- package/dist/infra/instrument.js +140 -0
- package/dist/infra/instrument.js.map +1 -0
- package/dist/infra/tools.d.ts +8 -0
- package/dist/infra/tools.js +620 -0
- package/dist/infra/tools.js.map +1 -0
- package/dist/server.d.ts +1 -1
- package/dist/server.js +5 -1
- package/dist/server.js.map +1 -1
- package/package.json +5 -3
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/** Gerador de unified diff (compatível com `git apply`) a partir de edições por linha. */
|
|
2
|
+
export function splitLines(content) {
|
|
3
|
+
if (content === '')
|
|
4
|
+
return { lines: [], trailingNewline: true };
|
|
5
|
+
const lines = content.split('\n');
|
|
6
|
+
const trailingNewline = lines[lines.length - 1] === '';
|
|
7
|
+
if (trailingNewline)
|
|
8
|
+
lines.pop();
|
|
9
|
+
return { lines, trailingNewline };
|
|
10
|
+
}
|
|
11
|
+
export function applyEdits(lines, edits) {
|
|
12
|
+
const out = [...lines];
|
|
13
|
+
for (const e of [...edits].sort((a, b) => b.start - a.start))
|
|
14
|
+
out.splice(e.start, e.deleteCount, ...e.insert);
|
|
15
|
+
return out;
|
|
16
|
+
}
|
|
17
|
+
/** Remove sobreposições (mantém a primeira edição de cada região). */
|
|
18
|
+
export function normalizeEdits(edits) {
|
|
19
|
+
const sorted = [...edits].sort((a, b) => a.start - b.start || b.deleteCount - a.deleteCount);
|
|
20
|
+
const out = [];
|
|
21
|
+
let lastEnd = -1;
|
|
22
|
+
for (const e of sorted) {
|
|
23
|
+
if (e.start < lastEnd)
|
|
24
|
+
continue;
|
|
25
|
+
out.push(e);
|
|
26
|
+
lastEnd = e.start + e.deleteCount;
|
|
27
|
+
}
|
|
28
|
+
return out;
|
|
29
|
+
}
|
|
30
|
+
export function unifiedDiff(path, content, rawEdits, context = 3) {
|
|
31
|
+
if (content === null) {
|
|
32
|
+
const added = rawEdits.flatMap((e) => e.insert);
|
|
33
|
+
return [`diff --git a/${path} b/${path}`, 'new file mode 100644', '--- /dev/null', `+++ b/${path}`, `@@ -0,0 +1,${added.length} @@`, ...added.map((l) => `+${l}`), ''].join('\n');
|
|
34
|
+
}
|
|
35
|
+
const { lines, trailingNewline } = splitLines(content);
|
|
36
|
+
const edits = normalizeEdits(rawEdits);
|
|
37
|
+
if (!edits.length)
|
|
38
|
+
return '';
|
|
39
|
+
const n = lines.length;
|
|
40
|
+
const groups = [];
|
|
41
|
+
for (const e of edits) {
|
|
42
|
+
const g = groups[groups.length - 1];
|
|
43
|
+
const prev = g?.[g.length - 1];
|
|
44
|
+
if (g && prev && e.start - (prev.start + prev.deleteCount) <= context * 2)
|
|
45
|
+
g.push(e);
|
|
46
|
+
else
|
|
47
|
+
groups.push([e]);
|
|
48
|
+
}
|
|
49
|
+
const out = [`diff --git a/${path} b/${path}`, `--- a/${path}`, `+++ b/${path}`];
|
|
50
|
+
let offset = 0;
|
|
51
|
+
for (const g of groups) {
|
|
52
|
+
const first = g[0];
|
|
53
|
+
const last = g[g.length - 1];
|
|
54
|
+
const oldStart = Math.max(0, first.start - context);
|
|
55
|
+
const oldEnd = Math.min(n, last.start + last.deleteCount + context);
|
|
56
|
+
const body = [];
|
|
57
|
+
let oldCount = 0;
|
|
58
|
+
let newCount = 0;
|
|
59
|
+
let i = oldStart;
|
|
60
|
+
let k = 0;
|
|
61
|
+
const noEol = '\';
|
|
62
|
+
while (i < oldEnd || (k < g.length && g[k].start === i)) {
|
|
63
|
+
const e = g[k];
|
|
64
|
+
if (e && e.start === i) {
|
|
65
|
+
for (let d = 0; d < e.deleteCount; d++) {
|
|
66
|
+
body.push(`-${lines[i + d] ?? ''}`);
|
|
67
|
+
oldCount++;
|
|
68
|
+
if (!trailingNewline && i + d === n - 1)
|
|
69
|
+
body.push(noEol);
|
|
70
|
+
}
|
|
71
|
+
for (const ins of e.insert) {
|
|
72
|
+
body.push(`+${ins}`);
|
|
73
|
+
newCount++;
|
|
74
|
+
}
|
|
75
|
+
i += e.deleteCount;
|
|
76
|
+
k++;
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
if (i >= oldEnd)
|
|
80
|
+
break;
|
|
81
|
+
const line = lines[i] ?? '';
|
|
82
|
+
if (!trailingNewline && i === n - 1) {
|
|
83
|
+
const insertsAfter = k < g.length && g[k].start === n;
|
|
84
|
+
if (insertsAfter) {
|
|
85
|
+
body.push(`-${line}`, noEol, `+${line}`);
|
|
86
|
+
oldCount++;
|
|
87
|
+
newCount++;
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
body.push(` ${line}`, noEol);
|
|
91
|
+
oldCount++;
|
|
92
|
+
newCount++;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
body.push(` ${line}`);
|
|
97
|
+
oldCount++;
|
|
98
|
+
newCount++;
|
|
99
|
+
}
|
|
100
|
+
i++;
|
|
101
|
+
}
|
|
102
|
+
const newStart = oldStart + offset;
|
|
103
|
+
out.push(`@@ -${oldCount ? oldStart + 1 : oldStart},${oldCount} +${newCount ? newStart + 1 : newStart},${newCount} @@`, ...body);
|
|
104
|
+
offset += newCount - oldCount;
|
|
105
|
+
}
|
|
106
|
+
return out.join('\n') + '\n';
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff.js","sourceRoot":"","sources":["../../src/infra/diff.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare const IGNORED_DIRS: Set<string>;
|
|
2
|
+
export interface WalkOptions {
|
|
3
|
+
maxFiles?: number;
|
|
4
|
+
maxDepth?: number;
|
|
5
|
+
}
|
|
6
|
+
/** Lista arquivos (caminhos relativos em formato POSIX), ignorando diretórios pesados. */
|
|
7
|
+
export declare function walkFiles(root: string, options?: WalkOptions): Promise<{
|
|
8
|
+
files: string[];
|
|
9
|
+
truncated: boolean;
|
|
10
|
+
}>;
|
|
11
|
+
export declare function readText(abs: string): Promise<string | null>;
|
|
12
|
+
export declare function lineOf(content: string, index: number): number;
|
|
13
|
+
export declare function isSourceFile(path: string): boolean;
|
|
14
|
+
export declare function isTestFile(path: string): boolean;
|
|
15
|
+
/** Índice do parêntese que fecha o aberto em `openIndex` (ignora strings e comentários simples). */
|
|
16
|
+
export declare function matchParen(content: string, openIndex: number): number;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/** Varredura do repositório local (somente leitura), comum às tools de IaC e instrumentação. */
|
|
2
|
+
import { readFile, readdir, stat } from 'node:fs/promises';
|
|
3
|
+
import { join, relative, sep } from 'node:path';
|
|
4
|
+
export const IGNORED_DIRS = new Set([
|
|
5
|
+
'node_modules', '.git', 'cdk.out', 'dist', 'build', '.next', 'coverage', '.terraform', '.serverless', '.aws-sam',
|
|
6
|
+
'.turbo', '.cache', 'out', 'vendor', '.venv', 'venv', '__pycache__', 'tmp', '.idea', '.vscode',
|
|
7
|
+
]);
|
|
8
|
+
/** Lista arquivos (caminhos relativos em formato POSIX), ignorando diretórios pesados. */
|
|
9
|
+
export async function walkFiles(root, options = {}) {
|
|
10
|
+
const maxFiles = options.maxFiles ?? 8000;
|
|
11
|
+
const maxDepth = options.maxDepth ?? 10;
|
|
12
|
+
const files = [];
|
|
13
|
+
let truncated = false;
|
|
14
|
+
async function visit(dir, depth) {
|
|
15
|
+
if (files.length >= maxFiles) {
|
|
16
|
+
truncated = true;
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
let entries;
|
|
20
|
+
try {
|
|
21
|
+
entries = await readdir(dir, { withFileTypes: true });
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
entries.sort((a, b) => a.name.localeCompare(b.name));
|
|
27
|
+
for (const entry of entries) {
|
|
28
|
+
if (files.length >= maxFiles) {
|
|
29
|
+
truncated = true;
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const abs = join(dir, entry.name);
|
|
33
|
+
if (entry.isDirectory()) {
|
|
34
|
+
if (IGNORED_DIRS.has(entry.name) || (entry.name.startsWith('.') && entry.name !== '.github'))
|
|
35
|
+
continue;
|
|
36
|
+
if (depth < maxDepth)
|
|
37
|
+
await visit(abs, depth + 1);
|
|
38
|
+
}
|
|
39
|
+
else if (entry.isFile()) {
|
|
40
|
+
files.push(relative(root, abs).split(sep).join('/'));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
await visit(root, 0);
|
|
45
|
+
return { files, truncated };
|
|
46
|
+
}
|
|
47
|
+
const MAX_BYTES = 512 * 1024;
|
|
48
|
+
export async function readText(abs) {
|
|
49
|
+
try {
|
|
50
|
+
const s = await stat(abs);
|
|
51
|
+
if (!s.isFile() || s.size > MAX_BYTES)
|
|
52
|
+
return null;
|
|
53
|
+
return await readFile(abs, 'utf8');
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
export function lineOf(content, index) {
|
|
60
|
+
let line = 1;
|
|
61
|
+
for (let i = 0; i < index && i < content.length; i++)
|
|
62
|
+
if (content.charCodeAt(i) === 10)
|
|
63
|
+
line++;
|
|
64
|
+
return line;
|
|
65
|
+
}
|
|
66
|
+
export function isSourceFile(path) {
|
|
67
|
+
return /\.(ts|tsx|js|mjs|cjs|jsx)$/.test(path) && !/\.d\.ts$/.test(path);
|
|
68
|
+
}
|
|
69
|
+
export function isTestFile(path) {
|
|
70
|
+
return /(^|\/)(test|tests|__tests__|__mocks__)\//.test(path) || /\.(test|spec)\.[cm]?[jt]sx?$/.test(path);
|
|
71
|
+
}
|
|
72
|
+
/** Índice do parêntese que fecha o aberto em `openIndex` (ignora strings e comentários simples). */
|
|
73
|
+
export function matchParen(content, openIndex) {
|
|
74
|
+
let depth = 0;
|
|
75
|
+
let quote = null;
|
|
76
|
+
for (let i = openIndex; i < content.length; i++) {
|
|
77
|
+
const c = content[i];
|
|
78
|
+
if (quote) {
|
|
79
|
+
if (c === '\\') {
|
|
80
|
+
i++;
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
if (c === quote)
|
|
84
|
+
quote = null;
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
if (c === '"' || c === "'" || c === '`') {
|
|
88
|
+
quote = c;
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
if (c === '/' && content[i + 1] === '/') {
|
|
92
|
+
const nl = content.indexOf('\n', i);
|
|
93
|
+
if (nl < 0)
|
|
94
|
+
return -1;
|
|
95
|
+
i = nl;
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
if (c === '/' && content[i + 1] === '*') {
|
|
99
|
+
const end = content.indexOf('*/', i + 2);
|
|
100
|
+
if (end < 0)
|
|
101
|
+
return -1;
|
|
102
|
+
i = end + 1;
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if (c === '(')
|
|
106
|
+
depth++;
|
|
107
|
+
else if (c === ')') {
|
|
108
|
+
depth--;
|
|
109
|
+
if (depth === 0)
|
|
110
|
+
return i;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return -1;
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/infra/files.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { IacAnalysis, IacStack } from './iac.js';
|
|
2
|
+
export declare const LOCK_PATH = "infra/fg-tracker.lock.json";
|
|
3
|
+
export declare const GUARD_PATH = "scripts/fg-tracker-guard.mjs";
|
|
4
|
+
export declare const DOC_PATH = "docs/fg-tracker-handover.md";
|
|
5
|
+
export declare const HANDOVER_DIR = "infra/_handover";
|
|
6
|
+
export declare const PATCH_PATH = "infra/_handover/fg-tracker-handover.patch";
|
|
7
|
+
export declare const HANDOVER_README = "infra/_handover/README.md";
|
|
8
|
+
export declare const CODE_DEPLOY_COMMAND = "npx fg-tracker-release deploy --release <sha>";
|
|
9
|
+
export interface HandoverContext {
|
|
10
|
+
projectId: string;
|
|
11
|
+
projectSlug: string;
|
|
12
|
+
projectName: string;
|
|
13
|
+
endpoint: string;
|
|
14
|
+
accountId: string | null;
|
|
15
|
+
environment: string | null;
|
|
16
|
+
regions: string[];
|
|
17
|
+
stackRegions: Record<string, string | null>;
|
|
18
|
+
version: string;
|
|
19
|
+
}
|
|
20
|
+
export interface FileChange {
|
|
21
|
+
path: string;
|
|
22
|
+
kind: 'patch' | 'create' | 'move' | 'manual';
|
|
23
|
+
description: string;
|
|
24
|
+
lines?: [number, number];
|
|
25
|
+
}
|
|
26
|
+
export interface HandoverEdits {
|
|
27
|
+
matched: IacStack[];
|
|
28
|
+
missing: string[];
|
|
29
|
+
unsupported: IacStack[];
|
|
30
|
+
changes: FileChange[];
|
|
31
|
+
patch: string;
|
|
32
|
+
moves: Array<{
|
|
33
|
+
from: string;
|
|
34
|
+
to: string;
|
|
35
|
+
}>;
|
|
36
|
+
warnings: string[];
|
|
37
|
+
}
|
|
38
|
+
export declare function buildHandoverEdits(root: string, analysis: IacAnalysis, stackNames: string[]): Promise<HandoverEdits>;
|
|
39
|
+
export declare function formatChanges(edits: HandoverEdits): string;
|
|
40
|
+
export declare function lockFile(ctx: HandoverContext, analysis: IacAnalysis, edits: HandoverEdits): string;
|
|
41
|
+
export declare const GUARD_SCRIPT = "#!/usr/bin/env node\n// Guard do FG Tracker (gerado por fg-tracker-mcp). Falha o CI se um stack transferido ao FG Tracker\n// (infra/fg-tracker.lock.json) ou marcado com fg-tracker:owner=true for sintetizado/implantado pelo reposit\u00F3rio.\n// Uso: node scripts/fg-tracker-guard.mjs [--cdk-out <dir>] [--lock <arquivo>] [--aws] [-- <stacks do cdk deploy>]\n// --aws consulta as tags dos stacks sintetizados com `aws cloudformation describe-stacks` (somente leitura).\nimport { existsSync, readFileSync } from 'node:fs';\nimport { spawnSync } from 'node:child_process';\nimport { dirname, join, resolve } from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst root = resolve(dirname(fileURLToPath(import.meta.url)), '..');\nconst args = process.argv.slice(2);\nconst flag = (name) => { const i = args.indexOf(name); return i >= 0 ? args[i + 1] : undefined; };\nconst sep = args.indexOf('--');\nconst deployArgs = sep >= 0 ? args.slice(sep + 1).filter((a) => !a.startsWith('-')) : [];\nconst lockPath = resolve(root, flag('--lock') ?? 'infra/fg-tracker.lock.json');\n\nif (!existsSync(lockPath)) {\n console.log('[fg-tracker-guard] sem ' + lockPath + ': nada a verificar.');\n process.exit(0);\n}\nconst lock = JSON.parse(readFileSync(lockPath, 'utf8'));\nconst owned = new Set((lock.stacks ?? []).flatMap((s) => [s.name, s.constructId].filter(Boolean)));\nconst violations = [];\n\n// 1) Stacks passados ao cdk deploy.\nfor (const name of deployArgs) if (owned.has(name)) violations.push('cdk deploy recebeu o stack transferido \"' + name + '\"');\n\n// 2) Assembly sintetizado (cdk.out/manifest.json).\nconst 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)));\nconst synthesized = [];\nfor (const dir of outDirs) {\n const manifestPath = join(dir, 'manifest.json');\n if (!existsSync(manifestPath)) continue;\n const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));\n for (const [id, artifact] of Object.entries(manifest.artifacts ?? {})) {\n if (artifact.type !== 'aws:cloudformation:stack') continue;\n const name = artifact.properties?.stackName ?? id;\n const tags = artifact.properties?.tags ?? {};\n synthesized.push({ name, region: artifact.environment?.split('/').pop() });\n if (owned.has(name) || owned.has(id)) violations.push('stack transferido \"' + name + '\" est\u00E1 no app CDK (' + manifestPath + ')');\n else if (tags['fg-tracker:owner'] === 'true') violations.push('stack \"' + name + '\" tem a tag fg-tracker:owner=true');\n }\n}\n\n// 3) C\u00F3digo-fonte do app: reintrodu\u00E7\u00E3o de new XStack(app, 'Nome').\nfor (const app of lock.cdkApps ?? []) {\n for (const file of app.entryFiles ?? []) {\n const path = resolve(root, file);\n if (!existsSync(path)) continue;\n const src = readFileSync(path, 'utf8');\n for (const name of owned) {\n const esc = name.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n if (new RegExp(\"new\\\\s+[\\\\w$.]+\\\\s*\\\\(\\\\s*[\\\\w$.]+\\\\s*,\\\\s*['\\\"`]\" + esc + \"['\\\"`]\").test(src) || new RegExp(\"stackName\\\\s*:\\\\s*['\\\"`]\" + esc + \"['\\\"`]\").test(src)) {\n violations.push('stack transferido \"' + name + '\" voltou a ser instanciado em ' + file);\n }\n }\n }\n}\n\n// 4) Opcional: tags dos stacks implantados (somente leitura).\nif (args.includes('--aws')) {\n for (const s of synthesized) {\n 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' });\n if (r.status !== 0) continue;\n const tags = JSON.parse(r.stdout || '[]') ?? [];\n if (tags.some((t) => t.Key === 'fg-tracker:owner' && t.Value === 'true')) violations.push('stack implantado \"' + s.name + '\" \u00E9 controlado pelo FG Tracker (tag fg-tracker:owner=true)');\n }\n}\n\nif (violations.length) {\n console.error('[fg-tracker-guard] deploy bloqueado:');\n for (const v of [...new Set(violations)]) console.error(' - ' + v);\n console.error('Esses stacks s\u00E3o controlados pelo FG Tracker (' + (lock.project?.url ?? '') + '). Altere a infra pelo diagrama ou fa\u00E7a a eje\u00E7\u00E3o antes de implant\u00E1-los pelo reposit\u00F3rio.');\n process.exit(1);\n}\nconsole.log('[fg-tracker-guard] ok: nenhum stack do FG Tracker no deploy (' + owned.size + ' transferido(s)).');\n";
|
|
42
|
+
export declare function handoverDoc(ctx: HandoverContext, edits: HandoverEdits, branch: string): string;
|
|
43
|
+
export declare function handoverReadme(edits: HandoverEdits): string;
|
|
44
|
+
export declare function writeHandoverFiles(root: string, files: Record<string, string>): Promise<Array<{
|
|
45
|
+
path: string;
|
|
46
|
+
overwritten: boolean;
|
|
47
|
+
}>>;
|