systemlink-cli 1.27.1__tar.gz → 1.27.3__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 (160) hide show
  1. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/PKG-INFO +1 -1
  2. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/pyproject.toml +1 -1
  3. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/_version.py +1 -1
  4. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/main.py +12 -2
  5. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/platform.py +21 -5
  6. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/skill_click.py +107 -4
  7. systemlink_cli-1.27.3/slcli/skills/slcli/SKILL.md +221 -0
  8. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/skills/slcli/references/analysis-recipes.md +87 -2
  9. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/skills/slcli/references/commands.md +76 -7
  10. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/skills/slcli/references/troubleshooting.md +41 -0
  11. systemlink_cli-1.27.3/slcli/skills/slcli/references/webapp/deployment.md +332 -0
  12. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/skills/slcli/references/webapp/overview.md +5 -1
  13. systemlink_cli-1.27.3/slcli/version_click.py +199 -0
  14. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_click.py +9 -2
  15. systemlink_cli-1.27.1/slcli/skills/slcli/SKILL.md +0 -91
  16. systemlink_cli-1.27.1/slcli/skills/slcli/references/webapp/deployment.md +0 -147
  17. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/LICENSE +0 -0
  18. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/dff-editor/editor.js +0 -0
  19. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/dff-editor/index.html +0 -0
  20. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/__init__.py +0 -0
  21. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/__main__.py +0 -0
  22. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/alarm_click.py +0 -0
  23. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/asset_click.py +0 -0
  24. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/cli_formatters.py +0 -0
  25. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/cli_utils.py +0 -0
  26. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/comment_click.py +0 -0
  27. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/completion_click.py +0 -0
  28. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/config.py +0 -0
  29. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/config_click.py +0 -0
  30. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/dataframe_click.py +0 -0
  31. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/dff_click.py +0 -0
  32. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/dff_decorators.py +0 -0
  33. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/example_click.py +0 -0
  34. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/example_loader.py +0 -0
  35. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/example_provisioner.py +0 -0
  36. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/examples/README.md +0 -0
  37. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/examples/_schema/schema-v1.0.json +0 -0
  38. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/examples/demo-data-1/README.md +0 -0
  39. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/examples/demo-data-1/config.yaml +0 -0
  40. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/examples/demo-data-2/README.md +0 -0
  41. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/examples/demo-data-2/config.yaml +0 -0
  42. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/examples/demo-data-3/config.yaml +0 -0
  43. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/examples/demo-data-3/leakage-current-results.json +0 -0
  44. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/examples/demo-data-3/overvoltage-results.json +0 -0
  45. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/examples/demo-data-3/product-xyz-compliance-report.json +0 -0
  46. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/examples/demo-data-3/product-xyz-specification.csv +0 -0
  47. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/examples/demo-data-3/thermal-response-results.json +0 -0
  48. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/examples/exercise-5-1-parametric-insights/README.md +0 -0
  49. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/examples/exercise-5-1-parametric-insights/config.yaml +0 -0
  50. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/examples/exercise-7-1-test-plans/README.md +0 -0
  51. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/examples/exercise-7-1-test-plans/config.yaml +0 -0
  52. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/examples/spec-compliance-notebooks/README.md +0 -0
  53. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/examples/spec-compliance-notebooks/config.yaml +0 -0
  54. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/examples/spec-compliance-notebooks/notebooks/SpecAnalysis_ComplianceCalculation.ipynb +0 -0
  55. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/examples/spec-compliance-notebooks/notebooks/SpecComplianceCalculation.ipynb +0 -0
  56. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/examples/spec-compliance-notebooks/notebooks/SpecfileExtractionAndIngestion.ipynb +0 -0
  57. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/examples/spec-compliance-notebooks/spec_template.xlsx +0 -0
  58. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/feed_click.py +0 -0
  59. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/file_click.py +0 -0
  60. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/function_click.py +0 -0
  61. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/function_templates.py +0 -0
  62. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/mcp_click.py +0 -0
  63. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/mcp_reachability.py +0 -0
  64. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/mcp_server.py +0 -0
  65. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/notebook_click.py +0 -0
  66. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/pkce.py +0 -0
  67. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/policy_click.py +0 -0
  68. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/policy_utils.py +0 -0
  69. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/profiles.py +0 -0
  70. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/response_handlers.py +0 -0
  71. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/rich_output.py +0 -0
  72. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/routine_click.py +0 -0
  73. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/skills/slcli/references/datasheet-workflow.md +0 -0
  74. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/skills/slcli/references/example-authoring.md +0 -0
  75. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/skills/slcli/references/filtering.md +0 -0
  76. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/skills/slcli/references/import-specs.min.json +0 -0
  77. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/skills/slcli/references/job-debugging/overview.md +0 -0
  78. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/skills/slcli/references/nipkg/overview.md +0 -0
  79. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/skills/slcli/references/notebook/interfaces.md +0 -0
  80. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/skills/slcli/references/notebook/notebook-patterns.md +0 -0
  81. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/skills/slcli/references/notebook/overview.md +0 -0
  82. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/skills/slcli/references/python-test/overview.md +0 -0
  83. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/skills/slcli/references/routine-examples.md +0 -0
  84. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/skills/slcli/references/webapp/angular-ui-packages.md +0 -0
  85. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/skills/slcli/references/webapp/layout-patterns.md +0 -0
  86. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/skills/slcli/references/webapp/nimble-angular.md +0 -0
  87. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/skills/slcli/references/webapp/systemlink-services.md +0 -0
  88. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/skills/slcli/references/webapp/troubleshooting.md +0 -0
  89. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/skills/slcli/scripts/spec_import_helper.py +0 -0
  90. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/spec_click.py +0 -0
  91. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/ssl_trust.py +0 -0
  92. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/state_click.py +0 -0
  93. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/system_click.py +0 -0
  94. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/system_query_utils.py +0 -0
  95. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/systemlink-logo.svg +0 -0
  96. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/table_utils.py +0 -0
  97. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/tag_click.py +0 -0
  98. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/templates_click.py +0 -0
  99. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/testmonitor_click.py +0 -0
  100. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/universal_handlers.py +0 -0
  101. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/user_click.py +0 -0
  102. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/utils.py +0 -0
  103. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/web_editor.py +0 -0
  104. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_bootstrap.py +0 -0
  105. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/.gitignore +0 -0
  106. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/README.md +0 -0
  107. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/angular.json +0 -0
  108. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/package.json +0 -0
  109. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/scripts/filter-sbom.js +0 -0
  110. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/app-routing.module.ts +0 -0
  111. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/app.component.html +0 -0
  112. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/app.component.scss +0 -0
  113. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/app.component.ts +0 -0
  114. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/app.module.ts +0 -0
  115. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/core/layout/app-shell.component.html +0 -0
  116. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/core/layout/app-shell.component.scss +0 -0
  117. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/core/layout/app-shell.component.ts +0 -0
  118. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/core/state/app-view-state.service.ts +0 -0
  119. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/core/systemlink/systemlink-context.service.ts +0 -0
  120. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/core/systemlink/theme-sync.service.ts +0 -0
  121. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/core/systemlink/webapp-home-data.service.ts +0 -0
  122. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/features/assets/assets-page.component.html +0 -0
  123. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/features/assets/assets-page.component.scss +0 -0
  124. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/features/assets/assets-page.component.ts +0 -0
  125. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/features/datasets/datasets-page.component.html +0 -0
  126. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/features/datasets/datasets-page.component.scss +0 -0
  127. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/features/datasets/datasets-page.component.ts +0 -0
  128. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/features/home/home-page.component.html +0 -0
  129. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/features/home/home-page.component.scss +0 -0
  130. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/features/home/home-page.component.ts +0 -0
  131. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/features/master-detail/master-detail-page.component.html +0 -0
  132. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/features/master-detail/master-detail-page.component.scss +0 -0
  133. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/features/master-detail/master-detail-page.component.ts +0 -0
  134. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/features/operations/operations-page.component.html +0 -0
  135. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/features/operations/operations-page.component.scss +0 -0
  136. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/features/operations/operations-page.component.ts +0 -0
  137. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/features/settings/settings-page.component.html +0 -0
  138. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/features/settings/settings-page.component.scss +0 -0
  139. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/features/settings/settings-page.component.ts +0 -0
  140. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/shared/components/empty-state.component.html +0 -0
  141. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/shared/components/empty-state.component.scss +0 -0
  142. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/shared/components/empty-state.component.ts +0 -0
  143. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/shared/components/error-banner.component.html +0 -0
  144. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/shared/components/error-banner.component.scss +0 -0
  145. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/shared/components/error-banner.component.ts +0 -0
  146. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/shared/components/loading-state.component.html +0 -0
  147. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/shared/components/loading-state.component.scss +0 -0
  148. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/shared/components/loading-state.component.ts +0 -0
  149. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/app/shared/states/view-state.model.ts +0 -0
  150. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/assets/README.md +0 -0
  151. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/index.html +0 -0
  152. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/main.ts +0 -0
  153. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/src/styles.scss +0 -0
  154. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/tsconfig.app.json +0 -0
  155. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/webapp_templates/angular/blank/tsconfig.json +0 -0
  156. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/workflow_preview.py +0 -0
  157. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/workflows_click.py +0 -0
  158. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/workitem_click.py +0 -0
  159. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/workspace_click.py +0 -0
  160. {systemlink_cli-1.27.1 → systemlink_cli-1.27.3}/slcli/workspace_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: systemlink-cli
3
- Version: 1.27.1
3
+ Version: 1.27.3
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.27.1"
3
+ version = "1.27.3"
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.27.1"
4
+ __version__ = "1.27.3"
@@ -43,6 +43,7 @@ from .templates_click import register_templates_commands
43
43
  from .testmonitor_click import register_testmonitor_commands
44
44
  from .user_click import register_user_commands
45
45
  from .utils import describe_config_source
46
+ from .version_click import register_version_commands
46
47
  from .webapp_click import register_webapp_commands
47
48
  from .workitem_click import register_workitem_commands
48
49
  from .workspace_click import register_workspace_commands
@@ -71,7 +72,15 @@ def _configure_rich_click_command_groups() -> None:
71
72
  "slcli": [
72
73
  {
73
74
  "name": "Configure",
74
- "commands": ["config", "login", "logout", "info", "completion", "example"],
75
+ "commands": [
76
+ "config",
77
+ "login",
78
+ "logout",
79
+ "info",
80
+ "version",
81
+ "completion",
82
+ "example",
83
+ ],
75
84
  },
76
85
  {
77
86
  "name": "Administer",
@@ -363,7 +372,7 @@ def cli(ctx: base_click.Context, version: bool, profile: Optional[str]) -> None:
363
372
 
364
373
  # Check for mandatory migration BEFORE any command runs
365
374
  # Skip migration check only for version flag and config migrate command
366
- if ctx.invoked_subcommand not in (None, "config"):
375
+ if ctx.invoked_subcommand not in (None, "config", "version"):
367
376
  from .profiles import ProfileConfig, has_keyring_credentials, migrate_from_keyring
368
377
 
369
378
  config_path = ProfileConfig.get_config_path()
@@ -769,5 +778,6 @@ register_testmonitor_commands(cli)
769
778
  register_webapp_commands(cli)
770
779
  register_skill_commands(cli)
771
780
  register_user_commands(cli)
781
+ register_version_commands(cli)
772
782
  register_workitem_commands(cli)
773
783
  register_workspace_commands(cli)
@@ -168,8 +168,9 @@ def get_platform() -> str:
168
168
 
169
169
  Detection priority:
170
170
  1. SYSTEMLINK_PLATFORM environment variable (explicit, most reliable)
171
- 2. Stored platform from keyring config (set during login via endpoint probing)
172
- 3. Return PLATFORM_UNKNOWN if no explicit or stored platform is available
171
+ 2. Platform stored on the active profile (set during login via endpoint probing)
172
+ 3. Stored platform from keyring config (legacy fallback)
173
+ 4. Return PLATFORM_UNKNOWN if no explicit or stored platform is available
173
174
 
174
175
  Note: Results are cached for performance. Use clear_platform_cache() to reset.
175
176
 
@@ -182,11 +183,26 @@ def get_platform() -> str:
182
183
  if env_platform in (PLATFORM_SLE, PLATFORM_SLS):
183
184
  return env_platform
184
185
 
185
- # Priority 2: Stored platform from keyring config (set during login)
186
- # This was detected via endpoint probing, which is reliable
186
+ if not any(os.environ.get(name) for name in ("SLCLI_API_URL", "SYSTEMLINK_API_URL")):
187
+ try:
188
+ from .profiles import get_active_profile
189
+
190
+ profile = get_active_profile()
191
+ profile_platform = str(profile.platform or "").upper() if profile else ""
192
+ if profile_platform in (PLATFORM_SLE, PLATFORM_SLS):
193
+ return profile_platform
194
+ except (
195
+ FileNotFoundError,
196
+ json.JSONDecodeError,
197
+ KeyError,
198
+ AttributeError,
199
+ click.ClickException,
200
+ ):
201
+ pass
202
+
187
203
  cfg = _get_keyring_config()
188
204
  if cfg:
189
- platform = cfg.get("platform", "")
205
+ platform = str(cfg.get("platform", "")).upper()
190
206
  if platform in (PLATFORM_SLE, PLATFORM_SLS):
191
207
  return platform
192
208
 
@@ -6,11 +6,14 @@ from pathlib import Path
6
6
  from typing import Any, Dict, List, Optional, Tuple
7
7
 
8
8
  import click
9
+ from packaging.version import InvalidVersion, Version
9
10
 
11
+ from ._version import __version__
10
12
  from .utils import ExitCodes, format_success
11
13
 
12
14
  SKILL_NAME = "slcli"
13
15
  _FALLBACK_SKILL_CHOICES = [SKILL_NAME]
16
+ _VERSION_FILENAME = ".slcli-version"
14
17
 
15
18
  # Mapping of client name -> (personal skills dir, project subdir relative to repo root)
16
19
  # personal dir uses Path.home() so it's always resolved at call time via _personal_dir().
@@ -119,6 +122,23 @@ def _expand_skill_selection(skill_names: Optional[List[str]] = None) -> List[str
119
122
  return requested
120
123
 
121
124
 
125
+ def _skill_installation_status(destination_root: Path, skill_name: str) -> str:
126
+ """Return the version status of an installed skill."""
127
+ destination_dir = destination_root / skill_name
128
+ if not destination_dir.exists():
129
+ return "missing"
130
+
131
+ version_file = destination_dir / _VERSION_FILENAME
132
+ if not version_file.exists():
133
+ return "unversioned"
134
+
135
+ try:
136
+ installed_version = version_file.read_text(encoding="utf-8").strip()
137
+ return "current" if Version(installed_version) >= Version(__version__) else "outdated"
138
+ except (InvalidVersion, OSError):
139
+ return "unversioned"
140
+
141
+
122
142
  def install_skills_to_directory(
123
143
  directory: Path,
124
144
  skill_names: Optional[List[str]] = None,
@@ -150,6 +170,7 @@ def install_skills_to_directory(
150
170
  destination_dir.unlink()
151
171
 
152
172
  shutil.copytree(source_dir, destination_dir)
173
+ (destination_dir / _VERSION_FILENAME).write_text(f"{__version__}\n", encoding="utf-8")
153
174
 
154
175
  return len(selected_skills)
155
176
 
@@ -184,6 +205,19 @@ def _resolve_destinations(clients: List[str], scope: str) -> List[Path]:
184
205
  return seen
185
206
 
186
207
 
208
+ def _requested_destinations(
209
+ directory: Optional[Path], client: Optional[str], scope: Optional[str]
210
+ ) -> List[Path]:
211
+ """Resolve either a custom skills directory or client-specific destinations."""
212
+ if directory is not None:
213
+ if client is not None or scope is not None:
214
+ raise ValueError("--directory cannot be combined with --client or --scope")
215
+ return [directory.expanduser()]
216
+
217
+ selected_clients = CLIENT_CHOICES if client == "all" else [client or "agents"]
218
+ return _resolve_destinations(selected_clients, scope or "project")
219
+
220
+
187
221
  def register_skill_commands(cli: Any) -> None:
188
222
  """Register the skill command group with the CLI.
189
223
 
@@ -217,6 +251,13 @@ def register_skill_commands(cli: Any) -> None:
217
251
  default=None,
218
252
  help="personal (~/ home dirs), project (current repo), or both.",
219
253
  )
254
+ @click.option(
255
+ "--directory",
256
+ "-d",
257
+ type=click.Path(file_okay=False, path_type=Path),
258
+ default=None,
259
+ help="Install directly into this skills directory.",
260
+ )
220
261
  @click.option(
221
262
  "--force",
222
263
  "-F",
@@ -225,7 +266,11 @@ def register_skill_commands(cli: Any) -> None:
225
266
  help="Overwrite existing skill installation without prompting.",
226
267
  )
227
268
  def install_skill(
228
- skill: Optional[str], client: Optional[str], scope: Optional[str], force: bool
269
+ skill: Optional[str],
270
+ client: Optional[str],
271
+ scope: Optional[str],
272
+ directory: Optional[Path],
273
+ force: bool,
229
274
  ) -> None:
230
275
  """Install bundled skills for supported AI clients."""
231
276
  requested_skills: Optional[List[str]]
@@ -235,11 +280,9 @@ def register_skill_commands(cli: Any) -> None:
235
280
  assert skill is not None
236
281
  requested_skills = [skill.lower()]
237
282
  selected_skill_names = _expand_skill_selection(requested_skills)
238
- selected_clients = CLIENT_CHOICES if client == "all" else [client or "agents"]
239
- selected_scope = scope or "project"
240
- destinations = _resolve_destinations(selected_clients, selected_scope)
241
283
 
242
284
  try:
285
+ destinations = _requested_destinations(directory, client, scope)
243
286
  installed_count = 0
244
287
  for destination in destinations:
245
288
  installed_count += install_skills_to_directory(
@@ -257,6 +300,9 @@ def register_skill_commands(cli: Any) -> None:
257
300
  except FileNotFoundError as exc:
258
301
  click.echo(f"✗ {exc}", err=True)
259
302
  sys.exit(ExitCodes.GENERAL_ERROR)
303
+ except OSError as exc:
304
+ click.echo(f"✗ Unable to install skills: {exc}", err=True)
305
+ sys.exit(ExitCodes.GENERAL_ERROR)
260
306
 
261
307
  format_success(
262
308
  "Installed bundled AI skills",
@@ -266,3 +312,60 @@ def register_skill_commands(cli: Any) -> None:
266
312
  "Installed": str(installed_count),
267
313
  },
268
314
  )
315
+
316
+ @skill.command(name="check")
317
+ @click.option(
318
+ "--skill",
319
+ "-k",
320
+ type=click.Choice(SKILL_CHOICES + ["all"], case_sensitive=False),
321
+ default=None,
322
+ help=f"Skill to check ({', '.join(SKILL_CHOICES)}, or all).",
323
+ )
324
+ @click.option(
325
+ "--client",
326
+ "-c",
327
+ type=click.Choice(CLIENT_CHOICES + ["all"], case_sensitive=False),
328
+ default=None,
329
+ help="AI client installation to check (agents, claude, or all).",
330
+ )
331
+ @click.option(
332
+ "--scope",
333
+ "-s",
334
+ type=click.Choice(["personal", "project", "both"], case_sensitive=False),
335
+ default=None,
336
+ help="personal (~/ home dirs), project (current repo), or both.",
337
+ )
338
+ @click.option(
339
+ "--directory",
340
+ "-d",
341
+ type=click.Path(file_okay=False, path_type=Path),
342
+ default=None,
343
+ help="Check skills directly in this directory.",
344
+ )
345
+ def check_skills(
346
+ skill: Optional[str],
347
+ client: Optional[str],
348
+ scope: Optional[str],
349
+ directory: Optional[Path],
350
+ ) -> None:
351
+ """Check whether installed skills match the bundled version."""
352
+ requested_skills = None if skill in (None, "all") else [skill.lower()]
353
+
354
+ try:
355
+ selected_skill_names = _expand_skill_selection(requested_skills)
356
+ destinations = _requested_destinations(directory, client, scope)
357
+ except ValueError as exc:
358
+ click.echo(f"✗ {exc}", err=True)
359
+ sys.exit(ExitCodes.INVALID_INPUT)
360
+
361
+ needs_update = False
362
+ click.echo(f"Bundled skill version: {__version__}")
363
+ for destination in destinations:
364
+ for skill_name in selected_skill_names:
365
+ status = _skill_installation_status(destination, skill_name)
366
+ indicator = "✓" if status == "current" else "✗"
367
+ click.echo(f"{indicator} {destination / skill_name}: {status}")
368
+ needs_update = needs_update or status != "current"
369
+
370
+ if needs_update:
371
+ sys.exit(ExitCodes.GENERAL_ERROR)
@@ -0,0 +1,221 @@
1
+ ---
2
+ name: slcli
3
+ description: >-
4
+ Query and manage NI SystemLink resources using the slcli command-line interface.
5
+ Use when the user asks about test results, assets, systems, work items,
6
+ specifications, webapps, notebooks, dataframes, files, feeds, tags,
7
+ authorization, users, example fixture authoring, example config.yaml files,
8
+ or other SystemLink resource workflows. Use it when the user asks to create,
9
+ validate, review, install, or troubleshoot a SystemLink example fixture.
10
+ argument-hint: >-
11
+ Describe the SystemLink workflow you want to inspect, automate, scaffold, or
12
+ troubleshoot.
13
+ ---
14
+
15
+ # SystemLink CLI
16
+
17
+ Use this skill when the task is primarily about `slcli` commands or a
18
+ SystemLink resource workflow that should be driven from the CLI.
19
+
20
+ ## When to use it
21
+
22
+ - Querying or managing SystemLink resources through `slcli`
23
+ - Looking up exact command syntax, flags, or JSON output patterns
24
+ - Building command sequences for analysis, provisioning, packaging, or cleanup
25
+ - Creating, validating, or reviewing `slcli example` fixture YAML
26
+ - Troubleshooting CLI behavior, platform gating, or command selection
27
+
28
+ ## Reference docs
29
+
30
+ Load only what the current task needs.
31
+
32
+ | Topic | File | When to load |
33
+ | --- | --- | --- |
34
+ | CLI command reference | [commands.md](./references/commands.md) | Looking up command syntax, options, or examples |
35
+ | Example fixture authoring | [example-authoring.md](./references/example-authoring.md) | Creating or reviewing `config.yaml`, resource references, file-backed fixtures, or validation behavior |
36
+ | Datasheet-to-spec workflow | [datasheet-workflow.md](./references/datasheet-workflow.md) | Importing specifications from PDF, CSV, or structured text |
37
+ | Minimal spec import payload | [import-specs.min.json](./references/import-specs.min.json) | Need a bundled create-compatible starter payload or conditions |
38
+ | Spec import helper | [spec_import_helper.py](./scripts/spec_import_helper.py) | Scaffold or validate a datasheet spec import payload |
39
+ | Filtering guide | [filtering.md](./references/filtering.md) | Advanced filters, LINQ syntax, and query composition |
40
+ | Analysis recipes | [analysis-recipes.md](./references/analysis-recipes.md) | Multi-step analysis workflows and reporting patterns |
41
+ | Troubleshooting | [troubleshooting.md](./references/troubleshooting.md) | SSL, workspace IDs, encoding, or scripting pitfalls |
42
+ | Notebook workflow | [notebook/overview.md](./references/notebook/overview.md) | Creating notebooks for SystemLink |
43
+ | Webapp workflow | [webapp/overview.md](./references/webapp/overview.md) | Hosted Angular webapp scaffolding and deployment |
44
+ | Python test workflow | [python-test/overview.md](./references/python-test/overview.md) | Python test app structure and deployment |
45
+ | Job debugging | [job-debugging/overview.md](./references/job-debugging/overview.md) | Salt job triage and recovery |
46
+ | NI package files | [nipkg/overview.md](./references/nipkg/overview.md) | File-package assembly and `nipkg pack` guidance |
47
+
48
+ ## Default approach
49
+
50
+ 1. At the start of troubleshooting or a substantial `slcli` workflow, run the
51
+ update preflight once per session:
52
+
53
+ ```bash
54
+ slcli version check
55
+ slcli skill check --client CLIENT --scope SCOPE
56
+ ```
57
+
58
+ Set `CLIENT` and `SCOPE` to the active skill installation, or use
59
+ `--directory PATH` for a custom skills directory. If the CLI is outdated,
60
+ recommend the update command printed by `version check`. If the skill is
61
+ missing, unversioned, or outdated, recommend `slcli skill install` with the
62
+ same target and `--force`. Ask before running either update because they
63
+ modify the user's environment. A failed or unavailable check is advisory:
64
+ report it briefly and continue the requested workflow unless version skew
65
+ is the likely cause.
66
+ 2. Prefer long-form flags in generated commands.
67
+ 3. Use `--format json` when the result will be filtered, transformed, or piped
68
+ into other tools.
69
+ 4. Use `--summary --group-by` for aggregation before fetching large raw result sets.
70
+ 5. Use convenience filters first, then fall back to `--filter` with `--substitution` for complex queries.
71
+ 6. Stay scoped to the user’s requested resource or workflow.
72
+ 7. Load deeper references only when the command surface alone is not enough.
73
+ 8. For example authoring or review, load `example-authoring.md` before proposing YAML.
74
+ 9. Prefer workspace IDs over names in scripted workflows when an endpoint is strict about identity.
75
+ 10. Use `make_api_request` from `slcli.utils` for helper scripts so auth, SSL, and error handling stay consistent.
76
+ 11. For datasheet imports, default to autonomy when the product or workspace can be resolved unambiguously.
77
+
78
+ ## Common command groups
79
+
80
+ | Group | Purpose | Key subcommands |
81
+ | --- | --- | --- |
82
+ | `testmonitor` | Test results and products | `result list/get`, `product list/create/update` |
83
+ | `alarm` | Alarm monitoring and lifecycle actions | `list`, `get`, `acknowledge`, `force-clear`, `delete`, `transition`, `monitor` |
84
+ | `spec` | Specifications | `list`, `query`, `get`, `create`, `import`, `export` |
85
+ | `asset` | Assets and calibration | `list`, `get`, `summary`, `calibration` |
86
+ | `system` | System fleet | `list`, `get`, `compare`, `summary`, `job` |
87
+ | `tag` | Tag read/write | `list`, `get-value`, `set-value`, `create` |
88
+ | `routine` | Event-action routines | `list`, `create`, `enable/disable` |
89
+ | `comment` | Resource comments | `list`, `add`, `update`, `delete` |
90
+ | `workitem` | Work items and workflows | `list`, `create`, `schedule`, `template`, `workflow` |
91
+ | `file` | File management | `list`, `upload`, `download`, `query`, `watch` |
92
+ | `notebook` | Jupyter notebooks | `manage list/create`, `execute start/sync` |
93
+ | `feed` | Package feeds | `list`, `create`, `package upload` |
94
+ | `customfield` | Dynamic form fields | `list`, `create`, `export`, `edit` |
95
+ | `template` | Test plan templates | `list`, `import`, `export` |
96
+ | `webapp` | Web applications | `new`, `pack`, `publish`, `list` |
97
+ | `config` | Connection profiles | `list`, `use`, `add`, `delete` |
98
+ | `user` | User management | `list`, `get`, `create`, `update` |
99
+ | `auth` | Authorization policies | `policy list/create`, `template list` |
100
+ | `workspace` | Workspaces | `list`, `get` |
101
+ | `version` | CLI update hygiene | `check` |
102
+ | `skill` | AI skill installation | `install`, `check` |
103
+ | `example` | Demo provisioning | `list`, `install`, `delete` |
104
+
105
+ Example package fixtures are declared as `package` resources after a `feed`
106
+ resource. Use `source.type: dummy` for deterministic packages, `file` for a
107
+ fixture-relative `.nipkg`, or `repository` for an explicit HTTPS package URL.
108
+ The repository catalog can identify packages and feeds, but package bytes must
109
+ come from a direct package URL or an existing feed download path.
110
+
111
+ ## Mandatory scope resolution
112
+
113
+ Before the first resource query, resolve the profile and workspace separately.
114
+ Treat a workspace supplied by the user as a workspace identifier, never as a
115
+ profile name. Match it exactly against either the workspace name or UUID.
116
+
117
+ 1. Run `slcli config list --format json` and select profiles whose `workspace`
118
+ field matches the requested workspace name. If the user supplied a UUID,
119
+ probe configured profiles sequentially instead. Do not infer a profile from
120
+ a similar name such as `demo-fred` or `fred-roaster`.
121
+ 2. Use the global `--profile NAME` override on every command. The option goes
122
+ before the command group, for example:
123
+
124
+ ```bash
125
+ slcli --profile PROFILE_NAME workspace list --format json
126
+ ```
127
+
128
+ This preserves the user's global active profile.
129
+ 3. If several profiles match, probe them sequentially with
130
+ `slcli --profile NAME info --skip-health --format json`. Continue past a
131
+ missing credential, unavailable endpoint, or permission error. Confirm the
132
+ selected candidate with one read-only workspace query before issuing the
133
+ actual resource query. Do not fan out the same query across candidates.
134
+ 4. Use the first authorized candidate. Ask the user only when several
135
+ candidates are authorized and the choice could change the answer.
136
+ 5. With the selected profile, run `workspace list --format json` and resolve
137
+ the requested workspace by exact name or UUID. Carry both the display name
138
+ and UUID, but use the UUID for subsequent queries when the command accepts
139
+ it.
140
+
141
+ When reading `slcli info --format json`, use `active_profile_name` as the
142
+ effective profile after CLI or environment overrides. `current_profile` is the
143
+ persisted config pointer and may differ. Use `api_url_source` to confirm where
144
+ the effective endpoint came from; never use `current_profile` alone to decide
145
+ which profile served a query.
146
+
147
+ ## Mandatory non-interactive webapp deployment protocol
148
+
149
+ For every webapp creation, publish, redeploy, or update task, load
150
+ [deployment.md](./references/webapp/deployment.md) and follow its ordered
151
+ protocol. Do not build or upload an artifact until the deployment target has
152
+ been resolved. The protocol is non-interactive: use JSON output and bounded
153
+ inventory commands, and do not rely on table pagination or terminal prompts.
154
+
155
+ 1. Discover the installed command surface before composing commands:
156
+ ```bash
157
+ slcli config list --format json
158
+ slcli webapp publish -h
159
+ slcli webapp list -h
160
+ ```
161
+ Installed `--help` wins over this skill and its references. Confirm every
162
+ option on the installed CLI; `webapp publish` currently has `--id`, `--name`,
163
+ and `--workspace`, while `webapp list` has bounded JSON output and `-f`.
164
+ Prefer long options in generated commands after confirming they exist.
165
+ 2. Resolve the effective profile and target workspace separately. Probe a
166
+ candidate with `info --skip-health --format json`, resolve the workspace
167
+ display name to its UUID with `workspace list --format json`, and carry the
168
+ UUID into every later command. Never use a similar profile name as a
169
+ substitute for workspace identity.
170
+ 3. Resolve the exact webapp target before building or uploading. Use a
171
+ bounded, filtered, non-interactive inventory, for example:
172
+ ```bash
173
+ slcli --profile PROFILE webapp list \
174
+ --workspace WORKSPACE_ID --filter "Coffee Tasting" \
175
+ --take 10 --format json
176
+ ```
177
+ The server-side `--filter` is a substring filter, so compare returned names
178
+ locally. One exact name match means update that webapp with its returned ID
179
+ by default. Multiple exact matches are ambiguous and require a selected ID.
180
+ No exact match means report that a new resource would be created and obtain
181
+ explicit confirmation or an explicit create instruction before using
182
+ `--name`; never create a duplicate as an implicit fallback.
183
+ 4. Inspect the project contract before running its dev server or production
184
+ build. Read `package.json` and `angular.json`; do not append `--host` when
185
+ the package script already supplies it. Remove or correct legacy Angular
186
+ options such as `buildOptimizer` and `vendorChunk` when they make `ng serve`
187
+ reject the configuration. Run the production build, detect its actual
188
+ output directory, and verify the hosted routing, CSP, authentication, and
189
+ service/workspace contract. The Test Monitor results service prefix is
190
+ `/nitest/v2/query-results`, not `/nitestmonitor/v2/query-results`; do not
191
+ hardcode `workspace=Default` when the target workspace was resolved.
192
+ 5. Publish only after steps 1-4 pass. Pass the resolved workspace for a new
193
+ webapp, or the exact existing webapp ID for an update. Capture the returned
194
+ webapp ID, published URL, and publish timestamp in the task record.
195
+ 6. Validate at three levels: deployment metadata with `webapp get`, an
196
+ authenticated CLI query for the target workspace and required resources,
197
+ and an authenticated browser check of the hosted URL. A reachable URL is
198
+ not proof of an authenticated app. If the browser redirects to login or
199
+ returns 401, report exactly: `deployment reachable, interactive hosted
200
+ validation pending.`
201
+
202
+ ## Product lookup and overview defaults
203
+
204
+ For product discovery, use this order:
205
+
206
+ 1. Try an exact or likely part number with `testmonitor product list
207
+ --part-number`.
208
+ 2. Try the name and family convenience filters.
209
+ 3. If a convenience filter returns `[]`, treat that as inconclusive. Scan the
210
+ resolved workspace catalog with a bounded JSON query and match name or part
211
+ number locally with `jq`.
212
+ 4. Fetch the selected product with `testmonitor product get <PRODUCT_ID>`.
213
+
214
+ For a product overview, fetch the product record and directly linked metadata
215
+ only. Use `--summary` for counts and statuses, and grouped summaries for
216
+ profiles, programs, or other supported dimensions. For result data, use only
217
+ dimensions exposed by the command, such as `status` and `programName`. Fetch
218
+ only the latest 5 to 10 results, projecting relevant fields with `jq`. Fetch
219
+ full result details only for a specific run or failure. Record an explicit UTC
220
+ `as of` time and treat counts from separate live queries as separate
221
+ observations.
@@ -17,10 +17,94 @@ Each recipe maps to a real-world scenario and shows the exact commands needed.
17
17
  - [Recipe 9: Product family workload distribution](#recipe-9-product-family-workload-distribution)
18
18
  - [Recipe 10: Environmental condition failure patterns](#recipe-10-environmental-condition-failure-patterns)
19
19
  - [Recipe 11: Create and schedule a work item on a specific fixture/slot and system](#recipe-11-create-and-schedule-a-work-item-on-a-specific-fixtureslot-and-system)
20
+ - [Product discovery and overview](#product-discovery-and-overview)
20
21
  - [General tips](#general-tips)
21
22
 
22
23
  ---
23
24
 
25
+ ## Product discovery and overview
26
+
27
+ **Question:** Tell me about a product in a specific workspace without
28
+ producing an oversized, inconsistent report.
29
+
30
+ **Prerequisite:** Complete the mandatory profile and workspace resolution in
31
+ the main `slcli` skill. Set `PROFILE` to the selected profile and
32
+ `WORKSPACE_ID` to the resolved workspace UUID. Capture the observation time
33
+ before querying live data:
34
+
35
+ ```bash
36
+ PROFILE="<PROFILE_NAME>"
37
+ WORKSPACE_ID="<WORKSPACE_UUID>"
38
+ AS_OF="$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
39
+ printf 'As of %s\n' "$AS_OF"
40
+ ```
41
+
42
+ **Lookup order:**
43
+
44
+ ```bash
45
+ # 1. Exact or likely part number
46
+ slcli --profile "$PROFILE" testmonitor product list \
47
+ --workspace "$WORKSPACE_ID" --part-number "<PART_NUMBER>" \
48
+ --format json --take 25
49
+
50
+ # 2. Name or family convenience filters, when the part-number lookup is empty
51
+ slcli --profile "$PROFILE" testmonitor product list \
52
+ --workspace "$WORKSPACE_ID" --name "<PRODUCT_NAME>" \
53
+ --format json --take 25
54
+ slcli --profile "$PROFILE" testmonitor product list \
55
+ --workspace "$WORKSPACE_ID" --family "<FAMILY>" \
56
+ --format json --take 25
57
+
58
+ # 3. Bounded workspace catalog fallback when convenience filters are empty
59
+ slcli --profile "$PROFILE" testmonitor product list \
60
+ --workspace "$WORKSPACE_ID" --format json --take 100 |
61
+ jq --arg name "<PRODUCT_NAME>" --arg part "<PART_NUMBER>" '
62
+ [ .[] | select(
63
+ (($name != "") and ((.name // "" | ascii_downcase) | contains($name | ascii_downcase)))
64
+ or (($part != "") and ((.partNumber // "" | ascii_downcase) | contains($part | ascii_downcase)))
65
+ ) | {id, name, partNumber, family, workspace} ]'
66
+ ```
67
+
68
+ An empty result from a name or family filter does not prove that the product is
69
+ absent. Increase the bounded catalog limit only deliberately, and project the
70
+ candidate fields in `jq` before displaying them. Fetch the selected record only
71
+ after identifying its ID:
72
+
73
+ ```bash
74
+ slcli --profile "$PROFILE" testmonitor product get <PRODUCT_ID> --format json
75
+ ```
76
+
77
+ **Overview budget:**
78
+
79
+ ```bash
80
+ # Directly linked metadata, only when relevant to the question
81
+ slcli --profile "$PROFILE" spec list --product <PRODUCT_ID> --format json
82
+
83
+ # Compact counts and status breakdown
84
+ slcli --profile "$PROFILE" testmonitor result list \
85
+ --part-number "<PART_NUMBER>" --summary --group-by status \
86
+ --format json
87
+
88
+ # Grouped program summary
89
+ slcli --profile "$PROFILE" testmonitor result list \
90
+ --part-number "<PART_NUMBER>" --summary --group-by programName \
91
+ --format json
92
+
93
+ # Latest 5 to 10 results, projected to relevant fields
94
+ slcli --profile "$PROFILE" testmonitor result list \
95
+ --part-number "<PART_NUMBER>" --order-by STARTED_AT --descending \
96
+ --take 10 --format json |
97
+ jq '[.[] | {id, status: .status.statusType, startedAt, programName,
98
+ partNumber, serialNumber}]'
99
+ ```
100
+
101
+ Use `testmonitor result get <RESULT_ID> --include-steps --format json` only
102
+ when the user asks about a particular run or failure. Counts from separate
103
+ commands are not one atomic snapshot; report the `as of` time and call out
104
+ live-data changes when totals do not agree.
105
+
106
+ ---
107
+
24
108
  ## Recipe 1: Operator failure rate analysis
25
109
 
26
110
  **Question:** Which operators have the highest failure rates and what should they
@@ -482,8 +566,9 @@ slcli workitem schedule wi-12345 \
482
566
  - **Start with `--summary`** to understand data shape before fetching raw records.
483
567
  - **Use `--group-by`** with `--summary` for aggregation: `status`, `programName`,
484
568
  `serialNumber`, `operator`, `hostName`, `systemId`.
485
- - **Chain with `jq`** for complex transformations — always use `-f json`.
486
- - **Use `--take` wisely** — start small (100-500), increase if needed.
569
+ - **Chain with `jq`** for complex transformations — always use `--format json`.
570
+ - **Use `--take` wisely** — start with 5-10 for recent detail and a bounded
571
+ catalog query for discovery; increase only when the question requires it.
487
572
  - **For rate calculations**, query total count and filtered count separately, then divide.
488
573
  - **Use `--order-by TOTAL_TIME_IN_SECONDS --descending`** to find slowest tests quickly.
489
574
  - **Asset `--connected` flag** limits to assets in currently connected systems.