Metadata-Version: 2.4
Name: legacy-similarity-analyzer
Version: 0.1.1
Summary: Structural near-duplicate detection for COBOL programs and JCL jobs
License-Expression: Apache-2.0
Keywords: cobol,jcl,mainframe,similarity,duplicate-detection
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Quality Assurance
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# Legacy Similarity Analyzer

Ferramenta independente para encontrar JCLs e programas COBOL que podem ser
migrados como uma única implementação parametrizável, com estratégias ou
métodos sobrescritos apenas nos pontos que variam.

Ela **não altera os fontes analisados** e não importa o pacote
`mainframe_modernization_toolkit`. Os extratores deste projeto são próprios,
menores e sem dependências externas. O toolkit existente foi usado apenas como
referência para os fatos determinísticos importantes (steps/DDs/condições em
JCL e parágrafos/CALL/COPY/SQL/I-O em COBOL).

## Estratégia

Uma comparação textual simples gera muitos falsos negativos: nomes de campos,
datasets, programas e literais mudam mesmo quando o algoritmo é o mesmo. Fazer
uma comparação estrutural cara de todos contra todos, por outro lado, não
escala bem.

O analisador usa um pipeline em duas etapas:

1. **Perfil estrutural determinístico**
   - COBOL: remove comentários e áreas de sequência, canonicaliza identificadores
     locais, extrai n-grams, sequência de verbos, parágrafos, CALLs, COPYs,
     operações SQL/I-O e formatos PIC.
   - JCL: combina continuações e extrai fluxo de EXEC/DD/IF, tipo de target,
     forma dos DDs, DISP, programas, procedures, datasets e condições.
2. **Recuperação MinHash/LSH**
   - cria 64 assinaturas por artefato e 16 bandas;
   - somente itens que colidem em alguma banda viram candidatos;
   - duplicatas estruturais exatas sempre são candidatas.
3. **Pontuação explicável**
   - combina estrutura, ordem, interface e tamanho;
   - JCL nunca é comparado com COBOL;
   - o relatório mostra as parcelas da pontuação e as diferenças concretas.
4. **Agrupamento conservador (complete-link incremental)**
   - um arquivo só entra no grupo se atingir o limiar contra **todos** os
     membros existentes;
   - isso evita o perigoso efeito corrente: A é parecido com B, B com C, mas
     A não é parecido com C.

Para aproximadamente 700 JCLs e 500 COBOLs, Python é suficiente. Há cerca de
370 mil pares possíveis separados por tipo; o LSH normalmente elimina a maior
parte antes da comparação detalhada. Spark só passa a ser interessante para
milhões de artefatos ou quando os perfis já vivem em um data lake distribuído.

## Uso

Requer Python 3.10 ou superior e não possui dependências de runtime.

```bash
cd legacy_similarity_analyzer
python -m pip install -e .
legacy-similarity /caminho/do/codebase \
  --config similarity-config.json \
  --output similarity-report.json \
  --threshold 0.80 \
  --cluster-threshold 0.82
```

A execução gera dois relatórios:

- `similarity-report.json`: relatório completo, incluindo artefatos e grupos;
- `similarity-report.csv`: relação simples entre arquivo e cluster, pronta para
  banco relacional, Excel, Google Sheets ou ingestão em Spark.

O CSV possui somente duas colunas e inclui todos os arquivos analisados:

```csv
programa,cluster_id
cobol/BILL001.cbl,COBOL-0001
cobol/BILL999.cbl,COBOL-0001
cobol/UNIQUE.cbl,
jcl/DAILY.jcl,JCL-0001
jcl/MONTHLY.jcl,JCL-0001
```

Um `cluster_id` vazio significa que o arquivo não foi agrupado com nenhum
outro artefato.

O caminho do CSV é derivado automaticamente do JSON. Para escolher outro:

```bash
legacy-similarity /caminho/do/codebase \
  --output reports/full-report.json \
  --csv-output reports/similar-pairs.csv
```

O arquivo de configuração determina exclusivamente quais extensões representam
JCL e COBOL. Não há inferência pelo conteúdo:

```json
{
  "jclExtensions": [".jcl", ".proc", ".prc", ".job"],
  "cobolExtensions": [".cbl", ".cob", ".cobol", ".pgm"]
}
```

O ponto inicial é opcional (`"jcl"` e `".jcl"` são equivalentes), e a
comparação não diferencia maiúsculas de minúsculas. Veja também
`similarity-config.example.json`.

Também pode ser usado como classe:

```python
from legacy_similarity import LegacySimilarityAnalyzer, SimilarityConfig

analyzer = LegacySimilarityAnalyzer(
    SimilarityConfig(
        jcl_suffixes=(".job", ".proc"),
        cobol_suffixes=(".pgm", ".cbl"),
        similarity_threshold=0.80,
        cluster_threshold=0.82,
    )
)
report = analyzer.analyze_directory("/caminho/do/codebase")
report.write_json("similarity-report.json")
report.write_csv("similarity-report.csv")

# Comparação direta, útil durante uma revisão:
pair = analyzer.compare_files("jobs/DAILY.jcl", "jobs/MONTHLY.jcl")
print(pair.score, pair.differences)
```

O JSON contém:

- `groups`: candidatos seguros para uma implementação comum;
- `matches`: pares semelhantes, suas pontuações e diferenças;
- `artifacts`: fatos extraídos para auditoria;
- `stats`: redução de candidatos e tempo de cada etapa.

## Como usar o resultado na migração

O grupo é uma hipótese de consolidação, não uma autorização automática para
apagar regras legadas. Para cada grupo:

1. escolha o `representative` como base da especificação determinística;
2. transforme `variationPoints` em parâmetros, Strategy objects ou métodos
   protegidos/sobrescritos;
3. execute os geradores de documentação, cápsulas e testes de caracterização
   do toolkit para **cada membro**;
4. somente consolide quando todos os testes do legado passarem contra a mesma
   implementação moderna.

Comece com limiar `0.85` para alta precisão. Depois revise falsos negativos e
reduza gradualmente até `0.78`–`0.80`. Não é recomendável usar abaixo de `0.70`
para decidir consolidação sem uma revisão humana forte.

## Testes

```bash
python -m unittest discover -s tests -v
```
