@netoalmanca/advpl-sensei 1.1.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.
Files changed (70) hide show
  1. package/agents/changelog-generator.md +63 -0
  2. package/agents/code-generator.md +215 -0
  3. package/agents/code-reviewer.md +145 -0
  4. package/agents/debugger.md +83 -0
  5. package/agents/doc-generator.md +67 -0
  6. package/agents/docs-reference.md +86 -0
  7. package/agents/migrator.md +84 -0
  8. package/agents/process-consultant.md +97 -0
  9. package/agents/refactorer.md +75 -0
  10. package/agents/sx-configurator.md +67 -0
  11. package/commands/changelog.md +66 -0
  12. package/commands/diagnose.md +67 -0
  13. package/commands/docs.md +81 -0
  14. package/commands/document.md +67 -0
  15. package/commands/explain.md +60 -0
  16. package/commands/generate.md +111 -0
  17. package/commands/migrate.md +81 -0
  18. package/commands/process.md +111 -0
  19. package/commands/refactor.md +65 -0
  20. package/commands/review.md +60 -0
  21. package/commands/sxgen.md +98 -0
  22. package/commands/test.md +103 -0
  23. package/dist/index.d.ts +2 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +143 -0
  26. package/dist/index.js.map +1 -0
  27. package/package.json +30 -0
  28. package/skills/advpl-code-generation/SKILL.md +163 -0
  29. package/skills/advpl-code-generation/patterns-fwformbrowse.md +485 -0
  30. package/skills/advpl-code-generation/patterns-jobs.md +519 -0
  31. package/skills/advpl-code-generation/patterns-mvc.md +765 -0
  32. package/skills/advpl-code-generation/patterns-pontos-entrada.md +708 -0
  33. package/skills/advpl-code-generation/patterns-rest.md +974 -0
  34. package/skills/advpl-code-generation/patterns-soap.md +639 -0
  35. package/skills/advpl-code-generation/patterns-treport.md +481 -0
  36. package/skills/advpl-code-generation/patterns-workflow.md +779 -0
  37. package/skills/advpl-code-generation/templates-classes.md +1096 -0
  38. package/skills/advpl-code-review/SKILL.md +72 -0
  39. package/skills/advpl-code-review/rules-best-practices.md +444 -0
  40. package/skills/advpl-code-review/rules-modernization.md +290 -0
  41. package/skills/advpl-code-review/rules-performance.md +333 -0
  42. package/skills/advpl-code-review/rules-security.md +302 -0
  43. package/skills/advpl-debugging/SKILL.md +265 -0
  44. package/skills/advpl-debugging/common-errors.md +1124 -0
  45. package/skills/advpl-debugging/performance-tips.md +768 -0
  46. package/skills/advpl-refactoring/SKILL.md +139 -0
  47. package/skills/advpl-to-tlpp-migration/SKILL.md +293 -0
  48. package/skills/advpl-to-tlpp-migration/migration-checklist.md +122 -0
  49. package/skills/advpl-to-tlpp-migration/migration-rules.md +265 -0
  50. package/skills/changelog-patterns/SKILL.md +99 -0
  51. package/skills/code-explanation/SKILL.md +66 -0
  52. package/skills/documentation-patterns/SKILL.md +172 -0
  53. package/skills/embedded-sql/SKILL.md +379 -0
  54. package/skills/probat-testing/SKILL.md +226 -0
  55. package/skills/probat-testing/patterns-unit-tests.md +614 -0
  56. package/skills/protheus-business/SKILL.md +92 -0
  57. package/skills/protheus-business/modulo-compras.md +780 -0
  58. package/skills/protheus-business/modulo-contabilidade.md +874 -0
  59. package/skills/protheus-business/modulo-estoque.md +876 -0
  60. package/skills/protheus-business/modulo-faturamento.md +800 -0
  61. package/skills/protheus-business/modulo-financeiro.md +1015 -0
  62. package/skills/protheus-business/modulo-fiscal.md +749 -0
  63. package/skills/protheus-business/modulo-manutencao.md +848 -0
  64. package/skills/protheus-business/modulo-pcp.md +743 -0
  65. package/skills/protheus-reference/SKILL.md +119 -0
  66. package/skills/protheus-reference/native-functions.md +7029 -0
  67. package/skills/protheus-reference/rest-api-reference.md +1758 -0
  68. package/skills/protheus-reference/restricted-functions.md +265 -0
  69. package/skills/protheus-reference/sx-dictionary.md +854 -0
  70. package/skills/sx-configuration/SKILL.md +184 -0
@@ -0,0 +1,72 @@
1
+ ---
2
+ name: advpl-code-review
3
+ description: Use when reviewing ADVPL/TLPP code for best practices, performance, security, and modernization opportunities
4
+ ---
5
+
6
+ # ADVPL/TLPP Code Review
7
+
8
+ ## Overview
9
+
10
+ Systematic code review methodology for ADVPL/TLPP on TOTVS Protheus. This skill provides structured rules to identify issues related to best practices, performance bottlenecks, security vulnerabilities, and modernization opportunities in existing codebases.
11
+
12
+ ## When to Use
13
+
14
+ - Reviewing ADVPL/TLPP source code before merge or deploy
15
+ - Auditing existing code for quality and compliance
16
+ - Identifying performance bottlenecks in slow routines
17
+ - Checking for security vulnerabilities (SQL injection, credential exposure)
18
+ - Evaluating code for migration readiness from .prw to .tlpp
19
+ - Onboarding reviews to enforce team coding standards
20
+
21
+ ## Review Categories
22
+
23
+ | Category | File | Focus | Severity Range |
24
+ |----------|------|-------|----------------|
25
+ | Best Practices | `rules-best-practices.md` | RecLock/MsUnlock pairing, variable scope, area management, error handling, documentation | CRITICAL - INFO |
26
+ | Performance | `rules-performance.md` | Embedded SQL optimization, loop efficiency, string operations, index usage | CRITICAL - INFO |
27
+ | Security | `rules-security.md` | SQL injection, input validation, credential exposure, sensitive data logging | CRITICAL - WARNING |
28
+ | Modernization | `rules-modernization.md` | TLPP migration, namespace usage, OOP patterns, modern UI frameworks | INFO |
29
+
30
+ ## Output Format
31
+
32
+ Each finding must include:
33
+
34
+ ```
35
+ [RULE-ID] SEVERITY: Brief description
36
+ File: filename.prw (line XX)
37
+ Issue: What was found
38
+ Fix: How to correct it
39
+ ```
40
+
41
+ ### Severity Levels
42
+
43
+ | Level | Meaning | Action Required |
44
+ |-------|---------|-----------------|
45
+ | **CRITICAL** | Data corruption, security breach, or system failure risk | Must fix before deploy |
46
+ | **WARNING** | Performance degradation, maintenance burden, or potential bugs | Should fix in current sprint |
47
+ | **INFO** | Improvement opportunity, style suggestion, or modernization hint | Fix when touching the code |
48
+
49
+ ## Review Process
50
+
51
+ 1. **Scan includes and headers** - Check for obsolete includes (`Protheus.ch` vs `TOTVS.CH`), missing documentation headers
52
+ 2. **Analyze variable declarations** - Verify scope (`Local` preferred), naming conventions (Hungarian notation)
53
+ 3. **Check database operations** - Validate `RecLock`/`MsUnlock` pairing, `GetArea`/`RestArea` usage, error handling around DB ops
54
+ 4. **Evaluate queries** - Review Embedded SQL for `SELECT *`, proper macro usage (`%exp:`, `%table:`, `%notDel%`), index alignment
55
+ 5. **Inspect security surface** - Look for SQL injection vectors, hardcoded credentials, sensitive data in logs, unvalidated REST input
56
+ 6. **Assess modernization** - Identify candidates for TLPP migration, OOP refactoring, modern UI patterns
57
+
58
+ ## Rule ID Format
59
+
60
+ | Prefix | Category | Example |
61
+ |--------|----------|---------|
62
+ | `BP` | Best Practices | `[BP-001]` RecLock without MsUnlock, `[BP-008]` Reserved system variables |
63
+ | `PERF` | Performance | `[PERF-001]` SELECT * in Embedded SQL |
64
+ | `SEC` | Security | `[SEC-001]` SQL injection, `[SEC-005]` Restricted TOTVS functions |
65
+ | `MOD` | Modernization | `[MOD-001]` .prw class candidate for .tlpp |
66
+
67
+ ## References
68
+
69
+ - `rules-best-practices.md` - Best practice rules with detection patterns and code examples
70
+ - `rules-performance.md` - Performance rules with detection patterns and code examples
71
+ - `rules-security.md` - Security rules with detection patterns and code examples
72
+ - `rules-modernization.md` - Modernization rules with detection patterns and code examples
@@ -0,0 +1,444 @@
1
+ # Best Practices Rules
2
+
3
+ Rules for detecting violations of ADVPL/TLPP best practices. Each rule includes a detection pattern, violation example, correct example, and explanation.
4
+
5
+ ---
6
+
7
+ ## [BP-001] RecLock without corresponding MsUnlock
8
+
9
+ **Severity:** CRITICAL
10
+
11
+ **Description:** Every `RecLock` call must have a corresponding `MsUnlock` call. Forgetting to unlock a record keeps it locked, blocking other users and threads from accessing it, potentially causing deadlocks and data access failures.
12
+
13
+ **What to look for:** A `RecLock` call that is not followed by `MsUnlock` within the same logical block. Check that all code paths (including error branches) release the lock.
14
+
15
+ **Violation:**
16
+
17
+ ```advpl
18
+ User Function UpdateClient()
19
+ Local cCodCli := "000001"
20
+
21
+ DbSelectArea("SA1")
22
+ DbSetOrder(1)
23
+
24
+ If DbSeek(xFilial("SA1") + cCodCli)
25
+ RecLock("SA1", .F.)
26
+ SA1->A1_NOME := "New Name"
27
+ // Missing MsUnlock - record stays locked!
28
+ EndIf
29
+
30
+ Return
31
+ ```
32
+
33
+ **Correct:**
34
+
35
+ ```advpl
36
+ User Function UpdateClient()
37
+ Local cCodCli := "000001"
38
+
39
+ DbSelectArea("SA1")
40
+ DbSetOrder(1)
41
+
42
+ If DbSeek(xFilial("SA1") + cCodCli)
43
+ If RecLock("SA1", .F.)
44
+ SA1->A1_NOME := "New Name"
45
+ MsUnlock()
46
+ EndIf
47
+ EndIf
48
+
49
+ Return
50
+ ```
51
+
52
+ **Why it matters:** An unreleased lock blocks all other threads attempting to write to the same record. In high-concurrency environments this leads to lock timeouts, deadlocks, and user complaints about frozen screens.
53
+
54
+ ---
55
+
56
+ ## [BP-002] Local variables declared outside the function header
57
+
58
+ **Severity:** ERROR
59
+
60
+ **Description:** In ADVPL/TLPP, ALL `Local` variable declarations MUST appear at the top of the function, immediately after the function signature and before any executable code. Declaring `Local` inside `If`, `While`, `For` blocks, or after any executable statement is a violation that can cause compilation errors or unpredictable behavior.
61
+
62
+ **What to look for:** `Local` keyword appearing after any executable statement (DbSelectArea, If, While, RecLock, assignments, function calls, etc.).
63
+
64
+ **Violation:**
65
+
66
+ ```advpl
67
+ User Function ProcessData()
68
+ Local aArea := GetArea()
69
+ Local cAlias := "SA1"
70
+
71
+ DbSelectArea(cAlias)
72
+ DbSetOrder(1)
73
+
74
+ If DbSeek(xFilial("SA1") + "000001")
75
+ Local cNome := AllTrim(SA1->A1_NOME) // WRONG: Local inside If block
76
+ Local nSaldo := SA1->A1_SALDO // WRONG: Local after executable code
77
+ EndIf
78
+
79
+ RestArea(aArea)
80
+ Return cNome
81
+ ```
82
+
83
+ **Correct:**
84
+
85
+ ```advpl
86
+ User Function ProcessData()
87
+ Local aArea := GetArea()
88
+ Local cAlias := "SA1"
89
+ Local cNome := ""
90
+ Local nSaldo := 0
91
+
92
+ DbSelectArea(cAlias)
93
+ DbSetOrder(1)
94
+
95
+ If DbSeek(xFilial("SA1") + "000001")
96
+ cNome := AllTrim(SA1->A1_NOME)
97
+ nSaldo := SA1->A1_SALDO
98
+ EndIf
99
+
100
+ RestArea(aArea)
101
+ Return cNome
102
+ ```
103
+
104
+ **Why it matters:** ADVPL/TLPP requires all variable declarations at the function header. Declaring variables in the middle of executable code violates the language specification and can lead to compilation errors in strict mode or undefined behavior. Variables that are conditionally needed should be declared at the top with a default value (Nil, "", 0, .F., {}) and assigned later.
105
+
106
+ ---
107
+
108
+ ## [BP-002b] Variables declared as Private or Public instead of Local
109
+
110
+ **Severity:** WARNING
111
+
112
+ **Description:** Variables should be declared as `Local` unless there is a specific need for broader scope. `Private` and `Public` variables pollute the call stack and can be accidentally overwritten by called functions.
113
+
114
+ **What to look for:** `Private` or `Public` variable declarations where `Local` would suffice. Legitimate uses of `Private` include passing variables to MVC models or legacy framework functions that expect them.
115
+
116
+ **Violation:**
117
+
118
+ ```advpl
119
+ User Function CalcTotal()
120
+ Private nTotal := 0
121
+ Private cCodCli := "000001"
122
+ Private nIdx := 0
123
+
124
+ For nIdx := 1 To 10
125
+ nTotal += GetValue(nIdx)
126
+ Next nIdx
127
+
128
+ Return nTotal
129
+ ```
130
+
131
+ **Correct:**
132
+
133
+ ```advpl
134
+ User Function CalcTotal()
135
+ Local nTotal := 0
136
+ Local cCodCli := "000001"
137
+ Local nIdx := 0
138
+
139
+ For nIdx := 1 To 10
140
+ nTotal += GetValue(nIdx)
141
+ Next nIdx
142
+
143
+ Return nTotal
144
+ ```
145
+
146
+ **Why it matters:** `Private` variables are visible to all functions called from the declaring function. A called function may unintentionally read or overwrite a `Private` variable, causing hard-to-trace bugs. `Local` variables are scoped to the declaring function only, making code predictable and safer.
147
+
148
+ ---
149
+
150
+ ## [BP-003] Missing GetArea/RestArea in functions that use DbSelectArea/DbSetOrder/DbSeek
151
+
152
+ **Severity:** WARNING
153
+
154
+ **Description:** Functions that change the current WorkArea (via `DbSelectArea`, `DbSetOrder`, `DbSeek`, etc.) must save and restore the caller's WorkArea state using `GetArea()` and `RestArea()`. Otherwise, the calling function's WorkArea context is silently altered.
155
+
156
+ **What to look for:** Any function that calls `DbSelectArea`, `DbSetOrder`, `DbSeek`, or `DbGoTo` without first calling `GetArea()` on the affected alias and calling `RestArea()` before returning.
157
+
158
+ **Violation:**
159
+
160
+ ```advpl
161
+ User Function GetClientName(cCodCli)
162
+ Local cNome := ""
163
+
164
+ DbSelectArea("SA1")
165
+ DbSetOrder(1)
166
+
167
+ If DbSeek(xFilial("SA1") + cCodCli)
168
+ cNome := SA1->A1_NOME
169
+ EndIf
170
+
171
+ Return cNome
172
+ ```
173
+
174
+ **Correct:**
175
+
176
+ ```advpl
177
+ User Function GetClientName(cCodCli)
178
+ Local cNome := ""
179
+ Local aAreaSA1 := SA1->(GetArea())
180
+
181
+ DbSelectArea("SA1")
182
+ DbSetOrder(1)
183
+
184
+ If DbSeek(xFilial("SA1") + cCodCli)
185
+ cNome := SA1->A1_NOME
186
+ EndIf
187
+
188
+ RestArea(aAreaSA1)
189
+
190
+ Return cNome
191
+ ```
192
+
193
+ **Why it matters:** Without saving and restoring the area, the calling function loses its WorkArea position. This causes incorrect reads, skipped records, and mysterious bugs that are extremely difficult to diagnose because they depend on call order.
194
+
195
+ ---
196
+
197
+ ## [BP-004] #Include "Protheus.ch" instead of #Include "TOTVS.CH"
198
+
199
+ **Severity:** WARNING
200
+
201
+ **Description:** The include `Protheus.ch` is obsolete. All `.prw` files should use `#Include "TOTVS.CH"` which is the current standard and includes all necessary definitions.
202
+
203
+ **What to look for:** Any line containing `#Include "Protheus.ch"` (case-insensitive).
204
+
205
+ **Violation:**
206
+
207
+ ```advpl
208
+ #Include "Protheus.ch"
209
+
210
+ User Function MyFunc()
211
+ // ...
212
+ Return
213
+ ```
214
+
215
+ **Correct:**
216
+
217
+ ```advpl
218
+ #Include "TOTVS.CH"
219
+
220
+ User Function MyFunc()
221
+ // ...
222
+ Return
223
+ ```
224
+
225
+ **Why it matters:** `Protheus.ch` is a legacy include that may not contain all current definitions and may be removed in future Protheus versions. `TOTVS.CH` is the officially supported include that aggregates all necessary header definitions.
226
+
227
+ ---
228
+
229
+ ## [BP-005] Missing Begin Sequence/Recover/End Sequence around critical operations
230
+
231
+ **Severity:** WARNING
232
+
233
+ **Description:** Critical operations such as `RecLock`, database writes, external API calls, and file operations should be wrapped in `Begin Sequence`/`Recover`/`End Sequence` blocks to handle errors gracefully instead of crashing.
234
+
235
+ **What to look for:** `RecLock`, `MsExecAuto`, `HttpGet`, `HttpPost`, `FT_FUse`, or web service calls that are not inside a `Begin Sequence` block.
236
+
237
+ **Violation:**
238
+
239
+ ```advpl
240
+ User Function ProcessOrder(cOrder)
241
+ Local lRet := .T.
242
+
243
+ DbSelectArea("SC5")
244
+ DbSetOrder(1)
245
+ DbSeek(xFilial("SC5") + cOrder)
246
+
247
+ RecLock("SC5", .F.)
248
+ SC5->C5_LIBEROK := "S"
249
+ MsUnlock()
250
+
251
+ // If RecLock fails or an error occurs, function crashes
252
+ // with an unhandled exception
253
+
254
+ Return lRet
255
+ ```
256
+
257
+ **Correct:**
258
+
259
+ ```advpl
260
+ User Function ProcessOrder(cOrder)
261
+ Local lRet := .T.
262
+ Local oError
263
+
264
+ DbSelectArea("SC5")
265
+ DbSetOrder(1)
266
+ DbSeek(xFilial("SC5") + cOrder)
267
+
268
+ Begin Sequence
269
+
270
+ If RecLock("SC5", .F.)
271
+ SC5->C5_LIBEROK := "S"
272
+ MsUnlock()
273
+ Else
274
+ lRet := .F.
275
+ ConOut("[ProcessOrder] Could not lock SC5 for order: " + cOrder)
276
+ EndIf
277
+
278
+ Recover Using oError
279
+ lRet := .F.
280
+ ConOut("[ProcessOrder] Error: " + oError:Description)
281
+
282
+ End Sequence
283
+
284
+ Return lRet
285
+ ```
286
+
287
+ **Why it matters:** Without error handling, any failure in database or external operations causes the entire thread to crash, potentially leaving records locked and data in an inconsistent state. Structured error handling allows graceful recovery and proper cleanup.
288
+
289
+ ---
290
+
291
+ ## [BP-006] Variable names not following Hungarian notation
292
+
293
+ **Severity:** INFO
294
+
295
+ **Description:** ADVPL convention uses Hungarian notation with a type prefix followed by PascalCase: `c` for character, `n` for numeric, `l` for logical, `d` for date, `a` for array, `o` for object, `b` for code block, `x` for variant/indefinite.
296
+
297
+ **What to look for:** Variable declarations where the name does not start with a recognized type prefix (`c`, `n`, `l`, `d`, `a`, `o`, `b`, `x`) or does not follow PascalCase after the prefix.
298
+
299
+ **Violation:**
300
+
301
+ ```advpl
302
+ User Function Calculate()
303
+ Local total := 0
304
+ Local clientName := ""
305
+ Local flag := .T.
306
+ Local items := {}
307
+ Local dt := Date()
308
+
309
+ // Variable names do not indicate their type
310
+
311
+ Return
312
+ ```
313
+
314
+ **Correct:**
315
+
316
+ ```advpl
317
+ User Function Calculate()
318
+ Local nTotal := 0
319
+ Local cClientName := ""
320
+ Local lFlag := .T.
321
+ Local aItems := {}
322
+ Local dDate := Date()
323
+
324
+ // Each variable name starts with its type prefix
325
+
326
+ Return
327
+ ```
328
+
329
+ **Why it matters:** Hungarian notation makes code self-documenting. When reading `nTotal`, any developer immediately knows it is a numeric value. This reduces bugs caused by type mismatches and speeds up code reviews.
330
+
331
+ ---
332
+
333
+ ## [BP-007] Functions missing Protheus.doc documentation header
334
+
335
+ **Severity:** INFO
336
+
337
+ **Description:** Every `User Function`, `Static Function`, and `Main Function` should have a `Protheus.doc` documentation header describing the function's purpose, author, date, parameters, and return value.
338
+
339
+ **What to look for:** Function definitions without a preceding `Protheus.doc` comment block.
340
+
341
+ **Violation:**
342
+
343
+ ```advpl
344
+ User Function CalcDiscount(nPrice, nPercent)
345
+ Local nDiscount := nPrice * (nPercent / 100)
346
+ Return nDiscount
347
+ ```
348
+
349
+ **Correct:**
350
+
351
+ ```advpl
352
+ /*/{Protheus.doc} CalcDiscount
353
+ Calculates discount value based on price and percentage.
354
+
355
+ @type User Function
356
+ @author Developer Name
357
+ @since 01/01/2025
358
+ @version 1.0
359
+
360
+ @param nPrice, Numeric, Original price
361
+ @param nPercent, Numeric, Discount percentage (0-100)
362
+
363
+ @return Numeric, Calculated discount value
364
+
365
+ @example
366
+ Local nDisc := CalcDiscount(100.00, 10) // Returns 10.00
367
+ /*/
368
+ User Function CalcDiscount(nPrice, nPercent)
369
+ Local nDiscount := nPrice * (nPercent / 100)
370
+ Return nDiscount
371
+ ```
372
+
373
+ **Why it matters:** Documentation headers enable IDE tooltips, automatic documentation generation, and help other developers understand the function's contract without reading the implementation. They are especially important in large teams and long-lived codebases.
374
+
375
+ ---
376
+
377
+ ## [BP-008] Using reserved system variables as Local/Static variable names
378
+
379
+ **Severity:** CRITICAL
380
+
381
+ **Description:** The Protheus framework maintains several `Private` variables to track the current company, branch, and environment context. Declaring a `Local` variable with the same name shadows the system variable, causing loss of context, incorrect data filtering, and hard-to-reproduce bugs in multi-branch/multi-company environments.
382
+
383
+ **Reserved variable names (NEVER use as Local/Static):**
384
+
385
+ | Variable | Purpose |
386
+ |----------|---------|
387
+ | `cFilial` | Branch context — used internally by xFilial() and other framework functions |
388
+ | `cFilAnt` | Current branch code — default value for xFilial() second parameter |
389
+ | `cEmpAnt` | Current company/group code — used by FWSizeFilial() and environment functions |
390
+ | `nModulo` | Current module number |
391
+ | `cUsuario` | Current user login |
392
+
393
+ **Violation:**
394
+
395
+ ```advpl
396
+ User Function MyJob()
397
+ Local cEmpresa := "99"
398
+ Local cFilial := "01" // WRONG: shadows system Private variable
399
+
400
+ RpcSetEnv(cEmpresa, cFilial)
401
+ // After this call, the system's cFilial Private is overwritten
402
+ // xFilial() and other functions may return incorrect values
403
+ Return
404
+ ```
405
+
406
+ **Correct:**
407
+
408
+ ```advpl
409
+ User Function MyJob()
410
+ Local cCodEmp := "99"
411
+ Local cCodFil := "01" // Safe: different name from system variable
412
+
413
+ RpcSetEnv(cCodEmp, cCodFil)
414
+ // System's cFilAnt/cEmpAnt are set correctly by RpcSetEnv
415
+ // xFilial() works as expected
416
+ Return
417
+ ```
418
+
419
+ **Recommended alternatives:**
420
+
421
+ | Instead of | Use |
422
+ |------------|-----|
423
+ | `cFilial` | `cCodFil` |
424
+ | `cEmpresa` | `cCodEmp` |
425
+ | `cFilAnt` | (never reassign — read-only system variable) |
426
+ | `cEmpAnt` | (never reassign — read-only system variable) |
427
+
428
+ **Use FW* functions to read company/branch values:**
429
+
430
+ | Function | Purpose |
431
+ |----------|---------|
432
+ | `FWCodFil()` | Returns current branch code (M0_CODFIL) |
433
+ | `FWCodEmp()` | Returns current company code |
434
+ | `FWFilial(cAlias)` | Returns branch for the given alias (respects sharing mode) |
435
+ | `FWCompany(cAlias)` | Returns company for the given alias |
436
+ | `FWGrpCompany()` | Returns current company group |
437
+ | `FWUnitBusiness(cAlias)` | Returns current business unit |
438
+ | `FWAllFilial()` | Returns array of all branches for current group/company |
439
+ | `FWAllCompany()` | Returns array of all companies for current group |
440
+ | `FWAllGrpCompany()` | Returns array of all company groups |
441
+ | `FWSizeFilial()` | Returns branch field size |
442
+ | `xFilial(cAlias)` | Returns branch for index composition (respects sharing mode) |
443
+
444
+ **Why it matters:** Shadowing system Private variables is one of the most dangerous bugs in Protheus because it is silent — the code compiles and appears to work in single-branch testing, but fails in multi-branch production environments where branch context is critical for data isolation.