d64b1132b9dfb906f27dc7bd883d24b787df3e41
3
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
3c87ab55e1 |
fix(v2): fix cache is_fallback bug, wire observability + data quality, drop debug webhook, fix GLPI URL
- Real bug found by code review while implementing this cycle: "Code - Reusar Classificacao em Cache" always hardcoded is_fallback: false when reconstructing a classification from memory, even when the cached classification was itself AI_FALLBACK. On a cache hit for a previously fallback-classified ticket, this would have let it skip applyFallbackPolicy's exclusion entirely (the policy checks aiClassification.is_fallback first). Fixed to derive is_fallback from the cached ai_classification value. - select-top10.node.js now carries `resolucao` (ia | cache | fallback_cap) through to the scored item, previously dropped -- needed to tell cache hits apart from real AI calls in observability. - Code - Comparar Legacy x V2 now computes the full observability summary (candidate_count, cache_hits/misses, ai_requested/success/errors, ai_fallback_count and by-reason breakdown, classification_counts, insufficient_context_count, actionable_real_count, critical_override_count, top10_count, blocked_count, coordination_count) and the data-quality review (buildDataQualityReview over INSUFFICIENT_CONTEXT tickets), both stored in the shadow_runs `summary` JSON column -- no new Data Table needed. - Removed the debug webhook entirely (Debug - Ver Painel, Data Table - Buscar Shadow Runs Recentes debug branch, Code - Montar Painel Debug, Debug - Responder) and the now-unused debug-panel.node.js driver. Workflow went from 37 to 33 nodes. Debugging goes through n8n execution data, the Data Tables, and the shadow diff instead, as requested. - Fixed glpi_base_url: was still V1's own placeholder (https://glpi.suaempresa.com.br, never a real value, not report anonymization) -- confirmed the real domain (https://glpi.gtigrupo.com.br) from the live, active GLPI x WhatsApp workflow's own GLPI API config in the same n8n instance. SQL still only ever receives it through {GLPI_BASE_URL} substitution from the Config node, never hardcoded. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> |
||
|
|
ea105d525c |
fix(v2): three real bugs found by an actual end-to-end run against production GLPI data
Ran the deployed workflow for real (temporary webhook trigger, briefly
activated, immediately deactivated and removed after each attempt) against
the real GLPI MySQL database and a real OpenAI credential. Found and fixed:
1. $env access is blocked on this n8n instance (N8N_BLOCK_ENV_ACCESS_IN_NODE).
parseConfig($env) threw "access to env vars denied" on the very first
Code node. Config now comes from the "Config - Coordenador GLPI v2" Set
node instead (same pattern the V1 workflow already used) -- expanded
that node with all 13 tunable parameters, and pointed the 3 affected
node drivers (build-sql-candidatos, decide-needs-ai, select-top10) at
it instead of $env.
2. Data Table "upsert" operation requires both `columns` (values) and a
separate `filters` (match condition) -- I had only set columns with
matchingColumns, which isn't enough; n8n refused to activate the
workflow ("Missing or invalid required parameters: filters"). Added
filters.conditions matching on ticket_id to both memory-writing Data
Table nodes.
3. Real architecture bug: "Data Table - Buscar Memoria" sat inline in the
41-candidate chain (Mesclar Contexto -> Buscar Memoria -> Decidir
Necessidade de IA). A bulk "get all rows" Data Table node run with 41
input items produced 41 identical fetches and its OWN output (the empty
memory table on a first run) replaced the 41 candidates entirely --
"Decidir Necessidade de IA" received 0 items and the whole main branch
silently skipped. Moved the memory fetch to a parallel branch off
Config (fires once) and added a real Merge node ("Merge - Aguardar
Memoria") to guarantee both the candidates and the memory rows have
executed before "Decidir Necessidade de IA" runs -- same synchronization
pattern already used for context and for the shadow comparison.
Also fixed a cosmetic bug found in the real message output: buildTopMessage
produced a quadruple newline between the header and the first ticket block
([header, '', ...blocks].join('\n\n') double-counts the blank line already
inserted by the '\n\n' join). Added a regression test.
Verified with a real execution (id 13599, 24/08/2026 19:25 UTC) against the
live GLPI database: 41 real candidates, 30 sent to OpenAI (capped), 11
fallback-capped, memory table populated with 41 real rows including
genuine WAITING_VENDOR/WAITING_REQUESTER classifications with real
blocker_type/waiting_for fields extracted from real ticket task content,
and a real shadow_runs row comparing Legacy x V2 (4 tickets removed by V2:
2 for INSUFFICIENT_CONTEXT, 1 WAITING_REQUESTER, 1 WAITING_VENDOR; 4 added).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
||
|
|
a99a25cb1a |
feat(v2): complete n8n workflow template (36 nodes) covering full V2 pipeline + shadow branch
- 14 new Code node drivers implementing the pipeline stages: normalize
candidates, build context SQL, merge context + hash, decide AI need,
prepare AI prompt, validate AI response, AI-disabled fallback, reuse
cached classification, compute score, select top 10, prepare memory/
envio records, build message/digest, compare legacy x V2, debug panel.
- Consolidated the two context queries (followups/tasks) into a single
UNION ALL query tagged by tipo, and added a "Merge - Unir Shadow"
synchronization node before comparing legacy x V2: n8n does not
guarantee relative execution order between sibling branches that only
share an early common ancestor, so cross-branch data was only safe to
read by name once a real Merge node forced both to complete first.
- Reordered score calculation before the memory upsert (score is needed
in the persisted row) and turned both Data Table writes into
side-effect branches that fan out from the main path instead of
gating it, so the Data Table node's own output shape never needs to
carry the full pipeline state forward.
- Fixed a duplicate-identifier bug in the build script: score.js's
require('./cooldown') survived inlining and collided with
cooldown.js's own computeCooldown function in the same Code node
scope. build-workflow.js now strips inter-module requires when
inlining, and a new test syntax-checks every generated jsCode string
plus asserts no leftover require() calls.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|