@provartesting/provardx-cli 1.5.2 → 1.6.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 (52) hide show
  1. package/README.md +5 -37
  2. package/lib/commands/provar/automation/project/validate.js +5 -3
  3. package/lib/commands/provar/automation/project/validate.js.map +1 -1
  4. package/lib/mcp/docs/PROVAR_TEST_STEP_REFERENCE.md +269 -79
  5. package/lib/mcp/docs/VALIDATION_RULE_REGISTRY.md +225 -0
  6. package/lib/mcp/prompts/loopPrompts.js +4 -3
  7. package/lib/mcp/prompts/loopPrompts.js.map +1 -1
  8. package/lib/mcp/rules/comparisonTypeSets.d.ts +21 -0
  9. package/lib/mcp/rules/comparisonTypeSets.js +45 -0
  10. package/lib/mcp/rules/comparisonTypeSets.js.map +1 -0
  11. package/lib/mcp/rules/provar_best_practices_rules.json +178 -8
  12. package/lib/mcp/rules/provar_layer1_rules.json +151 -0
  13. package/lib/mcp/rules/provar_test_step_schema.json +3005 -0
  14. package/lib/mcp/server.d.ts +15 -0
  15. package/lib/mcp/server.js +64 -1
  16. package/lib/mcp/server.js.map +1 -1
  17. package/lib/mcp/tools/automationTools.js +38 -1
  18. package/lib/mcp/tools/automationTools.js.map +1 -1
  19. package/lib/mcp/tools/bestPracticesEngine.js +1368 -10
  20. package/lib/mcp/tools/bestPracticesEngine.js.map +1 -1
  21. package/lib/mcp/tools/hierarchyValidate.d.ts +2 -1
  22. package/lib/mcp/tools/hierarchyValidate.js +7 -1
  23. package/lib/mcp/tools/hierarchyValidate.js.map +1 -1
  24. package/lib/mcp/tools/projectValidateFromPath.js +1 -2
  25. package/lib/mcp/tools/projectValidateFromPath.js.map +1 -1
  26. package/lib/mcp/tools/sfSpawn.d.ts +23 -0
  27. package/lib/mcp/tools/sfSpawn.js +72 -1
  28. package/lib/mcp/tools/sfSpawn.js.map +1 -1
  29. package/lib/mcp/tools/testCaseGenerate.js +377 -23
  30. package/lib/mcp/tools/testCaseGenerate.js.map +1 -1
  31. package/lib/mcp/tools/testCaseValidate.d.ts +46 -0
  32. package/lib/mcp/tools/testCaseValidate.js +313 -43
  33. package/lib/mcp/tools/testCaseValidate.js.map +1 -1
  34. package/lib/mcp/tools/testPlanValidate.js +3 -2
  35. package/lib/mcp/tools/testPlanValidate.js.map +1 -1
  36. package/lib/mcp/tools/testSuiteValidate.js +3 -2
  37. package/lib/mcp/tools/testSuiteValidate.js.map +1 -1
  38. package/lib/mcp/tools/uiActionApiIds.d.ts +23 -0
  39. package/lib/mcp/tools/uiActionApiIds.js +46 -0
  40. package/lib/mcp/tools/uiActionApiIds.js.map +1 -0
  41. package/lib/mcp/utils/qualityThreshold.d.ts +8 -0
  42. package/lib/mcp/utils/qualityThreshold.js +42 -0
  43. package/lib/mcp/utils/qualityThreshold.js.map +1 -0
  44. package/lib/mcp/utils/testCaseId.d.ts +23 -0
  45. package/lib/mcp/utils/testCaseId.js +156 -0
  46. package/lib/mcp/utils/testCaseId.js.map +1 -0
  47. package/lib/services/projectValidation.js +2 -1
  48. package/lib/services/projectValidation.js.map +1 -1
  49. package/messages/sf.provar.automation.project.validate.md +1 -1
  50. package/messages/sf.provar.mcp.start.md +1 -0
  51. package/oclif.manifest.json +4 -4
  52. package/package.json +4 -2
@@ -338,10 +338,10 @@
338
338
  "id": "VAR-NAMING-001",
339
339
  "category": "DataDrivenTesting",
340
340
  "name": "Variable names must use valid identifiers",
341
- "description": "Variable names, field references, and result names must contain only letters, digits, and underscores. Spaces, hyphens, and special characters cause RUNTIME FAILURES in Provar. Examples: {Account.Name} ✅ | {Account.Account Name} ❌ (space will fail)",
341
+ "description": "Variable names, field references, and result names must contain only letters, digits, and underscores. Spaces, hyphens, and special characters cause RUNTIME FAILURES in Provar (the test case still loads, so this is a major runtime defect, not a load-blocking critical). Examples: {Account.Name} ✅ | {Account.Account Name} ❌ (space will fail)",
342
342
  "appliesTo": ["Step"],
343
- "severity": "critical",
344
- "weight": 8,
343
+ "severity": "major",
344
+ "weight": 5,
345
345
  "recommendation": "Replace spaces and special characters with underscores. Use API field names (e.g., Account.Name) instead of field labels (e.g., Account.Account Name).",
346
346
  "check": {
347
347
  "type": "variableNaming",
@@ -588,6 +588,36 @@
588
588
  },
589
589
  "source": "Provar API Reference: UiConnect vs ApexConnect"
590
590
  },
591
+ {
592
+ "id": "UI-NITROX-CONNECT-ARGS-001",
593
+ "category": "ConnectionsAndEnvironments",
594
+ "name": "NitroX MS connect step has invalid arguments",
595
+ "description": "NitroXConnect:ms-* steps share a common argument set (connectionName, reuseConnectionName, privateBrowsingMode, resultName, resultScope, webBrowser) plus variant-specific args: ms-dynamics365 → appName; ms-powerapp → powerAppName; ms-powerpage → environment, powerPageName; ms-dataverse → none. NitroX MS variants do NOT support ApexConnect-only args (autoCleanup, lightningMode, alreadyOpenBehaviour, etc.) or arguments from sibling variants (e.g. powerAppName on ms-dynamics365).",
596
+ "appliesTo": ["Step"],
597
+ "severity": "critical",
598
+ "weight": 10,
599
+ "recommendation": "Remove invalid arguments from the NitroX MS connect step. Cross-variant args (e.g. powerAppName on ms-dynamics365) usually indicate the wrong apiId variant — verify which Microsoft product the step targets and update the apiId suffix accordingly.",
600
+ "check": {
601
+ "type": "nitroxConnectInvalidArgs",
602
+ "target": "step"
603
+ },
604
+ "source": "Provar 3.0.7 API Reference: NitroXConnect Microsoft variants"
605
+ },
606
+ {
607
+ "id": "UI-NITROX-VARIANT-ARG-001",
608
+ "category": "ConnectionsAndEnvironments",
609
+ "name": "NitroX MS connect step missing variant-specific argument",
610
+ "description": "Variants ms-dynamics365 (appName), ms-powerapp (powerAppName), and ms-powerpage (environment, powerPageName) each have variant-specific arguments. They may be left empty when declared as runtime-bound parameters via <generatedParameters><apiParam name=\"...\"/> (the data-driven test pattern). Otherwise they should be populated to avoid runtime null binding.",
611
+ "appliesTo": ["Step"],
612
+ "severity": "minor",
613
+ "weight": 2,
614
+ "recommendation": "Either populate the argument with a literal/variable value, or declare it as a runtime parameter under <generatedParameters> for data-driven tests.",
615
+ "check": {
616
+ "type": "nitroxVariantArgRequired",
617
+ "target": "step"
618
+ },
619
+ "source": "Provar 3.0.7 API Reference: NitroXConnect Microsoft variants"
620
+ },
591
621
  {
592
622
  "id": "APEX-AUTOCLEANUP-001",
593
623
  "category": "ConnectionsAndEnvironments",
@@ -862,7 +892,7 @@
862
892
  "appliesTo": ["Step"],
863
893
  "severity": "critical",
864
894
  "weight": 8,
865
- "recommendation": "Add 'comparisonType' argument with valid value: EqualTo, NotEqualTo, Contains, NotContains, StartsWith, EndsWith, GreaterThan, LessThan, Matches, IsNull, NotNull.",
895
+ "recommendation": "Add 'comparisonType' argument with a value from the AssertValues subset of ComparisonType: EqualTo, NotEqualTo, GreaterThan, GreaterThanOrEqualTo, LessThan, LessThanOrEqualTo, IsPresent, IsEmpty, Matches, NotMatches, Contains, NotContains, StartsWith, NotStartsWith, EndsWith, NotEndsWith. Note: UI Assert (uiAttributeAssertion) steps accept only the narrower subset EqualTo, Contains, StartsWith, EndsWith, Matches, None; a value used outside its step's subset is load-blocking.",
866
896
  "check": {
867
897
  "type": "mustContainArgument",
868
898
  "apiId": "com.provar.plugins.bundled.apis.AssertValues",
@@ -1476,7 +1506,7 @@
1476
1506
  "id": "ASSERT-VALUES-COMPARISON-001",
1477
1507
  "category": "TestCaseDesign",
1478
1508
  "name": "AssertValues should have meaningful expected values",
1479
- "description": "AssertValues steps using comparison operators (EqualTo, Contains, GreaterThan, etc.) should specify meaningful expectedValue arguments. Empty or missing expected values defeat the purpose of assertions and provide no validation. Without expected values, assertions cannot verify correct behavior. Comparison types requiring values: EqualTo, NotEqualTo, Contains, NotContains, StartsWith, NotStartsWith, EndsWith, NotEndsWith, Matches, NotMatches, GreaterThan, LessThan, GreaterThanOrEqualTo, LessThanOrEqualTo.",
1509
+ "description": "AssertValues steps using comparison operators (EqualTo, Contains, GreaterThan, etc.) should specify meaningful expectedValue arguments. Empty or missing expected values defeat the purpose of assertions and provide no validation. Without expected values, assertions cannot verify correct behavior. The AssertValues subset of ComparisonType is: EqualTo, NotEqualTo, GreaterThan, GreaterThanOrEqualTo, LessThan, LessThanOrEqualTo, IsPresent, IsEmpty, Matches, NotMatches, Contains, NotContains, StartsWith, NotStartsWith, EndsWith, NotEndsWith. Of these, the value-requiring comparators are EqualTo, NotEqualTo, Contains, NotContains, StartsWith, NotStartsWith, EndsWith, NotEndsWith, Matches, NotMatches, GreaterThan, LessThan, GreaterThanOrEqualTo, LessThanOrEqualTo (the presence checks IsPresent and IsEmpty do not need an expectedValue). UI Assert (uiAttributeAssertion) steps use a narrower subset: EqualTo, Contains, StartsWith, EndsWith, Matches, None.",
1480
1510
  "appliesTo": ["Step"],
1481
1511
  "severity": "major",
1482
1512
  "weight": 5,
@@ -2640,10 +2670,10 @@
2640
2670
  "id": "UI-BINDING-ORDER-001",
2641
2671
  "category": "LocatorPatterns",
2642
2672
  "name": "UI binding parameter order must have object= first",
2643
- "description": "In UI binding URIs, the object= parameter MUST come FIRST, followed by field= or action=. Wrong order causes 'Unknown control' errors in Provar at runtime.",
2673
+ "description": "In UI binding URIs, the object= parameter MUST come FIRST, followed by field= or action=. Wrong order causes 'Unknown control' errors in Provar at runtime (the test case still loads, so this is a major runtime defect, not a load-blocking critical).",
2644
2674
  "appliesTo": ["Step"],
2645
- "severity": "critical",
2646
- "weight": 10,
2675
+ "severity": "major",
2676
+ "weight": 5,
2647
2677
  "recommendation": "Correct the binding parameter order. Use 'object?object=ObjectName&action=ActionName' or 'object?object=ObjectName&field=FieldName'. Never put action= or field= before object=.",
2648
2678
  "check": {
2649
2679
  "type": "bindingParameterOrder",
@@ -2899,6 +2929,146 @@
2899
2929
  },
2900
2930
  "notes": "Provar internally stores dates as epoch timestamps (milliseconds since 1970-01-01). When valueClass='date' is used, Provar expects a numeric epoch value. String dates cause XML parsing/loading failures. All valid corpus examples use epoch timestamps with valueClass='date': 1637798400000, 1513209600000, etc.",
2901
2931
  "source": "Corpus analysis: All valueClass='date' values are epoch timestamps; string dates cause Provar IDE load failures"
2932
+ },
2933
+ {
2934
+ "id": "UI-NEST-STRUCT-001",
2935
+ "category": "XMLSchema",
2936
+ "name": "UI action steps must be nested inside a UiWithScreen substeps clause",
2937
+ "description": "UiDoAction, UiAssert, UiRead, UiFill, UiNavigate, UiWithRow, and UiHandleAlert steps must descend from a UiWithScreen or UiWithRow ancestor through a <clause name=\"substeps\"> path. Control-flow wrappers (IfThen, ForEach, DoWhile, WaitFor, Switch) between the screen ancestor and the UI action are allowed. Steps inside <clause name=\"hidden\"> are exempt. When emitted flat (e.g. as siblings of UiWithScreen in the root <steps>), Provar IDE cannot bind them to a screen context and they will not render correctly.",
2938
+ "appliesTo": ["Step"],
2939
+ "severity": "major",
2940
+ "weight": 7,
2941
+ "recommendation": "Wrap each UI action inside a parent UiWithScreen using this structure:\n\n <apiCall apiId=\"com.provar.plugins.forcedotcom.core.ui.UiWithScreen\" ...>\n <arguments>...</arguments>\n <clauses>\n <clause name=\"substeps\" testItemId=\"...\">\n <steps>\n <apiCall apiId=\"...UiDoAction\" .../>\n <apiCall apiId=\"...UiWithRow\" ...> ... </apiCall>\n </steps>\n </clause>\n </clauses>\n </apiCall>\n\nUiWithRow may contain its own <clauses><clause name=\"substeps\"> with further UI actions inside. Control-flow wrappers (IfThen, ForEach, DoWhile, WaitFor) between the screen ancestor and the UI action are allowed; <clause name=\"hidden\"> is exempt (disabled/settings blocks).",
2942
+ "check": {
2943
+ "type": "uiActionNestingStructure",
2944
+ "target": "step",
2945
+ "uiActionApiIds": [
2946
+ "com.provar.plugins.forcedotcom.core.ui.UiDoAction",
2947
+ "com.provar.plugins.forcedotcom.core.ui.UiAssert",
2948
+ "com.provar.plugins.forcedotcom.core.ui.UiRead",
2949
+ "com.provar.plugins.forcedotcom.core.ui.UiFill",
2950
+ "com.provar.plugins.forcedotcom.core.ui.UiNavigate",
2951
+ "com.provar.plugins.forcedotcom.core.ui.UiWithRow",
2952
+ "com.provar.plugins.forcedotcom.core.ui.UiHandleAlert"
2953
+ ],
2954
+ "screenContainerApiIds": [
2955
+ "com.provar.plugins.forcedotcom.core.ui.UiWithScreen",
2956
+ "com.provar.plugins.forcedotcom.core.ui.UiWithRow"
2957
+ ]
2958
+ },
2959
+ "notes": "Mirrors QH UiActionNestingStructureValidator (lambda/src/validator/best_practices_engine.py). Emits one violation per offending step so that (rule_id, test_item_id) de-dups against the API. UiWithRow plays a dual role: itself a UI action that must be nested, and a container whose substeps clause satisfies the rule for its descendants.",
2960
+ "source": "Field observation: flat-emitted UI actions (sibling of UiWithScreen) fail to render in Provar IDE despite scoring 100/94 in earlier local validation"
2961
+ },
2962
+ {
2963
+ "id": "VAR-STRING-LITERAL-001",
2964
+ "category": "TestCaseDesign",
2965
+ "name": "Variable reference stored as plain string",
2966
+ "description": "An argument value contains a {VarName} or {Obj.Field} pattern stored as class=\"value\" valueClass=\"string\". Provar passes the literal string to the API instead of resolving the variable. In data arguments the step silently receives the wrong input; in UI target arguments (sfUiTargetObjectId, sfUiTargetResultName) the literal {VarName} lands in the URL as %7BVarName%7D and the step fails at runtime (record 'no longer available'). The test case still loads, so this is a runtime execution error (major), not a load failure (critical) or a style warning (minor).",
2967
+ "appliesTo": ["Step"],
2968
+ "severity": "major",
2969
+ "weight": 5,
2970
+ "recommendation": "Replace with <value class=\"variable\"><path element=\"VarName\"/></value>. Use dotted paths for nested references: <path element=\"Obj\"/><path element=\"Field\"/>. If using provar.testcase.generate, the {VarName} syntax in attributes is converted automatically.",
2971
+ "check": {
2972
+ "type": "varStringLiteral"
2973
+ },
2974
+ "source": "Provar Test Step Schema: variable references must use class=\"variable\", not string literals"
2975
+ },
2976
+ {
2977
+ "id": "CONN-DB-002",
2978
+ "category": "ConnectionsAndEnvironments",
2979
+ "name": "DbConnect resultName must match dbConnectionName in DB operations",
2980
+ "description": "The resultName set on a DbConnect step is the connection handle variable that all subsequent DB operations (SqlQuery, DbRead, DbInsert, DbUpdate, DbDelete) must reference via their dbConnectionName argument. A mismatch between DbConnect resultName and dbConnectionName causes a runtime failure because the operation cannot find the open connection. This is the leading cause of silent Database step failures in Provar test suites.",
2981
+ "appliesTo": ["Step"],
2982
+ "severity": "major",
2983
+ "weight": 5,
2984
+ "recommendation": "Ensure every DB operation step's dbConnectionName argument exactly matches the resultName set on the preceding DbConnect step. For example, if DbConnect sets resultName='SQLServer', every SqlQuery/DbRead/DbInsert/DbUpdate/DbDelete in the same test must set dbConnectionName='SQLServer'.",
2985
+ "check": {
2986
+ "type": "dbConnectResultNameMismatch",
2987
+ "target": "testCase"
2988
+ },
2989
+ "source": "Provar DB Connection Best Practices - DbConnect resultName / dbConnectionName alignment"
2990
+ },
2991
+ {
2992
+ "id": "SETVALUES-FUNC-STR-001",
2993
+ "category": "StructureAndGrouping",
2994
+ "name": "SetValues must not use string interpolation for function calls",
2995
+ "description": "SetValues steps must use the correct XML structure for function calls (<value class=\"funcCall\">) rather than embedding Provar's curly-brace template syntax as a plain string literal (e.g. {Count(AccountList)}). At runtime Provar reads the string literally and does not evaluate it, so the target variable is set to the text \"{Count(AccountList)}\" instead of the computed count. This pattern is generated by AI models that reproduce the Provar UI tooltip syntax verbatim.",
2996
+ "appliesTo": ["Step"],
2997
+ "severity": "major",
2998
+ "weight": 5,
2999
+ "recommendation": "Replace the string literal with the proper funcCall XML: <value class=\"funcCall\" id=\"Count\"><argument id=\"value\"><value class=\"variable\"><path element=\"ListVariableName\"/></value></argument></value>. Supported functions include Count, Sum, Avg, Min, Max, Concat, StringLength, etc.",
3000
+ "check": {
3001
+ "type": "setValuesFuncCallString",
3002
+ "target": "step"
3003
+ },
3004
+ "notes": "AI models output {Count(var)} in a valueClass=string element because they mirror Provar's UI tooltip. The correct form is a funcCall value element. This causes silent test failures where the variable receives the literal string rather than the computed value.",
3005
+ "source": "Field observation: SetValues function-call string interpolation anti-pattern"
3006
+ },
3007
+ {
3008
+ "id": "SETVALUES-ZERO-IDX-001",
3009
+ "category": "StructureAndGrouping",
3010
+ "name": "SetValues string expression must not use [0] index",
3011
+ "description": "Provar's string-template engine is 1-indexed: {List[1]} accesses the first element. Using {List[0].Field} in a valueClass=string expression causes an out-of-bounds exception at runtime because index 0 is invalid in the template system. Note: the XML variable-path structure (<filter class=\"index\"><index valueClass=\"decimal\">0</index>) correctly uses 0-based indexing via a different code path — this rule targets only the broken string-template form.",
3012
+ "appliesTo": ["Step"],
3013
+ "severity": "major",
3014
+ "weight": 5,
3015
+ "recommendation": "Either switch to the proper XML variable path structure (<value class=\"variable\"><path element=\"List\"><filter class=\"index\"><index valueClass=\"decimal\">0</index></filter></path><path element=\"FieldName\"/></value>) or, if you must use string interpolation, change [0] to [1] to access the first element.",
3016
+ "check": {
3017
+ "type": "setValuesZeroIndexString",
3018
+ "target": "step"
3019
+ },
3020
+ "notes": "AI models that generate string-template expressions derive index numbers from the literal test intent (e.g. 'first item = index 0') but Provar string templates are 1-indexed. This causes runtime out-of-bounds errors.",
3021
+ "source": "Field observation: SetValues zero-index string interpolation anti-pattern"
3022
+ },
3023
+ {
3024
+ "id": "ASSERT-STR-VAR-001",
3025
+ "category": "StructureAndGrouping",
3026
+ "name": "AssertValues must not use string literal to reference a variable",
3027
+ "description": "AssertValues steps must use a proper XML variable reference (<value class=\"variable\">) when comparing against a stored variable. Using a string literal that wraps a variable name — e.g. <value class=\"value\" valueClass=\"string\">{RowCount}</value> — causes Provar to compare the literal text \"{RowCount}\" against the actual value, which always produces a false failure. The same applies to function-call expressions such as {Count(Results)}.",
3028
+ "appliesTo": ["Step"],
3029
+ "severity": "major",
3030
+ "weight": 5,
3031
+ "recommendation": "Replace the string literal with a proper variable reference: <value class=\"variable\"><path element=\"RowCount\"/></value>. For function calls, use a preceding SetValues step to compute the value into a variable, then reference that variable in AssertValues.",
3032
+ "check": {
3033
+ "type": "assertValuesStringExpr",
3034
+ "target": "step"
3035
+ },
3036
+ "notes": "AI models generate {VarName} in a valueClass=string element on the expectedValue side because they reproduce the Provar UI display format. The correct form is a class=variable element. This causes every assertion to fail with a string-vs-value mismatch.",
3037
+ "source": "Field observation: AssertValues string-variable reference anti-pattern"
3038
+ },
3039
+ {
3040
+ "id": "UI-LOCATOR-BUTTON-CASING-001",
3041
+ "category": "TestCaseDesign",
3042
+ "name": "Standard Salesforce flow buttons must use correct locator pattern",
3043
+ "description": "Standard Salesforce flow buttons must use the correct locator name. Cancel must use lowercase 'name=cancel'. The Continue button on the Record Type selection screen uses a special path-based locator 'name=save&path=selectRecordType' — using 'name=continue' or 'name=Continue' will not resolve and causes Provar to show 'Not Available' at runtime. AI models commonly generate these incorrectly.",
3044
+ "appliesTo": ["Step"],
3045
+ "severity": "major",
3046
+ "weight": 5,
3047
+ "recommendation": "Cancel button: use name=cancel (lowercase). Continue button on record type selection: use name=save&path=selectRecordType (NOT name=continue or name=Continue). Corpus-validated patterns from 2000+ real test cases.",
3048
+ "check": {
3049
+ "type": "uiLocatorButtonCasing",
3050
+ "target": "step",
3051
+ "apiId": "com.provar.plugins.forcedotcom.core.ui.UiDoAction"
3052
+ },
3053
+ "notes": "Corpus analysis: Cancel uses name=cancel (10 occurrences) vs name=Cancel (4). Continue on record type selection consistently uses name=save&path=selectRecordType across all corpus examples.",
3054
+ "source": "Corpus analysis: AllPOCProjects + InternalProjects (2108 test cases)"
3055
+ },
3056
+ {
3057
+ "id": "UI-LOCATOR-RECORDTYPE-001",
3058
+ "category": "TestCaseDesign",
3059
+ "name": "Record Type field locator must use name=RecordType not name=recordTypeId",
3060
+ "description": "On the Record Type selection screen (action=recordTypeNew), the Record Type picker field must use 'name=RecordType' in the locator URI with 'field=RecordTypeId' in the binding. AI models commonly generate 'name=recordTypeId' (the camelCase API name), which causes Provar to show 'Not Available' and the step fails at runtime.",
3061
+ "appliesTo": ["Step"],
3062
+ "severity": "major",
3063
+ "weight": 5,
3064
+ "recommendation": "Use name=RecordType (not name=recordTypeId or name=recordType) with field=RecordTypeId in the binding. Correct example: ui:locator?name=RecordType&binding=sf%3Aui%3Abinding%3Aobject%3Fobject%3D%7BtargetUrl%3Aobject%7D%26field%3DRecordTypeId",
3065
+ "check": {
3066
+ "type": "uiLocatorRecordTypeField",
3067
+ "target": "step",
3068
+ "apiId": "com.provar.plugins.forcedotcom.core.ui.UiDoAction"
3069
+ },
3070
+ "notes": "Corpus analysis: 258 occurrences of name=RecordType+field=RecordTypeId vs 0 occurrences of name=recordTypeId. The {targetUrl:object} binding resolves dynamically to the current screen's object.",
3071
+ "source": "Corpus analysis: AllPOCProjects + InternalProjects (2108 test cases)"
2902
3072
  }
2903
3073
  ]
2904
3074
  }
@@ -0,0 +1,151 @@
1
+ {
2
+ "schemaVersion": "1.0",
3
+ "name": "Provar Test Case Layer-1 Structural Validity Rules",
4
+ "description": "Single source of truth for the Layer-1 (structural validity) rule catalog. The DETECTION logic stays imperative in src/mcp/tools/testCaseValidate.ts; only the rule metadata (id, severity, applies_to, description) and the best-practice ownership/suppression mapping are centralized here. Consumers: testCaseValidate.ts (derives the bridge-suppression owned-set), scripts/build-validation-rule-registry.cjs (renders the Layer-1 registry rows), and test/unit/mcp/validationRuleRegistry.test.ts (drift guard). The `owns_bp_rules` field lists the Layer-2 `critical` best-practice rule ids whose concept this Layer-1 check already owns — those criticals are NOT bridged into is_valid (avoids double-reporting). Order is display order for the registry; keep it stable. severity is ERROR or WARNING (INFO reserved).",
5
+ "rules": [
6
+ {
7
+ "id": "TC_001",
8
+ "severity": "ERROR",
9
+ "applies_to": "document",
10
+ "description": "XML declaration present (<?xml …?> first line)."
11
+ },
12
+ {
13
+ "id": "TC_002",
14
+ "severity": "ERROR",
15
+ "applies_to": "document",
16
+ "description": "XML is well-formed (parses without error)."
17
+ },
18
+ {
19
+ "id": "TC_003",
20
+ "severity": "ERROR",
21
+ "applies_to": "document",
22
+ "description": "Root element is <testCase>.",
23
+ "owns_bp_rules": ["SCHEMA-ROOT-001"]
24
+ },
25
+ {
26
+ "id": "TC_010",
27
+ "severity": "ERROR",
28
+ "applies_to": "testCase",
29
+ "description": "testCase id, when present, is a non-negative integer (id is optional; guid is the identifier).",
30
+ "owns_bp_rules": ["SCHEMA-ID-001"]
31
+ },
32
+ {
33
+ "id": "TC_011",
34
+ "severity": "ERROR",
35
+ "applies_to": "testCase",
36
+ "description": "testCase has a guid attribute.",
37
+ "owns_bp_rules": ["VALID-GUID-001"]
38
+ },
39
+ {
40
+ "id": "TC_012",
41
+ "severity": "ERROR",
42
+ "applies_to": "testCase",
43
+ "description": "testCase guid is a valid UUID v4."
44
+ },
45
+ {
46
+ "id": "TC_020",
47
+ "severity": "ERROR",
48
+ "applies_to": "testCase",
49
+ "description": "testCase has a <steps> element.",
50
+ "owns_bp_rules": ["SCHEMA-STEPS-001", "VALID-STEPS-001"]
51
+ },
52
+ {
53
+ "id": "TC_030",
54
+ "severity": "ERROR",
55
+ "applies_to": "apiCall",
56
+ "description": "Each apiCall has a guid attribute."
57
+ },
58
+ {
59
+ "id": "TC_031",
60
+ "severity": "ERROR",
61
+ "applies_to": "apiCall",
62
+ "description": "Each apiCall guid is a valid UUID v4."
63
+ },
64
+ {
65
+ "id": "TC_032",
66
+ "severity": "ERROR",
67
+ "applies_to": "apiCall",
68
+ "description": "Each apiCall has an apiId attribute."
69
+ },
70
+ {
71
+ "id": "TC_033",
72
+ "severity": "WARNING",
73
+ "applies_to": "apiCall",
74
+ "description": "Each apiCall has a descriptive name attribute."
75
+ },
76
+ {
77
+ "id": "TC_034",
78
+ "severity": "ERROR",
79
+ "applies_to": "apiCall",
80
+ "description": "Each apiCall has a testItemId attribute.",
81
+ "owns_bp_rules": ["STEP-ITEMID-001"]
82
+ },
83
+ {
84
+ "id": "TC_035",
85
+ "severity": "ERROR",
86
+ "applies_to": "apiCall",
87
+ "description": "apiCall testItemId is a whole number."
88
+ },
89
+ {
90
+ "id": "DATA-001",
91
+ "severity": "WARNING",
92
+ "applies_to": "testCase",
93
+ "description": "<dataTable> only iterates under a test plan; flags direct testCase-mode execution."
94
+ },
95
+ {
96
+ "id": "VAR-REF-001",
97
+ "severity": "WARNING",
98
+ "applies_to": "argument",
99
+ "description": "A whole-token {Var} stored as valueClass=\"string\" (use class=\"variable\")."
100
+ },
101
+ {
102
+ "id": "VAR-REF-002",
103
+ "severity": "WARNING",
104
+ "applies_to": "argument",
105
+ "description": "{Var} tokens embedded in a plain string (use class=\"compound\")."
106
+ },
107
+ {
108
+ "id": "UI-TARGET-001",
109
+ "severity": "ERROR",
110
+ "applies_to": "apiCall",
111
+ "description": "UiWithScreen/UiWithRow target uses class=\"uiTarget\"."
112
+ },
113
+ {
114
+ "id": "UI-LOCATOR-001",
115
+ "severity": "ERROR",
116
+ "applies_to": "apiCall",
117
+ "description": "UI action locator uses class=\"uiLocator\"."
118
+ },
119
+ {
120
+ "id": "UI-INTERACTION-001",
121
+ "severity": "ERROR",
122
+ "applies_to": "apiCall",
123
+ "description": "UiDoAction interaction uses class=\"uiInteraction\"."
124
+ },
125
+ {
126
+ "id": "UI-ASSERT-STRUCTURE-001",
127
+ "severity": "ERROR",
128
+ "applies_to": "apiCall",
129
+ "description": "UiAssert uses nested field/column/page assertion containers, not a flat argument."
130
+ },
131
+ {
132
+ "id": "SETVALUES-STRUCTURE-001",
133
+ "severity": "ERROR",
134
+ "applies_to": "apiCall",
135
+ "description": "SetValues values argument uses class=\"valueList\" with <namedValues>."
136
+ },
137
+ {
138
+ "id": "ASSERT-001",
139
+ "severity": "WARNING",
140
+ "applies_to": "apiCall",
141
+ "description": "AssertValues namedValues format flagged for variable/Apex comparisons."
142
+ },
143
+ {
144
+ "id": "COMPARISON-TYPE-001",
145
+ "severity": "ERROR",
146
+ "applies_to": "apiCall",
147
+ "description": "comparisonType is within the step-scoped enum subset (load-blocking otherwise).",
148
+ "owns_bp_rules": ["COMPARISON-TYPE-ENUM-001"]
149
+ }
150
+ ]
151
+ }