systemlink-cli 1.29.1__tar.gz → 1.29.4__tar.gz

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 (177) hide show
  1. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/PKG-INFO +1 -1
  2. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/pyproject.toml +1 -1
  3. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/_version.py +1 -1
  4. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/config_click.py +20 -4
  5. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/platform.py +77 -22
  6. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/SKILL.md +1 -0
  7. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/evals/evals.json +275 -1
  8. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/evals/evals.schema.json +3 -2
  9. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/references/analysis-recipes.md +75 -0
  10. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/references/commands.md +12 -0
  11. systemlink_cli-1.29.4/slcli/skills/slcli/references/domain-concepts.md +106 -0
  12. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/references/filtering.md +37 -0
  13. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/scripts/eval_manifest.py +6 -2
  14. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/scripts/grade_eval_response.py +24 -1
  15. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/tsconfig.json +2 -3
  16. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/LICENSE +0 -0
  17. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/dff-editor/editor.js +0 -0
  18. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/dff-editor/index.html +0 -0
  19. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/__init__.py +0 -0
  20. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/__main__.py +0 -0
  21. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/alarm_click.py +0 -0
  22. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/asset_click.py +0 -0
  23. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/cli_formatters.py +0 -0
  24. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/cli_utils.py +0 -0
  25. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/comment_click.py +0 -0
  26. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/completion_click.py +0 -0
  27. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/config.py +0 -0
  28. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/dataframe_click.py +0 -0
  29. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/dff_click.py +0 -0
  30. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/dff_decorators.py +0 -0
  31. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/example_click.py +0 -0
  32. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/example_loader.py +0 -0
  33. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/example_provisioner.py +0 -0
  34. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/examples/README.md +0 -0
  35. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/examples/_schema/schema-v1.0.json +0 -0
  36. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/examples/demo-data-1/README.md +0 -0
  37. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/examples/demo-data-1/config.yaml +0 -0
  38. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/examples/demo-data-2/README.md +0 -0
  39. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/examples/demo-data-2/config.yaml +0 -0
  40. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/examples/demo-data-3/config.yaml +0 -0
  41. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/examples/demo-data-3/leakage-current-results.json +0 -0
  42. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/examples/demo-data-3/overvoltage-results.json +0 -0
  43. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/examples/demo-data-3/product-xyz-compliance-report.json +0 -0
  44. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/examples/demo-data-3/product-xyz-specification.csv +0 -0
  45. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/examples/demo-data-3/thermal-response-results.json +0 -0
  46. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/examples/exercise-5-1-parametric-insights/README.md +0 -0
  47. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/examples/exercise-5-1-parametric-insights/config.yaml +0 -0
  48. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/examples/exercise-7-1-test-plans/README.md +0 -0
  49. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/examples/exercise-7-1-test-plans/config.yaml +0 -0
  50. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/examples/spec-compliance-notebooks/README.md +0 -0
  51. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/examples/spec-compliance-notebooks/config.yaml +0 -0
  52. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/examples/spec-compliance-notebooks/notebooks/SpecAnalysis_ComplianceCalculation.ipynb +0 -0
  53. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/examples/spec-compliance-notebooks/notebooks/SpecComplianceCalculation.ipynb +0 -0
  54. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/examples/spec-compliance-notebooks/notebooks/SpecfileExtractionAndIngestion.ipynb +0 -0
  55. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/examples/spec-compliance-notebooks/spec_template.xlsx +0 -0
  56. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/feed_click.py +0 -0
  57. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/file_click.py +0 -0
  58. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/function_click.py +0 -0
  59. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/function_templates.py +0 -0
  60. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/main.py +0 -0
  61. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/mcp_click.py +0 -0
  62. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/mcp_reachability.py +0 -0
  63. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/mcp_server.py +0 -0
  64. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/mcp_skills.py +0 -0
  65. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/notebook_click.py +0 -0
  66. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/pkce.py +0 -0
  67. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/policy_click.py +0 -0
  68. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/policy_utils.py +0 -0
  69. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/profiles.py +0 -0
  70. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/response_handlers.py +0 -0
  71. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/rich_output.py +0 -0
  72. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/routine_click.py +0 -0
  73. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skill_click.py +0 -0
  74. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/evals/COPILOT_BATCH_RUN_PROMPT.md +0 -0
  75. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/evals/README.md +0 -0
  76. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/evals/files/spec-import/battery-specs.csv +0 -0
  77. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/evals/files/webapp-package/icon.svg +0 -0
  78. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/evals/files/webapp-package/nipkg.config.json +0 -0
  79. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/evals/files/webapp-package/webapp-content/index.html +0 -0
  80. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/evals/trigger_evals.json +0 -0
  81. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/references/datasheet-workflow.md +0 -0
  82. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/references/example-authoring.md +0 -0
  83. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/references/import-specs.min.json +0 -0
  84. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/references/job-debugging/overview.md +0 -0
  85. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/references/nipkg/overview.md +0 -0
  86. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/references/notebook/interfaces.md +0 -0
  87. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/references/notebook/notebook-patterns.md +0 -0
  88. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/references/notebook/overview.md +0 -0
  89. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/references/python-test/overview.md +0 -0
  90. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/references/routine-examples.md +0 -0
  91. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/references/troubleshooting.md +0 -0
  92. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/references/webapp/angular-ui-packages.md +0 -0
  93. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/references/webapp/deployment.md +0 -0
  94. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/references/webapp/layout-patterns.md +0 -0
  95. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/references/webapp/nimble-angular.md +0 -0
  96. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/references/webapp/overview.md +0 -0
  97. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/references/webapp/systemlink-services.md +0 -0
  98. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/references/webapp/troubleshooting.md +0 -0
  99. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/scripts/benchmark_iteration.py +0 -0
  100. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/scripts/compare_iteration.py +0 -0
  101. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/scripts/grade_iteration.py +0 -0
  102. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/scripts/prepare_eval_prompts.py +0 -0
  103. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/scripts/prepare_eval_workspace.py +0 -0
  104. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/scripts/render_eval_review.py +0 -0
  105. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/skills/slcli/scripts/spec_import_helper.py +0 -0
  106. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/spec_click.py +0 -0
  107. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/ssl_trust.py +0 -0
  108. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/state_click.py +0 -0
  109. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/system_click.py +0 -0
  110. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/system_query_utils.py +0 -0
  111. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/systemlink-logo.svg +0 -0
  112. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/table_utils.py +0 -0
  113. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/tag_click.py +0 -0
  114. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/templates_click.py +0 -0
  115. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/testmonitor_click.py +0 -0
  116. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/universal_handlers.py +0 -0
  117. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/user_click.py +0 -0
  118. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/utils.py +0 -0
  119. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/version_click.py +0 -0
  120. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/web_editor.py +0 -0
  121. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_bootstrap.py +0 -0
  122. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_click.py +0 -0
  123. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/.gitignore +0 -0
  124. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/README.md +0 -0
  125. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/angular.json +0 -0
  126. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/package.json +0 -0
  127. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/scripts/filter-sbom.js +0 -0
  128. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/app-routing.module.ts +0 -0
  129. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/app.component.html +0 -0
  130. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/app.component.scss +0 -0
  131. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/app.component.ts +0 -0
  132. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/app.module.ts +0 -0
  133. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/core/layout/app-shell.component.html +0 -0
  134. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/core/layout/app-shell.component.scss +0 -0
  135. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/core/layout/app-shell.component.ts +0 -0
  136. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/core/state/app-view-state.service.ts +0 -0
  137. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/core/systemlink/systemlink-context.service.ts +0 -0
  138. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/core/systemlink/theme-sync.service.ts +0 -0
  139. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/core/systemlink/webapp-home-data.service.ts +0 -0
  140. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/features/assets/assets-page.component.html +0 -0
  141. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/features/assets/assets-page.component.scss +0 -0
  142. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/features/assets/assets-page.component.ts +0 -0
  143. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/features/datasets/datasets-page.component.html +0 -0
  144. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/features/datasets/datasets-page.component.scss +0 -0
  145. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/features/datasets/datasets-page.component.ts +0 -0
  146. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/features/home/home-page.component.html +0 -0
  147. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/features/home/home-page.component.scss +0 -0
  148. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/features/home/home-page.component.ts +0 -0
  149. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/features/master-detail/master-detail-page.component.html +0 -0
  150. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/features/master-detail/master-detail-page.component.scss +0 -0
  151. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/features/master-detail/master-detail-page.component.ts +0 -0
  152. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/features/operations/operations-page.component.html +0 -0
  153. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/features/operations/operations-page.component.scss +0 -0
  154. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/features/operations/operations-page.component.ts +0 -0
  155. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/features/settings/settings-page.component.html +0 -0
  156. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/features/settings/settings-page.component.scss +0 -0
  157. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/features/settings/settings-page.component.ts +0 -0
  158. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/shared/components/empty-state.component.html +0 -0
  159. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/shared/components/empty-state.component.scss +0 -0
  160. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/shared/components/empty-state.component.ts +0 -0
  161. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/shared/components/error-banner.component.html +0 -0
  162. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/shared/components/error-banner.component.scss +0 -0
  163. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/shared/components/error-banner.component.ts +0 -0
  164. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/shared/components/loading-state.component.html +0 -0
  165. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/shared/components/loading-state.component.scss +0 -0
  166. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/shared/components/loading-state.component.ts +0 -0
  167. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/app/shared/states/view-state.model.ts +0 -0
  168. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/assets/README.md +0 -0
  169. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/index.html +0 -0
  170. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/main.ts +0 -0
  171. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/src/styles.scss +0 -0
  172. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/webapp_templates/angular/blank/tsconfig.app.json +0 -0
  173. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/workflow_preview.py +0 -0
  174. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/workflows_click.py +0 -0
  175. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/workitem_click.py +0 -0
  176. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/workspace_click.py +0 -0
  177. {systemlink_cli-1.29.1 → systemlink_cli-1.29.4}/slcli/workspace_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: systemlink-cli
3
- Version: 1.29.1
3
+ Version: 1.29.4
4
4
  Summary: SystemLink Integrator CLI - cross-platform CLI for SystemLink workflows and templates.
5
5
  License-File: LICENSE
6
6
  Author: Fred Visser
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "systemlink-cli"
3
- version = "1.29.1"
3
+ version = "1.29.4"
4
4
  description = "SystemLink Integrator CLI - cross-platform CLI for SystemLink workflows and templates."
5
5
  authors = ["Fred Visser <fred.visser@emerson.com>"]
6
6
  packages = [{ include = "slcli" }]
@@ -1,4 +1,4 @@
1
1
  """Version information for slcli."""
2
2
 
3
3
  # This file is auto-generated. Do not edit manually.
4
- __version__ = "1.29.1"
4
+ __version__ = "1.29.4"
@@ -109,6 +109,11 @@ def _all_service_probes_unauthorized(services: dict[str, str]) -> bool:
109
109
  return bool(services) and all(status == "unauthorized" for status in services.values())
110
110
 
111
111
 
112
+ def _any_service_probes_unauthorized(services: dict[str, str]) -> bool:
113
+ """Return True if any recorded service probe failed with authorization."""
114
+ return bool(services) and any(status == "unauthorized" for status in services.values())
115
+
116
+
112
117
  def _normalize_fingerprint(fingerprint: str) -> str:
113
118
  """Normalize a SHA-256 certificate fingerprint supplied by a user."""
114
119
  normalized = fingerprint.replace(":", "").replace(" ", "").strip().upper()
@@ -179,7 +184,10 @@ def _trust_certificate_if_requested(
179
184
 
180
185
  try:
181
186
  save_managed_certificate(certificate)
182
- retry_status = check_service_status(url, credential, auth_scheme=auth_scheme)
187
+ if auth_scheme == "bearer":
188
+ retry_status = check_web_server_auth(url, credential, auth_scheme=auth_scheme)
189
+ else:
190
+ retry_status = check_service_status(url, credential, auth_scheme=auth_scheme)
183
191
  except (OSError, ValueError) as exc:
184
192
  _exit_with_validation_error(
185
193
  f"Could not save the trusted certificate: {exc}. Profile was not saved.",
@@ -303,10 +311,10 @@ def _add_profile_impl(
303
311
 
304
312
  assert isinstance(api_key, str)
305
313
 
306
- # PKCE uses the Web URL for bearer service probes; API-key login uses the API URL.
314
+ # Validate PKCE against the Web Server identity route; API-key login retains API probes.
307
315
  click.echo("Checking server connectivity and services...")
308
316
  if auth_mode == "pkce":
309
- status = check_service_status(web_url, api_key, auth_scheme="bearer")
317
+ status = check_web_server_auth(web_url, api_key, auth_scheme="bearer")
310
318
  else:
311
319
  status = check_service_status(url, api_key)
312
320
 
@@ -321,6 +329,11 @@ def _add_profile_impl(
321
329
  )
322
330
 
323
331
  platform = status["platform"]
332
+ if auth_mode == "pkce":
333
+ platform_status = check_service_status(web_url, api_key, auth_scheme="bearer")
334
+ detected_platform = platform_status.get("platform")
335
+ if detected_platform in (PLATFORM_SLE, PLATFORM_SLS):
336
+ platform = detected_platform
324
337
  services = status.get("services", {})
325
338
 
326
339
  if not status["server_reachable"]:
@@ -330,7 +343,10 @@ def _add_profile_impl(
330
343
  ExitCodes.NETWORK_ERROR,
331
344
  )
332
345
 
333
- if status["auth_valid"] is False and _all_service_probes_unauthorized(services):
346
+ if status["auth_valid"] is False and (
347
+ _all_service_probes_unauthorized(services)
348
+ or (_any_service_probes_unauthorized(services) and platform == PLATFORM_SLS)
349
+ ):
334
350
  auth_failure_message = (
335
351
  "PKCE bearer token validation failed. The server responded, but the token was not authorized. "
336
352
  if auth_mode == "pkce"
@@ -88,6 +88,7 @@ FILE_QUERY_LINQ_PATH = "/nifile/v1/service-groups/Default/query-files-linq"
88
88
  SYSTEM_SEARCH_PATH = "/nisysmgmt/v1/materialized/search-systems"
89
89
  SYSTEM_QUERY_PATH = "/nisysmgmt/v1/query-systems"
90
90
  WEB_SERVER_AUTH_PATH = "/niauth/v1/auth"
91
+ SLS_PLATFORM_PROBE_PATH = "/nitagrule/"
91
92
 
92
93
  SLE_ONLY_SERVICE_NAMES = (
93
94
  "Dynamic Form Fields",
@@ -97,17 +98,22 @@ SLE_ONLY_SERVICE_NAMES = (
97
98
  )
98
99
 
99
100
 
100
- def _detect_platform_from_services(services: Dict[str, str]) -> str:
101
- """Infer the platform from SLE-only service probes.
101
+ def _detect_platform_from_services(
102
+ services: Dict[str, str], sls_platform_status: Optional[str] = None
103
+ ) -> str:
104
+ """Infer the platform from positive platform capability probes.
102
105
 
103
106
  Args:
104
107
  services: Mapping of service display name to probe status.
105
108
 
106
109
  Returns:
107
110
  PLATFORM_SLE when any SLE-only service is reachable or explicitly
108
- unauthorized, PLATFORM_SLS when all SLE-only services are missing,
111
+ unauthorized, PLATFORM_SLS when the SLS-only platform probe succeeds,
109
112
  otherwise PLATFORM_UNKNOWN.
110
113
  """
114
+ if sls_platform_status == "ok":
115
+ return PLATFORM_SLS
116
+
111
117
  sle_statuses = [services.get(name) for name in SLE_ONLY_SERVICE_NAMES if name in services]
112
118
  if not sle_statuses:
113
119
  return PLATFORM_UNKNOWN
@@ -115,12 +121,47 @@ def _detect_platform_from_services(services: Dict[str, str]) -> str:
115
121
  if any(status in ("ok", "unauthorized") for status in sle_statuses):
116
122
  return PLATFORM_SLE
117
123
 
118
- if all(status == "not_found" for status in sle_statuses):
119
- return PLATFORM_SLS
120
-
121
124
  return PLATFORM_UNKNOWN
122
125
 
123
126
 
127
+ def _is_valid_sls_platform_probe(response: requests.Response) -> bool:
128
+ """Return whether a Tag Rule Engine response identifies an SLS instance."""
129
+ try:
130
+ payload = response.json()
131
+ except ValueError:
132
+ return False
133
+
134
+ return isinstance(payload, dict) and (
135
+ isinstance(payload.get("v1"), dict) and "version" in payload
136
+ )
137
+
138
+
139
+ def _probe_sls_platform(api_url: str, credential: str, auth_scheme: str = "api-key") -> str:
140
+ """Probe the unauthenticated Tag Rule Engine versioning endpoint."""
141
+ headers = get_auth_headers(credential, auth_scheme, "application/json")
142
+ ssl_verify = get_ssl_verify(api_url)
143
+
144
+ try:
145
+ response = requests.get(
146
+ f"{api_url}{SLS_PLATFORM_PROBE_PATH}",
147
+ headers=headers,
148
+ verify=ssl_verify,
149
+ timeout=10,
150
+ )
151
+ except requests.exceptions.SSLError:
152
+ return "certificate_error"
153
+ except requests.RequestException:
154
+ return "unreachable"
155
+
156
+ if response.status_code == 200:
157
+ return "ok" if _is_valid_sls_platform_probe(response) else "error"
158
+ if response.status_code in (401, 403):
159
+ return "unauthorized"
160
+ if response.status_code in (404, 501):
161
+ return "not_found"
162
+ return "error"
163
+
164
+
124
165
  def _get_keyring_config() -> Dict[str, Any]:
125
166
  """Attempt to read a single JSON config entry from keyring.
126
167
 
@@ -200,6 +241,7 @@ def get_platform() -> str:
200
241
  ):
201
242
  pass
202
243
 
244
+ # Priority 3: Stored platform from keyring config (legacy fallback)
203
245
  cfg = _get_keyring_config()
204
246
  if cfg:
205
247
  platform = str(cfg.get("platform", "")).upper()
@@ -438,7 +480,7 @@ def _get_service_status_snapshot(force_refresh: bool = False) -> Optional[Dict[s
438
480
 
439
481
  _, api_url, credential, auth_scheme = api_context
440
482
  if auth_scheme == "bearer":
441
- status = check_service_status(api_url, credential, auth_scheme)
483
+ status = check_web_server_auth(api_url, credential, auth_scheme)
442
484
  else:
443
485
  status = check_service_status(api_url, credential)
444
486
  _save_service_status_snapshot(api_context, status)
@@ -783,8 +825,6 @@ def _check_service_status(
783
825
 
784
826
  services: Dict[str, str] = {}
785
827
  any_responded = False
786
- any_authorized = False
787
- all_unauthorized = True
788
828
  certificate_error = False
789
829
 
790
830
  for display_name, method, url_path in SERVICE_CHECKS:
@@ -809,26 +849,39 @@ def _check_service_status(
809
849
 
810
850
  if resp.status_code in (200, 400):
811
851
  services[display_name] = "ok"
812
- any_authorized = True
813
- all_unauthorized = False
814
852
  elif resp.status_code == 401:
815
853
  services[display_name] = "unauthorized"
816
854
  elif resp.status_code == 403:
817
855
  services[display_name] = "unauthorized"
818
856
  elif resp.status_code == 404:
819
857
  services[display_name] = "not_found"
820
- all_unauthorized = False
821
858
  else:
822
859
  services[display_name] = "error"
823
- all_unauthorized = False
824
860
  except requests.exceptions.SSLError:
825
861
  services[display_name] = "certificate_error"
826
862
  certificate_error = True
827
863
  except requests.RequestException:
828
864
  services[display_name] = "unreachable"
829
865
 
866
+ sls_platform_status = _probe_sls_platform(api_url, credential, auth_scheme)
867
+ certificate_error = certificate_error or sls_platform_status == "certificate_error"
868
+
830
869
  # Determine overall status
831
870
  if not any_responded:
871
+ if sls_platform_status not in ("unreachable", "certificate_error"):
872
+ return {
873
+ "server_reachable": True,
874
+ "auth_valid": None,
875
+ "services": services,
876
+ "certificate_error": certificate_error,
877
+ "certificate": None,
878
+ "file_query_endpoint": None,
879
+ "elasticsearch_available": None,
880
+ "system_query_endpoint": None,
881
+ "materialized_search_available": None,
882
+ "platform": _detect_platform_from_services(services, sls_platform_status),
883
+ }
884
+
832
885
  certificate_details: Optional[Dict[str, Any]] = None
833
886
  if certificate_error:
834
887
  try:
@@ -850,20 +903,20 @@ def _check_service_status(
850
903
  "platform": PLATFORM_UNREACHABLE,
851
904
  }
852
905
 
853
- # Determine auth status: valid if any service accepted the key
854
- # If all responding services returned 401/403, the key is invalid
855
- auth_valid = any_authorized if any_responded else None
856
- if all_unauthorized and any_responded:
857
- auth_valid = False
858
-
859
- # Determine platform from multiple SLE-only service responses.
860
- platform = _detect_platform_from_services(services)
906
+ # Determine platform from positive capability probes.
907
+ platform = _detect_platform_from_services(services, sls_platform_status)
908
+ initial_auth_valid = any(status == "ok" for status in services.values())
861
909
 
862
910
  file_capability = get_file_query_capability(api_url, credential, auth_scheme)
863
911
  services["File"] = file_capability["status"]
864
912
  system_capability = get_system_query_capability(api_url, credential, auth_scheme)
865
913
  services["Systems"] = system_capability["status"]
866
914
 
915
+ # Recompute auth after capability probes add their final service statuses.
916
+ auth_valid = initial_auth_valid or any(
917
+ status in ("ok", "fallback") for status in services.values()
918
+ )
919
+
867
920
  return {
868
921
  "server_reachable": True,
869
922
  "auth_valid": auth_valid,
@@ -945,7 +998,9 @@ def get_platform_info(skip_health: bool = False) -> Dict[str, Any]:
945
998
  server_reachable = status["server_reachable"]
946
999
  auth_valid = status["auth_valid"]
947
1000
  services = status["services"]
948
- platform = status["platform"]
1001
+ detected_platform = status.get("platform", PLATFORM_UNKNOWN)
1002
+ if detected_platform != PLATFORM_UNKNOWN:
1003
+ platform = detected_platform
949
1004
  file_query_endpoint = status.get("file_query_endpoint")
950
1005
  elasticsearch_available = status.get("elasticsearch_available")
951
1006
  system_query_endpoint = status.get("system_query_endpoint")
@@ -36,6 +36,7 @@ Load only what the current task needs.
36
36
  | Datasheet-to-spec workflow | [datasheet-workflow.md](./references/datasheet-workflow.md) | Importing specifications from PDF, CSV, or structured text |
37
37
  | Minimal spec import payload | [import-specs.min.json](./references/import-specs.min.json) | Need a bundled create-compatible starter payload or conditions |
38
38
  | Spec import helper | [spec_import_helper.py](./scripts/spec_import_helper.py) | Scaffold or validate a datasheet spec import payload |
39
+ | Domain concepts | [domain-concepts.md](./references/domain-concepts.md) | Interpreting resource terminology, relationships, identifiers, status intent, or availability |
39
40
  | Filtering guide | [filtering.md](./references/filtering.md) | Advanced filters, LINQ syntax, and query composition |
40
41
  | Analysis recipes | [analysis-recipes.md](./references/analysis-recipes.md) | Multi-step analysis workflows and reporting patterns |
41
42
  | Troubleshooting | [troubleshooting.md](./references/troubleshooting.md) | SSL, workspace IDs, encoding, or scripting pitfalls |
@@ -3,7 +3,7 @@
3
3
  "skill_name": "slcli",
4
4
  "recommended_suites": {
5
5
  "gating": [1, 4, 5, 7, 10],
6
- "regression": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
6
+ "regression": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
7
7
  },
8
8
  "evals": [
9
9
  {
@@ -637,6 +637,280 @@
637
637
  ]
638
638
  }
639
639
  ]
640
+ },
641
+ {
642
+ "id": 12,
643
+ "tags": ["regression", "testmonitor", "status-intent"],
644
+ "prompt": "Show me failed SystemLink tests from the last seven days. Treat every terminal failure outcome as a failure.",
645
+ "expected_output": "Uses one parameterized testmonitor query covering FAILED, ERRORED, and TERMINATED, constrained to results started during the last seven days without matching unrelated statuses.",
646
+ "files": [],
647
+ "expectations": [
648
+ "Uses the testmonitor result list command",
649
+ "Expands broad failure intent to FAILED, ERRORED, and TERMINATED",
650
+ "Uses substitutions rather than interpolating status values",
651
+ "Adds a parameterized startedAt lower bound for the last seven days",
652
+ "Does not implement failure as everything other than PASSED"
653
+ ],
654
+ "grading_rules": [
655
+ {
656
+ "text": "Queries test results",
657
+ "critical": true,
658
+ "positive_control": "slcli testmonitor result list --format json",
659
+ "negative_control": "slcli testmonitor product list --format json",
660
+ "scope": "command",
661
+ "mode": "any_of",
662
+ "patterns": [
663
+ "slcli\\s+testmonitor\\s+result\\s+list"
664
+ ]
665
+ },
666
+ {
667
+ "text": "Includes all terminal failure statuses",
668
+ "critical": true,
669
+ "positive_control": "slcli testmonitor result list --filter 'status.statusType == @0 or status.statusType == @1 or status.statusType == @2' --substitution FAILED --substitution ERRORED --substitution TERMINATED",
670
+ "negative_control": "slcli testmonitor result list --status FAILED",
671
+ "scope": "command",
672
+ "mode": "all_of",
673
+ "patterns": [
674
+ "--substitution\\s+FAILED",
675
+ "--substitution\\s+ERRORED",
676
+ "--substitution\\s+TERMINATED",
677
+ "--filter\\s+[^\\n]*status\\.statusType\\s*==\\s*@0",
678
+ "--filter\\s+[^\\n]*status\\.statusType\\s*==\\s*@1",
679
+ "--filter\\s+[^\\n]*status\\.statusType\\s*==\\s*@2"
680
+ ]
681
+ },
682
+ {
683
+ "text": "Avoids not-passed filtering",
684
+ "critical": true,
685
+ "positive_control": "slcli testmonitor result list --filter 'status.statusType == @0' --substitution FAILED",
686
+ "negative_control": "slcli testmonitor result list --filter 'status.statusType != @0' --substitution PASSED",
687
+ "scope": "command",
688
+ "mode": "none_of",
689
+ "patterns": [
690
+ "status\\.statusType\\s*!=",
691
+ "NOT\\s+PASSED"
692
+ ]
693
+ },
694
+ {
695
+ "text": "Constrains results to the last seven days",
696
+ "critical": true,
697
+ "positive_control": "slcli testmonitor result list --filter '(status.statusType == @0 or status.statusType == @1 or status.statusType == @2) and startedAt >= @3' --substitution FAILED --substitution ERRORED --substitution TERMINATED --substitution 2026-09-10T00:00:00Z",
698
+ "negative_control": "slcli testmonitor result list --filter 'status.statusType == @0 or status.statusType == @1 or status.statusType == @2' --substitution FAILED --substitution ERRORED --substitution TERMINATED",
699
+ "scope": "command",
700
+ "mode": "all_of",
701
+ "validator": "last_n_days",
702
+ "days": 7,
703
+ "control_reference_date": "2026-09-17",
704
+ "patterns": [
705
+ "startedAt\\s*>=\\s*@\\d+",
706
+ "--substitution\\s+\\d{4}-\\d{2}-\\d{2}T00:00:00Z"
707
+ ]
708
+ }
709
+ ]
710
+ },
711
+ {
712
+ "id": 13,
713
+ "tags": ["regression", "packages", "routing"],
714
+ "prompt": "Show the commands to check packages available in feed FEED-1, packages installed on system SYS-1, and packages declared by desired state STATE-1.",
715
+ "expected_output": "Routes repository availability, observed installation, and desired-state membership to three distinct slcli command surfaces.",
716
+ "files": [],
717
+ "expectations": [
718
+ "Uses feed package list for available packages",
719
+ "Uses system details with installed packages for observed installation",
720
+ "Uses state details for desired packages",
721
+ "Does not imply that any one package view proves another"
722
+ ],
723
+ "grading_rules": [
724
+ {
725
+ "text": "Queries available feed packages",
726
+ "critical": true,
727
+ "positive_control": "slcli feed package list --feed-id FEED-1 --format json",
728
+ "negative_control": "slcli feed list --format json",
729
+ "scope": "command",
730
+ "mode": "all_of",
731
+ "patterns": [
732
+ "slcli\\s+feed\\s+package\\s+list",
733
+ "--feed-id\\s+FEED-1"
734
+ ]
735
+ },
736
+ {
737
+ "text": "Queries installed system packages",
738
+ "critical": true,
739
+ "positive_control": "slcli system get SYS-1 --include-packages --format json",
740
+ "negative_control": "slcli system get SYS-1 --format json",
741
+ "scope": "command",
742
+ "mode": "all_of",
743
+ "patterns": [
744
+ "slcli\\s+system\\s+get\\s+SYS-1",
745
+ "--include-packages"
746
+ ]
747
+ },
748
+ {
749
+ "text": "Queries desired-state packages",
750
+ "critical": true,
751
+ "positive_control": "slcli state get STATE-1 --format json",
752
+ "negative_control": "slcli state list --format json",
753
+ "scope": "command",
754
+ "mode": "any_of",
755
+ "patterns": [
756
+ "slcli\\s+state\\s+get\\s+STATE-1"
757
+ ]
758
+ },
759
+ {
760
+ "text": "Keeps package views independent",
761
+ "critical": true,
762
+ "positive_control": "slcli feed package list --feed-id FEED-1 --format json\nslcli system get SYS-1 --include-packages --format json\nslcli state get STATE-1 --format json\nThese are independent facts; do not infer one from another.",
763
+ "negative_control": "slcli feed package list --feed-id FEED-1 --format json\nslcli system get SYS-1 --include-packages --format json\nslcli state get STATE-1 --format json",
764
+ "scope": "response",
765
+ "mode": "all_of",
766
+ "patterns": [
767
+ "independent facts",
768
+ "do not infer"
769
+ ]
770
+ }
771
+ ]
772
+ },
773
+ {
774
+ "id": 14,
775
+ "tags": ["regression", "systems", "health"],
776
+ "prompt": "Check the current health of SystemLink system SYS-1, including current health signals and active alarm instances.",
777
+ "expected_output": "Combines system state, active alarm instances, and current CPU, memory, and disk health-tag values without inventing thresholds or claiming that an empty instance query means no alarm rule is configured.",
778
+ "files": [],
779
+ "expectations": [
780
+ "Retrieves system details and active alarm instances",
781
+ "Reads the three standard current health tags",
782
+ "Treats missing or stale evidence as an incomplete health conclusion",
783
+ "Does not invent utilization thresholds"
784
+ ],
785
+ "grading_rules": [
786
+ {
787
+ "text": "Includes system and alarm state",
788
+ "critical": true,
789
+ "positive_control": "slcli system get SYS-1 --include-alarms --format json",
790
+ "negative_control": "slcli system get SYS-1 --format json",
791
+ "scope": "command",
792
+ "mode": "all_of",
793
+ "patterns": [
794
+ "slcli\\s+system\\s+get\\s+SYS-1",
795
+ "--include-(?:alarms|all)"
796
+ ]
797
+ },
798
+ {
799
+ "text": "Reads CPU, memory, and disk health tags",
800
+ "critical": true,
801
+ "positive_control": "slcli tag get-value SYS-1.Health.CPU.MeanUsePercentage\nslcli tag get-value SYS-1.Health.Memory.UsePercentage\nslcli tag get-value SYS-1.Health.Disk.UsePercentage",
802
+ "negative_control": "slcli tag get-value SYS-1.Health.CPU.MeanUsePercentage",
803
+ "scope": "commands",
804
+ "mode": "all_of",
805
+ "patterns": [
806
+ "SYS-1\\.Health\\.CPU\\.MeanUsePercentage",
807
+ "SYS-1\\.Health\\.Memory\\.UsePercentage",
808
+ "SYS-1\\.Health\\.Disk\\.UsePercentage"
809
+ ]
810
+ },
811
+ {
812
+ "text": "Treats incomplete evidence as inconclusive",
813
+ "critical": true,
814
+ "positive_control": "slcli system get SYS-1 --include-alarms --format json\nslcli tag get-value SYS-1.Health.CPU.MeanUsePercentage\nMissing or stale evidence makes the health conclusion incomplete.",
815
+ "negative_control": "slcli system get SYS-1 --include-alarms --format json\nslcli tag get-value SYS-1.Health.CPU.MeanUsePercentage",
816
+ "scope": "response",
817
+ "mode": "any_of",
818
+ "patterns": [
819
+ "(?:missing|stale).{0,80}(?:incomplete|insufficient|cannot|can't|not definitive)"
820
+ ]
821
+ },
822
+ {
823
+ "text": "Does not invent utilization thresholds",
824
+ "critical": true,
825
+ "positive_control": "slcli system get SYS-1 --include-alarms --format json\nslcli tag get-value SYS-1.Health.CPU.MeanUsePercentage",
826
+ "negative_control": "slcli system get SYS-1 --include-alarms --format json\nCPU above 80% means the system is unhealthy.",
827
+ "scope": "response",
828
+ "mode": "none_of",
829
+ "patterns": [
830
+ "(?:cpu|memory|disk|utilization|usage).{0,50}(?:above|below|greater than|less than|[<>]\\s*\\d+%?)"
831
+ ]
832
+ }
833
+ ]
834
+ },
835
+ {
836
+ "id": 15,
837
+ "tags": ["regression", "files", "relationships"],
838
+ "prompt": "Find files attached to SystemLink system SYS-1 in workspace WORKSPACE-1. SYS-1 is the exact system ID.",
839
+ "expected_output": "Lists files in the resolved workspace and filters the system-reference property locally rather than treating the system ID as a file ID.",
840
+ "files": [],
841
+ "expectations": [
842
+ "Uses the file list command with the resolved workspace",
843
+ "Filters properties.minionId with the supplied system ID",
844
+ "Does not use SYS-1 as a file ID"
845
+ ],
846
+ "grading_rules": [
847
+ {
848
+ "text": "Queries the system file-reference property",
849
+ "critical": true,
850
+ "positive_control": "slcli file list --workspace WORKSPACE-1 --take 1000 --format json | jq --arg system_id SYS-1 '[.[] | select(.properties.minionId == $system_id)]'",
851
+ "negative_control": "slcli file list --workspace WORKSPACE-1 --id-filter SYS-1 --format json",
852
+ "scope": "response",
853
+ "mode": "all_of",
854
+ "patterns": [
855
+ "slcli\\s+file\\s+list",
856
+ "--workspace\\s+WORKSPACE-1",
857
+ "properties\\.minionId[^\\n]*system_id"
858
+ ]
859
+ },
860
+ {
861
+ "text": "Does not treat the system ID as a file ID",
862
+ "critical": true,
863
+ "positive_control": "select(.properties.minionId == $system_id)",
864
+ "negative_control": "select(.id == $system_id)",
865
+ "scope": "response",
866
+ "mode": "none_of",
867
+ "patterns": [
868
+ "select\\(\\.id\\s*=="
869
+ ]
870
+ }
871
+ ]
872
+ },
873
+ {
874
+ "id": 16,
875
+ "tags": ["regression", "assets", "instrument-intent"],
876
+ "prompt": "Show me all connected DMM instruments in SystemLink.",
877
+ "expected_output": "Uses the connected asset inventory query as a 40xx candidate search, then verifies that returned model names contain a standalone 40xx family before presenting them as DMMs.",
878
+ "files": [],
879
+ "expectations": [
880
+ "Uses the asset list command",
881
+ "Maps DMM to the 40xx model family",
882
+ "Limits results to connected assets",
883
+ "Verifies the returned model names match the standalone 40xx family"
884
+ ],
885
+ "grading_rules": [
886
+ {
887
+ "text": "Queries connected assets",
888
+ "critical": true,
889
+ "positive_control": "slcli asset list --model 40 --connected --format json",
890
+ "negative_control": "slcli system list --has-package DAQmx --format json",
891
+ "scope": "command",
892
+ "mode": "all_of",
893
+ "patterns": [
894
+ "slcli\\s+asset\\s+list",
895
+ "--connected"
896
+ ]
897
+ },
898
+ {
899
+ "text": "Maps DMM to the 40xx model family",
900
+ "critical": true,
901
+ "positive_control": "slcli asset list --model 40 --connected --format json | jq '[.[] | select(.modelName | test(\"(^|[^0-9])40[0-9]{2}([^0-9]|$)\"))]'",
902
+ "negative_control": "slcli asset list --model DMM --connected",
903
+ "scope": "response",
904
+ "mode": "all_of",
905
+ "patterns": [
906
+ "--model\\s+40",
907
+ "jq\\s+",
908
+ "test\\(\\\"",
909
+ "40\\[0-9\\]\\{2\\}",
910
+ "\\[\\^0-9\\]"
911
+ ]
912
+ }
913
+ ]
640
914
  }
641
915
  ]
642
916
  }
@@ -37,8 +37,9 @@
37
37
  "critical": {"type": "boolean"},
38
38
  "positive_control": {"type": "string", "minLength": 1},
39
39
  "negative_control": {"type": "string", "minLength": 1},
40
- "scope": {"enum": ["response", "command"]},
41
- "validator": {"enum": ["previous_calendar_month"]},
40
+ "scope": {"enum": ["response", "command", "commands"]},
41
+ "validator": {"enum": ["previous_calendar_month", "last_n_days"]},
42
+ "days": {"type": "integer", "minimum": 1},
42
43
  "control_reference_date": {"type": "string", "format": "date"},
43
44
  "mode": {"enum": ["all_of", "any_of", "none_of"]},
44
45
  "patterns": {"type": "array", "minItems": 1, "items": {"type": "string"}}