Skip to main content

foundry-extension-scenario-authoring

**WORKFLOW SKILL** — Authors and validates cli-interactive-tester scenarios for the azure.ai.agents extension: writes a new scenario YAML (or fixes an existing one) so it follows the tier/tag/hook/fixtures/requires conventions and goals-are-the-contract judging rules, then lint-validates it via list_scenarios (never start_session — no Azure cost). Typically driven through the foundry-extension-scenario-author agent. USE FOR: write a new scenario, add coverage for a command/flag, fix a scenario's tags/hooks/requires, add a fixture, close a coverage gap flagged by a PR regression run. DO NOT USE FOR: RUNNING scenarios or a suite — never drives a scenario or incurs Azure cost (use foundry-extension-scenario-suite-run for a sweep, or foundry-extension-scenario-pr-regression for a PR), driving a single scenario (foundry-extension-scenario-worker), azd core preflight (azd-preflight), changelog (changelog-generation), creating PRs (pull-request), scenarios for other extensions.

معلومات المصدر

المستودع
Azure/azure-dev
آخر نشاط في المصدر
٢٥ سبتمبر ٢٠٢٦ في ١٧:١٧
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٥٧٠
التفرعات
٣٦٧

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
foundry-extension-scenario-authoring
license
MIT
metadata
{"version":"1.4"}
description
**WORKFLOW SKILL** — Authors and validates cli-interactive-tester scenarios for the azure.ai.agents extension: writes a new scenario YAML (or fixes an existing one) so it follows the tier/tag/hook/fixtures/requires conventions and goals-are-the-contract judging rules, then lint-validates it via list_scenarios (never start_session — no Azure cost). Typically driven through the foundry-extension-scenario-author agent. USE FOR: write a new scenario, add coverage for a command/flag, fix a scenario's tags/hooks/requires, add a fixture, close a coverage gap flagged by a PR regression run. DO NOT USE FOR: RUNNING scenarios or a suite — never drives a scenario or incurs Azure cost (use foundry-extension-scenario-suite-run for a sweep, or foundry-extension-scenario-pr-regression for a PR), driving a single scenario (foundry-extension-scenario-worker), azd core preflight (azd-preflight), changelog (changelog-generation), creating PRs (pull-request), scenarios for other extensions.
# foundry-extension-scenario-authoring Authors and validates goal-based **scenarios** for the `azure.ai.agents` [cli-interactive-tester](https://github.com/coreai-microsoft/cli-interactive-tester) suite under `cli/azd/extensions/azure.ai.agents/tests/cli-interactive-tester-scenarios/`. This skill **writes and lints** scenarios; it never **runs** them (running is `foundry-extension-scenario-suite-run` / `foundry-extension-scenario-pr-regression`, driven by the `foundry-extension-scenario-worker` agent, and incurs Azure cost for Tier 1b / Tier 2). **Tools invoked**: the cli-interactive-tester MCP `list_scenarios` tool (for tag/lint validation only — never `start_session`, which would incur Azure cost), read/edit of scenario YAML files, and `ask_user`. ## The authoring contract (read this first) A scenario's `goals:` are its **contract**: a run PASSES only when the product's real behavior matches what the goals literally describe. So the whole point of authoring is to write goals that are a *verifiable spec of correct behavior* — not a loose description the driver has to interpret charitably. The judging rules are single-sourced in the scenarios README: [**How scenarios are judged (authoring contract)**](../../../cli/azd/extensions/azure.ai.agents/tests/cli-interactive-tester-scenarios/README.md#how-scenarios-are-judged-authoring-contract). The consequences for how you write goals: - **Write goals as literal, checkable assertions.** "Confirm the process exits cleanly and prints a version string" is checkable; "make sure version works" is not. A driver will FAIL a scenario whose goals aren't met — it will not rationalize a near-miss into a pass. - **Never encode a workaround in a goal.** If a goal names a flag/command that doesn't exist or expects output that never appears, the scenario FAILS by design. Keep goals current with the product; don't paper over a bug in the goal text. - **Key interactive pickers off stable text labels, not positions.** The driver prefers `choice_text` over `choice_index`, so phrase picker goals around the label (e.g. *select "Use the code in the current directory"*) — indices shift between releases. - **Enumerate expected product prompts.** Goals define every product prompt allowed during the scenario. Name each prompt with stable user-visible text and state the response. Use "if asked" only for a genuinely optional prompt. Never write "follow the prompts" or another catch-all; an unlisted product prompt must fail the scenario. - **Give every executed invoke explicit input.** Write the literal command with a quoted positional message. Use `--input-file` only when file input is what the scenario tests, and define the file contents first. Never leave command construction to the worker with wording such as "run invoke and send a simple message"; bare invoke does not prompt for a message. - **Guard pre-filled prompts.** When a prompt comes pre-populated (e.g. the agent name), the goal must tell the driver to **clear the field first** before typing, or the typed value appends to the default. See the RESOURCE NAMING / AGENT NAME goals in `tier1/1.04-init-from-code.yaml` for the canonical phrasing. - **Gate cost explicitly.** Any goal that reaches `azd provision` / real resource creation belongs in Tier 1b or Tier 2 and must be tagged and tiered accordingly (see below). > The deeper *why* behind the picker / clear-field / no-retry rules is the executor spec > [`driving-mechanics.md`](../../../cli/azd/extensions/azure.ai.agents/tests/cli-interactive-tester-scenarios/driving-mechanics.md). > You don't need to restate it — just author goals that hold under it. ## Scenario anatomy One file targets **one** command or flow. The taxonomy behind each field is single-sourced in the README — this is the annotated skeleton; follow the links for the rules: ```yaml # One-line comment: tier, what it targets, and any cost/prerequisite note. name: "short-kebab-name" # tester run label; keep it short and unique-ish command: "azd ai agent <subcommand> …" # the installed extension entry point cwd: "~/working/azd-agents-<slug>-{instance}" # see cwd + idempotency below; /tmp for read-only tags: ["tier:N", "cmd:<name>", "parallel-safe"] # REQUIRED — see the Tags taxonomy requires: "tier1/1.0X-….yaml" # optional; only when this scenario needs another to PASS first produces: "~/working/azd-agents-…-{instance}/generated-agent" # optional producer output env: # optional; init scenarios disable agent auto-detect AZD_DISABLE_AGENT_DETECT: "1" allocate_ports: [agent] # optional; only for scenarios that bind a port (e.g. 2.12) pre: # optional host-side setup (reset dir, seed fixture, auth guard) - run: "rm -rf {cwd-or-path}" cwd: "~/working" name: "reset working dir" post: # optional host-side cleanup - run: "…" name: "cleanup" goals: # product behavior is the literal, checkable contract - "Wait for … and confirm …." - "Take a screenshot of the final output." # best-effort evidence; capture failure is an observation - "Report a finding if …." ``` Field references (do not restate these — link to them): - **Tiers & placement** — which directory (`tier0/`…`tier2/`) and cost profile: [README § Tiers](../../../cli/azd/extensions/azure.ai.agents/tests/cli-interactive-tester-scenarios/README.md#tiers). - **Tags** — the `tier:N` / `cmd:*` / trait namespaces and rules: [README § Tags](../../../cli/azd/extensions/azure.ai.agents/tests/cli-interactive-tester-scenarios/README.md#tags). - **`requires:`** — cross-scenario prerequisites (Tier 1b → Tier 1): [README § The `requires:` field](../../../cli/azd/extensions/azure.ai.agents/tests/cli-interactive-tester-scenarios/README.md#the-requires-field). - **`produces:`** — the verified Tier 1 scaffold handed to Tier 1b: [README § Producer/consumer scaffold handoff](../../../cli/azd/extensions/azure.ai.agents/tests/cli-interactive-tester-scenarios/README.md#producerconsumer-scaffold-handoff). - **Profile/session placeholders** (`{prefix}`, `{subscription}`, `{region}`, `{model}`, `{model_version}`, `{model_sku}`, `{tenant}`, `{run_id}`, `{shared_agent_name}`, `{foundry_project_name}`, `{fixtures_dir}`, `{instance}`): [README § Profile / overrides](../../../cli/azd/extensions/azure.ai.agents/tests/cli-interactive-tester-scenarios/README.md#profile--overrides). - **Pre/post hooks** — semantics (host-side, sequential, fail-fast), fields, and the reset / fixture-seed / auth-guard patterns: [README § Pre/post hooks](../../../cli/azd/extensions/azure.ai.agents/tests/cli-interactive-tester-scenarios/README.md#prepost-hooks). - **Fixtures** — the `{fixtures_dir}` seed pattern: [README § Fixtures](../../../cli/azd/extensions/azure.ai.agents/tests/cli-interactive-tester-scenarios/README.md#fixtures). - **Idempotency** — how a stateful scenario resets itself so re-runs start clean: [README § Re-running scenarios](../../../cli/azd/extensions/azure.ai.agents/tests/cli-interactive-tester-scenarios/README.md#re-running-scenarios-idempotency). - **Conventions & parallel-readiness** — resource naming, `{instance}` suffixing, port allocation: [README § Conventions](../../../cli/azd/extensions/azure.ai.agents/tests/cli-interactive-tester-scenarios/README.md#conventions) and [§ Parallel-readiness](../../../cli/azd/extensions/azure.ai.agents/tests/cli-interactive-tester-scenarios/README.md#parallel-readiness--port-allocation). ## Authoring procedure 1. **Confirm the target and scope.** Identify the single command / flow under test and whether it is a happy path or a `negative-path` (error / non-zero-exit) assertion. One command per file — if you're tempted to test two, that's two scenarios (or a documented lifecycle scenario, like `2.07-sessions-lifecycle`). If the request is broad or ambiguous, ask via `ask_user` which command and tier are intended. 2. **Pick the tier and file placement.** Choose the lowest tier that can actually exercise the behavior (offline Tier 0 > auth-only Tier 1 > deploy-verify Tier 1b > cloud Tier 2), because cost and flakiness rise with tier. Place the file in the matching `tierN/` directory and name it `<tier-number>.<seq>-<slug>.yaml`, continuing the existing numbering in that directory. 3. **Write `command` and `cwd`.** - `command:` invokes the installed extension (`azd ai agent …`) or `azd …` for provision/deploy/down steps. - Read-only, stateless scenarios (`version`, `--help`, `sample list`) use `cwd: "/tmp"` and declare no hooks. - Stateful scenarios use a dedicated working dir suffixed with `-{instance}` (e.g. `~/working/azd-agents-<slug>-{instance}`) so parallel instances stay isolated. 4. **Make it idempotent with hooks.** For a stateful scenario add a `pre` hook that `rm -rf`s its own `cwd` (and, if it needs source code, a second hook that seeds a fixture from `{fixtures_dir}` — see `tier1/1.04-init-from-code.yaml`). Prefer **pre-wipe only** for local-only scenarios so the scaffold stays on disk for inspection. Tier 1b scenarios that provision paid resources require an always-run `post` hook with a suitable timeout for `azd down --force --purge`. Tier 2 setup additionally downs a project at its current-run path before removing that directory; teardown failure must abort setup and preserve state for recovery. Do not use `continue_on_error` when cleanup failure would orphan resources. 5. **Add a fixture only if required.** If the flow needs pre-existing source (the "use the code in the current directory" path), add the minimal tree under `fixtures/<name>/` and seed it via the hook. Keep fixtures minimal, but make them runnable when a later scenario deploys and invokes the generated scaffold; detection-only placeholders are not sufficient for deploy-verification prerequisites. 6. **Declare producer/consumer handoff when required.** A Tier 1 scenario whose scaffold is deployed by Tier 1b sets `produces:` to the exact generated project directory. Its Tier 1b consumer points `requires:` at that Tier 1 scenario (a **relative path from the scenarios root**) and uses `{prerequisite_scaffold_dir}` for `cwd` and every scaffold hook path. Never duplicate the producer's path in the consumer. Don't use `requires:` to sequence independent scenarios — it is a hard prerequisite, not an ordering hint. 7. **Write the `tags:` list.** At minimum: one `tier:N`, at least one `cmd:*`, and exactly one of `parallel-safe` / `serial-only` (Tier 0/1/1b → `parallel-safe`; Tier 2 → `serial-only`). Add `negative-path`, `picker`, or `verify-deploy` when they apply. Multi-command flows carry multiple `cmd:*` tags. 8. **Write the `goals:` as the contract.** Follow the authoring-contract rules above: literal, checkable product behavior, stable-label picks, clear-field-before-typing, best-effort screenshot evidence, and a final "report a finding if …" goal. Screenshot errors and timeouts are observations and do not block later product goals; all product expectations remain strict. For multi-select prompts, choose one explicit intent: - A **default assertion** lists what must already be selected and unselected, then says to leave that selection unchanged and continue. A mismatch must fail without repair. - A **final-state instruction** lists what should end selected and unselected without asserting the initial state, allowing the worker to change only the differences. An already-correct selection advances without changing any choice. Keep action names, indices, payloads, and keystrokes out of scenario goals; the worker owns those mechanics. For resource-creating flows, include the RESOURCE NAMING and AGENT NAME goals (prefix `{prefix}-`, suffix `-{instance}`) so parallel runs don't collide. Foundry project prompts must use the orchestrator-derived `{foundry_project_name}` because the service limits those names to 32 characters. ## Validation loop (no execution) Validate **statically** — never `start_session`, never drive the scenario, never provision. 1. **Tag lint via `list_scenarios`.** Run `list_scenarios(root="<scenarios-dir>", tags=[<the new scenario's tags>])` and confirm the new file appears under each of its tags. If `list_scenarios` reports `tags: []` for the file, the `tags:` field is missing or malformed — fix it. (`list_scenarios` uses a real YAML parser, so this also catches YAML syntax errors in the file.) 2. **YAML shape.** Re-read the file and confirm required fields (`name`, `command`, `cwd`, `tags`, `goals`) are present and well-formed, that `goals` is a non-empty list of strings, and that any Tier 1 producer declares the exact scaffold directory in `produces:`. 3. **`requires:` resolves.** If `requires:` is set, confirm the referenced path exists relative to the scenarios root and points at the intended prerequisite. 4. **Fixture / hook paths resolve.** If a `pre` hook seeds a fixture, confirm the referenced `fixtures/<name>/` tree exists and the hook uses `{fixtures_dir}` (not a hardcoded path). 5. **Placeholders only reference known variables.** Every `{name}`-shaped token in `command` / `cwd` / hooks / goals is processed as a placeholder and must be a documented profile/session placeholder (including `{model_version}`, `{model_sku}`, and `{foundry_project_name}`) or, for Tier 1b, `{prerequisite_scaffold_dir}`. This includes embedded shell syntax: format an awk action as `{ print }`, not `{print}`, so it cannot be mistaken for an unknown placeholder. Reject every unknown brace-delimited token during static validation. 6. **Invoke input is explicit.** For every goal or `command` that executes `azd ai agent invoke`, confirm the literal command includes a positional message or an intentional `--input-file` whose contents are defined by the scenario. Command-list and help assertions that only mention `invoke` are not executable calls. 7. **Coverage cross-check.** If this scenario closes a coverage gap flagged by a PR regression run, confirm its `cmd:*` tag matches the changed command so future impact-mapping picks it up. Report the validation result to the user. If they then want to *run* the new scenario to confirm it drives cleanly, that's a separate, cost-gated step — hand off to the `foundry-extension-scenario-suite-run` skill / `foundry-extension-scenario-orchestrator` agent (Tier 1b / Tier 2 incur Azure cost and need explicit consent). This skill stops at a validated, unexecuted scenario. ## Exit criteria - A single-command scenario YAML was authored (or corrected) in the correct `tierN/` directory with a compliant `tags:` list, appropriate `cwd` + idempotency hooks, any needed fixture / `requires:`, and `goals:` written as a literal, checkable contract. - The static validation loop passed: `list_scenarios` lists the file under all its tags (not `tags: []`), the YAML parses, and every `requires:` / fixture / placeholder reference resolves. - **No scenario was executed** and no Azure resources were created; any run-to-confirm was handed off to the run skills with a cost note.
عرض على GitHub