Free MCP tools reference¶
Auto-generated from the real MCP tool registry — the exact tools/list response a free-tier client receives (silex-archaeology 0.12.12). 14 tools. Drift between this page and the registry fails the site build (--check).
create_workspace¶
Create a workspace and trigger the ingestion scan in background.
Quando usar: primeiro passo pra analisar um repositório novo (kit de
onboarding — MCP-KIT-1 #1136). Próximo passo: get_workspace_stats
(poll até scan_status=completed); se não souber o workspace_id,
list_workspaces primeiro.
Two modes, both returning immediately after the workspace is registered
(BEFORE scan completes). In both cases the scan (chunking, Neo4j/SQLite
mirror, Qdrant, communities, semantic labeling) runs in a daemon thread —
check progress with get_workspace_stats(workspace_id).
FRESH-FREE-1 (#1737): terminado o scan, o índice ACOMPANHA os seus commits
sem você instalar nada — cada chamada de tool compara o HEAD que o
índice cobre com o HEAD atual (mais o git status) e re-ingere só os
arquivos tocados; toda resposta carrega index_age dizendo quantos
commits o repo andou desde o scan e se aquela chamada refrescou. O hook git
(silex-fresh-hook-install) continua valendo como OTIMIZAÇÃO (deixa o
índice pronto no próprio commit, poupando o diff na chamada), nunca como
requisito; rescan_workspace(workspace_id) é o caminho manual.
Mode git (default) — multi-repo CLONE:
Clones each repo (reusing existing clones for the same URL+branch) and
registers one Repo per spec. Wraps the same engine as
POST /api/workspaces.
Mode local (EXT-ZEROCONF-2 #1040) — attach IN-PLACE, no clone/copy:
Registers local_path as the workspace source via
create_workspace_with_source and scans the directory WHERE IT IS
(zero clone, zero copy). This is the Jornada B path: the "Analisar
este repositório" button in the Extension analyses the repo the user
already has open. repos is IGNORED in this mode.
| Parameter | Type | Default | Required |
|---|---|---|---|
name |
string |
— |
yes |
repos |
array | null |
None |
no |
description |
null | string |
None |
no |
source_type |
string |
'git' |
no |
local_path |
null | string |
None |
no |
include_ignored |
boolean |
False |
no |
install_claude_read_hook |
boolean |
False |
no |
Example call:
generate_domain_report¶
Generate a human-readable Markdown domain report for sharing with QA, functional analysts and tech leads.
Quando usar: fechamento do fluxo de exploração — consolidar
entidades/rules/FSMs/workflows num relatório compartilhável (kit de
onboarding — MCP-KIT-1 #1136). Próximo passo: nenhum obrigatório; para
enriquecer com LLM primeiro, confira silex.llm_provider.status e
rode de novo com enrich_with_llm=True.
Runs the full extraction pipeline, then renders a report with: - Summary (entities, rules, state machines, workflows) - Entity table with fields, relationships, PKs - State machine diagrams with transitions - Business rules table (with 🔧 heuristic / 🤖 llm badges) - Enums table - Workflow summaries - Gap analysis with severity emojis - Recommended next steps
| Parameter | Type | Default | Required |
|---|---|---|---|
workspace_id |
string |
— |
yes |
domain_id |
string |
'auto' |
no |
output_dir |
string |
'' |
no |
enrich_with_llm |
boolean |
False |
no |
llm_provider |
string |
'azure' |
no |
language |
string |
'en' |
no |
force_inline |
boolean |
False |
no |
Example call:
get_code_communities¶
Hierarchical code communities (Leiden) with members + labels — tier-aware, filtrável por arquivo e com orçamento.
Quando usar: descobrir A COMUNIDADE DE UM ARQUIVO antes de ler o código —
get_code_communities(workspace_id, member_filter="Api/services/x.py")
devolve, numa chamada barata, a comunidade que contém o arquivo e o caminho
dela até a raiz (ancestors); o id que volta é o community_id do
silex.community.code_pack. Sem member_filter, é o mapa navegável do
codebase depois do scan (kit de onboarding — MCP-KIT-1 #1136). Próximo
passo: silex.community.code_pack (código da comunidade) ou
get_structural_findings (achados sem LLM).
Orçamento por default (COMMUNITIES-PAGE-1 #1690): o mapa inteiro do
workspace do próprio Silex mede 1.183.055 chars — retorno que o cliente MCP
recusa. Agora a resposta respeita max_total_chars (default ~40k, mesma
folga do code_pack) medido no envelope como você o recebe: se não couber,
vem truncated: true com next_cursor opaco e continuation_hint —
chame de novo com cursor=<next_cursor> (MESMOS parâmetros) até não vir
mais cursor; a união das páginas reconstrói o mapa completo, sem perda nem
duplicata. Comunidade grande demais pra uma página só pagina por dentro:
members parcial vem com members_truncated: true e members_total.
max_total_chars=0 devolve tudo de uma vez (ilimitado) — e sem
member_filter/level o campo communities é byte-idêntico à lista
histórica desta tool. O index_age anexado entra na conta do orçamento
(reservado antes da paginação — FRESH-FREE-2 #1748).
member_filter: arquivo(s) ou membro(s) — um valor, lista JSON ou
separados por vírgula. Casa por igualdade case-insensitive OU por sufixo com
separador (o mirror guarda path absoluto, você informa o relativo — /,
\, caixa e prefixo .//.\ são normalizados dos dois lados antes
de comparar, PACK-FILTER-WINPATH-1 #1722/PACK-FILTER-WINPATH-2 #1727:
relativo, relativo com \, relativo com .//.\ inicial — o que o
tab-complete do PowerShell produz — e absoluto casam o MESMO membro; /
inicial e ../ NÃO são tratados como ./), a mesma tolerância do
code_pack, em QUALQUER nível (prefere o nível 0, o escopo mais coeso).
Valor sem casamento sai em filter_unmatched com lista vazia — ausência
honesta, não erro. Nome puro (sem separador) que casa mais de um ARQUIVO
distinto sai em filter_ambiguous ([{"value": ..., "matched": [...]}])
— as comunidades dos DOIS (ou mais) arquivos são servidas, nunca uma
escolhida a dedo em silêncio; dois membros do MESMO arquivo não são
ambíguos entre si, e a contagem é a MESMA do code_pack (#1727).
level: -1 (default) = todos; 1 = super-comunidades, 0 =
subs.
J1-MAPA-1 (#1077): fonte do MAPA navegável do Domain Explorer no free-tier.
Delega ao leitor canônico único fetch_communities_with_members (DOGFOOD-2 #678), que resolve o tier: no free lê .silex/workspace.db (SQLite), no
pro/enterprise lê Postgres — SHAPE IDÊNTICO nos dois. Cada comunidade
preserva a forma que generate_domain_jsons anexa no campo
communities: id, label, level, parent_id, algorithm, cohesion,
bridge_nodes, members (+ member_count e, com filtro, ancestors).
Ordem estável (supers por size desc; cada sub logo após o pai).
communities: [] quando o workspace não tem community detection rodada —
o consumidor trata como "sem mapa" (orientação #1058), nunca mapa fantasma.
Schema community_map/v1.
| Parameter | Type | Default | Required |
|---|---|---|---|
workspace_id |
string |
— |
yes |
member_filter |
string |
'' |
no |
level |
integer |
-1 |
no |
max_total_chars |
integer |
40000 |
no |
cursor |
string |
'' |
no |
Example call:
get_rules_by_ids¶
Batch-fetch rules from the materialized business_logic.json.
Quando usar: resolver linked_rule_ids (de um step de workflow ou de
silex.business_logic.submit) em rule dicts completos, num round-trip
(kit de onboarding — MCP-KIT-1 #1136). Próximo passo:
generate_domain_report pra visão consolidada do domínio.
Sprint 2026-04-17. Used by the Workflow Viewer to resolve
step.linked_rule_ids into full rule dicts in a single round-trip
(avoids N calls to get_operation_detail per workflow).
| Parameter | Type | Default | Required |
|---|---|---|---|
workspace_id |
string |
— |
yes |
rule_ids |
array |
— |
yes |
Example call:
get_structural_findings¶
Structural findings — pontes, hubs e áreas órfãs do grafo local (sem LLM).
Quando usar: depois do mapa (get_code_communities), pra achados
estruturais objetivos (pontes/hubs/órfãos) sem gastar LLM (kit de
onboarding — MCP-KIT-1 #1136). Próximo passo:
silex.community.code_pack pra aprofundar numa comunidade específica.
Orçamento por default (FINDINGS-BUDGET-1 #1723): no campo (FIPE,
2026-09-09, repo TS de 325 arquivos) esta tool devolveu 1,86 MB e o
cliente MCP recusou. Agora a resposta respeita max_total_chars (default
~40k, mesma folga do code_pack e do mapa) medido no envelope JSON como
você o recebe: se não couber, vem truncated: true com next_cursor
opaco e continuation_hint — chame de novo com cursor=<next_cursor>
(MESMOS parâmetros, inclusive max_total_chars) até não vir mais cursor;
a união das páginas reconstrói os achados completos, sem perda nem
duplicata. O corte é sempre em fronteira de ITEM (nunca achado pela metade)
e percorre as famílias na ordem do envelope. Toda família declara o conjunto
inteiro em <familia>_total (nunca omitido, mesmo quando a lista vem
parcial ou vazia nesta página) e <familia>_capped diz se a página cortou
— nunca truncamento silencioso. Um achado sozinho maior que o orçamento
(uma família de clone com 150 membros, p.ex.) vem INTEIRO e a página declara
budget_exceeded: true — nunca achado pela metade, nunca página vazia.
max_total_chars=0 devolve tudo de uma vez (ilimitado); cursor de outra
sequência (outro focus_stale, outro max_total_chars, outro
workspace) vira invalid_cursor honesto, nunca página misturada. Schema
structural_findings/v1.
Agregados também paginam (FINDINGS-BUDGET-2 #1750): no campo (3º teste,
0.12.4) o portal-relatorios tinha 488 comunidades, e
risk_markers.by_community inteiro em toda página passava do orçamento
sozinho — a paginação degenerava a 1 item/página. Agora
by_community/top_files são posições do MESMO cursor (logo depois dos
markers): numa sequência paginada, toda página declara dentro de
risk_markers o by_community_total/by_community_capped e o
top_files_total/top_files_capped (o agregado da página pode vir
parcial ou vazio), e a união das páginas reconstrói os agregados inteiros.
Resposta que cabe numa página só (e max_total_chars=0) volta
byte-idêntica, sem esses aditivos. O index_age anexado entra na conta do
orçamento. Os achados são computados UMA vez por scan e reusados enquanto
você pagina (cache por mtime do mirror no tier free: mirror mudou →
recomputa) — paginar não custa mais um cômputo inteiro por página.
ACHADOS-1 (#1114): a fonte da seção Achados do Domain Explorer (irmã do
mapa J1-MAPA-1 #1077). Fina por cima do service
compute_structural_findings, que deriva os três achados dos MESMOS dados
do mapa (comunidades de código + arestas code_references) via os leitores
canônicos tier-aware — free lê o espelho SQLite, pro/enterprise Postgres/
Neo4j. NÃO recomputa comunidades nem escreve no grafo.
Shape: {workspace_id, bridges, hubs, orphan_areas, hardcoded_secrets,
shared_literals, shared_literals_total, shared_literals_capped,
clone_families, clone_families_total, clone_families_capped,
dead_code_candidates, risk_markers,
config_usage, state_contradictions, empty_catches, empty_catches_total,
nesting_hotspots, nesting_hotspots_total, oversized_units,
oversized_units_total} (com focus_stale=True, adiciona
focus_stale_applied/focus_stale_file_count).
hardcoded_secrets (SENSOR-SECRET-1 #1200) é aditivo: connection string
Password=/Pwd= ou api key/token/secret literal em código de
aplicação, com âncora file/line e valor SEMPRE mascarado
(masked_value, nunca o segredo em claro).
shared_literals (SENSOR-LIT-1 #1201) é aditivo: literal distintivo
(≥6 chars, não-rota/SQL/path/formato) compartilhado entre arquivos de
≥2 comunidades ou 2 linguagens vira achado shared_literal com âncoras
de TODOS os arquivos envolvidos (padrão golden: FP_events PHP×JS do
SuiteCRM) — literal trivial/único/de alta frequência nunca vira achado.
Cap de 100 literais (os que cruzam mais comunidades/arquivos primeiro)
declarado via shared_literals_total/shared_literals_capped —
nunca truncamento silencioso.
clone_families (SENSOR-CLONE-1 #1202) é aditivo: bloco de código
idêntico (normalizado, janela de ≥5 linhas significativas) repetido em
≥2 arquivos de aplicação vira UMA família clone_family com TODOS os
membros ancorados (file/line_start/line_end por membro) —
nunca N achados soltos pro mesmo clone. Cap de 100 famílias (as maiores
primeiro) declarado via clone_families_total/clone_families_capped
— nunca truncamento silencioso.
dead_code_candidates (SENSOR-DEAD-1 #1203) é aditivo: símbolo de
aplicação (chunk com method) sem referência textual fora da própria
definição vira candidato dead_code_candidate com âncora e
confidence (alta privado/interno, baixa público/protegido —
reflection/DI podem chamar sem referência estática, NUNCA um veredito).
Exclusões estruturadas (entry point, handler DOM *_handler_L<linha>,
action de *Controller, override/interface, teste/vendor) nunca viram
achado — controller action pública NUNCA é flagada (anti-aceite:
falso-positivo mata a confiança no achado).
risk_markers (SENSOR-MARK-1 #1204) é aditivo:
{markers, total, by_community, top_files, top_files_total,
top_files_capped} — marcador TODO/HACK/FIXME em contexto de
comentário (//, #, /*, <!--, ' só em VB) vira achado
marker_kind/file/line/text ancorado, agregado por
comunidade e por top arquivos (cap declarado, nunca truncamento
silencioso). Marcador dentro de STRING literal (sem delimitador de
comentário na linha) nunca conta. age_days sai SEMPRE None aqui —
a leitura tier-aware não expõe root de disco resolvível pra git
blame; só o extractor de business_logic.rules (pipeline real, com
context.workspace_path) calcula a idade, best-effort, nunca quebra
sem git.
config_usage (SENSOR-CONF-1 #1205) é aditivo:
{declared_unused, used_undeclared, diagnostics} — chave declarada em
appsettings*.json/web.config sem NENHUMA leitura no código vira
declared_unused (âncora na declaração, severidade baixa); chave lida
(Configuration["K"]/AppSettings["K"]/GetValue<T>("K")/
GetSection("K")/GetConnectionString("K")) e ausente de TODA
config do repo vira used_undeclared (âncora na leitura, severidade
média — risco de runtime); declarada E lida não vira achado. Chave
passada como variável/concatenação (não literal) nunca vira candidato —
sai como diagnóstico dynamic_key (nunca silêncio). Limitação: este
consumidor só lê chunks tier-aware (sem disco) — web.config não é
chunkeado pelo ingestor hoje, então só surge aqui se presente como chunk;
o extractor real (business_logic.rules, com
context.workspace_path) lê ambos direto do disco, sem essa limitação.
state_contradictions (CONTRA-1 #1221) é aditivo: literal de estado numa
condition de regra (ex.: status != 11) cujo campo resolve pra um enum do
domínio (ex.: Situacao {1..9}) mas NÃO está entre os valores válidos vira
achado state_not_in_domain com âncora dos DOIS lados (client_anchor da
condition + domain_anchor da declaração do enum) e mensagem legível.
Reusa o parser de enum de numeric_state_catalog (não re-parseia) — enum
[Flags]/aberto tem domínio aberto e nunca contradiz; campo que não
resolve pra enum conhecido não vira achado (conservador, zero falso
positivo); literal dentro dos valores válidos não vira achado.
empty_catches/nesting_hotspots/oversized_units (SILEX-GUARD-1 #1537) são aditivos — erros recorrentes de LLM que hoje só aparecem no
gate do Sonar, ancorados file/line: catch/except vazio ou
genérico-sem-tratamento (empty|generic_only; catch com
log/throw/rethrow nunca conta); aninhamento por método acima do limiar
(default 5, threshold sempre explícito no finding); arquivo/classe
acima do limiar de LOC (defaults 400/200, derivados das âncoras dos
chunks). Positioning: o agente entrega → o guardrail (Silex) valida → o
Sonar confirma.
config_usage também declara o corte de CADA sub-lista
(declared_unused_total/used_undeclared_total/diagnostics_total)
e risk_markers mantém total/top_files_total do conjunto
COMPLETO mesmo quando os markers vêm paginados (by_community/
top_files paginam com _total/_capped próprios — #1750).
focus_stale (SILEX-GUARD-1 #1537, integração FRESH-1 #1535) é o modo
delta: com focus_stale=True, TODOS os kinds ancorados por arquivo são
filtrados à interseção com o conjunto stale corrente do mirror
(invalidate_paths) — responde "o que ESTE change trouxe", não "o que o
codebase inteiro tem". Mirror ausente/sem stale devolve tudo, NUNCA erro.
Default False preserva o contrato byte-idêntico.
Grafo/chunks sem dado → os grupos vêm vazios (o consumidor renderiza o
estado honesto, nunca achado inventado).
| Parameter | Type | Default | Required |
|---|---|---|---|
workspace_id |
string |
— |
yes |
focus_stale |
boolean |
False |
no |
max_total_chars |
integer |
40000 |
no |
cursor |
string |
'' |
no |
Example call:
get_workspace_stats¶
Get overview stats for a workspace: classes, edges, communities, languages.
language (SCAN-IGNORE-1 #1329, mesmo contrato stateless de
generate_domain_report): idioma da linha honesta vendor_generated
— "en" (default) ou "pt-br". Idioma desconhecido devolve erro
estruturado (normalize_language), nunca fallback silencioso.
Quando usar: poll depois de create_workspace até scan_status
virar completed (kit de onboarding — MCP-KIT-1 #1136). Próximo
passo: get_code_communities (mapa) quando o scan terminar.
Tier-aware (STATS-TIER-1 #1057). Este é o elo do poll do botão de 1 clique:
o free-tier não tem Neo4j instalado, então o ramo pago (que consulta o
grafo) importava neo4j incondicionalmente e o poll morria com
No module named 'neo4j' mesmo com o scan já completo.
- Tier
free: contagens vêm do espelho SQLite do workspace (workspace.db— chunks/edges/comunidades, ONBOARD-2 #667 e DOGFOOD-2 #678), SEM tocar Neo4j (o import deneo4jsó acontece no ramo pago, padrão lazy #669/#1059). Todo campo do shape tem fonte real no mirror — nenhum é hardcoded; campos sem dado no mirror caem para 0/[] honestamente (mirror vazio → contagens zeradas, não erro). - Tier pago (
pro/enterprise/legacyexplícito): comportamento byte-idêntico ao histórico (Neo4j para classes/edges/ linguagens + Postgres para comunidades). Desde REFA-1B (#1043) o mundo pesado é DECLARADO — ausência deSILEX_TIERresolve free.
O shape de resposta é IDÊNTICO entre tiers:
{workspace_id, classes, edges, communities, languages, scan_status,
heartbeat_age_seconds, stale_file_count, last_invalidation_at, scan_phase,
extraction_status, vendor_generated_excluded, ignored, purged, next_action}.
ignored (SCAN-GITIGNORE-1 #1724): {count, by_rule, sample, disabled,
git_available, fallback, warnings, traversed} — contagem honesta de TUDO
que o scan pulou, nunca silêncio. by_rule quebra por origem:
root_gitignore/nested_gitignore/info_exclude/global_excludes
(o git é a autoridade quando o diretório é um checkout git —
.gitignore da raiz E aninhado, .git/info/exclude,
core.excludesFile; sem git, PathSpec só da raiz), builtin_dirs
(poda estrutural: node_modules, dist, venv, obj…),
self_artifact (.silex//.claude/ — depósito do próprio Silex),
vendor (vendor/generated/minified), submodule, nested_git,
fallback e unknown. sample traz até 10 paths.
disabled: true quando o workspace foi criado com
include_ignored=True (opt-out): vale SÓ pro mecanismo de gitignore —
os filtros incondicionais (self_artifact, builtin_dirs) continuam
podando e contando, então count segue maior que zero. warnings/
fallback declaram degradação (git indisponível; raiz do workspace
dentro de subárvore que o repo pai ignora por inteiro) e traversed
lista o que entrou no mirror por FORA da autoridade do git (sub-repo
aninhado percorrido). None até o primeiro scan pós-#1724 completar.
purged (RESCAN-PURGE-1 #1745): {files, chunks, references} — o que o
ÚLTIMO scan completo tirou do mirror: arquivo apagado/renomeado ou que a
travessia atual não visita mais (.gitignore novo, filtro), com as
arestas dele. Comparação de path normalizada (/ × \, caixa da
unidade no Windows); o que é gravado não muda. null quando o último
completo não rodou o purge (tier pesado, 0 chunks) ou antes deste campo
existir. Nunca silêncio sobre o que SAIU do índice.
J1-DONE-1 (#1069): scan_status (registry de workspaces, mesma coluna nos
dois tiers — scanning/completed/error/pending) é o sinal de
"pipeline COMPLETO" que o poll do botão de 1 clique passou a exigir; ``classes
0`` só prova o fim do chunking (existe minutos antes de linking/Leiden/ comunidades). Campo aditivo — leitor antigo ignora.
J1-RESCAN-1 (#1071): heartbeat_age_seconds (segundos desde o
updated_at do registry, null quando indisponível) expõe a idade do
heartbeat da #1072. É a fonte que o botão usa pra distinguir scanning
vivo (idade pequena) de scanning zumbi (idade estagnada — só sobra em
kill -9), sem hardcodar heurística sem lastro no registry. Campo aditivo.
SCAN-PROGRESS-1 (#1172): scan_phase responde ONDE o scan está — não só
vivo×travado (isso já era scan_status+heartbeat_age_seconds).
Mother-smoke rodada 2 (2026-07-08): braço B esperou ~35min com o stats
"congelado" (embedding em CPU) sem saber em qual etapa. Shape:
{stage, label, index, total, result} — stage/index/total
do vocabulário e catálogo REAIS do motor (Api.ingestao.pipeline.
STAGE_LABELS/STAGES, 1-based); result traz os contadores da fase
CONCLUÍDA (null enquanto ela está em andamento). null até a 1ª
transição de fase de um scan, ou em registries anteriores a esta coluna.
Campo aditivo.
SILEX-EXTRACT-PHASE-1 (#1377): extraction_status fecha a ponta que a
SCAN-PROGRESS-1 (#1172) deixou declarada — depois do scan completo (fase
7/7 semantic_labeling), os extractors rodam em background e o stats
congelava em "7/7" enquanto o produto ainda trabalhava. Campo ADITIVO
("running"/"done"/"error"; null = workspace que nunca
rodou extractors, ou registry anterior à coluna) derivado dos eventos de
extraction que o trigger_extractors JÁ emite — nunca um segundo
catálogo de fases: scan_phase permanece EXATAMENTE as 7 fases do
pipeline (contrato #1172/j2-21). Com scan_phase 7/7, é este campo
que distingue "parado" de "trabalho em voo". Campo aditivo.
FRESH-FREE-3 (#1747): esta chamada é SEM escopo (não recebe
member_filter), então index_age.touched_in_scope lista os arquivos
de CÓDIGO (filtrados por EXTENSION_MAP, nunca binário sem parser
pdf/docx/xlsx) que diferem do último scan no workspace INTEIRO — mas é uma
LISTA truncada a MAX_TOUCHED_IN_SCOPE (20) paths, enquanto
index_age.touched_total é o NÚMERO completo e nunca trunca: os dois só
coincidem quando cabem no teto (FRESH-FREE-2 #1748).
touched_total é a mesma contagem que code_pack/entity.pack
reportam pro MESMO workspace, mesmo quando o escopo deles é mais estreito
— ver a nota em silex.community.code_pack.
| Parameter | Type | Default | Required |
|---|---|---|---|
workspace_id |
string |
— |
yes |
language |
string |
'en' |
no |
Example call:
list_workspaces¶
List all registered workspaces, most recently updated first.
Quando usar: descobrir workspaces já existentes antes de repetir
create_workspace (kit de onboarding — MCP-KIT-1 #1136). Próximo
passo: get_workspace_stats(workspace_id) com o id escolhido.
Reads the local registry in-process (same tier-aware path as
create_workspace — no HTTP, no running API required). Read-only
— no side effects. Use this before create_workspace or any
workspace-scoped tool to let the caller pick an existing workspace
by name instead of requiring a raw UUID.
No parameters.
Example call:
rescan_workspace¶
Atualiza o índice do workspace com o que mudou no código — sem re-escanear tudo.
Quando usar: o mapa/pack respondeu com index_age.commits_behind > 0 (ou
com um aviso de índice sem base), você acabou de commitar/trocar de branch,
ou quer forçar a atualização antes de ler o código (kit de onboarding —
MCP-KIT-1 #1136). Próximo passo: silex.community.code_pack /
get_workspace_stats — a resposta já vem do índice novo.
FRESH-FREE-1 (#1737): o default é INCREMENTAL. Compara o HEAD que o
índice cobre (scanned_head) com o HEAD atual — git diff
--name-status <scanned_head>..HEAD + git status --porcelain (não
commitado e não rastreado) — e re-ingere SÓ os arquivos tocados,
sincronamente (o campo mediu 93 s de rescan completo contra dezenas de ms
do incremental). Arquivo que o scan ignora (.silex/, vendor/generated)
nunca entra. No caminho incremental o scan_status do workspace não é
tocado: ele não é um scan novo, é o índice acompanhando o repo.
Cai no rescan COMPLETO (comportamento histórico, thread em background)
quando não há como fazer incremental honesto: full=True explícito, repo
sem git, workspace escaneado antes desta coluna existir (sem
scanned_head — o completo estabelece a base), ÍNDICE NÃO SAUDÁVEL
(scan_status diferente de completed, ou completo sem comunidades),
ou DELTA GRANDE (mais arquivos tocados do que o refresh por chamada ingere
sem segurar a resposta — canonical_fresh.MAX_DELTA_FILES).
Adivinhar que o índice está fresco seria pior que o silêncio que esta tool
existe pra matar — e um delta aplicado sobre índice quebrado nunca o
conserta (é o caminho de recuperação da #1071, preservado aqui).
Recupera também o que o diff NÃO enxerga: path marcado stale que ninguém
re-ingeriu (por invalidate_paths, ou por um hook cujo rescan parcial
estourou o timeout) entra no trabalho desta chamada mesmo com o git em dia
— antes, o incremental respondia completed sem ingerir nada. Stale
pendente acima do teto cai no completo, como o delta grande; o que sobrar
volta declarado em stale_file_count com next_action pro full.
J1-RESCAN-1 (#1071): o caminho completo recupera workspace com scan
incompleto (morreu no meio → error; completou sem comunidades; ou
scanning zumbi — heartbeat estagnado só sobra em kill -9) SEM criar
nada novo: re-roda o MESMO run_scan_pipeline (via
_run_scan_tracked, com a morte-honesta e o heartbeat da #1072) sobre os
Repo que já existem. NÃO chama create_workspace — nenhuma linha
nova em workspaces nem em repos.
Recusa (idempotente, sem empilhar scans — anti-loop) quando já há um scan em
voo SAUDÁVEL: scan_status='scanning' com heartbeat fresco
(heartbeat_age_seconds <= SCAN_STALE_THRESHOLD_S). O zumbi (heartbeat
estagnado) NÃO é saudável — esse re-dispara.
SILEX-FRESH-1 (#1535): paths (opcional) engata o rescan PARCIAL —
re-ingest apenas da interseção stale ∩ paths no mirror, sem churn
global (chunks intocados mantêm id). Tem precedência sobre o incremental.
FRESH-FREE-3 (#1747): index_age.touched_total (dentro do bloco que
esta tool também carrega) é a contagem do workspace INTEIRO — arquivos de
código (EXTENSION_MAP) que diferem do último scan, nunca um binário
sem parser (pdf/docx/xlsx). No modo incremental, o refresh desta CHAMADA
AVANÇA a base (scanned_head) e ingere o delta; touched_total e
touched_in_scope continuam declarando o que difere da base NOVA — o
que segue tocado e ainda não commitado (working tree sujo) reaparece
IDÊNTICO na chamada seguinte, sem que o refresh desta chamada desligue
esse sinal (touched ESTÁVEL, FRESH-FREE-2 #1748) — ver touched_total ×
touched_in_scope em Api.services.canonical_fresh (docstring do
módulo).
| Parameter | Type | Default | Required |
|---|---|---|---|
workspace_id |
string |
— |
yes |
paths |
array | null |
None |
no |
full |
boolean |
False |
no |
Example call:
silex.business_logic.submit¶
Persiste rules extraídas pelo LLM do cliente (com provenance) (#675).
Quando usar: depois de silex.community.code_pack — submeter as
rules que o LLM do cliente extraiu do código lido (kit de onboarding
— MCP-KIT-1 #1136). Próximo passo: silex.contract.fact.generate
pra consolidar o escopo, ou generate_domain_report pra visão
completa do domínio.
Fecha o loop da arqueologia client-orchestrated (ONBOARD-6): recebe as
rules que o LLM do cliente extraiu do code_pack, valida a
evidência e as persiste no business_logic.json materializado —
shape consumido por silex.contract.fact.generate (passa a montar o
fact_contract com rules reais, não fixture).
Trava não-negociável: rule sem evidência é alucinação. Cada rule
exige provenance — class_name (símbolo), source_file
(arquivo) e line_start ou evidence (localização/trecho). Rule
sem isso é rejeitada (erro estruturado) e nada é persistido
(atômico). As rules entram como proposed (camada 1.5 — fato
candidato, nunca ground-truth silencioso); promover é review humano.
Merge idempotente: re-submeter a mesma rule não duplica.
A âncora é VERIFICADA contra o código real (ANCORA-SUBMIT-1 #1684),
não só exigida: quando o workspace tem mirror (o workspace.db do
scan free-tier), cada rule é conferida contra os chunks daquele
workspace — source_file precisa existir, line_start..line_end
precisa cair DENTRO de um chunk daquele arquivo (fora do chunk é fora,
sem tolerância de "linhas perto") e evidence, quando é a única
localização, precisa aparecer no código do chunk (comparação ignora
espaços). Códigos de rejeição:
anchor_file_not_in_workspace (arquivo desconhecido),
anchor_file_ambiguous (caminho relativo que casa com 2+ arquivos —
mande o caminho completo), anchor_outside_chunks (a resposta lista
as known_ranges do arquivo — método + linhas — pra você corrigir) e
evidence_not_in_file. Rule verificada é persistida com
provenance.anchor {verified, chunk_id, method, file}. Sem mirror o
submit aceita como antes e diz na cara: report.anchor_verification
= "skipped_no_mirror" + aviso em warnings — nunca bloqueio,
nunca silêncio.
| Parameter | Type | Default | Required |
|---|---|---|---|
workspace_id |
string |
— |
yes |
rules_json |
string |
— |
yes |
artifact_root |
string |
'' |
no |
db_path |
string |
'' |
no |
Example call:
{
"tool": "silex.business_logic.submit",
"arguments": {
"workspace_id": "<workspace_id>",
"rules_json": "<rules_json>"
}
}
silex.community.code_pack¶
Devolve o pack de leitura de uma comunidade — código + evidência (#675).
Quando usar: depois de escolher uma comunidade (via
get_code_communities/get_structural_findings) pra ler o
código-fonte e extrair rules com o LLM do cliente (kit de onboarding
— MCP-KIT-1 #1136). Próximo passo: silex.business_logic.submit
com as rules extraídas.
Substrato da arqueologia client-orchestrated (ONBOARD-6): o server
não roda LLM. Dado um escopo coeso (comunidade/package), esta tool
resolve os membros (Postgres) e devolve o código dos chunks (do
.silex/workspace.db free-tier, ONBOARD-2) + evidência estrutural
(arquivo/classe/método/linhas/labels + arestas :REFERENCES
intra-escopo), num formato enxuto pro LLM do cliente (claude-code)
interpretar e extrair as rules — que voltam por
silex.business_logic.submit.
Camada 1 (fato, fiel ao código). Read-only — não muta nada. Happy path free-tier: zero chave, zero GPU.
Orçamento por default (PACK-BUDGET-1 #1325): comece SEM parâmetros —
o pack já respeita um orçamento default (~40k chars) que cabe no teto de
resultado do seu cliente MCP. Se houver mais código do que cabe, o
retorno vem truncated: true com um next_cursor opaco e uma
continuation_hint textual: chame de novo com cursor=<next_cursor>
(mesmos parâmetros) pra pegar a próxima página. Pagine até o retorno vir
sem next_cursor — a concatenação reconstrói o pack inteiro, byte a
byte, sem perda. Corte é SEMPRE em fronteira de chunk (nunca código pela
metade). Poder avançado: max_total_chars=0 devolve tudo de uma vez
(ilimitado); max_chunk_chars/max_chunks_per_member são knobs
finos ortogonais ao orçamento.
O orçamento vale pro ENVELOPE inteiro (PACK-EDGES-BUDGET-1 #1686):
as edges e o scope.classes paginam JUNTO com os membros — cada
membro carrega as arestas que ele origina e a sua entrada em
scope.classes, então uma comunidade grande não estoura mais o teto
pelo lado das arestas (medido no próprio Silex: 102.882 chars com
max_total_chars=6000). Nada é descartado pra caber: paginar até
esgotar reconstrói membros, chunks, arestas e classes sem perda nem
duplicata. metrics.edges_total_in_scope é o total do escopo e
metrics.edges_in_page o que veio nesta página; scope.class_count
continua o total de membros do território.
Alvo alcançável (mesma história): order="relevance" (default)
ordena os membros por grau intra-escopo desc (desempate alfabético) — o
hub da comunidade vem na página 1 — e, desde a PACK-CHUNK-RANK-1
(#1698), vale também DENTRO de cada membro: os chunks saem por grau do
SÍMBOLO desc (in + out nas code_references, desempate por
arquivo/linha), então os hubs do arquivo abrem o membro mesmo quando
você não sabe o nome de nada (medido no Silex: assemble_code_pack
era o 23º dos 29 chunks do seu membro-módulo). Desde a
PACK-MEMBER-RANK-1 (#1713) a mesma palavra vale para o símbolo
PROMOVIDO a membro próprio (uma função de módulo que o mapa reconhece
pelo nome): se o arquivo de origem dele também é membro deste pack, ele
não espera mais o membro-módulo inteiro — entra na lista de chunks do
módulo, na posição que o grau dele manda, com promoted_member
dizendo de qual membro veio (medido no Silex: _community_code_pack,
grau 71, saiu da página 17 de 18 para a 1). Ele continua listado em
scope.classes, as arestas dele continuam as mesmas
(metrics.members_folded conta as dobras), e member_filter pelo
nome dele continua levando ao código. order="name" mantém
a ordem alfabética entre os membros e a de LINHA dentro deles, sem
dobra nenhuma — pra quem quer ler o arquivo de cima a baixo. member_filter aponta direto pro alvo: lista JSON
(["Api/services/pedido.py", "Pedido"]) ou valores separados por
vírgula, casando por igualdade case-insensitive com o nome do membro OU
por sufixo de arquivo ("pedido.py" casa
/repo/Api/services/pedido.py) — relativo, relativo com \ (mirror
Windows), relativo com prefixo .//.\ (tab-complete do
PowerShell) e absoluto casam o MESMO membro (PACK-FILTER-WINPATH-1 #1722/PACK-FILTER-WINPATH-2 #1727: separador, caixa e prefixo relativo
normalizados dos dois lados antes de comparar; / inicial e ../
NÃO são tratados como ./). Nome puro (sem separador, ex:
"pedido.py") que casa mais de um ARQUIVO distinto do escopo serve
OS DOIS (nunca escolhe um a dedo) e DECLARA o casamento múltiplo em
filter_ambiguous ([{"value": ..., "matched": [...]}]) — dois
membros do MESMO arquivo não são ambíguos entre si; nunca resolvido em
silêncio; informe o relativo com subdiretório pra desambiguar. Valor
sem casamento algum sai em
filter_unmatched; filtro que não casa nada devolve members: []
+ gap filter_without_match (ausência honesta, não erro). O cursor é
selado com esses parâmetros: reapresentá-lo com order/
member_filter/knobs diferentes devolve invalid_cursor em vez de
misturar páginas de sequências distintas.
O SÍMBOLO na página 1 (PACK-SYMBOL-FILTER-1 #1697): o
member_filter leva ao arquivo, mas dentro dele os chunks saem em
ordem de linha — num arquivo grande o que você nomeou cai na 17ª página.
symbol_filter põe o alvo na frente do membro dele, em três formas:
(1) nome — "assemble_code_pack", "Pedido" ou qualificado
"Pedido.confirmar" (igualdade case-insensitive com o método/classe
do chunk; NUNCA substring: "pack" não casa assemble_code_pack);
(2) linha — "contract_tools.py:1742" (sufixo de arquivo, mesma
tolerância do member_filter, + a linha); (3) faixa —
"contract_tools.py:1742-1905" (todo chunk cujo intervalo intersecta
a faixa). Nas formas (2) e (3) o <arquivo> casa com a MESMA
tolerância do member_filter — separador (/ ou \), caixa e
prefixo .//.\ normalizados dos dois lados, só em fronteira de
separador (PACK-SYMBOL-RANGE-WINPATH-1 #1867). Vários valores: lista
JSON ou separados por vírgula. É
REORDENAÇÃO, não recorte: o resto do membro segue atrás e paginar até
esgotar continua reconstruindo o pack inteiro. Valor sem casamento sai
em symbol_filter_unmatched; nenhum casando vira gap
symbol_without_match (ausência honesta, não erro) — sintaxe
malformada ("arquivo.py:", faixa invertida) é que vira
invalid_arguments. Também faz parte do selo do cursor.
Símbolo que está no ARQUIVO filtrado mas cujo nó mora em outra
comunidade (promovido pelo mapa) vem servido do mesmo jeito, dobrado no
membro-módulo, com o gap symbol_served_from_other_member
(ref/member/community_id da origem — null quando o
catálogo não resolve) declarando de onde ele veio (#1828); origem em
mais de uma comunidade (homônimo) vem community_id/label
null + candidates: [{community_id, label, level}] ordenados por
community_id — ambiguidade se declara, nunca se resolve por posição
de lista (#1843). E o alvo que
casou mas não coube nesta página vem como gap
symbol_matched_beyond_budget com o next_cursor que o alcança —
página sem o alvo nunca é página calada.
Chunk pedido maior que a página (PACK-BIG-CLASS-CHUNK-1 #1861): o
chunk que casa o filtro EXPLÍCITO (member_filter resolvido em
membro, ou symbol_filter) e cujo CÓDIGO sozinho é maior que o
max_total_chars da página não cabe em página nenhuma: ele não é
servido (serviria acima do teto) nem cortado pela metade (o corte é
sempre em fronteira de chunk) e sai DECLARADO no gap
chunk_exceeds_page_budget {member, symbol, chunk_type,
line_start, line_end, chunk_chars, page_budget,
min_max_total_chars} — uma vez por chunk, na página que abre o membro
dele, mesmo quando outros chunks entraram. O continuation_hint
nomeia a saída (max_total_chars>=N, estimativa que já inclui o
overhead do envelope desta página, ou max_total_chars=0) e
metrics.chunks_exceeding_budget conta os declarados. É o oposto do
silêncio que havia: member_filter="QueueItem" com
max_total_chars=4000 devolvia members: [] + gaps: [], e com
8000 servia to_dict/load engolindo o chunk class de
12.925 chars. Sem filtro nenhum (leitura exploratória) nada muda: a
unidade isolada maior que o orçamento segue emitida inteira.
SÓ o trecho (symbol_only, PACK-RANGE-ONLY-1 #1835):
symbol_only=true (com symbol_filter) serve APENAS os chunks que
casaram — nos membros servidos, com o god symbol inteiro (cabeçalho +
blocos), sem o resto do arquivo; nada casou → members: [] + gap
symbol_without_match, e metrics.chunks_omitted_by_symbol_only
diz quantas views ficaram de fora. Sem o knob nada muda (o
symbol_filter prioriza, não recorta); symbol_only=true sem
symbol_filter → invalid_arguments. Faz parte do selo do cursor.
Sem package_id/community_id (MCP-INSTRUCTIONS-1 #1689):
member_filter sozinho já delimita o escopo — casa os valores
contra os membros das comunidades do workspace em QUALQUER nível
(preferindo o nível 0; COMMUNITIES-PAGE-1 #1690) e resolve pra UMA
delas, com scope.level reportando o nível usado. Sem casamento algum → member_filter_unmatched; casamento
espalhado por mais de uma comunidade → member_filter_ambiguous
(com candidates — reapresente com package_id/community_id
explícito, ou filtre por um arquivo/classe só). Casa por MEMBRO (classe
ou módulo-arquivo, MAPA-PROCEDURAL-1 #1677): módulo procedural resolve
direto; classe dentro de um arquivo com outras classes pede
package_id/community_id explícito (via get_code_communities)
ou silex.entity.pack(workspace_id, entity_name).
Truncamento consciente de chunk (PACK-CHUNK-TRUNC-1 #1338): quando
max_chunk_chars corta o código de um chunk, o corte recua pra a
última quebra de linha completa dentro do limite — nunca no meio de
uma linha/método. O chunk truncado vem com truncated: true +
chunk_handle opaco + continuation_hint: chame de novo só com
chunk_handle=<handle> (mesmos workspace_id/db_path; não
precisa repetir package_id/community_id) pra receber o RESTO
do código desse chunk, byte a byte, numa resposta chunk_continuation.
FRESH-FREE-3 (#1747): index_age.touched_total (bloco aditivo
no envelope) é a contagem do workspace INTEIRO — arquivos de código,
filtrados por EXTENSION_MAP (binário sem parser como pdf/docx/
xlsx nunca conta) — NUNCA o escopo desta chamada: um member_filter
estreito que não casa com nada tocado ainda assim reporta o total
certo, em vez de 0 escondendo que algo mudou em outro lugar do
workspace. index_age.touched_in_scope é o subconjunto que casa
com os membros DESTE pack, uma LISTA truncada a
MAX_TOUCHED_IN_SCOPE (20) paths — touched_total é um NÚMERO e
nunca trunca, então os dois só batem quando o total cabe no teto e
tudo que mudou está neste pack. O conjunto é estável: um arquivo
editado e não commitado segue em touched_in_scope na chamada que o
ingere (refreshed_now: true) e nas seguintes (FRESH-FREE-2 #1748).
O index_age entra na conta do max_total_chars: é reservado
antes da paginação, nunca anexado por fora do orçamento.
| Parameter | Type | Default | Required |
|---|---|---|---|
workspace_id |
string |
— |
yes |
package_id |
string |
'' |
no |
community_id |
string |
'' |
no |
db_path |
string |
'' |
no |
max_chunk_chars |
integer |
0 |
no |
max_chunks_per_member |
integer |
0 |
no |
max_total_chars |
integer |
40000 |
no |
cursor |
string |
'' |
no |
chunk_handle |
string |
'' |
no |
order |
string |
'relevance' |
no |
member_filter |
string |
'' |
no |
symbol_filter |
string |
'' |
no |
symbol_only |
boolean |
False |
no |
Example call:
silex.community.label_submit¶
Persiste nomes de comunidade dados pelo SEU LLM (com proveniência) (#1619).
Quando usar: depois de get_code_communities +
silex.community.code_pack — o label heurístico não diz o negócio?
Leia o pack, dê o nome e submeta aqui (kit de onboarding — no tier
free é o ÚNICO caminho de nomeação: o motor não usa provider próprio,
label_communities não se aplica). Próximo passo:
get_code_communities de novo pra confirmar o nome na leitura.
Fecha o loop da nomeação client-orchestrated (COMMUNITY-LABEL-CLIENT-1,
mesmo padrão do garçom de silex.business_logic.submit): o LLM do
cliente lê o código, propõe o nome, o Silex persiste — com trava
doutrinária idêntica à de rules: label sem evidência é alucinação.
Cada entrada exige provenance — âncora do que foi lido
(classes do pack, source_file e/ou evidence). Lote com
QUALQUER entrada sem proveniência é rejeitado por inteiro (erro
estruturado) e nada é persistido, nem parcialmente. Upsert
idempotente por comunidade; fonte registrada client_orchestrated;
o nome sobrevive a re-scan via cache lookup-only.
| Parameter | Type | Default | Required |
|---|---|---|---|
workspace_id |
string |
— |
yes |
labels_json |
string |
— |
yes |
db_path |
string |
'' |
no |
Example call:
{
"tool": "silex.community.label_submit",
"arguments": {
"workspace_id": "<workspace_id>",
"labels_json": "<labels_json>"
}
}
silex.contract.fact.generate¶
Gera o contrato de fato (fact_contract/v1) de um escopo coeso.
Quando usar: depois de silex.business_logic.submit (ou de rules
heurísticas já materializadas), pra consolidar o escopo num contrato
versionado (kit de onboarding — MCP-KIT-1 #1136). Próximo passo:
nenhum obrigatório — o fact_contract é o artefato de saída deste
ramo do fluxo.
Coleta as rules já extraídas (com provenance de símbolo) de uma
comunidade/package materializada e as serializa num artefato
versionado com status: proposed. É agregação/serialização sobre o
business_logic.json materializado — não nova extração.
Camada 1 (fato, fiel ao código). Propor ledger candidato é MH-3;
review/promoção proposed→active é MH-4 — fora desta tool.
| Parameter | Type | Default | Required |
|---|---|---|---|
workspace_id |
string |
— |
yes |
package_id |
string |
'' |
no |
community_id |
string |
'' |
no |
artifact_root |
string |
'' |
no |
use_cache |
boolean |
True |
no |
Example call:
silex.entity.pack¶
Devolve o agregado inteiro (raiz + partes) em 1 chamada (#1141).
Quando usar: pra responder "me explica o agregado X" — a pergunta nº1 da
arqueologia. Prefira esta tool ao silex.community.code_pack quando
você já sabe o NOME da entidade: o Leiden particiona por acoplamento, não
por agregado, então o pack por comunidade quase nunca entrega o agregado
inteiro (medido na cobaia eShop: a comunidade da raiz Order tem 7
membros, enquanto OrderItem, Address, Buyer e OrderStatus
— o mesmo agregado — moram em 4 comunidades DIFERENTES). Esta tool
ATRAVESSA comunidades. Próximo passo: silex.business_logic.submit com
as rules extraídas.
Camada 1 (fato, fiel ao código). Read-only — não muta nada. Roda no
free-tier puro: só o .silex/workspace.db (sem Postgres/Neo4j).
Raiz determinística, nunca chute silencioso: quando o nome casa com
mais de uma classe (ex: o agregado Order de Ordering.Domain × o
DTO homônimo do ClientApp), a escolha usa sinais MEDIDOS do
free-tier — rules ancoradas, nº de chunks, chars de código — e as
candidatas rejeitadas voltam DECLARADAS em candidates com o motivo.
Empate em todos os sinais → diagnostic entity_ambiguous com as
candidatas, nunca um chute.
Toda âncora existe: todo item traz arquivo:linha de um chunk real.
Classe relacionada sem código (tipo de framework) é excluída e contada
em metrics.unanchored_refs_excluded — nunca âncora inventada.
Hop-do-repositório + fronteira declarada (PACK-FRONTEIRA-1 #1396):
em DDD a coreografia de MUTAÇÃO do agregado vive atrás da interface do
repositório (medido no eShop: 15 classes seguram IOrderRepository
e ZERO delas aponta pra Order) — o 1-hop puro não a contém. Quando
as arestas a 1 hop da raiz contêm interface(s) de repositório
(heurística DECLARADA no retorno: sufixo Repository no nome do
vizinho, cobrindo o padrão exato I<raiz>Repository), os CALLERS
dessa interface entram em mutators_via_repository (top-N por
weight, teto = used_by_cap, corte contado em
metrics.mutators_via_repository_omitted — nunca silencioso; âncora
real obrigatória; quem já tem aresta direta com a raiz fica em
uses/used_by, nunca duplicado). É SÓ o hop da interface de
repositório — 2-hops genérico continua fora (Pro/Neo4j). E o retorno
declara a FRONTEIRA em texto legível (boundary.statement +
boundary.not_covered): o que o pack NÃO cobre (mediator/DI sem
aresta estrutural, refs sem âncora) — used_by_omitted: 0 deixa de
ser o único sinal de completude.
summary_first (default): devolve só o MAPA do agregado (nomes +
âncoras + comunidades), barato. Peça o código depois com
summary_first=False. O orçamento, o next_cursor e o
chunk_handle são os MESMOS do silex.community.code_pack
(PACK-BUDGET-1 #1325 / PACK-CHUNK-TRUNC-1 #1338): o payload INTEIRO
respeita max_total_chars (default ~40k; 0 = ilimitado) e
paginar até esgotar reconstrói o pack byte a byte.
| Parameter | Type | Default | Required |
|---|---|---|---|
workspace_id |
string |
— |
yes |
entity_name |
string |
'' |
no |
summary_first |
boolean |
True |
no |
db_path |
string |
'' |
no |
used_by_cap |
integer |
25 |
no |
max_chunk_chars |
integer |
0 |
no |
max_chunks_per_member |
integer |
0 |
no |
max_total_chars |
integer |
40000 |
no |
cursor |
string |
'' |
no |
chunk_handle |
string |
'' |
no |
Example call:
silex.repo.map¶
Mapa do repositório — ASSINATURAS ranqueadas, nunca corpo (#1769).
Quando usar: antes de pedir código, pra saber ONDE está o que importa
pra tarefa — passe em mentions os arquivos/símbolos que a conversa
já citou (["Api/fresh/hook.py", "PedidoService"]) e o mapa volta
com eles e a vizinhança deles no topo. Próximo passo:
silex.community.code_pack(workspace_id, member_filter=[<arquivos do
topo do mapa>]) pra ler o código de verdade. member_filter é
alias de mentions (o nome que o code_pack usa), mesma forma;
com os dois vale a união, mentions primeiro, sem duplicata. Forma
inválida (42, item não-string) → invalid_arguments com
param.
Cada arquivo traz rank, score, a community de menor nível
do seu membro principal (o de mais símbolos no arquivo; null sem
detecção) e symbols — chunk_id, name,
kind, line_start/line_end, signature e
signature_source: metadata (gravada pelo parser na ingestão),
ast (projeção tree-sitter do código já no índice — TS/JS/C#) ou
unavailable (signature: null; nunca a primeira linha do código
fingindo de assinatura).
Ranking: PageRank dirigido ponderado (code_references.weight)
sobre os MEMBROS do mapa — a mesma identidade das comunidades e dos
achados; nome externo (get/str) não é nó, e o mesmo par gravado
com o UUID com e sem hífen conta uma vez
(ranking.duplicate_pairs_collapsed). Personalização: damping 0.85,
teleporte 50% uniforme + 50% nos membros mencionados
(ranking.personalization.applied); sem mentions o ranking é
uniforme. Com menção, o que você mencionou é rank 1..k NA ORDEM em que
mencionou (ranking.personalization.mentions_pinned) e as arestas
incidentes aos mencionados entram com peso ×10, percorríveis nos dois
sentidos (mention_edge_boost) — quem chama e quem é chamado pelo
mencionado vem antes dos hubs globais. Grafo sem arestas ou sem convergência → ranking.method =
"in_degree" com reason, inventário completo (grau zero incluído).
Menção sem casamento sai em mentions_unmatched; homônimo — path
que casa mais de um arquivo, ou nome que casa símbolos DIFERENTES em
arquivos diferentes (main em N módulos) — sai em
mentions_ambiguous (matched com os 3 primeiros arquivos +
matched_total) e não personaliza nenhum: informe o path com
diretório. Classe parcial (Form.cs + Form.Designer.cs) é um
símbolo só e personaliza.
Orçamento: max_total_chars (default 8000) vale pro envelope
INTEIRO medido como você recebe (index_age e cursor incluídos);
símbolos nunca são cortados. Mais do que cabe → truncated: true +
next_cursor: chame de novo com cursor=<next_cursor> e as MESMAS
mentions (o orçamento pode mudar entre páginas); a união das
páginas é o mapa inteiro. 0 = ilimitado. Orçamento menor que o
envelope com 1 símbolo (ou que o envelope do workspace sem símbolo) →
erro budget_too_small com min_total_chars. Cursor de outro workspace/mentions →
invalid_cursor; índice alterado desde a página anterior →
snapshot_changed (recomece sem cursor).
| Parameter | Type | Default | Required |
|---|---|---|---|
workspace_id |
string |
— |
yes |
mentions |
array | null | string |
None |
no |
max_total_chars |
integer |
8000 |
no |
cursor |
string |
'' |
no |
member_filter |
array | null | string |
None |
no |
Example call: