Files
dc/.agents/skills/sas/SKILL.md
T
hermes f7db8719f5
Build / Build-and-ng-test (pull_request) Successful in 5m8s
Lighthouse Checks / lighthouse (pull_request) Successful in 21m24s
Build / Build-and-test-development (pull_request) Successful in 25m20s
fix: agent skills and nextviya deploys
2026-08-19 17:17:30 +01:00

5.0 KiB

name, description
name description
sas Expert guidance for the SAS programming language — DATA step, PROC SQL, macro language, formats, ODS, and common procedures. Pure SAS syntax only, no SASjs-framework content. Use when writing, reviewing, or debugging .sas programs, or answering SAS language questions.

SAS Language

Write idiomatic, production-quality SAS code. This skill covers the SAS language itself, independent of any framework.

Scope

  • DATA step programming (SET/MERGE/BY, RETAIN, arrays, DO loops, hash objects, first./last. processing)
  • PROC SQL (joins, subqueries, views, pass-through with CONNECT TO)
  • Macro language (%macro/%mend, macro variables, %local/%global, conditional %IF logic, quoting functions %STR/%NRSTR/%BQUOTE, CALL SYMPUTX)
  • Common PROCs: SORT, MEANS/SUMMARY, FREQ, TRANSPOSE, REPORT, PRINT, CONTENTS, DATASETS, FORMAT, IMPORT/EXPORT
  • Formats and informats (user-defined via PROC FORMAT, picture formats)
  • ODS output (HTML, PDF, RTF, Excel, OUTPUT destination)
  • File I/O: LIBNAME, FILENAME, INFILE/INPUT, FILE/PUT

Non-negotiable: no WARNINGs

Generated SAS code must run cleanly — zero WARNINGs (and zero ERRORs) in the log. Treat every WARNING: as a defect: uninitialized variables, implicit type conversions, truncation notes that should be warnings, "no observations", unresolved macro references, etc. If a warning is truly unavoidable, suppress it deliberately (e.g. an explicit option) and comment why. Likewise avoid superfluous NOTEs where reasonable.

Style rules

These follow the @sasjs/core coding standards — apply them to all SAS code:

  • One statement per line; indentation = 2 spaces, no tabs, no trailing whitespace
  • Lines no longer than 80 characters; unix (LF) line endings; UTF-8
  • Avoid non-ASCII / special characters entirely — maximum compatibility across SAS installations and encodings
  • Always end steps with run;; for proc sql (and CAS-connected procs) quit; is essential to avoid WARNING: You cannot disconnect or terminate session ... on Viya
  • All dataset references must be 2-level (work.blah, not blah) — protects against DATASTMTCHK=ALLKEYWORDS and an active USER library
  • Explicit length / attrib for character variables rather than relying on defaults (avoids implicit length=8 truncation)
  • Use literal suffixes for clarity ('01JAN2020'd, '12:30't)
  • Prefer proc sort with nodupkey over manual dedup logic
  • Macros:
    • Define with parentheses, even with no parameters: %macro x(); not %macro x;
    • Closing %mend; must repeat the macro name
    • Macro calls are not terminated with a semicolon: %my_macro() not %my_macro();
    • Mandatory parameters positional; optional parameters keyword (var=) style
    • Macro names lowercase, verb-noun convention
    • Macro variables without trailing dot (&var not &var.) unless needed to prevent incorrect resolution
    • Macro variable NAMES are case-insensitive: &Foo, &FOO, and &foo all resolve to the same symbol (same for %symexist/%superq/symget arguments, which take a NAME not a value). Don't chase case mismatches as a bug — it's never the cause.
    • ALL macro variables must be %local unless deliberately global (globals should use an application prefix to avoid collisions); use call symputx (not symput) in DATA steps
    • Comment with /* */ inside macros (asterisk comments are compiled into the macro)
    • Guard macro logic with %length(&var)=0 checks rather than &var= (empty comparisons are unsafe)
  • Avoid naming collisions: use %sysfunc-/&syslast-based work tables (e.g. data &output; set &syslast; run;) rather than hard-coded names
  • No open (non-macro) conditional code: wrap platform-branching or conditionally-executed blocks (e.g. %if %mf_getplatform()=VIYA %then %do; ... %end;) in a %macro ... %mend and invoke the macro. Open %if at program level fails in some execution contexts (job/scheduler/test harnesses) and hides scope leaks.

Portability awareness

  • Note when code differs between SAS 9.4 and Viya (e.g. CAS actions vs procs, proc casutil for sashdat loading, no X command on locked-down servers)
  • Avoid hard-coded physical paths and engine-specific options unless asked
  • No open macro code with if/else logic: wrap branching blocks in %macro ... %mend and call them — open %if/%else does not behave as expected in all SAS environments.

Common pitfalls to flag when reviewing

  • Unintended many-to-many MERGEs
  • Automatic variable _ERROR_ / implicit RETAIN surprises
  • Macro timing issues: referencing &macrovar before it exists, %if evaluating data-step variables (use if/symget instead)
  • Automatic macro variables (&syscc, &syswarningtext, &syserrortext, &sysdate, &sysuserid, etc.) are READ-ONLY — attempting to overwrite them (e.g. %let syswarningtext=; or call symput('syscc',...)) raises ERROR: Unable to assign value to a macro variable that is read only (or similar). Never try to "clear" them.
  • Truncation from implicit length=8 on first assignment
  • proc sql cartesian product warnings