@salesforce/afv-skills 1.14.0 → 1.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/skills/activating-datacloud/SKILL.md +0 -1
- package/skills/analyzing-omnistudio-dependencies/SKILL.md +0 -1
- package/skills/applying-slds/SKILL.md +322 -0
- package/skills/applying-slds/checklists.md +83 -0
- package/skills/applying-slds/examples.md +283 -0
- package/skills/applying-slds/guidance/README.md +83 -0
- package/skills/applying-slds/guidance/blueprints-index.md +213 -0
- package/skills/applying-slds/guidance/icons-guidance.md +186 -0
- package/skills/applying-slds/guidance/overviews/borders.md +236 -0
- package/skills/applying-slds/guidance/overviews/color.md +266 -0
- package/skills/applying-slds/guidance/overviews/display-density.md +366 -0
- package/skills/applying-slds/guidance/overviews/icons.md +240 -0
- package/skills/applying-slds/guidance/overviews/illustrations.md +235 -0
- package/skills/applying-slds/guidance/overviews/shadows.md +176 -0
- package/skills/applying-slds/guidance/overviews/spacing.md +216 -0
- package/skills/applying-slds/guidance/overviews/typography.md +323 -0
- package/skills/applying-slds/guidance/overviews/utilities.md +542 -0
- package/skills/applying-slds/guidance/slds-development-guide.md +288 -0
- package/skills/applying-slds/guidance/styling-hooks/borders.md +202 -0
- package/skills/applying-slds/guidance/styling-hooks/color/expressive-palette-hooks.md +153 -0
- package/skills/applying-slds/guidance/styling-hooks/color/index.md +171 -0
- package/skills/applying-slds/guidance/styling-hooks/color/semantic/accent-hooks.md +204 -0
- package/skills/applying-slds/guidance/styling-hooks/color/semantic/feedback-hooks.md +768 -0
- package/skills/applying-slds/guidance/styling-hooks/color/semantic/surface-hooks.md +337 -0
- package/skills/applying-slds/guidance/styling-hooks/color/system-hooks.md +132 -0
- package/skills/applying-slds/guidance/styling-hooks/index.md +327 -0
- package/skills/applying-slds/guidance/styling-hooks/shadows.md +238 -0
- package/skills/applying-slds/guidance/styling-hooks/spacing.md +254 -0
- package/skills/applying-slds/guidance/styling-hooks/typography.md +448 -0
- package/skills/applying-slds/guidance/utilities/alignment.md +119 -0
- package/skills/applying-slds/guidance/utilities/borders.md +131 -0
- package/skills/applying-slds/guidance/utilities/box.md +125 -0
- package/skills/applying-slds/guidance/utilities/color.md +165 -0
- package/skills/applying-slds/guidance/utilities/dark-mode.md +111 -0
- package/skills/applying-slds/guidance/utilities/description-list.md +168 -0
- package/skills/applying-slds/guidance/utilities/floats.md +117 -0
- package/skills/applying-slds/guidance/utilities/grid.md +264 -0
- package/skills/applying-slds/guidance/utilities/horizontal-list.md +110 -0
- package/skills/applying-slds/guidance/utilities/hyphenation.md +84 -0
- package/skills/applying-slds/guidance/utilities/index.md +205 -0
- package/skills/applying-slds/guidance/utilities/interactions.md +89 -0
- package/skills/applying-slds/guidance/utilities/layout.md +109 -0
- package/skills/applying-slds/guidance/utilities/line-clamp.md +131 -0
- package/skills/applying-slds/guidance/utilities/margin.md +155 -0
- package/skills/applying-slds/guidance/utilities/media-object.md +161 -0
- package/skills/applying-slds/guidance/utilities/name-value-list.md +152 -0
- package/skills/applying-slds/guidance/utilities/padding.md +155 -0
- package/skills/applying-slds/guidance/utilities/position.md +177 -0
- package/skills/applying-slds/guidance/utilities/print.md +114 -0
- package/skills/applying-slds/guidance/utilities/scrollable.md +126 -0
- package/skills/applying-slds/guidance/utilities/sizing.md +190 -0
- package/skills/applying-slds/guidance/utilities/themes.md +121 -0
- package/skills/applying-slds/guidance/utilities/truncate.md +127 -0
- package/skills/applying-slds/guidance/utilities/typography.md +166 -0
- package/skills/applying-slds/guidance/utilities/vertical-list.md +166 -0
- package/skills/applying-slds/guidance/utilities/visibility.md +228 -0
- package/skills/applying-slds/metadata/README.md +84 -0
- package/skills/applying-slds/metadata/blueprints/components/accordion.yaml +304 -0
- package/skills/applying-slds/metadata/blueprints/components/activity-timeline.yaml +92 -0
- package/skills/applying-slds/metadata/blueprints/components/alert.yaml +103 -0
- package/skills/applying-slds/metadata/blueprints/components/app-launcher.yaml +94 -0
- package/skills/applying-slds/metadata/blueprints/components/avatar-group.yaml +81 -0
- package/skills/applying-slds/metadata/blueprints/components/avatar.yaml +97 -0
- package/skills/applying-slds/metadata/blueprints/components/badges.yaml +102 -0
- package/skills/applying-slds/metadata/blueprints/components/brand-band.yaml +198 -0
- package/skills/applying-slds/metadata/blueprints/components/breadcrumbs.yaml +95 -0
- package/skills/applying-slds/metadata/blueprints/components/builder-header.yaml +192 -0
- package/skills/applying-slds/metadata/blueprints/components/button-groups.yaml +82 -0
- package/skills/applying-slds/metadata/blueprints/components/button-icons.yaml +295 -0
- package/skills/applying-slds/metadata/blueprints/components/buttons.yaml +230 -0
- package/skills/applying-slds/metadata/blueprints/components/cards.yaml +124 -0
- package/skills/applying-slds/metadata/blueprints/components/carousel.yaml +140 -0
- package/skills/applying-slds/metadata/blueprints/components/chat.yaml +179 -0
- package/skills/applying-slds/metadata/blueprints/components/checkbox-button-group.yaml +192 -0
- package/skills/applying-slds/metadata/blueprints/components/checkbox-button.yaml +204 -0
- package/skills/applying-slds/metadata/blueprints/components/checkbox-toggle.yaml +177 -0
- package/skills/applying-slds/metadata/blueprints/components/checkbox.yaml +108 -0
- package/skills/applying-slds/metadata/blueprints/components/color-picker.yaml +172 -0
- package/skills/applying-slds/metadata/blueprints/components/combobox.yaml +136 -0
- package/skills/applying-slds/metadata/blueprints/components/counter.yaml +147 -0
- package/skills/applying-slds/metadata/blueprints/components/data-tables.yaml +157 -0
- package/skills/applying-slds/metadata/blueprints/components/datepickers.yaml +130 -0
- package/skills/applying-slds/metadata/blueprints/components/datetime-picker.yaml +155 -0
- package/skills/applying-slds/metadata/blueprints/components/docked-composer.yaml +201 -0
- package/skills/applying-slds/metadata/blueprints/components/docked-form-footer.yaml +161 -0
- package/skills/applying-slds/metadata/blueprints/components/docked-utility-bar.yaml +175 -0
- package/skills/applying-slds/metadata/blueprints/components/drop-zone.yaml +115 -0
- package/skills/applying-slds/metadata/blueprints/components/dueling-picklist.yaml +196 -0
- package/skills/applying-slds/metadata/blueprints/components/dynamic-icons.yaml +128 -0
- package/skills/applying-slds/metadata/blueprints/components/dynamic-menu.yaml +141 -0
- package/skills/applying-slds/metadata/blueprints/components/expandable-section.yaml +115 -0
- package/skills/applying-slds/metadata/blueprints/components/expression.yaml +143 -0
- package/skills/applying-slds/metadata/blueprints/components/feeds.yaml +125 -0
- package/skills/applying-slds/metadata/blueprints/components/file-selector.yaml +154 -0
- package/skills/applying-slds/metadata/blueprints/components/files.yaml +119 -0
- package/skills/applying-slds/metadata/blueprints/components/form-element.yaml +145 -0
- package/skills/applying-slds/metadata/blueprints/components/global-header.yaml +120 -0
- package/skills/applying-slds/metadata/blueprints/components/global-navigation.yaml +100 -0
- package/skills/applying-slds/metadata/blueprints/components/icons.yaml +138 -0
- package/skills/applying-slds/metadata/blueprints/components/illustration.yaml +205 -0
- package/skills/applying-slds/metadata/blueprints/components/input.yaml +151 -0
- package/skills/applying-slds/metadata/blueprints/components/list-builder.yaml +127 -0
- package/skills/applying-slds/metadata/blueprints/components/lookups.yaml +132 -0
- package/skills/applying-slds/metadata/blueprints/components/map.yaml +118 -0
- package/skills/applying-slds/metadata/blueprints/components/menus.yaml +134 -0
- package/skills/applying-slds/metadata/blueprints/components/modals.yaml +152 -0
- package/skills/applying-slds/metadata/blueprints/components/notifications.yaml +88 -0
- package/skills/applying-slds/metadata/blueprints/components/page-headers.yaml +135 -0
- package/skills/applying-slds/metadata/blueprints/components/panels.yaml +149 -0
- package/skills/applying-slds/metadata/blueprints/components/path.yaml +154 -0
- package/skills/applying-slds/metadata/blueprints/components/picklist.yaml +125 -0
- package/skills/applying-slds/metadata/blueprints/components/pills.yaml +154 -0
- package/skills/applying-slds/metadata/blueprints/components/popovers.yaml +120 -0
- package/skills/applying-slds/metadata/blueprints/components/progress-bar.yaml +110 -0
- package/skills/applying-slds/metadata/blueprints/components/progress-indicator.yaml +133 -0
- package/skills/applying-slds/metadata/blueprints/components/progress-ring.yaml +102 -0
- package/skills/applying-slds/metadata/blueprints/components/prompt.yaml +126 -0
- package/skills/applying-slds/metadata/blueprints/components/publishers.yaml +178 -0
- package/skills/applying-slds/metadata/blueprints/components/radio-button-group.yaml +172 -0
- package/skills/applying-slds/metadata/blueprints/components/radio-group.yaml +112 -0
- package/skills/applying-slds/metadata/blueprints/components/rich-text-editor.yaml +135 -0
- package/skills/applying-slds/metadata/blueprints/components/scoped-notifications.yaml +188 -0
- package/skills/applying-slds/metadata/blueprints/components/scoped-tabs.yaml +97 -0
- package/skills/applying-slds/metadata/blueprints/components/select.yaml +127 -0
- package/skills/applying-slds/metadata/blueprints/components/setup-assistant.yaml +152 -0
- package/skills/applying-slds/metadata/blueprints/components/slider.yaml +111 -0
- package/skills/applying-slds/metadata/blueprints/components/spinners.yaml +135 -0
- package/skills/applying-slds/metadata/blueprints/components/split-view.yaml +112 -0
- package/skills/applying-slds/metadata/blueprints/components/summary-detail.yaml +103 -0
- package/skills/applying-slds/metadata/blueprints/components/tabs.yaml +138 -0
- package/skills/applying-slds/metadata/blueprints/components/textarea.yaml +116 -0
- package/skills/applying-slds/metadata/blueprints/components/tiles.yaml +108 -0
- package/skills/applying-slds/metadata/blueprints/components/timepicker.yaml +111 -0
- package/skills/applying-slds/metadata/blueprints/components/toast.yaml +154 -0
- package/skills/applying-slds/metadata/blueprints/components/tooltips.yaml +107 -0
- package/skills/applying-slds/metadata/blueprints/components/tree-grid.yaml +116 -0
- package/skills/applying-slds/metadata/blueprints/components/trees.yaml +116 -0
- package/skills/applying-slds/metadata/blueprints/components/trial-bar.yaml +112 -0
- package/skills/applying-slds/metadata/blueprints/components/vertical-navigation.yaml +130 -0
- package/skills/applying-slds/metadata/blueprints/components/vertical-tabs.yaml +140 -0
- package/skills/applying-slds/metadata/blueprints/components/visual-picker.yaml +150 -0
- package/skills/applying-slds/metadata/blueprints/components/welcome-mat.yaml +136 -0
- package/skills/applying-slds/metadata/hooks-index.json +6272 -0
- package/skills/applying-slds/metadata/icon-metadata.json +38466 -0
- package/skills/applying-slds/metadata/utilities-index.json +21912 -0
- package/skills/applying-slds/references/component-selection.md +112 -0
- package/skills/applying-slds/references/icons-decision-guide.md +124 -0
- package/skills/applying-slds/references/styling-decision-guide.md +228 -0
- package/skills/applying-slds/references/utilities-quick-ref.md +125 -0
- package/skills/applying-slds/scripts/search-blueprints.cjs +117 -0
- package/skills/applying-slds/scripts/search-hooks.cjs +139 -0
- package/skills/applying-slds/scripts/search-icons.cjs +174 -0
- package/skills/applying-slds/scripts/search-utilities.cjs +161 -0
- package/skills/building-mobile-apps/SKILL.md +0 -1
- package/skills/building-omnistudio-callable-apex/SKILL.md +0 -1
- package/skills/building-omnistudio-datamapper/SKILL.md +0 -1
- package/skills/building-omnistudio-flexcard/SKILL.md +0 -1
- package/skills/building-omnistudio-integration-procedure/SKILL.md +0 -1
- package/skills/building-omnistudio-omniscript/SKILL.md +0 -1
- package/skills/building-sf-integrations/SKILL.md +0 -1
- package/skills/configuring-connected-apps/SKILL.md +0 -1
- package/skills/connecting-datacloud/SKILL.md +0 -1
- package/skills/creating-b2b-commerce-store/SKILL.md +0 -1
- package/skills/debugging-apex-logs/SKILL.md +0 -1
- package/skills/deploying-metadata/SKILL.md +0 -1
- package/skills/deploying-omnistudio-datapacks/SKILL.md +0 -1
- package/skills/developing-agentforce/SKILL.md +0 -1
- package/skills/fetching-salesforce-docs/SKILL.md +0 -1
- package/skills/generating-custom-lightning-type/SKILL.md +17 -39
- package/skills/generating-custom-lightning-type/assets/primitive-types-and-constraints.md +41 -0
- package/skills/generating-custom-lightning-type/references/widget-rendition.md +124 -0
- package/skills/generating-lwc-components/SKILL.md +0 -1
- package/skills/generating-mermaid-diagrams/SKILL.md +0 -1
- package/skills/generating-visual-diagrams/SKILL.md +0 -1
- package/skills/handling-sf-data/SKILL.md +0 -1
- package/skills/harmonizing-datacloud/SKILL.md +0 -1
- package/skills/integrating-b2b-commerce-open-code-components/SKILL.md +0 -1
- package/skills/investigating-agentforce-architecture/README.md +156 -0
- package/skills/investigating-agentforce-architecture/SKILL.md +230 -0
- package/skills/investigating-agentforce-architecture/assets/cli/describe_sobject.yaml +16 -0
- package/skills/investigating-agentforce-architecture/assets/cli/describe_tooling_sobject.yaml +17 -0
- package/skills/investigating-agentforce-architecture/assets/cli/list_metadata_genaiprompttemplate.yaml +17 -0
- package/skills/investigating-agentforce-architecture/assets/cli/org_display.yaml +15 -0
- package/skills/investigating-agentforce-architecture/assets/cli/retrieve_genai_plugin.yaml +18 -0
- package/skills/investigating-agentforce-architecture/assets/cli/show_access_token.yaml +27 -0
- package/skills/investigating-agentforce-architecture/assets/mermaid/action_tree.mmd +20 -0
- package/skills/investigating-agentforce-architecture/assets/mermaid/data_flow.mmd +19 -0
- package/skills/investigating-agentforce-architecture/assets/mermaid/dependency_graph.mmd +19 -0
- package/skills/investigating-agentforce-architecture/assets/mermaid/invocation_sequence.mmd +20 -0
- package/skills/investigating-agentforce-architecture/assets/mermaid/planner_state.mmd +18 -0
- package/skills/investigating-agentforce-architecture/assets/soql/apex_class_bodies_by_ids.soql +3 -0
- package/skills/investigating-agentforce-architecture/assets/soql/apex_class_bodies_by_names.soql +3 -0
- package/skills/investigating-agentforce-architecture/assets/soql/bot_definition_details.soql +3 -0
- package/skills/investigating-agentforce-architecture/assets/soql/bot_version_lookup.soql +4 -0
- package/skills/investigating-agentforce-architecture/assets/soql/flow_definition_by_ids.soql +3 -0
- package/skills/investigating-agentforce-architecture/assets/soql/flow_definition_ids_by_names.soql +3 -0
- package/skills/investigating-agentforce-architecture/assets/soql/flow_definition_view_by_durable_ids.soql +4 -0
- package/skills/investigating-agentforce-architecture/assets/soql/flow_metadata_by_id.soql +3 -0
- package/skills/investigating-agentforce-architecture/assets/soql/functions_by_plugins.soql +5 -0
- package/skills/investigating-agentforce-architecture/assets/soql/planner_attrs_by_parent_ids.soql +3 -0
- package/skills/investigating-agentforce-architecture/assets/soql/planner_bundle_functions.soql +3 -0
- package/skills/investigating-agentforce-architecture/assets/soql/planner_definition_by_agent_chain.soql +3 -0
- package/skills/investigating-agentforce-architecture/assets/soql/plugin_functions_by_plugin_ids.soql +3 -0
- package/skills/investigating-agentforce-architecture/assets/soql/plugin_instructions_by_plugin_ids.soql +3 -0
- package/skills/investigating-agentforce-architecture/assets/soql/plugins_by_planner.soql +4 -0
- package/skills/investigating-agentforce-architecture/references/architecture_sections.md +243 -0
- package/skills/investigating-agentforce-architecture/references/contract.json +244 -0
- package/skills/investigating-agentforce-architecture/references/soql_fields.md +512 -0
- package/skills/investigating-agentforce-architecture/scripts/_shared/__init__.py +1 -0
- package/skills/investigating-agentforce-architecture/scripts/_shared/fs_guard.py +329 -0
- package/skills/investigating-agentforce-architecture/scripts/_shared/paths.py +110 -0
- package/skills/investigating-agentforce-architecture/scripts/_shared/runtime.py +59 -0
- package/skills/investigating-agentforce-architecture/scripts/_shared/sql.py +10 -0
- package/skills/investigating-agentforce-architecture/scripts/cache_check.py +234 -0
- package/skills/investigating-agentforce-architecture/scripts/config.py +131 -0
- package/skills/investigating-agentforce-architecture/scripts/fetch_soql.py +689 -0
- package/skills/investigating-agentforce-architecture/scripts/finalize.py +295 -0
- package/skills/investigating-agentforce-architecture/scripts/main.py +2835 -0
- package/skills/investigating-agentforce-architecture/scripts/metadata_listing.py +265 -0
- package/skills/investigating-agentforce-architecture/scripts/parallel_retrieve.py +69 -0
- package/skills/investigating-agentforce-architecture/scripts/parse_bundle.py +215 -0
- package/skills/investigating-agentforce-architecture/scripts/parse_wave.py +845 -0
- package/skills/investigating-agentforce-architecture/scripts/probe_channels.py +302 -0
- package/skills/investigating-agentforce-architecture/scripts/render_architecture.py +1043 -0
- package/skills/investigating-agentforce-architecture/scripts/resolve_bot.py +255 -0
- package/skills/investigating-agentforce-architecture/scripts/resolve_invocation_target.py +130 -0
- package/skills/investigating-agentforce-architecture/scripts/rest_client.py +763 -0
- package/skills/investigating-agentforce-architecture/scripts/retrieve_planner.py +13 -0
- package/skills/investigating-agentforce-architecture/scripts/sf_cli.py +242 -0
- package/skills/investigating-agentforce-architecture/scripts/soql_loader.py +253 -0
- package/skills/investigating-agentforce-architecture/scripts/summarize_tree.py +143 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/__init__.py +0 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/_bootstrap.py +23 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/fixtures/__init__.py +0 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/fixtures/genai_payloads.py +400 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_cache_check.py +307 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_cache_check_main.py +283 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_config.py +115 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_end_to_end_fixture.py +651 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_finalize.py +278 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_flow_children_inflation.py +582 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_fs_guard.py +113 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_iterative_wave_b.py +478 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_main_pipeline.py +3359 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_parallel_retrieve.py +131 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_parse_bundle.py +400 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_parse_wave.py +644 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_parse_wave_classifiers.py +224 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_parse_wave_helpers.py +380 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_parse_wave_main.py +397 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_per_branch_visited.py +244 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_probe_channels.py +359 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_probe_cli_recipes.py +185 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_render_architecture.py +810 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_resolve_bot.py +203 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_resolve_creds.py +157 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_resolve_invocation_target.py +145 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_rest_client.py +1253 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_runtime_override.py +100 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_sf_cli.py +261 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_signature_stamping.py +466 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_soql_loader.py +501 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_summarize_tree.py +241 -0
- package/skills/investigating-agentforce-architecture/scripts/tests/test_write_emit_ctx.py +480 -0
- package/skills/investigating-agentforce-architecture/tools/emit_env.py +157 -0
- package/skills/investigating-agentforce-architecture/tools/emit_result.py +262 -0
- package/skills/investigating-agentforce-architecture/tools/sanitize.py +33 -0
- package/skills/investigating-agentforce-architecture/tools/write_emit_ctx.py +332 -0
- package/skills/investigating-agentforce-d360/README.md +123 -0
- package/skills/investigating-agentforce-d360/SKILL.md +163 -0
- package/skills/investigating-agentforce-d360/assets/dc/app_generation.sql +51 -0
- package/skills/investigating-agentforce-d360/assets/dc/content_category.sql +44 -0
- package/skills/investigating-agentforce-d360/assets/dc/content_quality.sql +41 -0
- package/skills/investigating-agentforce-d360/assets/dc/discover_sessions.sql +36 -0
- package/skills/investigating-agentforce-d360/assets/dc/feedback.sql +47 -0
- package/skills/investigating-agentforce-d360/assets/dc/feedback_details.sql +38 -0
- package/skills/investigating-agentforce-d360/assets/dc/gateway_records.sql +45 -0
- package/skills/investigating-agentforce-d360/assets/dc/gateway_request_llm.sql +50 -0
- package/skills/investigating-agentforce-d360/assets/dc/gateway_request_metadata.sql +44 -0
- package/skills/investigating-agentforce-d360/assets/dc/gateway_request_tags.sql +42 -0
- package/skills/investigating-agentforce-d360/assets/dc/gateway_requests.sql +89 -0
- package/skills/investigating-agentforce-d360/assets/dc/gateway_responses.sql +43 -0
- package/skills/investigating-agentforce-d360/assets/dc/generations.sql +52 -0
- package/skills/investigating-agentforce-d360/assets/dc/interactions.sql +53 -0
- package/skills/investigating-agentforce-d360/assets/dc/messages.sql +53 -0
- package/skills/investigating-agentforce-d360/assets/dc/messaging_session.sql +37 -0
- package/skills/investigating-agentforce-d360/assets/dc/moment_interactions.sql +34 -0
- package/skills/investigating-agentforce-d360/assets/dc/moments.sql +39 -0
- package/skills/investigating-agentforce-d360/assets/dc/participants.sql +48 -0
- package/skills/investigating-agentforce-d360/assets/dc/sessions.sql +78 -0
- package/skills/investigating-agentforce-d360/assets/dc/steps.sql +64 -0
- package/skills/investigating-agentforce-d360/assets/dc/tag_associations.sql +46 -0
- package/skills/investigating-agentforce-d360/assets/dc/tag_definition_associations.sql +37 -0
- package/skills/investigating-agentforce-d360/assets/dc/tag_definitions.sql +50 -0
- package/skills/investigating-agentforce-d360/assets/dc/tags.sql +37 -0
- package/skills/investigating-agentforce-d360/assets/dc/telemetry_spans.sql +55 -0
- package/skills/investigating-agentforce-d360/references/artifacts.md +50 -0
- package/skills/investigating-agentforce-d360/references/dc_dmo_fields.md +823 -0
- package/skills/investigating-agentforce-d360/references/dc_pipeline_contract.md +608 -0
- package/skills/investigating-agentforce-d360/scripts/_shared/__init__.py +2 -0
- package/skills/investigating-agentforce-d360/scripts/_shared/cli_override.py +98 -0
- package/skills/investigating-agentforce-d360/scripts/_shared/fs_guard.py +334 -0
- package/skills/investigating-agentforce-d360/scripts/_shared/paths.py +155 -0
- package/skills/investigating-agentforce-d360/scripts/_shared/runtime.py +59 -0
- package/skills/investigating-agentforce-d360/scripts/_shared/sql.py +14 -0
- package/skills/investigating-agentforce-d360/scripts/assemble_dc.py +1624 -0
- package/skills/investigating-agentforce-d360/scripts/config.py +45 -0
- package/skills/investigating-agentforce-d360/scripts/dc.py +188 -0
- package/skills/investigating-agentforce-d360/scripts/discover_sessions.py +556 -0
- package/skills/investigating-agentforce-d360/scripts/fetch_dc.py +1045 -0
- package/skills/investigating-agentforce-d360/scripts/render_dc.py +1750 -0
- package/skills/investigating-agentforce-d360/scripts/resolve_session.py +264 -0
- package/skills/investigating-agentforce-d360/scripts/storage.py +92 -0
- package/skills/investigating-agentforce-d360/scripts/tests/__init__.py +0 -0
- package/skills/investigating-agentforce-d360/scripts/tests/_bootstrap.py +15 -0
- package/skills/investigating-agentforce-d360/scripts/tests/fixtures/__init__.py +0 -0
- package/skills/investigating-agentforce-d360/scripts/tests/fixtures/synthetic_session.py +424 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_assemble_dc_bootstrap_and_mode.py +115 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_assemble_dc_gateway_direct.py +220 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_assemble_dc_gateway_direct_integration.py +158 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_assemble_dc_helpers.py +287 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_assemble_dc_integration.py +247 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_dc_and_resolve_session.py +433 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_discover_sessions.py +458 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_discover_sessions_grep_ci.py +193 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_fetch_dc_helpers.py +266 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_fetch_dc_identity.py +528 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_fetch_dc_main.py +251 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_fetch_dc_waterfall.py +229 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_fetch_dc_waterfall_full.py +283 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_identity_coherence.py +327 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_render_dc_branches.py +256 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_render_dc_gateway_direct.py +130 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_render_dc_helpers.py +291 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_render_dc_integration.py +220 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_render_dc_planner_llm_calls.py +284 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_render_dc_show_prompts_gating.py +215 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_resolve_from_disk.py +100 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_resolve_session_main.py +149 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_runtime_override.py +104 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_session_shape.py +95 -0
- package/skills/investigating-agentforce-d360/scripts/tests/test_session_shape_dropped_by_stdm.py +85 -0
- package/skills/managing-managed-event-subscription/SKILL.md +152 -0
- package/skills/managing-managed-event-subscription/assets/managed-event-subscription-template.xml +20 -0
- package/skills/managing-managed-event-subscription/references/delete-guide.md +57 -0
- package/skills/managing-managed-event-subscription/references/topic-name-formats.md +26 -0
- package/skills/managing-managed-event-subscription/references/update-constraints.md +30 -0
- package/skills/modeling-omnistudio-epc-catalog/SKILL.md +0 -1
- package/skills/observing-agentforce/SKILL.md +0 -1
- package/skills/orchestrating-datacloud/SKILL.md +0 -1
- package/skills/preparing-datacloud/SKILL.md +0 -1
- package/skills/querying-soql/SKILL.md +0 -1
- package/skills/retrieving-datacloud/SKILL.md +0 -1
- package/skills/running-apex-tests/SKILL.md +0 -1
- package/skills/running-code-analyzer/SKILL.md +0 -1
- package/skills/segmenting-datacloud/SKILL.md +0 -1
- package/skills/testing-agentforce/SKILL.md +0 -1
- package/skills/uplifting-components-to-slds2/SKILL.md +3 -2
- package/skills/uplifting-components-to-slds2/references/color-hooks-decision-guide.md +30 -9
- package/skills/uplifting-components-to-slds2/references/examples.md +24 -6
- package/skills/validating-slds/SKILL.md +262 -0
- package/skills/validating-slds/references/quality-checks.md +308 -0
- package/skills/validating-slds/references/report-format.md +302 -0
- package/skills/validating-slds/scripts/analyze-quality.cjs +521 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"""Shared CLI override helper for d360 entry scripts.
|
|
2
|
+
|
|
3
|
+
D360 has 5 independent entry scripts (``fetch_dc.py``, ``assemble_dc.py``,
|
|
4
|
+
``render_dc.py``, ``resolve_session.py``, ``discover_sessions.py``) — each
|
|
5
|
+
needs the same ``--data-dir`` / ``--cache-dir`` flags and the same
|
|
6
|
+
3-level namespace rebind. This module factors that duplication into one
|
|
7
|
+
helper.
|
|
8
|
+
|
|
9
|
+
Usage in each entry script::
|
|
10
|
+
|
|
11
|
+
from _shared.cli_override import add_cli_flags, apply_overrides
|
|
12
|
+
|
|
13
|
+
parser = argparse.ArgumentParser(...)
|
|
14
|
+
parser.add_argument(...)
|
|
15
|
+
add_cli_flags(parser)
|
|
16
|
+
args = parser.parse_args()
|
|
17
|
+
apply_overrides(args, caller_globals=globals())
|
|
18
|
+
|
|
19
|
+
The ``caller_globals=globals()`` parameter is the magic that lets us
|
|
20
|
+
rebind the entry script's own ``DATA_ROOT`` / ``CACHE_ROOT`` snapshot —
|
|
21
|
+
without it, only ``paths.X`` and ``config.X`` would update, and the
|
|
22
|
+
entry script's local ``DATA_ROOT`` would still point at the default.
|
|
23
|
+
"""
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
import argparse
|
|
27
|
+
from pathlib import Path
|
|
28
|
+
|
|
29
|
+
_SKILL_NAME = "investigating-agentforce-d360"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def add_cli_flags(parser: argparse.ArgumentParser) -> None:
|
|
33
|
+
"""Add --data-dir / --cache-dir flags to the given parser.
|
|
34
|
+
|
|
35
|
+
Defaults are runtime-agnostic (``~/.vibe/...``); other
|
|
36
|
+
runtimes (AFV OOTB, Codex, Cursor, OpenCode) override at invocation
|
|
37
|
+
time.
|
|
38
|
+
"""
|
|
39
|
+
parser.add_argument(
|
|
40
|
+
"--data-dir",
|
|
41
|
+
type=Path,
|
|
42
|
+
default=None,
|
|
43
|
+
help=(
|
|
44
|
+
"Override data root (default: "
|
|
45
|
+
"~/.vibe/data/investigating-agentforce-d360)."
|
|
46
|
+
),
|
|
47
|
+
)
|
|
48
|
+
parser.add_argument(
|
|
49
|
+
"--cache-dir",
|
|
50
|
+
type=Path,
|
|
51
|
+
default=None,
|
|
52
|
+
help=(
|
|
53
|
+
"Override cache root (default: "
|
|
54
|
+
"~/.vibe/cache/investigating-agentforce-d360)."
|
|
55
|
+
),
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def apply_overrides(args: argparse.Namespace, caller_globals: dict) -> None:
|
|
60
|
+
"""Apply --data-dir / --cache-dir overrides across all 3 namespace levels.
|
|
61
|
+
|
|
62
|
+
Must be called BEFORE any pipeline code reads ``DATA_ROOT`` or
|
|
63
|
+
``CACHE_ROOT``.
|
|
64
|
+
|
|
65
|
+
Levels rebound:
|
|
66
|
+
1. ``paths.DATA_ROOT`` (the source of truth)
|
|
67
|
+
2. ``config.DATA_ROOT`` (the re-export)
|
|
68
|
+
3. The caller's own local ``DATA_ROOT`` (via ``caller_globals``)
|
|
69
|
+
|
|
70
|
+
Why 3 levels? Python's ``from X import Y`` snapshots ``Y`` into the
|
|
71
|
+
caller's local namespace at import time. Mutating ``X.Y`` later does
|
|
72
|
+
NOT update the caller's local binding. Without the 3rd-level rebind,
|
|
73
|
+
any function in the caller that references ``DATA_ROOT`` still sees
|
|
74
|
+
the default path even after ``paths.DATA_ROOT`` was overridden.
|
|
75
|
+
"""
|
|
76
|
+
if not (args.data_dir or args.cache_dir):
|
|
77
|
+
return
|
|
78
|
+
|
|
79
|
+
from _shared import runtime, paths
|
|
80
|
+
import config
|
|
81
|
+
|
|
82
|
+
if args.data_dir:
|
|
83
|
+
runtime.set_data_root_override(args.data_dir)
|
|
84
|
+
new_data = runtime.resolve_data_root(_SKILL_NAME)
|
|
85
|
+
paths.DATA_ROOT = new_data
|
|
86
|
+
config.DATA_ROOT = new_data
|
|
87
|
+
# Rebind caller's local snapshot, if it captured DATA_ROOT.
|
|
88
|
+
if "DATA_ROOT" in caller_globals:
|
|
89
|
+
caller_globals["DATA_ROOT"] = new_data
|
|
90
|
+
|
|
91
|
+
if args.cache_dir:
|
|
92
|
+
runtime.set_cache_root_override(args.cache_dir)
|
|
93
|
+
new_cache = runtime.resolve_cache_root(_SKILL_NAME)
|
|
94
|
+
paths.CACHE_ROOT = new_cache
|
|
95
|
+
if hasattr(config, "CACHE_ROOT"):
|
|
96
|
+
config.CACHE_ROOT = new_cache
|
|
97
|
+
if "CACHE_ROOT" in caller_globals:
|
|
98
|
+
caller_globals["CACHE_ROOT"] = new_cache
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
r"""Filesystem-safety and input-validation guard.
|
|
3
|
+
|
|
4
|
+
One script, six check types. Emits a STATUS=INVALID_INPUT RESULT block on
|
|
5
|
+
failure + tees to $ERROR_TEE on disk + exits 1.
|
|
6
|
+
|
|
7
|
+
Guiding principle: the agent MUST suffix every call with `|| exit 1` — Python
|
|
8
|
+
`sys.exit(1)` only terminates this subprocess, not the parent bash. A bare
|
|
9
|
+
call without `|| exit 1` silently continues past a failed guard, which is
|
|
10
|
+
the worst possible failure mode for a security check.
|
|
11
|
+
|
|
12
|
+
Check types:
|
|
13
|
+
symlink — path must NOT be a symlink (rejects pre-planted attacker bait)
|
|
14
|
+
owned — path must be owned by current UID (rejects foreign-owned dirs)
|
|
15
|
+
uuid — value must match ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$
|
|
16
|
+
org_id_15 — value must match ^[A-Za-z0-9]{15}$ (Salesforce org ID slice)
|
|
17
|
+
api_name — value must match ^[A-Za-z0-9_]+$ (Salesforce API identifier)
|
|
18
|
+
api_version — value must match ^v[0-9]+\.[0-9]+$ (e.g. v60.0)
|
|
19
|
+
agent_version — value must match ^v[0-9]+$ (e.g. v5 — Agentforce agent version, no dot-minor)
|
|
20
|
+
not_empty — value must be non-empty string
|
|
21
|
+
|
|
22
|
+
Python-importable API:
|
|
23
|
+
validate_api_name(value, label="...") — raises ValidationError on bad input
|
|
24
|
+
validate_api_version(value, label="...") — raises ValidationError on bad input
|
|
25
|
+
validate_agent_version(value, label="...") — raises ValidationError on bad input
|
|
26
|
+
validate_org_id_15(value, label="...") — raises ValidationError on bad input
|
|
27
|
+
ValidationError — carries (label, reason)
|
|
28
|
+
|
|
29
|
+
The Python API is used by in-process callers (SOQL loader, path builders in
|
|
30
|
+
config.py) that need a raise-based boundary rather than the process-exit
|
|
31
|
+
CLI behavior. Regex is shared — do NOT duplicate API_NAME_RE / API_VERSION_RE.
|
|
32
|
+
|
|
33
|
+
Usage:
|
|
34
|
+
python3 fs_guard.py <value> <label> <check> || exit 1
|
|
35
|
+
|
|
36
|
+
# Input validation
|
|
37
|
+
python3 fs_guard.py "$AGENT_API_NAME" agent_api_name api_name || exit 1
|
|
38
|
+
python3 fs_guard.py "$ORG_ALIAS" org_alias not_empty || exit 1
|
|
39
|
+
|
|
40
|
+
# Filesystem safety
|
|
41
|
+
python3 fs_guard.py "$WORK_DIR" WORK_DIR symlink || exit 1
|
|
42
|
+
python3 fs_guard.py "$WORK_DIR" WORK_DIR owned || exit 1
|
|
43
|
+
python3 fs_guard.py "$ORG_ID_15" ORG_ID_15 org_id_15 || exit 1
|
|
44
|
+
|
|
45
|
+
Inputs:
|
|
46
|
+
argv[1] value or path to check
|
|
47
|
+
argv[2] label (appears in ERROR_DETAIL; used to identify which guard tripped)
|
|
48
|
+
argv[3] check type (one of the 6 above)
|
|
49
|
+
env $ERROR_TEE (optional): path to disk-tee file. Defaults to
|
|
50
|
+
$HOME/.vibe/data/investigating-agentforce-d360/_last_error_result.txt.
|
|
51
|
+
Also reads $AGENT_API_NAME / $ORG_ID_18 / $ORG_ID_15 for
|
|
52
|
+
RESULT-block context if set.
|
|
53
|
+
|
|
54
|
+
Outputs:
|
|
55
|
+
on failure: STATUS=INVALID_INPUT RESULT block on stdout + tee to disk, exit 1
|
|
56
|
+
on success: silent, exit 0
|
|
57
|
+
on bad argv: exit 1 with a minimal ERROR_DETAIL ("fs_guard internal: ...")
|
|
58
|
+
"""
|
|
59
|
+
import os
|
|
60
|
+
import pathlib
|
|
61
|
+
import re
|
|
62
|
+
import sys
|
|
63
|
+
|
|
64
|
+
# Anchored \A...\Z (not ^...$) — Python's `$` matches before a trailing
|
|
65
|
+
# newline, so "00DTESTORG12345\n" passes ^...$ + .match(). Every call
|
|
66
|
+
# site below MUST use .fullmatch() for the same reason; .match() is
|
|
67
|
+
# unsafe even with \A...\Z anchors. Mirrors the pattern in
|
|
68
|
+
# _shared/paths.py SESSION_ID_RE.
|
|
69
|
+
UUID_RE = re.compile(r"\A[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\Z") # @rule-suppress starter-sec-002 — re.compile, not eval/exec
|
|
70
|
+
ORG_ID_15_RE = re.compile(r"\A[A-Za-z0-9]{15}\Z") # @rule-suppress starter-sec-002 — re.compile, not eval/exec
|
|
71
|
+
API_NAME_RE = re.compile(r"\A[A-Za-z0-9_]+\Z") # @rule-suppress starter-sec-002 — re.compile, not eval/exec
|
|
72
|
+
# P0-5: api_version check — matches `v60.0`, `v66.0`, etc. Used before any
|
|
73
|
+
# Path composition that embeds the api_version segment.
|
|
74
|
+
API_VERSION_RE = re.compile(r"\Av[0-9]+\.[0-9]+\Z") # @rule-suppress starter-sec-002 — re.compile, not eval/exec
|
|
75
|
+
# Agent-version check — matches Agentforce version identifiers (`v1`, `v5`,
|
|
76
|
+
# `v12`). Deliberately stricter than api_name (rejects free-form names like
|
|
77
|
+
# `release_1`) and looser than api_version (rejects `v66.0` which is a REST
|
|
78
|
+
# API version, never an agent version). Lives on its own so callers that
|
|
79
|
+
# embed agent_version in a filesystem path get the tight regex, not the
|
|
80
|
+
# permissive api_name fallback.
|
|
81
|
+
AGENT_VERSION_RE = re.compile(r"\Av[0-9]+\Z") # @rule-suppress starter-sec-002 — re.compile, not eval/exec
|
|
82
|
+
VALID_CHECKS = {"symlink", "owned", "uuid", "org_id_15", "api_name", "api_version", "agent_version", "not_empty"}
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
# -----------------------------------------------------------------------------
|
|
86
|
+
# Python-importable API (P0-1, P0-5)
|
|
87
|
+
# -----------------------------------------------------------------------------
|
|
88
|
+
# In-process callers (soql_loader.load_soql, config.build_*_dir) need a
|
|
89
|
+
# raise-based validation boundary, distinct from the CLI script's exit-1
|
|
90
|
+
# behavior. The regexes are shared with the CLI checks above — do NOT
|
|
91
|
+
# duplicate. If a regex changes, both surfaces update in lockstep.
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class ValidationError(ValueError):
|
|
95
|
+
"""Raised by the Python-importable validators on bad input.
|
|
96
|
+
|
|
97
|
+
Carries the label (which field failed) + reason. Callers (e.g.
|
|
98
|
+
soql_loader.load_soql) convert this into `_unresolved[]` entries or
|
|
99
|
+
RESULT-level INVALID_INPUT responses as appropriate.
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
def __init__(self, label: str, reason: str) -> None:
|
|
103
|
+
self.label = label
|
|
104
|
+
self.reason = reason
|
|
105
|
+
super().__init__(f"{label}: {reason}")
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def validate_api_name(value, label: str = "value") -> None:
|
|
109
|
+
"""Validate `value` against ^[A-Za-z0-9_]+$ (Salesforce API identifier).
|
|
110
|
+
|
|
111
|
+
P0-1: used by soql_loader.load_soql at the substitution boundary to catch
|
|
112
|
+
injection attempts in names pulled from Bot XML, Flow.Metadata, ApexClass
|
|
113
|
+
SymbolTable, etc.
|
|
114
|
+
|
|
115
|
+
P0-5: used by config.build_*_dir helpers for path components that must
|
|
116
|
+
not contain `..`, `/`, or other traversal characters.
|
|
117
|
+
|
|
118
|
+
Raises ValidationError on any of: None, non-string, empty, regex miss.
|
|
119
|
+
"""
|
|
120
|
+
if value is None:
|
|
121
|
+
raise ValidationError(label, "is None")
|
|
122
|
+
if not isinstance(value, str):
|
|
123
|
+
raise ValidationError(label, f"must be str, got {type(value).__name__}")
|
|
124
|
+
if not value:
|
|
125
|
+
raise ValidationError(label, "must not be empty")
|
|
126
|
+
if not API_NAME_RE.fullmatch(value):
|
|
127
|
+
# Preview first 20 chars so logs/_unresolved entries carry enough
|
|
128
|
+
# context to debug, without dumping an unbounded attacker-controlled
|
|
129
|
+
# string into output.
|
|
130
|
+
preview = value[:20]
|
|
131
|
+
raise ValidationError(
|
|
132
|
+
label,
|
|
133
|
+
f"does not match [A-Za-z0-9_]+ (preview={preview!r})",
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def validate_api_version(value, label: str = "api_version") -> None:
|
|
138
|
+
"""Validate `value` against ^v[0-9]+\\.[0-9]+$ (Salesforce API version).
|
|
139
|
+
|
|
140
|
+
P0-5: used by config.build_*_dir helpers. api_version is returned by
|
|
141
|
+
`sf org display` and later embedded in cache paths; reject anything that
|
|
142
|
+
could escape the cache subtree.
|
|
143
|
+
"""
|
|
144
|
+
if value is None:
|
|
145
|
+
raise ValidationError(label, "is None")
|
|
146
|
+
if not isinstance(value, str):
|
|
147
|
+
raise ValidationError(label, f"must be str, got {type(value).__name__}")
|
|
148
|
+
if not value:
|
|
149
|
+
raise ValidationError(label, "must not be empty")
|
|
150
|
+
if not API_VERSION_RE.fullmatch(value):
|
|
151
|
+
preview = value[:20]
|
|
152
|
+
raise ValidationError(
|
|
153
|
+
label,
|
|
154
|
+
f"does not match v<major>.<minor> (preview={preview!r})",
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def validate_agent_version(value, label: str = "agent_version") -> None:
|
|
159
|
+
"""Validate `value` against ^v[0-9]+$ (Agentforce agent version).
|
|
160
|
+
|
|
161
|
+
Strictly `v<digits>` with no dot-minor — matches the shape Agentforce
|
|
162
|
+
actually uses (`v1`, `v5`, `v12`). Rejects `release_1`, `v66.0`, `FOO`,
|
|
163
|
+
and anything else that could silently slip past a permissive api_name
|
|
164
|
+
check and land in a filesystem path.
|
|
165
|
+
|
|
166
|
+
P0-5: used by path-builder helpers for the agent_version segment.
|
|
167
|
+
"""
|
|
168
|
+
if value is None:
|
|
169
|
+
raise ValidationError(label, "is None")
|
|
170
|
+
if not isinstance(value, str):
|
|
171
|
+
raise ValidationError(label, f"must be str, got {type(value).__name__}")
|
|
172
|
+
if not value:
|
|
173
|
+
raise ValidationError(label, "must not be empty")
|
|
174
|
+
if not AGENT_VERSION_RE.fullmatch(value):
|
|
175
|
+
preview = value[:20]
|
|
176
|
+
raise ValidationError(
|
|
177
|
+
label,
|
|
178
|
+
f"does not match v<digits> (preview={preview!r})",
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def validate_org_id_15(value, label: str = "org_id_15") -> None:
|
|
183
|
+
"""Validate `value` against ^[A-Za-z0-9]{15}$ (Salesforce 15-char org ID).
|
|
184
|
+
|
|
185
|
+
P0-5: stricter than validate_api_name — enforces exact 15 chars AND
|
|
186
|
+
no underscores. `org_id_15` always comes from a Salesforce-generated
|
|
187
|
+
field, never from free-form input.
|
|
188
|
+
"""
|
|
189
|
+
if value is None:
|
|
190
|
+
raise ValidationError(label, "is None")
|
|
191
|
+
if not isinstance(value, str):
|
|
192
|
+
raise ValidationError(label, f"must be str, got {type(value).__name__}")
|
|
193
|
+
if not value:
|
|
194
|
+
raise ValidationError(label, "must not be empty")
|
|
195
|
+
if not ORG_ID_15_RE.fullmatch(value):
|
|
196
|
+
preview = value[:20]
|
|
197
|
+
raise ValidationError(
|
|
198
|
+
label,
|
|
199
|
+
f"must be exactly 15 alphanumeric chars (preview={preview!r})",
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def scrub(s: str) -> str:
|
|
204
|
+
# Same rules as sanitize.py; duplicated locally so this script has no
|
|
205
|
+
# intra-skill imports. Keeps the agent-script boundary clean.
|
|
206
|
+
bad = set("`$\"\\\r\t\0\n")
|
|
207
|
+
return "".join(c for c in (s or "") if c not in bad)
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def emit_failure(reason: str, label: str) -> None:
|
|
211
|
+
agent_api_name = scrub(os.environ.get("AGENT_API_NAME", ""))
|
|
212
|
+
org_id_18 = scrub(os.environ.get("ORG_ID_18", ""))
|
|
213
|
+
org_id_15 = scrub(os.environ.get("ORG_ID_15", ""))
|
|
214
|
+
label_safe = scrub(label)
|
|
215
|
+
reason_safe = scrub(reason)
|
|
216
|
+
|
|
217
|
+
block = (
|
|
218
|
+
"=== RESULT ===\n"
|
|
219
|
+
"STATUS=INVALID_INPUT\n"
|
|
220
|
+
f"ERROR_DETAIL={label_safe}: {reason_safe}\n"
|
|
221
|
+
f"AGENT_API_NAME={agent_api_name}\n"
|
|
222
|
+
f"ORG_ID_18={org_id_18}\n"
|
|
223
|
+
f"ORG_ID_15={org_id_15}\n"
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
# Default ERROR_TEE lives under the skill-scoped data root. Runtime-agnostic
|
|
227
|
+
# default mirrors runtime.resolve_data_root() in the sibling runtime module
|
|
228
|
+
# (duplicated rather than imported because fs_guard.py is also invoked
|
|
229
|
+
# standalone from SKILL.md bash, where the override hook isn't active).
|
|
230
|
+
tee_default = str(
|
|
231
|
+
pathlib.Path.home()
|
|
232
|
+
/ ".vibe"
|
|
233
|
+
/ "data"
|
|
234
|
+
/ "investigating-agentforce-d360"
|
|
235
|
+
/ "_last_error_result.txt"
|
|
236
|
+
)
|
|
237
|
+
tee_path = os.environ.get("ERROR_TEE") or tee_default
|
|
238
|
+
try:
|
|
239
|
+
p = pathlib.Path(tee_path)
|
|
240
|
+
p.parent.mkdir(parents=True, exist_ok=True)
|
|
241
|
+
p.write_text(block)
|
|
242
|
+
except OSError:
|
|
243
|
+
pass
|
|
244
|
+
|
|
245
|
+
sys.stdout.write(block)
|
|
246
|
+
sys.exit(1)
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
def check_symlink(value: str, label: str) -> None:
|
|
250
|
+
if pathlib.Path(value).is_symlink():
|
|
251
|
+
emit_failure(f"path is a symlink (refusing to follow): {value}", label)
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def check_owned(value: str, label: str) -> None:
|
|
255
|
+
p = pathlib.Path(value)
|
|
256
|
+
if not p.exists():
|
|
257
|
+
return
|
|
258
|
+
try:
|
|
259
|
+
st = p.stat()
|
|
260
|
+
except OSError as e:
|
|
261
|
+
emit_failure(f"stat failed: {e}", label)
|
|
262
|
+
return
|
|
263
|
+
if st.st_uid != os.getuid():
|
|
264
|
+
emit_failure(f"foreign-owned (uid {st.st_uid} != current {os.getuid()}): {value}", label)
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
def check_uuid(value: str, label: str) -> None:
|
|
268
|
+
if not UUID_RE.fullmatch(value):
|
|
269
|
+
emit_failure("does not match UUID pattern (8-4-4-4-12 lowercase hex)", label)
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
def check_org_id_15(value: str, label: str) -> None:
|
|
273
|
+
if not ORG_ID_15_RE.fullmatch(value):
|
|
274
|
+
emit_failure("must be exactly 15 alphanumeric characters", label)
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
def check_api_name(value: str, label: str) -> None:
|
|
278
|
+
if not API_NAME_RE.fullmatch(value):
|
|
279
|
+
emit_failure("does not match [A-Za-z0-9_]+ (Salesforce API name rules)", label)
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
def check_api_version(value: str, label: str) -> None:
|
|
283
|
+
# P0-5: api_version must be `vNN.N` — no slashes, no dots beyond the one,
|
|
284
|
+
# no path-traversal sequences.
|
|
285
|
+
if not API_VERSION_RE.fullmatch(value):
|
|
286
|
+
emit_failure("does not match v<major>.<minor> (e.g. v60.0)", label)
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
def check_agent_version(value: str, label: str) -> None:
|
|
290
|
+
# Agent version must be `v<digits>` — no dots, no slashes.
|
|
291
|
+
if not AGENT_VERSION_RE.fullmatch(value):
|
|
292
|
+
emit_failure("does not match v<digits> (e.g. v5)", label)
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
def check_not_empty(value: str, label: str) -> None:
|
|
296
|
+
if not value:
|
|
297
|
+
emit_failure("must not be empty", label)
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
CHECKS = {
|
|
301
|
+
"symlink": check_symlink,
|
|
302
|
+
"owned": check_owned,
|
|
303
|
+
"uuid": check_uuid,
|
|
304
|
+
"org_id_15": check_org_id_15,
|
|
305
|
+
"api_name": check_api_name,
|
|
306
|
+
"api_version": check_api_version,
|
|
307
|
+
"agent_version": check_agent_version,
|
|
308
|
+
"not_empty": check_not_empty,
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
def main() -> int:
|
|
313
|
+
if len(sys.argv) != 4:
|
|
314
|
+
sys.stdout.write(
|
|
315
|
+
"=== RESULT ===\n"
|
|
316
|
+
"STATUS=INVALID_INPUT\n"
|
|
317
|
+
"ERROR_DETAIL=fs_guard internal: wrong argv count (need value, label, check)\n"
|
|
318
|
+
)
|
|
319
|
+
return 1
|
|
320
|
+
value, label, check = sys.argv[1], sys.argv[2], sys.argv[3]
|
|
321
|
+
|
|
322
|
+
for arg in (value, label, check):
|
|
323
|
+
if any(c == "\0" or (ord(c) < 0x20 and c not in "\t\n") for c in arg):
|
|
324
|
+
emit_failure("argv contains control characters", label or "argv")
|
|
325
|
+
|
|
326
|
+
if check not in VALID_CHECKS:
|
|
327
|
+
emit_failure(f"unknown check type '{check}' (valid: {', '.join(sorted(VALID_CHECKS))})", label)
|
|
328
|
+
|
|
329
|
+
CHECKS[check](value, label)
|
|
330
|
+
return 0
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
if __name__ == "__main__":
|
|
334
|
+
sys.exit(main())
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"""Canonical path helpers for investigating-agentforce-d360.
|
|
2
|
+
|
|
3
|
+
Layout:
|
|
4
|
+
|
|
5
|
+
~/.vibe/data/investigating-agentforce-d360/
|
|
6
|
+
└── <org_id_15>/
|
|
7
|
+
└── <agent_api_name>__<agent_version>/
|
|
8
|
+
└── <session_id>/ ← per-session DC artifacts
|
|
9
|
+
├── dc.*.json
|
|
10
|
+
├── dc._session_manifest.json
|
|
11
|
+
├── dc._session_tree.json
|
|
12
|
+
└── dc._session_summary.md
|
|
13
|
+
|
|
14
|
+
Validation strategy
|
|
15
|
+
-------------------
|
|
16
|
+
The three "agent-identity" segments (org_id_15, agent_api_name, agent_version)
|
|
17
|
+
are validated by the regex helpers in the sibling ``fs_guard`` module. Any
|
|
18
|
+
segment containing ``..``, ``/``, or characters outside its regex charclass
|
|
19
|
+
raises ``PathValidationError`` — direct ``Path`` composition from unvalidated
|
|
20
|
+
input would be a path-traversal vulnerability and is prohibited.
|
|
21
|
+
|
|
22
|
+
``session_id`` is validated locally via ``SESSION_ID_RE.fullmatch`` because
|
|
23
|
+
fs_guard's ``api_name`` rule is too permissive for it (session IDs can contain
|
|
24
|
+
hyphens, which API names cannot). The regex is fully anchored (``\\A...\\Z``)
|
|
25
|
+
and call sites MUST use ``fullmatch`` — ``match`` would silently accept a
|
|
26
|
+
traversal suffix like ``abc\\n../etc``.
|
|
27
|
+
"""
|
|
28
|
+
from __future__ import annotations
|
|
29
|
+
|
|
30
|
+
import re
|
|
31
|
+
from pathlib import Path
|
|
32
|
+
|
|
33
|
+
from . import fs_guard
|
|
34
|
+
from . import runtime
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# -----------------------------------------------------------------------------
|
|
38
|
+
# Roots
|
|
39
|
+
# -----------------------------------------------------------------------------
|
|
40
|
+
# Runtime-agnostic defaults, overridable via --data-dir / --cache-dir
|
|
41
|
+
# CLI flags on every entry script (fetch_dc, assemble_dc, render_dc,
|
|
42
|
+
# resolve_session, discover_sessions). See runtime.py for details.
|
|
43
|
+
|
|
44
|
+
DATA_ROOT: Path = runtime.resolve_data_root("investigating-agentforce-d360")
|
|
45
|
+
CACHE_ROOT: Path = runtime.resolve_cache_root("investigating-agentforce-d360")
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
# -----------------------------------------------------------------------------
|
|
49
|
+
# Session-ID validation
|
|
50
|
+
# -----------------------------------------------------------------------------
|
|
51
|
+
|
|
52
|
+
# Fully anchored — call sites MUST use fullmatch (tested). Characters allowed:
|
|
53
|
+
# alphanumeric + underscore + hyphen, matching both UUIDs and MessagingSession
|
|
54
|
+
# IDs.
|
|
55
|
+
SESSION_ID_RE = re.compile(r"\A[A-Za-z0-9_\-]+\Z") # @rule-suppress starter-sec-002 — re.compile, not eval/exec
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class PathValidationError(ValueError):
|
|
59
|
+
"""Raised when a path segment fails validation.
|
|
60
|
+
|
|
61
|
+
Wraps fs_guard's ``ValidationError`` as well as local ``session_id``
|
|
62
|
+
rejections so callers have a single exception type to catch.
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
def __init__(self, label: str, reason: str) -> None:
|
|
66
|
+
self.label = label
|
|
67
|
+
self.reason = reason
|
|
68
|
+
super().__init__(f"{label}: {reason}")
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
# -----------------------------------------------------------------------------
|
|
72
|
+
# Validation helpers
|
|
73
|
+
# -----------------------------------------------------------------------------
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def _validate_agent_triple(
|
|
77
|
+
org_id_15: str, agent_api_name: str, agent_version: str
|
|
78
|
+
) -> None:
|
|
79
|
+
"""Validate the three identity segments. Raises PathValidationError on
|
|
80
|
+
failure, wrapping fs_guard's ValidationError so callers don't need to
|
|
81
|
+
know about fs_guard internals."""
|
|
82
|
+
try:
|
|
83
|
+
fs_guard.validate_org_id_15(org_id_15, label="org_id_15")
|
|
84
|
+
fs_guard.validate_api_name(agent_api_name, label="agent_api_name")
|
|
85
|
+
fs_guard.validate_agent_version(agent_version, label="agent_version")
|
|
86
|
+
except fs_guard.ValidationError as e:
|
|
87
|
+
raise PathValidationError(e.label, e.reason) from e
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def validate_session_id(session_id: str) -> None:
|
|
91
|
+
"""Validate session_id via SESSION_ID_RE.fullmatch.
|
|
92
|
+
|
|
93
|
+
Raises :class:`PathValidationError` on any of: None, non-string, empty,
|
|
94
|
+
regex miss. This is the public validator every caller that composes a
|
|
95
|
+
Path segment from a session-id MUST go through — direct
|
|
96
|
+
``Path / session_id`` composition bypasses the anchored-regex check.
|
|
97
|
+
"""
|
|
98
|
+
if session_id is None:
|
|
99
|
+
raise PathValidationError("session_id", "is None")
|
|
100
|
+
if not isinstance(session_id, str):
|
|
101
|
+
raise PathValidationError(
|
|
102
|
+
"session_id", f"must be str, got {type(session_id).__name__}"
|
|
103
|
+
)
|
|
104
|
+
if not session_id:
|
|
105
|
+
raise PathValidationError("session_id", "must not be empty")
|
|
106
|
+
if not SESSION_ID_RE.fullmatch(session_id):
|
|
107
|
+
preview = session_id[:40]
|
|
108
|
+
raise PathValidationError(
|
|
109
|
+
"session_id",
|
|
110
|
+
f"does not match {SESSION_ID_RE.pattern} (preview={preview!r})",
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
_validate_session_id = validate_session_id # backward-compat alias
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
# -----------------------------------------------------------------------------
|
|
118
|
+
# Path builders
|
|
119
|
+
# -----------------------------------------------------------------------------
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def agent_dir(
|
|
123
|
+
org_id_15: str, agent_api_name: str, agent_version: str
|
|
124
|
+
) -> Path:
|
|
125
|
+
"""Return ``DATA_ROOT/<org_id_15>/<agent_api_name>__<agent_version>/``.
|
|
126
|
+
|
|
127
|
+
All three segments are regex-validated before being joined. Any segment
|
|
128
|
+
containing ``..``, ``/``, or characters outside its regex charclass
|
|
129
|
+
raises ``PathValidationError``.
|
|
130
|
+
"""
|
|
131
|
+
_validate_agent_triple(org_id_15, agent_api_name, agent_version)
|
|
132
|
+
return DATA_ROOT / org_id_15 / f"{agent_api_name}__{agent_version}"
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def session_dir(
|
|
136
|
+
org_id_15: str,
|
|
137
|
+
agent_api_name: str,
|
|
138
|
+
agent_version: str,
|
|
139
|
+
session_id: str,
|
|
140
|
+
) -> Path:
|
|
141
|
+
"""Return
|
|
142
|
+
``DATA_ROOT/<org_id_15>/<agent_api_name>__<agent_version>/<session_id>/``.
|
|
143
|
+
|
|
144
|
+
All four segments are validated. The first three go through fs_guard;
|
|
145
|
+
``session_id`` goes through ``SESSION_ID_RE.fullmatch``. Any rejection
|
|
146
|
+
raises ``PathValidationError``.
|
|
147
|
+
"""
|
|
148
|
+
_validate_agent_triple(org_id_15, agent_api_name, agent_version)
|
|
149
|
+
validate_session_id(session_id)
|
|
150
|
+
return (
|
|
151
|
+
DATA_ROOT
|
|
152
|
+
/ org_id_15
|
|
153
|
+
/ f"{agent_api_name}__{agent_version}"
|
|
154
|
+
/ session_id
|
|
155
|
+
)
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"""Runtime override hook for DATA_ROOT / CACHE_ROOT.
|
|
2
|
+
|
|
3
|
+
Default layout is ``~/.vibe/data/<skill>`` and
|
|
4
|
+
``~/.vibe/cache/<skill>`` — runtime-agnostic branding that
|
|
5
|
+
follows the repo's "tool-agnostic language" guideline.
|
|
6
|
+
|
|
7
|
+
Other runtimes (AFV OOTB, Codex, Cursor, OpenCode) can override via
|
|
8
|
+
``--data-dir`` / ``--cache-dir`` CLI flags on entry scripts. Those flags
|
|
9
|
+
call ``set_*_override()`` BEFORE any pipeline module imports ``paths.py``,
|
|
10
|
+
so the resolution helpers below pick up the override.
|
|
11
|
+
|
|
12
|
+
Three-level rebind contract
|
|
13
|
+
---------------------------
|
|
14
|
+
Python's ``from X import Y`` snapshots ``Y`` into the importer's local
|
|
15
|
+
namespace. Mutating ``X.Y`` later does NOT update the importer's local
|
|
16
|
+
binding. Entry scripts that capture ``DATA_ROOT`` / ``CACHE_ROOT`` at
|
|
17
|
+
module top must therefore rebind in THREE places after override:
|
|
18
|
+
|
|
19
|
+
1. ``paths.DATA_ROOT`` — the source of truth
|
|
20
|
+
2. ``config.DATA_ROOT`` — the re-export
|
|
21
|
+
3. The entry script's own local ``DATA_ROOT`` (via ``global``)
|
|
22
|
+
"""
|
|
23
|
+
from __future__ import annotations
|
|
24
|
+
|
|
25
|
+
from pathlib import Path
|
|
26
|
+
from typing import Optional
|
|
27
|
+
|
|
28
|
+
_DATA_OVERRIDE: Optional[Path] = None
|
|
29
|
+
_CACHE_OVERRIDE: Optional[Path] = None
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def set_data_root_override(p: Optional[Path]) -> None:
|
|
33
|
+
"""Set the data-root override. Pass ``None`` to clear."""
|
|
34
|
+
global _DATA_OVERRIDE
|
|
35
|
+
_DATA_OVERRIDE = p
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def set_cache_root_override(p: Optional[Path]) -> None:
|
|
39
|
+
"""Set the cache-root override. Pass ``None`` to clear."""
|
|
40
|
+
global _CACHE_OVERRIDE
|
|
41
|
+
_CACHE_OVERRIDE = p
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def resolve_data_root(skill_name: str) -> Path:
|
|
45
|
+
"""Resolve the data root for ``skill_name``.
|
|
46
|
+
|
|
47
|
+
Returns the override if set, else the runtime-agnostic default
|
|
48
|
+
``~/.vibe/data/<skill_name>``.
|
|
49
|
+
"""
|
|
50
|
+
return _DATA_OVERRIDE or (Path.home() / ".vibe" / "data" / skill_name)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def resolve_cache_root(skill_name: str) -> Path:
|
|
54
|
+
"""Resolve the cache root for ``skill_name``.
|
|
55
|
+
|
|
56
|
+
Returns the override if set, else the runtime-agnostic default
|
|
57
|
+
``~/.vibe/cache/<skill_name>``.
|
|
58
|
+
"""
|
|
59
|
+
return _CACHE_OVERRIDE or (Path.home() / ".vibe" / "cache" / skill_name)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""Canonical SQL-escaping helpers for investigating-agentforce-d360.
|
|
2
|
+
|
|
3
|
+
Single source of truth for DC-SQL string-literal escaping. Behavioral contract
|
|
4
|
+
is fixed — do not change the escape strategy without updating every caller and
|
|
5
|
+
its tests.
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def _escape_sql_literal(s: str) -> str:
|
|
11
|
+
"""Double single quotes per DC SQL escaping rule. Handles O'Brien →
|
|
12
|
+
O''Brien, `'; DROP --` → `''; DROP --` (still harmless because it's
|
|
13
|
+
wrapped in surrounding single quotes)."""
|
|
14
|
+
return s.replace("'", "''")
|