From 3258e2ae9a697f5cfe4de21201162f2f9a829e79 Mon Sep 17 00:00:00 2001 From: Nitya Narasimhan Date: Fri, 14 Aug 2026 18:43:26 +0000 Subject: [PATCH 1/5] walkthrough(v2): mixed-path fix + per-lab progress banners - NEW scripts/link-portal-rg.sh: idempotent linker that binds an azd env to a portal-created rg-contoso-travel (discovers Foundry account + project, sets USE_EXISTING_AI_PROJECT, preempts the AI_PROJECT_DEPLOYMENTS JSON gotcha). Fixes the second-RG risk for UI->CLI learners (ref issue #2). - Lab 05: 'Path check' preface pointing portal-first learners at the linker. - Lab 02: forward-reference tip naming the linker. - Lab 00: mermaid warning box now names scripts/link-portal-rg.sh; new RG-context diagram in the Next section. - Lab 01: 'pre-flight your quota with Copilot' tip using the microsoft-foundry quota sub-skill (ref pre-flight 0.4). - specs/course.yaml: fix stale 'azd up' titles for 01-provision-azd (=> 'azd provision') and 05-deploy-hosted-agent (=> 'azd deploy') (ref 0.5a). - Fundamentals 00-06: add compact 'You are here' progress banner right after each 'This lab covers' callout, current lab highlighted in workshop teal (matches DevOps-loop active-node style). - AGENTS.md: new Known-gotcha bullet for the mixed UI->CLI second-RG risk. pytest -q: 14 passed. Tracked under nitya/agent-optimization-workshop#4. --- AGENTS.md | 9 +++ labs/fundamentals/00-overview.md | 43 ++++++++++++ labs/fundamentals/01-provision-azd.md | 25 +++++++ labs/fundamentals/02-provision-portal.md | 22 ++++-- labs/fundamentals/03-deploy-models.md | 12 ++++ labs/fundamentals/04-create-prompt-agent.md | 12 ++++ labs/fundamentals/05-deploy-hosted-agent.md | 25 +++++++ labs/fundamentals/06-verify.md | 12 ++++ scripts/link-portal-rg.sh | 78 +++++++++++++++++++++ specs/course.yaml | 4 +- 10 files changed, 236 insertions(+), 6 deletions(-) create mode 100755 scripts/link-portal-rg.sh diff --git a/AGENTS.md b/AGENTS.md index f037155..4212b45 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -75,6 +75,15 @@ maintainer follow-ups (screenshots, exact commands, model pinning, etc.). manage hosted agents but has no create flow — `azd deploy` is the only supported creation path today. Do not add "portal path" instructions for hosted agents unless the portal ships that flow. +- **Mixed UI→CLI path creates a second resource group.** A learner who did Lab + 02 (portal) has `rg-contoso-travel` in Azure but no `.azure/` env locally. + Running `azd env new … && azd provision` in Lab 05 then creates a *second* + RG (`rg-`) instead of reusing the portal one. Fix: `bash + scripts/link-portal-rg.sh` (idempotent — discovers the RG + Foundry account + + project and seeds the azd env with `AZURE_RESOURCE_GROUP`, + `AZURE_AI_ACCOUNT_NAME`, `AZURE_AI_PROJECT_NAME`, and + `USE_EXISTING_AI_PROJECT=true`). Kept in sync with the Lab 05 "Path check" + callout and the Lab 00 overview mermaid warning. - **`azd provision` fails with `invalid character 'n' after object key:value pair`.** The four `*Json` params in `infra/main.parameters.json` are quoted-string substitutions (e.g. `"value": "${AI_PROJECT_DEPLOYMENTS=[]}"`) diff --git a/labs/fundamentals/00-overview.md b/labs/fundamentals/00-overview.md index 4c3a5f2..273e298 100644 --- a/labs/fundamentals/00-overview.md +++ b/labs/fundamentals/00-overview.md @@ -27,6 +27,18 @@ flowchart LR > 🧭 **This lab covers:** _Plan_ — get the mental model before you touch anything. +### 📍 You are here + +```mermaid +flowchart LR + L0["00
overview"]:::active --> L1["01
azd"] + L0 --> L2["02
portal"] + L1 --> L3["03
models"] + L2 --> L3 + L3 --> L4["04
prompt agent"] --> L5["05
hosted agent"] --> L6["06
verify"] + classDef active fill:#0ea5e9,stroke:#0369a1,color:#fff; +``` + ## 📋 Steps 1. **Know the [scenario](#scenario).** @@ -83,6 +95,37 @@ If you can answer all three, you're ready to provision. ## ➡️ Next +Both provisioning paths land in the **same resource group** (`rg-contoso-travel`) +and every later lab writes into that one group — so whichever door you pick, the +rest of the workshop is identical. + +```mermaid +flowchart TB + Start(["Lab 00 · pick your path"]) + Start -->|CLI-first| L01["Lab 01
azd env new + azd provision"] + Start -->|UI-first| L02["Lab 02
Portal: create Foundry project"] + + L01 --> RG + L02 --> RG + + subgraph RG["📦 rg-contoso-travel  ·  one resource group, either path"] + direction TB + F["Foundry account + project
created by Lab 01 or Lab 02"] + M["Lab 03 · Model deployments
gpt-5.4-mini + gpt-5.4-judge"] + P["Lab 04 · Prompt Agent
lives inside the Foundry project"] + H["Lab 05 · Hosted agent + registry + capability host
azd env set ENABLE_HOSTED_AGENTS=true → azd provision → azd deploy"] + F --> M --> P --> H + end + + V["Lab 06 · Verify (read-only)"] + RG --> V + + Warn["⚠️ Mixed path (UI → CLI)?
Before Lab 05, run ./scripts/link-portal-rg.sh
to bind an azd env to the portal-created RG.
Otherwise azd deploy creates a second RG."]:::warn + RG -.->|watch out| Warn + + classDef warn fill:#fef3c7,stroke:#f59e0b,color:#111827; +``` + Choose one: - Code-first → **[Lab 01 — Provision with `azd`](./01-provision-azd.md)** diff --git a/labs/fundamentals/01-provision-azd.md b/labs/fundamentals/01-provision-azd.md index e3b72bd..e848806 100644 --- a/labs/fundamentals/01-provision-azd.md +++ b/labs/fundamentals/01-provision-azd.md @@ -28,6 +28,18 @@ flowchart LR > 🧭 **This lab covers:** _Build_ — provisioning the substrate you'll deploy the > Concierge onto. +### 📍 You are here + +```mermaid +flowchart LR + L0["00
overview"] --> L1["01
azd"]:::active + L0 --> L2["02
portal"] + L1 --> L3["03
models"] + L2 --> L3 + L3 --> L4["04
prompt agent"] --> L5["05
hosted agent"] --> L6["06
verify"] + classDef active fill:#0ea5e9,stroke:#0369a1,color:#fff; +``` + ## Before you start Confirm you have: @@ -41,6 +53,19 @@ Confirm you have: 3. Either the workshop **devcontainer** open (see `.devcontainer/README.md`) or `az`, `azd`, and Python 3.13+ installed locally. +> 💡 **Tip — pre-flight your quota with Copilot.** After `az login` (Step 1 +> below), paste this prompt into Copilot Chat to have the +> [`microsoft-foundry`](https://github.com/microsoft/azure-skills/tree/main/skills/microsoft-foundry) +> `quota` sub-skill confirm capacity before you provision: +> +> > Use the microsoft-foundry quota skill to confirm I have GlobalStandard +> > capacity 100 in eastus2 for `gpt-5.4-mini@2026-03-17` and +> > `gpt-5.4@2026-03-05`. If not, recommend the best of `eastus2` / +> > `swedencentral` / `northcentralus`. +> +> If eastus2 comes back short, switch to whichever region the skill +> recommends before running `azd provision`. + > ⚠️ **Cost:** provisioning runs in **your** subscription and incurs cost. > You'll tear it all down with `azd down` at the end. diff --git a/labs/fundamentals/02-provision-portal.md b/labs/fundamentals/02-provision-portal.md index 6766cd3..6ebf911 100644 --- a/labs/fundamentals/02-provision-portal.md +++ b/labs/fundamentals/02-provision-portal.md @@ -23,6 +23,18 @@ flowchart LR > 🧭 **This lab covers:** _Build_ — provisioning the substrate through the UI. +### 📍 You are here + +```mermaid +flowchart LR + L0["00
overview"] --> L1["01
azd"] + L0 --> L2["02
portal"]:::active + L1 --> L3["03
models"] + L2 --> L3 + L3 --> L4["04
prompt agent"] --> L5["05
hosted agent"] --> L6["06
verify"] + classDef active fill:#0ea5e9,stroke:#0369a1,color:#fff; +``` + ## Before you start - An **Azure subscription** with permission to create resources. @@ -63,10 +75,12 @@ flowchart LR -> 💡 **Tip:** if you later want to switch to the `azd` path, you can point -> `azd` at this existing project by setting `AZURE_EXISTING_AIPROJECT_RESOURCE_ID` -> in your `azd` environment — the Bicep in `infra/core/ai/existing-ai-project.bicep` -> supports this. +> 💡 **Tip — moving to CLI later?** If you plan to run the CLI-only steps in +> [Lab 05](./05-deploy-hosted-agent.md) to deploy the hosted agent, you'll +> run [`scripts/link-portal-rg.sh`](../../scripts/link-portal-rg.sh) once +> before Lab 05 Step 1. It binds an `azd env` to this portal-created RG so +> `azd provision` reuses it — no second resource group. You don't need to run +> it now. ## ✅ Verify diff --git a/labs/fundamentals/03-deploy-models.md b/labs/fundamentals/03-deploy-models.md index dd4f23f..c7665e9 100644 --- a/labs/fundamentals/03-deploy-models.md +++ b/labs/fundamentals/03-deploy-models.md @@ -24,6 +24,18 @@ flowchart LR > 🧭 **This lab covers:** _Build_ — putting a model behind an endpoint. +### 📍 You are here + +```mermaid +flowchart LR + L0["00
overview"] --> L1["01
azd"] + L0 --> L2["02
portal"] + L1 --> L3["03
models"]:::active + L2 --> L3 + L3 --> L4["04
prompt agent"] --> L5["05
hosted agent"] --> L6["06
verify"] + classDef active fill:#0ea5e9,stroke:#0369a1,color:#fff; +``` + ## Models this workshop uses | Deployment name | Purpose | Default region | diff --git a/labs/fundamentals/04-create-prompt-agent.md b/labs/fundamentals/04-create-prompt-agent.md index 1666c17..a1f9ba6 100644 --- a/labs/fundamentals/04-create-prompt-agent.md +++ b/labs/fundamentals/04-create-prompt-agent.md @@ -21,6 +21,18 @@ flowchart LR > 🧭 **This lab covers:** _Build_ — creating the prompt-agent flavor of the Concierge. +### 📍 You are here + +```mermaid +flowchart LR + L0["00
overview"] --> L1["01
azd"] + L0 --> L2["02
portal"] + L1 --> L3["03
models"] + L2 --> L3 + L3 --> L4["04
prompt agent"]:::active --> L5["05
hosted agent"] --> L6["06
verify"] + classDef active fill:#0ea5e9,stroke:#0369a1,color:#fff; +``` + ## What's a "prompt agent"? A **Prompt Agent** in Foundry is a lightweight, portal-authored agent: it has diff --git a/labs/fundamentals/05-deploy-hosted-agent.md b/labs/fundamentals/05-deploy-hosted-agent.md index 9943a1a..f771490 100644 --- a/labs/fundamentals/05-deploy-hosted-agent.md +++ b/labs/fundamentals/05-deploy-hosted-agent.md @@ -20,6 +20,18 @@ flowchart LR > 🧭 **This lab covers:** _Deploy_ — publishing a containerized agent to Foundry. +### 📍 You are here + +```mermaid +flowchart LR + L0["00
overview"] --> L1["01
azd"] + L0 --> L2["02
portal"] + L1 --> L3["03
models"] + L2 --> L3 + L3 --> L4["04
prompt agent"] --> L5["05
hosted agent"]:::active --> L6["06
verify"] + classDef active fill:#0ea5e9,stroke:#0369a1,color:#fff; +``` + ## Before you start The hosted agent is **not** deployed by `azd provision` in Lab 01 — that step @@ -34,6 +46,19 @@ host). You'll enable both below. ## 📋 Steps +> 🧭 **Path check — portal-first only.** If you provisioned via the portal +> (Lab 02) and this is your first `azd` step, run the linker script **once** +> before Step 1 so `azd provision` reuses your existing resource group +> instead of creating a second one: +> +> ```bash +> ./scripts/link-portal-rg.sh +> ``` +> +> The script auto-discovers the RG, Foundry account, and project, then binds +> them into an `azd env` named `contoso-travel`. Idempotent — safe to re-run. +> **Skip this if you did Lab 01 (`azd`) already.** + 1. **Make sure the hosted-agents extension is installed.** The `azd ai agent` commands and hosted `azd deploy` come from the **`azure.ai.agents`** azd extension. The workshop devcontainer installs it diff --git a/labs/fundamentals/06-verify.md b/labs/fundamentals/06-verify.md index a3b2a0c..c714ce1 100644 --- a/labs/fundamentals/06-verify.md +++ b/labs/fundamentals/06-verify.md @@ -22,6 +22,18 @@ flowchart LR > 🧭 **This lab covers:** _Evaluate_ (informally) — a smoke check before the > real evaluation labs. +### 📍 You are here + +```mermaid +flowchart LR + L0["00
overview"] --> L1["01
azd"] + L0 --> L2["02
portal"] + L1 --> L3["03
models"] + L2 --> L3 + L3 --> L4["04
prompt agent"] --> L5["05
hosted agent"] --> L6["06
verify"]:::active + classDef active fill:#0ea5e9,stroke:#0369a1,color:#fff; +``` + ## The canonical question > **"What business-class flights are available from Chicago to Rome under diff --git a/scripts/link-portal-rg.sh b/scripts/link-portal-rg.sh new file mode 100755 index 0000000..a0231da --- /dev/null +++ b/scripts/link-portal-rg.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env bash +# link-portal-rg.sh — bind an azd env to a portal-created Foundry resource group. +# +# Use this ONCE before Lab 05 if your Foundry project was provisioned via the +# portal (Lab 02) instead of azd (Lab 01). It teaches azd about the existing +# resource group + Foundry account + project so `azd provision` (Step 2 of +# Lab 05) reuses them instead of creating a second copy in a new RG. +# +# Usage: +# ./scripts/link-portal-rg.sh [resource-group] [azd-env-name] +# +# Defaults: rg-contoso-travel contoso-travel +# +# Idempotent — safe to re-run. Requires `az` logged in and `jq` on PATH +# (both are already present in the workshop devcontainer). + +set -euo pipefail + +RG="${1:-rg-contoso-travel}" +ENV="${2:-contoso-travel}" + +# --- sanity checks --------------------------------------------------------- +command -v az >/dev/null 2>&1 || { echo "❌ 'az' not found on PATH."; exit 127; } +command -v azd >/dev/null 2>&1 || { echo "❌ 'azd' not found on PATH."; exit 127; } +command -v jq >/dev/null 2>&1 || { echo "❌ 'jq' not found on PATH."; exit 127; } + +az account show >/dev/null 2>&1 || { + echo "❌ 'az' is not logged in. Run: az login --use-device-code"; exit 1; } + +# --- discover the RG + Foundry resources ----------------------------------- +LOC=$(az group show -n "$RG" --query location -o tsv 2>/dev/null) || { + echo "❌ Resource group '$RG' not found in the current subscription." + echo " Pass a different name: ./scripts/link-portal-rg.sh " + exit 1 +} +SUB=$(az account show --query id -o tsv) + +# Foundry account = an AIServices account inside the RG (Lab 02 creates exactly one). +ACCT=$(az cognitiveservices account list -g "$RG" \ + --query "[?kind=='AIServices'] | [0].name" -o tsv 2>/dev/null || true) +if [[ -z "$ACCT" || "$ACCT" == "null" ]]; then + echo "❌ No Foundry (AIServices) account found in resource group '$RG'." + echo " Did Lab 02 complete? Check the portal → Resource groups → $RG." + exit 1 +fi + +# Project name — best-effort. Older API versions omit the 'project list' verb; +# in that case the workshop uses the default pattern 'ai-project-'. +PROJ=$(az cognitiveservices account project list \ + -g "$RG" --name "$ACCT" --query "[0].name" -o tsv 2>/dev/null || true) + +# --- bind the azd env ------------------------------------------------------ +if azd env list -o json 2>/dev/null | jq -e ".[] | select(.Name==\"$ENV\")" >/dev/null; then + azd env select "$ENV" >/dev/null +else + azd env new "$ENV" --no-prompt +fi + +azd env set AZURE_SUBSCRIPTION_ID "$SUB" +azd env set AZURE_RESOURCE_GROUP "$RG" +azd env set AZURE_LOCATION "$LOC" +azd env set AZURE_AI_ACCOUNT_NAME "$ACCT" +[[ -n "$PROJ" && "$PROJ" != "null" ]] && azd env set AZURE_AI_PROJECT_NAME "$PROJ" +azd env set USE_EXISTING_AI_PROJECT true +azd env set AI_PROJECT_DEPLOYMENTS "[]" # sidestep the JSON-escape gotcha in Lab 05 + +# --- report ---------------------------------------------------------------- +echo "" +echo "✅ azd env '$ENV' linked to existing resource group '$RG' in $LOC." +echo " Foundry account: $ACCT" +[[ -n "$PROJ" && "$PROJ" != "null" ]] && echo " Foundry project: $PROJ" +echo "" +echo "Values now set (subscription id truncated for readability):" +azd env get-values | grep -E "^(AZURE_(SUBSCRIPTION_ID|RESOURCE_GROUP|LOCATION|AI_ACCOUNT_NAME|AI_PROJECT_NAME))|^USE_EXISTING_AI_PROJECT|^AI_PROJECT_DEPLOYMENTS" \ + | sed -E 's|(AZURE_SUBSCRIPTION_ID=")([^"]{4})[^"]*(")|\1\2…\3|' +echo "" +echo "Next: run Lab 05 Step 2 (azd provision) — it will reuse '$RG' instead of" +echo "creating a new one." diff --git a/specs/course.yaml b/specs/course.yaml index db4a0dd..099c6b6 100644 --- a/specs/course.yaml +++ b/specs/course.yaml @@ -24,7 +24,7 @@ phases: produces: [] consumes: [] - id: "01-provision-azd" - title: Provision Foundry with `azd up` + title: Provision Foundry with `azd provision` loop_node: build time_min: 15 prereqs: ["fundamentals/00-overview"] @@ -56,7 +56,7 @@ phases: - {type: data, name: hotels} - {type: data, name: car_rentals} - id: "05-deploy-hosted-agent" - title: Deploy the Hosted Agent (`azd up`) + title: Deploy the Hosted Agent (`azd deploy`) loop_node: deploy time_min: 15 prereqs: ["fundamentals/03-deploy-models"] From 295246c88d8517be6ce54063cdc67df92d425cea Mon Sep 17 00:00:00 2001 From: Nitya Narasimhan Date: Mon, 17 Aug 2026 17:03:30 +0000 Subject: [PATCH 2/5] Added Troubleshooting.md - New labs/TROUBLESHOOTING.md as the single source of truth for cross-cutting gotchas (9 sections, Symptom/Cause/Fix/Prevent template). - Codified two-variant Gotcha convention in labs/_template/lab-template.md, specs/lab-template.schema.json, and AGENTS.md. - Shortened cross-cutting callouts in Lab 01/03/05 to one-liner + link. - Compressed AGENTS.md 'Known gotchas' from prose to terse pointers. - Added tests/test_lab_content.py::test_gotcha_callouts_follow_convention drift-check (15 passed). --- AGENTS.md | 85 +++--- labs/TROUBLESHOOTING.md | 320 ++++++++++++++++++++ labs/_template/lab-template.md | 7 +- labs/fundamentals/01-provision-azd.md | 11 +- labs/fundamentals/03-deploy-models.md | 13 +- labs/fundamentals/05-deploy-hosted-agent.md | 58 +--- specs/lab-template.schema.json | 6 +- tests/test_lab_content.py | 60 ++++ 8 files changed, 463 insertions(+), 97 deletions(-) create mode 100644 labs/TROUBLESHOOTING.md diff --git a/AGENTS.md b/AGENTS.md index 4212b45..b88275b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -49,6 +49,25 @@ Every file under `labs/{fundamentals,core,more}/*.md` **must** follow - Callouts: `> 🎯` `> ✅` `> 💡` `> ⚠️` `> 🧭` `> 🧠` - Every generative step ships a `reference/` artifact under `artifacts/` +### Callout conventions — Gotchas + +Two-variant rule (guarded by `tests/test_lab_content.py`): + +1. **Inline gotcha** — a single lab-specific mistake, ≤ 4 lines, fits in the + step's flow. Format: `> ⚠️ **Gotcha:** .` +2. **Cross-cutting gotcha** — infra/tool errors that recur across labs, or + need multi-step recovery. Author them **once** in + [`labs/TROUBLESHOOTING.md`](./labs/TROUBLESHOOTING.md) under a stable H3 + using the **Symptom / Cause / Fix / Prevent** template. In the lab, keep + the callout to one line: + + ```markdown + > ⚠️ **Gotcha — .** Details in [Troubleshooting ·
](../TROUBLESHOOTING.md#anchor). + ``` + +`> ⚠️ **Cost:** …` and `> ⚠️ **Known limitation:** …` follow the same visual +style but are not enforced by the drift-check. + ## Workshop-Coach agent Do **not** modify `.github/agents/workshop-coach.agent.md` behavior contract @@ -65,45 +84,39 @@ maintainer follow-ups (screenshots, exact commands, model pinning, etc.). ## Known gotchas -- **Foundry hosted-agent 409 on `azd deploy`.** Reusing the same `azd env` name - after a torn-down deploy can hit stale server-side state on the Foundry agents - data plane, producing `RESPONSE 409: 409 Conflict … modified concurrently` - even though `azd ai agent doctor` sees no agent. Recovery: `azd down --purge - --force` → `azd env new ` → `azd provision` → `azd deploy`. - Captured in the Lab 05 gotcha callout — keep those two in sync. +Canonical entries live in [`labs/TROUBLESHOOTING.md`](./labs/TROUBLESHOOTING.md). +Bullets below are pointers — keep them in lockstep with the canonical section +anchors and the in-lab callouts that link to them. + +- **`azd provision` — soft-deleted resource blocks re-provision.** Purge the + Cognitive Services (Foundry) account or use a fresh `azd env` name. + [Troubleshooting](./labs/TROUBLESHOOTING.md#soft-deleted-cognitive-services-account-blocks-re-provision) + · Lab 01. +- **`azd provision` — `invalid character 'n' after object key:value pair`.** + Non-empty `AI_PROJECT_DEPLOYMENTS` (or the other three `*Json` params) breaks + the parameters file on azd ≤ 1.31. Workaround: `azd env set + AI_PROJECT_DEPLOYMENTS "[]"`. Structural fix tracked as `TODO(nitya)` in + `infra/main.bicep` (switch the four params to `array`/`object` types). + [Troubleshooting](./labs/TROUBLESHOOTING.md#azd-provision-fails-with-invalid-character-n-after-object-keyvalue-pair) + · Lab 03 + Lab 05. +- **`azd deploy` — 409 Conflict.** Reusing the same `azd env` name after a + torn-down deploy hits stale Foundry data-plane state; recovery needs a fresh + env name. [Troubleshooting](./labs/TROUBLESHOOTING.md#409-conflict-on-azd-deploy) + · Lab 05. +- **`azd deploy` — 404 `Subdomain does not map to a resource`.** Stale bearer + token, not a missing resource. Re-auth **both** `az` and `azd` (independent + token caches). [Troubleshooting](./labs/TROUBLESHOOTING.md#404-subdomain-does-not-map-to-a-resource-on-azd-deploy) + · Lab 05. +- **Mixed UI→CLI path creates a second resource group.** A portal-first + learner running `azd env new … && azd provision` in Lab 05 creates a second + RG. Fix: `bash scripts/link-portal-rg.sh` (idempotent). + [Troubleshooting](./labs/TROUBLESHOOTING.md#ui-provision--cli-deploy-creates-a-second-resource-group) + · Lab 05 "Path check" + Lab 00 overview warning. - **Portal cannot *create* hosted agents.** The Foundry portal can view and manage hosted agents but has no create flow — `azd deploy` is the only supported creation path today. Do not add "portal path" instructions for - hosted agents unless the portal ships that flow. -- **Mixed UI→CLI path creates a second resource group.** A learner who did Lab - 02 (portal) has `rg-contoso-travel` in Azure but no `.azure/` env locally. - Running `azd env new … && azd provision` in Lab 05 then creates a *second* - RG (`rg-`) instead of reusing the portal one. Fix: `bash - scripts/link-portal-rg.sh` (idempotent — discovers the RG + Foundry account + - project and seeds the azd env with `AZURE_RESOURCE_GROUP`, - `AZURE_AI_ACCOUNT_NAME`, `AZURE_AI_PROJECT_NAME`, and - `USE_EXISTING_AI_PROJECT=true`). Kept in sync with the Lab 05 "Path check" - callout and the Lab 00 overview mermaid warning. -- **`azd provision` fails with `invalid character 'n' after object key:value - pair`.** The four `*Json` params in `infra/main.parameters.json` are - quoted-string substitutions (e.g. `"value": "${AI_PROJECT_DEPLOYMENTS=[]}"`) - and azd 1.30 does not JSON-escape embedded `"` on substitution. Any non-empty - override (e.g. a user-supplied `AI_PROJECT_DEPLOYMENTS` array) breaks the - parameters file. Workaround: `azd env set AI_PROJECT_DEPLOYMENTS "[]"` and - re-provision — the defaults in `infra/main.bicep` still deploy - `gpt-5.4-mini` + `gpt-5.4-judge`. Structural fix (`TODO(nitya)` in - `infra/main.bicep`): change the four params to `array`/`object` types, drop - the `json()` calls, and substitute without surrounding quotes. Kept in sync - with Lab 03 + Lab 05 gotcha callouts. -- **`azd deploy` fails with `RESPONSE 404: ResourceNotFound — Subdomain does - not map to a resource`.** The Foundry agents data plane returns 404 (not - 401) when the caller's bearer token is expired or revoked — typically - `AADSTS50173` after a password change, credential rotation, or Conditional - Access policy update. The account is fine; auth is stale. `azd` and `az` - cache tokens independently, so both must be refreshed: `az logout && az - login --tenant ` then `azd auth logout && azd auth login --tenant-id - `, then re-run `azd deploy`. Kept in sync with the Lab 05 gotcha - callout. + hosted agents unless the portal ships that flow. *(No troubleshooting entry + — this is a static product limitation, not an error.)* ## Tests diff --git a/labs/TROUBLESHOOTING.md b/labs/TROUBLESHOOTING.md new file mode 100644 index 0000000..98270f5 --- /dev/null +++ b/labs/TROUBLESHOOTING.md @@ -0,0 +1,320 @@ +# Workshop Troubleshooting + +Canonical home for **detailed** gotchas — infra and tool errors that recur +across labs or need multi-step recovery. Individual lab files keep short +`> ⚠️ **Gotcha:** …` callouts and link here for the full recipe. + +> 💡 **Authoring convention.** See [`labs/_template/lab-template.md`](./_template/lab-template.md) +> and the "Callout conventions" section in [`AGENTS.md`](../AGENTS.md). +> Small, lab-specific mistakes stay inline. Anything recurring, cross-cutting, +> or > 5 lines lives here — one section per issue. + +Every section below follows the same template: + +- **Symptom** — the exact error message (or the observable behavior). +- **Cause** — what's really going on. +- **Fix** — the commands / clicks that unblock. +- **Prevent** — optional; how to avoid hitting it again. + +--- + +## Provisioning (`azd provision`) + +### Soft-deleted Cognitive Services account blocks re-provision + +**Symptom.** `azd provision` fails with: + +```text +ERROR: A soft-deleted resource with this name exists and is blocking deployment. +... +FlagMustBeSetForRestore: An existing resource with ID +'/subscriptions/…/providers/Microsoft.CognitiveServices/accounts/' +has been soft-deleted. +``` + +`azd`'s hint text incorrectly labels this *"Azure Key Vault soft-delete +recovery"* — the inner error names the real resource type (most often a +Cognitive Services / Foundry account). + +**Cause.** A previous run (or a deleted Codespace) tore the Foundry account +down; it remains in soft-delete for the retention window and blocks a +same-name re-provision. + +**Fix (A — purge, then re-provision):** + +```bash +az cognitiveservices account list-deleted -o table + +az cognitiveservices account purge \ + --location \ + --resource-group \ + --name + +azd provision +``` + +Purge needs `Microsoft.CognitiveServices/locations/deletedAccounts/delete` — +plain **Contributor** may not suffice. If you hit `AuthorizationFailed`, ask a +subscription **Owner** to purge (or use Fix B). + +**Fix (B — sidestep with a fresh env name):** + +```bash +azd env new contoso-travel-$(date +%m%d) +azd provision +``` + +A new env name changes the synthesized resource names, so the collision +disappears. + +**Prevent.** `azd down --purge --force` purges the account as it tears down. +The trap is losing a Codespace (or the `.azure/` folder) before purging. + +--- + +### `azd provision` fails with `invalid character 'n' after object key:value pair` + +**Symptom.** `azd provision` fails immediately with: + +```text +invalid character 'n' after object key:value pair +``` + +**Cause.** The four `*Json` params in `infra/main.parameters.json` +(`AI_PROJECT_DEPLOYMENTS`, `AI_PROJECT_CONNECTIONS`, +`AI_PROJECT_CREDENTIALS`, `AI_PROJECT_DEPENDENT_RESOURCES`) are +quoted-string substitutions like `"value": "${AI_PROJECT_DEPLOYMENTS=[]}"`. +azd 1.30 does not JSON-escape embedded `"` on substitution, so any +non-empty override breaks the parameters file. + +**Fix.** Reset the override to `[]`; the defaults in `infra/main.bicep` still +deploy `gpt-5.4-mini` + `gpt-5.4-judge`: + +```bash +azd env set AI_PROJECT_DEPLOYMENTS "[]" +azd provision +``` + +**Prevent.** Only set `AI_PROJECT_DEPLOYMENTS` (etc.) when you actually need +a non-default deployment set, and clear it before re-provisions that add +resources (e.g. enabling hosted agents in Lab 05). Structural fix tracked as +`TODO(nitya)` in `infra/main.bicep`: change the four params to `array` / +`object` types, drop the `json()` calls, and substitute without surrounding +quotes. + +--- + +### Quota / capacity errors on `azd provision` or model deploy + +**Symptom.** Either: + +- `azd provision` fails with a quota / capacity error, or +- In the portal, the **Deploy** button on the model card is greyed out. + +**Cause.** Your subscription doesn't have the requested capacity for the +target model in the target region. + +**Fix.** Switch to a region with headroom (from the supported list): + +```bash +azd env set AZURE_LOCATION swedencentral # or northcentralus +azd provision +``` + +For the portal path: pick a different region on the model card, or open +**Management center → Quota** in Foundry and request an increase. + +**Prevent.** Pre-flight the quota before provisioning — see the workshop's +pre-flight step 0.4 and the `microsoft-foundry` `quota` skill. + +--- + +### `azd provision` reports `no project exists — run 'azd init'` + +**Symptom.** + +```text +ERROR: no project exists; to create a new project, run 'azd init' +``` + +**Cause.** You're running `azd` from a folder that doesn't contain +`azure.yaml`. + +**Fix.** `cd` to the repo root (the folder that has `azure.yaml`) and re-run. + +--- + +## Hosted-agent deploy (`azd deploy`) + +### 409 Conflict on `azd deploy` + +**Symptom.** + +```text +RESPONSE 409: 409 Conflict … The resource already exists or was modified +concurrently. Please retry. +``` + +A plain retry doesn't clear it. The portal Agents blade may also show +*"Project not found"*. `azd ai agent doctor` finds nothing. + +**Cause.** The Foundry agents data plane is holding a stale registration +keyed on the current project/agent name — even after a torn-down deploy. + +**Fix.** + +```bash +azd down --purge --force # tear down + purge soft-delete +azd env new contoso-travel-v2 # any new name → new account+project hash +azd env set ENABLE_HOSTED_AGENTS true +azd provision +azd deploy contoso-travel-concierge +``` + +The new env name changes the `uniqueString()` hash used by the infra, giving +you a genuinely fresh Foundry project and clearing the cache. + +--- + +### 404 `Subdomain does not map to a resource` on `azd deploy` + +**Symptom.** + +```text +RESPONSE 404: ResourceNotFound — Subdomain does not map to a resource +``` + +**Cause.** The Foundry agents data plane returns 404 (not 401) when the +caller's bearer token is expired or revoked — typically `AADSTS50173` after +a password change, credential rotation, or Conditional Access policy update +that moved `TokensValidFrom` past your issued-at time. The account is fine; +auth is stale. + +**Fix.** `az` and `azd` cache tokens independently, so **both** must be +refreshed: + +```bash +az logout && az login --tenant +azd auth logout && azd auth login --tenant-id +azd deploy contoso-travel-concierge +``` + +Quick sanity check that the resource itself is healthy (returns HTTP 200 +even unauthenticated): + +```bash +curl -sS -o /dev/null -w "%{http_code}\n" \ + "https://$(azd env get-value AZURE_AI_ACCOUNT_NAME).services.ai.azure.com/" +``` + +--- + +### `refresh token has expired due to inactivity` on `azd deploy` + +**Symptom.** + +```text +AzureDeveloperCLICredential: … The refresh token has expired due to +inactivity. The token was issued on and was inactive for 90.00:00:00. +``` + +**Cause.** `azd`'s cached refresh token wasn't used within its inactivity +window (90 days). + +**Fix.** Same recovery as the 404 above — refresh **both** `az` and `azd` +independently. See the 404 section for the commands. + +--- + +## Auth & RBAC + +### Missing RBAC roles for hosted-agent deploy + +**Symptom.** `azd deploy` returns an authorization error even though `az` +and `azd` are freshly logged in; or `azd provision` succeeds but a later +step (e.g. Prompt Optimizer, LLM-judge evaluators) fails with a permissions +error. + +**Cause.** `azd provision` assigns the roles the deploying user and the +project's managed identity need. If the caller lacked +`User Access Administrator` on the RG at provision time, the role +assignments in `infra/core/ai/ai-project.bicep` were silently skipped. + +**Required roles.** Grounded in `infra/core/ai/ai-project.bicep`: + +*Provision-time (the user running `azd provision`), on the subscription or RG:* + +| Role | Why | +|------|-----| +| **Owner** *or* **Contributor** + **User Access Administrator** | Needed to create resources **and** create role assignments | + +*Data-plane (the user running `azd deploy`), auto-granted on the Foundry account:* + +| Role | Role definition ID | Why | +|------|--------------------|-----| +| **Azure AI User** (aka Foundry User) | `53ca6127-db72-4b80-b1b0-d745d6d5456d` | Auth to the project endpoint | +| **Azure AI Project Manager** | `eadc314b-1a2d-4efa-be10-5d325db5065e` | Create / update / delete hosted agents | +| **Cognitive Services OpenAI Contributor** | `a001fd3d-188f-4b5d-821b-7da978bf7442` | Prompt Optimizer (Core 03) | + +The project's system-assigned managed identity also gets +**Cognitive Services OpenAI User** and **Azure AI User** on the account for +hosted-agent inference and LLM-judge evaluators. + +**Check (CLI):** + +```bash +ME=$(az ad signed-in-user show --query id -o tsv) +ACCOUNT_ID=$(az cognitiveservices account show \ + -g "$AZURE_RESOURCE_GROUP" -n "$AZURE_AI_ACCOUNT_NAME" --query id -o tsv) +az role assignment list --assignee "$ME" --scope "$ACCOUNT_ID" \ + --query "[].{role:roleDefinitionName, scope:scope}" -o table +``` + +Expected rows include `Azure AI User`, `Azure AI Project Manager`, and +`Cognitive Services OpenAI Contributor`. + +**Check (portal).** Foundry account → **Access control (IAM)** → +**Role assignments** → filter by your UPN. Same three roles. + +**Fix.** Ask a subscription Owner to assign the three roles at the Foundry +account scope, or re-run `azd provision` as an Owner. + +--- + +## Mixed provisioning paths + +### UI provision + CLI deploy creates a second resource group + +**Symptom.** You provisioned via the portal (Lab 02), then ran +`azd env new … && azd provision` in Lab 05 — and Azure now shows **two** +resource groups (the portal RG + `rg-`). + +**Cause.** `azd env new` doesn't discover existing portal-created resources. +Without `AZURE_RESOURCE_GROUP` (and the Foundry account/project) seeded into +the env, `azd provision` synthesizes fresh names and creates a second RG. + +**Fix.** Run the linker script **once** before your first `azd` step: + +```bash +./scripts/link-portal-rg.sh +``` + +The script (idempotent) auto-discovers the portal-created RG, Foundry +account, and project, then seeds the `azd env` with `AZURE_RESOURCE_GROUP`, +`AZURE_AI_ACCOUNT_NAME`, `AZURE_AI_PROJECT_NAME`, and +`USE_EXISTING_AI_PROJECT=true`. After that, `azd provision` reuses the +portal RG. + +**Prevent.** If you took the portal path in Lab 02, always run the linker +before your first `azd env new … && azd provision`. + +--- + +## Notes + +- Single-turn agent behavior failures (evaluator score anomalies, wrong + specialist, hallucinated IDs) live in + [`labs/more/troubleshooting.md`](./more/troubleshooting.md) — that's a + diagnosis lab, not an infra reference. +- Report new gotchas by opening an issue or adding a section here following + the Symptom / Cause / Fix / Prevent template. diff --git a/labs/_template/lab-template.md b/labs/_template/lab-template.md index 4725f99..92f8fc5 100644 --- a/labs/_template/lab-template.md +++ b/labs/_template/lab-template.md @@ -42,7 +42,12 @@ flowchart LR > 💡 **Tip:** short, high-value hints go here. > -> ⚠️ **Gotcha:** call out common mistakes here. +> ⚠️ **Gotcha:** _small, lab-specific_ mistakes go inline (≤ 4 lines). +> +> ⚠️ **Gotcha — .** For _cross-cutting_ infra/tool errors +> (anything that recurs across labs or needs multi-step recovery), keep the +> callout to one line and link to the canonical entry in +> [`labs/TROUBLESHOOTING.md`](../TROUBLESHOOTING.md). ## ✅ Verify diff --git a/labs/fundamentals/01-provision-azd.md b/labs/fundamentals/01-provision-azd.md index e848806..c9123d4 100644 --- a/labs/fundamentals/01-provision-azd.md +++ b/labs/fundamentals/01-provision-azd.md @@ -159,6 +159,12 @@ Confirm you have: > are **not** provisioned in this lab — you enable and create them when you > deploy the hosted agent in [Lab 05](./05-deploy-hosted-agent.md). + > ⚠️ **Gotcha — soft-deleted resource blocks re-provision.** If you ran + > `azd provision` in this repo before and see `A soft-deleted resource with + > this name exists and is blocking deployment`, purge the account (or use a + > fresh env name). Details in + > [Troubleshooting · Soft-deleted Cognitive Services account](../TROUBLESHOOTING.md#soft-deleted-cognitive-services-account-blocks-re-provision). + 5. **Read the outputs.** @@ -176,9 +182,8 @@ Confirm you have: ![New Microsoft Foundry portal — New Foundry toggle on, Build tab highlighted, endpoint and API key visible on the overview](./images/01-provision-infra-03.png) - > ⚠️ **Gotcha:** if `azd provision` fails on quota, retry in a different region - > from the list above using `azd env set AZURE_LOCATION swedencentral` then - > `azd provision` again. + > ⚠️ **Gotcha — quota / capacity error on `azd provision`.** Details in + > [Troubleshooting · Quota / capacity errors](../TROUBLESHOOTING.md#quota--capacity-errors-on-azd-provision-or-model-deploy). ## ✅ Verify diff --git a/labs/fundamentals/03-deploy-models.md b/labs/fundamentals/03-deploy-models.md index c7665e9..6d14667 100644 --- a/labs/fundamentals/03-deploy-models.md +++ b/labs/fundamentals/03-deploy-models.md @@ -76,12 +76,10 @@ flowchart LR > azd provision > ``` > -> ⚠️ **Known limitation:** once this override is set, later re-provisions +> ⚠️ **Known limitation.** Once this override is set, later re-provisions > (e.g. enabling hosted agents in [Lab 05](./05-deploy-hosted-agent.md)) fail -> with `invalid character 'n' after object key:value pair` — azd 1.30 doesn't -> escape the JSON when it substitutes into the Bicep parameters file. Clear it -> before re-provisioning (`azd env set AI_PROJECT_DEPLOYMENTS "[]"`). Tracked -> as `TODO(nitya)` in [`infra/main.bicep`](../../infra/main.bicep). +> with `invalid character 'n' after object key:value pair`. Details in +> [Troubleshooting · `invalid character 'n'`](../TROUBLESHOOTING.md#azd-provision-fails-with-invalid-character-n-after-object-keyvalue-pair). **If you provisioned with the portal (Lab 02):** @@ -106,9 +104,8 @@ flowchart LR `gpt-5.4-judge`. 1. You'll reference this in Core Lab 02. -> ⚠️ **Gotcha:** if the deploy button is greyed out, you're out of quota. -> Try a different region from the supported list, or request a quota increase -> from **Management center → Quota**. +> ⚠️ **Gotcha — Deploy button greyed out.** You're out of quota. Details in +> [Troubleshooting · Quota / capacity errors](../TROUBLESHOOTING.md#quota--capacity-errors-on-azd-provision-or-model-deploy). ## ✅ Verify diff --git a/labs/fundamentals/05-deploy-hosted-agent.md b/labs/fundamentals/05-deploy-hosted-agent.md index f771490..9ab7876 100644 --- a/labs/fundamentals/05-deploy-hosted-agent.md +++ b/labs/fundamentals/05-deploy-hosted-agent.md @@ -79,19 +79,9 @@ host). You'll enable both below. This adds the registry + capability host to your existing resource group. > ⚠️ **Gotcha — `invalid character 'n' after object key:value pair`.** - > `azd provision` fails when your env has a custom `AI_PROJECT_DEPLOYMENTS` - > (or `AI_PROJECT_CONNECTIONS` / `_CREDENTIALS` / `_DEPENDENT_RESOURCES`) - > JSON value set — azd 1.30 doesn't escape the quotes when it substitutes - > it into the Bicep parameters file. Clear it and re-run; the defaults in - > `infra/main.bicep` still deploy `gpt-5.4-mini` + `gpt-5.4-judge`: - > - > ```bash - > azd env set AI_PROJECT_DEPLOYMENTS "[]" - > azd provision - > ``` - > - > Need a custom deployment list? See the workaround in - > [Lab 03](./03-deploy-models.md). + > A stale `AI_PROJECT_DEPLOYMENTS` env value breaks `azd provision`. Clear + > it with `azd env set AI_PROJECT_DEPLOYMENTS "[]"` and re-run. Details in + > [Troubleshooting · `invalid character 'n'`](../TROUBLESHOOTING.md#azd-provision-fails-with-invalid-character-n-after-object-keyvalue-pair). 3. **Deploy the hosted agent.** ```bash @@ -139,41 +129,13 @@ host). You'll enable both below. > manage** hosted agents but does not have a *create* flow for them. `azd > deploy` is the one supported way to publish a hosted agent today. -> ⚠️ **Gotcha — 409 Conflict on `azd deploy`.** If deploy fails with -> `RESPONSE 409: 409 Conflict … The resource already exists or was modified -> concurrently. Please retry.` and a plain retry doesn't clear it (portal may -> also show *"Project not found"* on the Agents blade), the Foundry data plane -> is holding a stale registration keyed on the current project/agent name. -> Recovery: -> -> ```bash -> azd down --purge --force # tear down + purge soft-delete -> azd env new contoso-travel-v2 # any new name → new account+project hash -> azd env set ENABLE_HOSTED_AGENTS true -> azd provision -> azd deploy contoso-travel-concierge -> ``` -> -> The new env name changes the `uniqueString()` hash used by the infra, which -> gives you a genuinely fresh Foundry project and clears the cache. - -> ⚠️ **Gotcha — 404 "Subdomain does not map to a resource" on `azd deploy`.** -> The Foundry agents data plane returns `RESPONSE 404: ResourceNotFound — -> Subdomain does not map to a resource` when the caller's bearer token is -> expired or revoked (typical trigger: `AADSTS50173` — a password change, -> credential rotation, or Conditional Access policy moved `TokensValidFrom` -> past your issued-at time). The account is fine; auth is stale. `azd deploy` -> uses its own token cache separate from `az`, so **both** must be refreshed: -> -> ```bash -> az logout && az login --tenant -> azd auth logout && azd auth login --tenant-id -> azd deploy contoso-travel-concierge -> ``` -> -> Quick sanity check that the resource itself is healthy (should return `HTTP -> 200` even unauthenticated): -> `curl -sS -o /dev/null -w "%{http_code}\n" https://$(azd env get-value AZURE_AI_ACCOUNT_NAME).services.ai.azure.com/` +> ⚠️ **Gotcha — 409 Conflict on `azd deploy`.** Stale Foundry data-plane +> state after a torn-down deploy. Recovery needs a fresh `azd env` name. +> Details in [Troubleshooting · 409 Conflict](../TROUBLESHOOTING.md#409-conflict-on-azd-deploy). + +> ⚠️ **Gotcha — 404 `Subdomain does not map to a resource` on `azd deploy`.** +> Stale bearer token (not the resource). Re-auth **both** `az` and `azd`. +> Details in [Troubleshooting · 404 Subdomain does not map](../TROUBLESHOOTING.md#404-subdomain-does-not-map-to-a-resource-on-azd-deploy). ## Redeploying after a code change diff --git a/specs/lab-template.schema.json b/specs/lab-template.schema.json index bc2b44a..0389143 100644 --- a/specs/lab-template.schema.json +++ b/specs/lab-template.schema.json @@ -23,6 +23,10 @@ "steps_section": { "type": "string", "pattern": "📋" }, "verify_section": { "type": "string", "pattern": "✅" }, "recap_section": { "type": "string", "pattern": "🧠" }, - "next_section": { "type": "string", "pattern": "➡️" } + "next_section": { "type": "string", "pattern": "➡️" }, + "gotcha_convention": { + "type": "string", + "description": "Non-schema-enforced authoring rule (guarded by tests/test_lab_content.py): a > ⚠️ **Gotcha** callout is either (a) a single lab-specific mistake, ≤ 4 lines, inline; or (b) a one-line pointer to labs/TROUBLESHOOTING.md# for cross-cutting infra/tool errors. Deep multi-step recovery details live only in labs/TROUBLESHOOTING.md." + } } } diff --git a/tests/test_lab_content.py b/tests/test_lab_content.py index cf26425..19d5ca0 100644 --- a/tests/test_lab_content.py +++ b/tests/test_lab_content.py @@ -1,4 +1,8 @@ """Every lab file must have the required pedagogy sections.""" +from __future__ import annotations + +import re + from conftest import SECTION_PATTERNS, lab_path, load_course_spec @@ -12,3 +16,59 @@ def test_all_labs_use_template_sections(): assert pattern.search(text), ( f"{phase['id']}/{lab['id']} missing section: {section}" ) + + +# Header shape from AGENTS.md § "Callout conventions — Gotchas": +# Inline: > ⚠️ **Gotcha:** ... +# Cross-cutting: > ⚠️ **Gotcha — .** ... (must link to TROUBLESHOOTING.md#anchor) +_GOTCHA_INLINE = re.compile(r"^\s*>\s*⚠️\s*\*\*Gotcha:\*\*") +_GOTCHA_CROSSCUT = re.compile(r"^\s*>\s*⚠️\s*\*\*Gotcha\s+—") +_TROUBLESHOOTING_LINK = re.compile(r"TROUBLESHOOTING\.md#") + + +def _iter_blockquotes(text: str): + """Yield (start_line, [line, ...]) for each contiguous `>`-prefixed block.""" + lines = text.splitlines() + i, n = 0, len(lines) + while i < n: + if re.match(r"^\s*>", lines[i]): + start = i + block = [] + while i < n and re.match(r"^\s*>", lines[i]): + block.append(lines[i]) + i += 1 + yield start, block + else: + i += 1 + + +def test_gotcha_callouts_follow_convention(): + """Enforce the two-variant Gotcha rule from AGENTS.md. + + - Inline (`> ⚠️ **Gotcha:**`): must be ≤ 4 lines of blockquote. + - Cross-cutting (`> ⚠️ **Gotcha — ...**`): must link to + `../TROUBLESHOOTING.md#` inside the same blockquote. + """ + spec = load_course_spec() + violations: list[str] = [] + for phase in spec["phases"]: + for lab in phase["labs"]: + p = lab_path(phase["id"], lab["id"]) + text = p.read_text(encoding="utf-8") + rel = f"{phase['id']}/{lab['id']}.md" + for start, block in _iter_blockquotes(text): + header = block[0] + if _GOTCHA_CROSSCUT.search(header): + body = "\n".join(block) + if not _TROUBLESHOOTING_LINK.search(body): + violations.append( + f"{rel}:{start + 1} cross-cutting Gotcha missing " + f"TROUBLESHOOTING.md link" + ) + elif _GOTCHA_INLINE.search(header) and len(block) > 4: + violations.append( + f"{rel}:{start + 1} inline Gotcha exceeds 4 lines " + f"({len(block)} lines) — split it out to " + f"labs/TROUBLESHOOTING.md and link instead" + ) + assert not violations, "gotcha convention violations:\n " + "\n ".join(violations) From 6bd77f9e98821f10d24672aecccd42dd4d69dfe1 Mon Sep 17 00:00:00 2001 From: Nitya Narasimhan Date: Tue, 18 Aug 2026 17:12:03 +0000 Subject: [PATCH 3/5] data: shift booking dates +730d to keep workshop future-relative Every date in flights.csv, hotels.csv, car_rentals.csv (and JSON mirrors + src/ + src.original/ copies) was in 2025, i.e. in the past relative to today (2026-08-18). Concierge answers were reduced to 'no availability' for every current-date-aware query, tanking Lab 04 grounding demos and every downstream Core lab (Observe/Evaluate/Optimize/Monitor). Shift: exactly +730 days (2 non-leap years) applied to every date column across all four copies. Relative gaps preserved (hotel stays, car rentals remain the same length). No schema changes (regex was date-only). No test changes (no date content assertions). Parity across the three CSV copies confirmed byte-identical. pytest -q -> 15 passed. Range after shift: min 2027-08-15, max 2028-01-05. --- data/car_rentals.csv | 30 ++++++++-------- data/flights.csv | 40 ++++++++++----------- data/hotels.csv | 30 ++++++++-------- data/json/car_rentals.json | 60 +++++++++++++++---------------- data/json/flights.json | 40 ++++++++++----------- data/json/hotels.json | 60 +++++++++++++++---------------- src.original/data/car_rentals.csv | 30 ++++++++-------- src.original/data/flights.csv | 40 ++++++++++----------- src.original/data/hotels.csv | 30 ++++++++-------- src/data/car_rentals.csv | 30 ++++++++-------- src/data/flights.csv | 40 ++++++++++----------- src/data/hotels.csv | 30 ++++++++-------- 12 files changed, 230 insertions(+), 230 deletions(-) diff --git a/data/car_rentals.csv b/data/car_rentals.csv index aa69160..8402644 100644 --- a/data/car_rentals.csv +++ b/data/car_rentals.csv @@ -1,16 +1,16 @@ rental_id,company,city,car_type,price_per_day_usd,available,pickup_date,return_date -CT-CR-001,Contoso Wheels,Paris,Economy,45.00,true,2025-08-15,2025-08-30 -CT-CR-002,Contoso Wheels,Paris,SUV,85.00,true,2025-08-15,2025-08-30 -CT-CR-003,EuroDrive,Paris,Luxury,150.00,true,2025-08-15,2025-08-30 -CT-CR-004,Contoso Wheels,London,Economy,50.00,true,2025-09-01,2025-09-15 -CT-CR-005,Contoso Wheels,London,SUV,95.00,true,2025-09-01,2025-09-15 -CT-CR-006,BritCars,London,Luxury,175.00,false,2025-09-01,2025-09-15 -CT-CR-007,Contoso Wheels,Tokyo,Economy,55.00,true,2025-10-05,2025-10-20 -CT-CR-008,NipponRide,Tokyo,Minivan,90.00,true,2025-10-05,2025-10-20 -CT-CR-009,NipponRide,Tokyo,Luxury,200.00,true,2025-10-05,2025-10-20 -CT-CR-010,Contoso Wheels,Rome,Economy,40.00,true,2025-11-01,2025-11-15 -CT-CR-011,ItaliaWheels,Rome,SUV,80.00,true,2025-11-01,2025-11-15 -CT-CR-012,ItaliaWheels,Rome,Luxury,160.00,false,2025-11-01,2025-11-15 -CT-CR-013,Contoso Wheels,Cancún,Economy,35.00,true,2025-12-20,2026-01-05 -CT-CR-014,SolRentals,Cancún,SUV,70.00,true,2025-12-20,2026-01-05 -CT-CR-015,SolRentals,Cancún,Minivan,65.00,true,2025-12-20,2026-01-05 +CT-CR-001,Contoso Wheels,Paris,Economy,45.00,true,2027-08-15,2027-08-30 +CT-CR-002,Contoso Wheels,Paris,SUV,85.00,true,2027-08-15,2027-08-30 +CT-CR-003,EuroDrive,Paris,Luxury,150.00,true,2027-08-15,2027-08-30 +CT-CR-004,Contoso Wheels,London,Economy,50.00,true,2027-09-01,2027-09-15 +CT-CR-005,Contoso Wheels,London,SUV,95.00,true,2027-09-01,2027-09-15 +CT-CR-006,BritCars,London,Luxury,175.00,false,2027-09-01,2027-09-15 +CT-CR-007,Contoso Wheels,Tokyo,Economy,55.00,true,2027-10-05,2027-10-20 +CT-CR-008,NipponRide,Tokyo,Minivan,90.00,true,2027-10-05,2027-10-20 +CT-CR-009,NipponRide,Tokyo,Luxury,200.00,true,2027-10-05,2027-10-20 +CT-CR-010,Contoso Wheels,Rome,Economy,40.00,true,2027-11-01,2027-11-15 +CT-CR-011,ItaliaWheels,Rome,SUV,80.00,true,2027-11-01,2027-11-15 +CT-CR-012,ItaliaWheels,Rome,Luxury,160.00,false,2027-11-01,2027-11-15 +CT-CR-013,Contoso Wheels,Cancún,Economy,35.00,true,2027-12-20,2028-01-05 +CT-CR-014,SolRentals,Cancún,SUV,70.00,true,2027-12-20,2028-01-05 +CT-CR-015,SolRentals,Cancún,Minivan,65.00,true,2027-12-20,2028-01-05 diff --git a/data/flights.csv b/data/flights.csv index cdb119b..398114c 100644 --- a/data/flights.csv +++ b/data/flights.csv @@ -1,21 +1,21 @@ flight_id,airline,origin,destination,departure_date,departure_time,arrival_time,price_usd,cabin_class,available_seats -CT-FL-001,Contoso Skyways,Seattle,Paris,2025-08-15,08:30,04:30+1,750.00,Economy,42 -CT-FL-002,Contoso Skyways,Seattle,Paris,2025-08-15,14:00,10:00+1,1450.00,Business,12 -CT-FL-003,Contoso Skyways,Paris,Seattle,2025-08-22,11:00,14:00,780.00,Economy,38 -CT-FL-004,Contoso Skyways,Paris,Seattle,2025-08-22,18:00,21:00,1520.00,Business,8 -CT-FL-005,Atlantic Jet,New York,London,2025-09-01,19:00,07:00+1,620.00,Economy,55 -CT-FL-006,Atlantic Jet,New York,London,2025-09-01,22:00,10:00+1,2100.00,First,4 -CT-FL-007,Atlantic Jet,London,New York,2025-09-10,09:00,12:00,650.00,Economy,48 -CT-FL-008,Atlantic Jet,London,New York,2025-09-10,15:00,18:00,1380.00,Business,10 -CT-FL-009,Pacific Wings,San Francisco,Tokyo,2025-10-05,13:00,17:00+1,890.00,Economy,60 -CT-FL-010,Pacific Wings,San Francisco,Tokyo,2025-10-05,23:00,05:00+2,2450.00,Business,6 -CT-FL-011,Pacific Wings,Tokyo,San Francisco,2025-10-15,10:00,06:00,920.00,Economy,52 -CT-FL-012,Pacific Wings,Tokyo,San Francisco,2025-10-15,22:00,18:00,2500.00,First,3 -CT-FL-013,EuroStar Air,Chicago,Rome,2025-11-01,16:00,08:00+1,710.00,Economy,45 -CT-FL-014,EuroStar Air,Chicago,Rome,2025-11-01,20:00,12:00+1,1680.00,Business,9 -CT-FL-015,EuroStar Air,Rome,Chicago,2025-11-10,07:00,12:00,740.00,Economy,40 -CT-FL-016,EuroStar Air,Rome,Chicago,2025-11-10,14:00,19:00,1700.00,Business,7 -CT-FL-017,SunBird Airlines,Denver,Cancún,2025-12-20,06:00,11:30,480.00,Economy,70 -CT-FL-018,SunBird Airlines,Denver,Cancún,2025-12-20,10:00,15:30,950.00,Business,15 -CT-FL-019,SunBird Airlines,Cancún,Denver,2025-12-28,14:00,18:30,510.00,Economy,65 -CT-FL-020,SunBird Airlines,Cancún,Denver,2025-12-28,08:00,12:30,980.00,Business,11 +CT-FL-001,Contoso Skyways,Seattle,Paris,2027-08-15,08:30,04:30+1,750.00,Economy,42 +CT-FL-002,Contoso Skyways,Seattle,Paris,2027-08-15,14:00,10:00+1,1450.00,Business,12 +CT-FL-003,Contoso Skyways,Paris,Seattle,2027-08-22,11:00,14:00,780.00,Economy,38 +CT-FL-004,Contoso Skyways,Paris,Seattle,2027-08-22,18:00,21:00,1520.00,Business,8 +CT-FL-005,Atlantic Jet,New York,London,2027-09-01,19:00,07:00+1,620.00,Economy,55 +CT-FL-006,Atlantic Jet,New York,London,2027-09-01,22:00,10:00+1,2100.00,First,4 +CT-FL-007,Atlantic Jet,London,New York,2027-09-10,09:00,12:00,650.00,Economy,48 +CT-FL-008,Atlantic Jet,London,New York,2027-09-10,15:00,18:00,1380.00,Business,10 +CT-FL-009,Pacific Wings,San Francisco,Tokyo,2027-10-05,13:00,17:00+1,890.00,Economy,60 +CT-FL-010,Pacific Wings,San Francisco,Tokyo,2027-10-05,23:00,05:00+2,2450.00,Business,6 +CT-FL-011,Pacific Wings,Tokyo,San Francisco,2027-10-15,10:00,06:00,920.00,Economy,52 +CT-FL-012,Pacific Wings,Tokyo,San Francisco,2027-10-15,22:00,18:00,2500.00,First,3 +CT-FL-013,EuroStar Air,Chicago,Rome,2027-11-01,16:00,08:00+1,710.00,Economy,45 +CT-FL-014,EuroStar Air,Chicago,Rome,2027-11-01,20:00,12:00+1,1680.00,Business,9 +CT-FL-015,EuroStar Air,Rome,Chicago,2027-11-10,07:00,12:00,740.00,Economy,40 +CT-FL-016,EuroStar Air,Rome,Chicago,2027-11-10,14:00,19:00,1700.00,Business,7 +CT-FL-017,SunBird Airlines,Denver,Cancún,2027-12-20,06:00,11:30,480.00,Economy,70 +CT-FL-018,SunBird Airlines,Denver,Cancún,2027-12-20,10:00,15:30,950.00,Business,15 +CT-FL-019,SunBird Airlines,Cancún,Denver,2027-12-28,14:00,18:30,510.00,Economy,65 +CT-FL-020,SunBird Airlines,Cancún,Denver,2027-12-28,08:00,12:30,980.00,Business,11 diff --git a/data/hotels.csv b/data/hotels.csv index 5c82e4f..fc4f55e 100644 --- a/data/hotels.csv +++ b/data/hotels.csv @@ -1,16 +1,16 @@ hotel_id,name,city,country,star_rating,price_per_night_usd,amenities,available_rooms,check_in_date,check_out_date -CT-HT-001,Le Marais Grand Hotel,Paris,France,5,320.00,"WiFi,Pool,Spa,Restaurant,Gym",8,2025-08-15,2025-08-30 -CT-HT-002,Montmartre Budget Inn,Paris,France,3,95.00,"WiFi,Breakfast",22,2025-08-15,2025-08-30 -CT-HT-003,Seine River Suites,Paris,France,4,210.00,"WiFi,Restaurant,Gym,River View",14,2025-08-15,2025-08-30 -CT-HT-004,The Westminster Palace,London,United Kingdom,5,380.00,"WiFi,Pool,Spa,Restaurant,Concierge",6,2025-09-01,2025-09-15 -CT-HT-005,Camden Town Hostel,London,United Kingdom,2,65.00,"WiFi,Shared Kitchen",30,2025-09-01,2025-09-15 -CT-HT-006,Kensington Gardens Hotel,London,United Kingdom,4,245.00,"WiFi,Restaurant,Gym,Parking",11,2025-09-01,2025-09-15 -CT-HT-007,Shibuya Sky Tower Hotel,Tokyo,Japan,5,290.00,"WiFi,Pool,Spa,Restaurant,Rooftop Bar",10,2025-10-05,2025-10-20 -CT-HT-008,Asakusa Traditional Ryokan,Tokyo,Japan,4,180.00,"WiFi,Hot Spring,Traditional Breakfast,Garden",5,2025-10-05,2025-10-20 -CT-HT-009,Shinjuku Business Hotel,Tokyo,Japan,3,110.00,"WiFi,Breakfast,Laundry",25,2025-10-05,2025-10-20 -CT-HT-010,Roma Colosseum View,Rome,Italy,4,230.00,"WiFi,Restaurant,Rooftop Terrace,Breakfast",12,2025-11-01,2025-11-15 -CT-HT-011,Trastevere Boutique B&B,Rome,Italy,3,125.00,"WiFi,Breakfast,Garden",9,2025-11-01,2025-11-15 -CT-HT-012,Vatican Luxury Residence,Rome,Italy,5,410.00,"WiFi,Pool,Spa,Restaurant,Concierge,Gym",4,2025-11-01,2025-11-15 -CT-HT-013,Cancún Beachfront Resort,Cancún,Mexico,5,350.00,"WiFi,Pool,Beach Access,Spa,All-Inclusive,Kids Club",20,2025-12-20,2026-01-05 -CT-HT-014,Playa Del Sol Hotel,Cancún,Mexico,4,195.00,"WiFi,Pool,Beach Access,Restaurant",16,2025-12-20,2026-01-05 -CT-HT-015,Centro Cancún Budget Stay,Cancún,Mexico,2,72.00,"WiFi,Breakfast,Parking",35,2025-12-20,2026-01-05 +CT-HT-001,Le Marais Grand Hotel,Paris,France,5,320.00,"WiFi,Pool,Spa,Restaurant,Gym",8,2027-08-15,2027-08-30 +CT-HT-002,Montmartre Budget Inn,Paris,France,3,95.00,"WiFi,Breakfast",22,2027-08-15,2027-08-30 +CT-HT-003,Seine River Suites,Paris,France,4,210.00,"WiFi,Restaurant,Gym,River View",14,2027-08-15,2027-08-30 +CT-HT-004,The Westminster Palace,London,United Kingdom,5,380.00,"WiFi,Pool,Spa,Restaurant,Concierge",6,2027-09-01,2027-09-15 +CT-HT-005,Camden Town Hostel,London,United Kingdom,2,65.00,"WiFi,Shared Kitchen",30,2027-09-01,2027-09-15 +CT-HT-006,Kensington Gardens Hotel,London,United Kingdom,4,245.00,"WiFi,Restaurant,Gym,Parking",11,2027-09-01,2027-09-15 +CT-HT-007,Shibuya Sky Tower Hotel,Tokyo,Japan,5,290.00,"WiFi,Pool,Spa,Restaurant,Rooftop Bar",10,2027-10-05,2027-10-20 +CT-HT-008,Asakusa Traditional Ryokan,Tokyo,Japan,4,180.00,"WiFi,Hot Spring,Traditional Breakfast,Garden",5,2027-10-05,2027-10-20 +CT-HT-009,Shinjuku Business Hotel,Tokyo,Japan,3,110.00,"WiFi,Breakfast,Laundry",25,2027-10-05,2027-10-20 +CT-HT-010,Roma Colosseum View,Rome,Italy,4,230.00,"WiFi,Restaurant,Rooftop Terrace,Breakfast",12,2027-11-01,2027-11-15 +CT-HT-011,Trastevere Boutique B&B,Rome,Italy,3,125.00,"WiFi,Breakfast,Garden",9,2027-11-01,2027-11-15 +CT-HT-012,Vatican Luxury Residence,Rome,Italy,5,410.00,"WiFi,Pool,Spa,Restaurant,Concierge,Gym",4,2027-11-01,2027-11-15 +CT-HT-013,Cancún Beachfront Resort,Cancún,Mexico,5,350.00,"WiFi,Pool,Beach Access,Spa,All-Inclusive,Kids Club",20,2027-12-20,2028-01-05 +CT-HT-014,Playa Del Sol Hotel,Cancún,Mexico,4,195.00,"WiFi,Pool,Beach Access,Restaurant",16,2027-12-20,2028-01-05 +CT-HT-015,Centro Cancún Budget Stay,Cancún,Mexico,2,72.00,"WiFi,Breakfast,Parking",35,2027-12-20,2028-01-05 diff --git a/data/json/car_rentals.json b/data/json/car_rentals.json index 53ed607..37480d9 100644 --- a/data/json/car_rentals.json +++ b/data/json/car_rentals.json @@ -6,8 +6,8 @@ "car_type": "Economy", "price_per_day_usd": "45.00", "available": "true", - "pickup_date": "2025-08-15", - "return_date": "2025-08-30" + "pickup_date": "2027-08-15", + "return_date": "2027-08-30" }, { "rental_id": "CT-CR-002", @@ -16,8 +16,8 @@ "car_type": "SUV", "price_per_day_usd": "85.00", "available": "true", - "pickup_date": "2025-08-15", - "return_date": "2025-08-30" + "pickup_date": "2027-08-15", + "return_date": "2027-08-30" }, { "rental_id": "CT-CR-003", @@ -26,8 +26,8 @@ "car_type": "Luxury", "price_per_day_usd": "150.00", "available": "true", - "pickup_date": "2025-08-15", - "return_date": "2025-08-30" + "pickup_date": "2027-08-15", + "return_date": "2027-08-30" }, { "rental_id": "CT-CR-004", @@ -36,8 +36,8 @@ "car_type": "Economy", "price_per_day_usd": "50.00", "available": "true", - "pickup_date": "2025-09-01", - "return_date": "2025-09-15" + "pickup_date": "2027-09-01", + "return_date": "2027-09-15" }, { "rental_id": "CT-CR-005", @@ -46,8 +46,8 @@ "car_type": "SUV", "price_per_day_usd": "95.00", "available": "true", - "pickup_date": "2025-09-01", - "return_date": "2025-09-15" + "pickup_date": "2027-09-01", + "return_date": "2027-09-15" }, { "rental_id": "CT-CR-006", @@ -56,8 +56,8 @@ "car_type": "Luxury", "price_per_day_usd": "175.00", "available": "false", - "pickup_date": "2025-09-01", - "return_date": "2025-09-15" + "pickup_date": "2027-09-01", + "return_date": "2027-09-15" }, { "rental_id": "CT-CR-007", @@ -66,8 +66,8 @@ "car_type": "Economy", "price_per_day_usd": "55.00", "available": "true", - "pickup_date": "2025-10-05", - "return_date": "2025-10-20" + "pickup_date": "2027-10-05", + "return_date": "2027-10-20" }, { "rental_id": "CT-CR-008", @@ -76,8 +76,8 @@ "car_type": "Minivan", "price_per_day_usd": "90.00", "available": "true", - "pickup_date": "2025-10-05", - "return_date": "2025-10-20" + "pickup_date": "2027-10-05", + "return_date": "2027-10-20" }, { "rental_id": "CT-CR-009", @@ -86,8 +86,8 @@ "car_type": "Luxury", "price_per_day_usd": "200.00", "available": "true", - "pickup_date": "2025-10-05", - "return_date": "2025-10-20" + "pickup_date": "2027-10-05", + "return_date": "2027-10-20" }, { "rental_id": "CT-CR-010", @@ -96,8 +96,8 @@ "car_type": "Economy", "price_per_day_usd": "40.00", "available": "true", - "pickup_date": "2025-11-01", - "return_date": "2025-11-15" + "pickup_date": "2027-11-01", + "return_date": "2027-11-15" }, { "rental_id": "CT-CR-011", @@ -106,8 +106,8 @@ "car_type": "SUV", "price_per_day_usd": "80.00", "available": "true", - "pickup_date": "2025-11-01", - "return_date": "2025-11-15" + "pickup_date": "2027-11-01", + "return_date": "2027-11-15" }, { "rental_id": "CT-CR-012", @@ -116,8 +116,8 @@ "car_type": "Luxury", "price_per_day_usd": "160.00", "available": "false", - "pickup_date": "2025-11-01", - "return_date": "2025-11-15" + "pickup_date": "2027-11-01", + "return_date": "2027-11-15" }, { "rental_id": "CT-CR-013", @@ -126,8 +126,8 @@ "car_type": "Economy", "price_per_day_usd": "35.00", "available": "true", - "pickup_date": "2025-12-20", - "return_date": "2026-01-05" + "pickup_date": "2027-12-20", + "return_date": "2028-01-05" }, { "rental_id": "CT-CR-014", @@ -136,8 +136,8 @@ "car_type": "SUV", "price_per_day_usd": "70.00", "available": "true", - "pickup_date": "2025-12-20", - "return_date": "2026-01-05" + "pickup_date": "2027-12-20", + "return_date": "2028-01-05" }, { "rental_id": "CT-CR-015", @@ -146,7 +146,7 @@ "car_type": "Minivan", "price_per_day_usd": "65.00", "available": "true", - "pickup_date": "2025-12-20", - "return_date": "2026-01-05" + "pickup_date": "2027-12-20", + "return_date": "2028-01-05" } ] diff --git a/data/json/flights.json b/data/json/flights.json index 9a2169f..82720ef 100644 --- a/data/json/flights.json +++ b/data/json/flights.json @@ -4,7 +4,7 @@ "airline": "Contoso Skyways", "origin": "Seattle", "destination": "Paris", - "departure_date": "2025-08-15", + "departure_date": "2027-08-15", "departure_time": "08:30", "arrival_time": "04:30+1", "price_usd": "750.00", @@ -16,7 +16,7 @@ "airline": "Contoso Skyways", "origin": "Seattle", "destination": "Paris", - "departure_date": "2025-08-15", + "departure_date": "2027-08-15", "departure_time": "14:00", "arrival_time": "10:00+1", "price_usd": "1450.00", @@ -28,7 +28,7 @@ "airline": "Contoso Skyways", "origin": "Paris", "destination": "Seattle", - "departure_date": "2025-08-22", + "departure_date": "2027-08-22", "departure_time": "11:00", "arrival_time": "14:00", "price_usd": "780.00", @@ -40,7 +40,7 @@ "airline": "Contoso Skyways", "origin": "Paris", "destination": "Seattle", - "departure_date": "2025-08-22", + "departure_date": "2027-08-22", "departure_time": "18:00", "arrival_time": "21:00", "price_usd": "1520.00", @@ -52,7 +52,7 @@ "airline": "Atlantic Jet", "origin": "New York", "destination": "London", - "departure_date": "2025-09-01", + "departure_date": "2027-09-01", "departure_time": "19:00", "arrival_time": "07:00+1", "price_usd": "620.00", @@ -64,7 +64,7 @@ "airline": "Atlantic Jet", "origin": "New York", "destination": "London", - "departure_date": "2025-09-01", + "departure_date": "2027-09-01", "departure_time": "22:00", "arrival_time": "10:00+1", "price_usd": "2100.00", @@ -76,7 +76,7 @@ "airline": "Atlantic Jet", "origin": "London", "destination": "New York", - "departure_date": "2025-09-10", + "departure_date": "2027-09-10", "departure_time": "09:00", "arrival_time": "12:00", "price_usd": "650.00", @@ -88,7 +88,7 @@ "airline": "Atlantic Jet", "origin": "London", "destination": "New York", - "departure_date": "2025-09-10", + "departure_date": "2027-09-10", "departure_time": "15:00", "arrival_time": "18:00", "price_usd": "1380.00", @@ -100,7 +100,7 @@ "airline": "Pacific Wings", "origin": "San Francisco", "destination": "Tokyo", - "departure_date": "2025-10-05", + "departure_date": "2027-10-05", "departure_time": "13:00", "arrival_time": "17:00+1", "price_usd": "890.00", @@ -112,7 +112,7 @@ "airline": "Pacific Wings", "origin": "San Francisco", "destination": "Tokyo", - "departure_date": "2025-10-05", + "departure_date": "2027-10-05", "departure_time": "23:00", "arrival_time": "05:00+2", "price_usd": "2450.00", @@ -124,7 +124,7 @@ "airline": "Pacific Wings", "origin": "Tokyo", "destination": "San Francisco", - "departure_date": "2025-10-15", + "departure_date": "2027-10-15", "departure_time": "10:00", "arrival_time": "06:00", "price_usd": "920.00", @@ -136,7 +136,7 @@ "airline": "Pacific Wings", "origin": "Tokyo", "destination": "San Francisco", - "departure_date": "2025-10-15", + "departure_date": "2027-10-15", "departure_time": "22:00", "arrival_time": "18:00", "price_usd": "2500.00", @@ -148,7 +148,7 @@ "airline": "EuroStar Air", "origin": "Chicago", "destination": "Rome", - "departure_date": "2025-11-01", + "departure_date": "2027-11-01", "departure_time": "16:00", "arrival_time": "08:00+1", "price_usd": "710.00", @@ -160,7 +160,7 @@ "airline": "EuroStar Air", "origin": "Chicago", "destination": "Rome", - "departure_date": "2025-11-01", + "departure_date": "2027-11-01", "departure_time": "20:00", "arrival_time": "12:00+1", "price_usd": "1680.00", @@ -172,7 +172,7 @@ "airline": "EuroStar Air", "origin": "Rome", "destination": "Chicago", - "departure_date": "2025-11-10", + "departure_date": "2027-11-10", "departure_time": "07:00", "arrival_time": "12:00", "price_usd": "740.00", @@ -184,7 +184,7 @@ "airline": "EuroStar Air", "origin": "Rome", "destination": "Chicago", - "departure_date": "2025-11-10", + "departure_date": "2027-11-10", "departure_time": "14:00", "arrival_time": "19:00", "price_usd": "1700.00", @@ -196,7 +196,7 @@ "airline": "SunBird Airlines", "origin": "Denver", "destination": "Canc\u00fan", - "departure_date": "2025-12-20", + "departure_date": "2027-12-20", "departure_time": "06:00", "arrival_time": "11:30", "price_usd": "480.00", @@ -208,7 +208,7 @@ "airline": "SunBird Airlines", "origin": "Denver", "destination": "Canc\u00fan", - "departure_date": "2025-12-20", + "departure_date": "2027-12-20", "departure_time": "10:00", "arrival_time": "15:30", "price_usd": "950.00", @@ -220,7 +220,7 @@ "airline": "SunBird Airlines", "origin": "Canc\u00fan", "destination": "Denver", - "departure_date": "2025-12-28", + "departure_date": "2027-12-28", "departure_time": "14:00", "arrival_time": "18:30", "price_usd": "510.00", @@ -232,7 +232,7 @@ "airline": "SunBird Airlines", "origin": "Canc\u00fan", "destination": "Denver", - "departure_date": "2025-12-28", + "departure_date": "2027-12-28", "departure_time": "08:00", "arrival_time": "12:30", "price_usd": "980.00", diff --git a/data/json/hotels.json b/data/json/hotels.json index 131faf7..d9b8380 100644 --- a/data/json/hotels.json +++ b/data/json/hotels.json @@ -8,8 +8,8 @@ "price_per_night_usd": "320.00", "amenities": "WiFi,Pool,Spa,Restaurant,Gym", "available_rooms": "8", - "check_in_date": "2025-08-15", - "check_out_date": "2025-08-30" + "check_in_date": "2027-08-15", + "check_out_date": "2027-08-30" }, { "hotel_id": "CT-HT-002", @@ -20,8 +20,8 @@ "price_per_night_usd": "95.00", "amenities": "WiFi,Breakfast", "available_rooms": "22", - "check_in_date": "2025-08-15", - "check_out_date": "2025-08-30" + "check_in_date": "2027-08-15", + "check_out_date": "2027-08-30" }, { "hotel_id": "CT-HT-003", @@ -32,8 +32,8 @@ "price_per_night_usd": "210.00", "amenities": "WiFi,Restaurant,Gym,River View", "available_rooms": "14", - "check_in_date": "2025-08-15", - "check_out_date": "2025-08-30" + "check_in_date": "2027-08-15", + "check_out_date": "2027-08-30" }, { "hotel_id": "CT-HT-004", @@ -44,8 +44,8 @@ "price_per_night_usd": "380.00", "amenities": "WiFi,Pool,Spa,Restaurant,Concierge", "available_rooms": "6", - "check_in_date": "2025-09-01", - "check_out_date": "2025-09-15" + "check_in_date": "2027-09-01", + "check_out_date": "2027-09-15" }, { "hotel_id": "CT-HT-005", @@ -56,8 +56,8 @@ "price_per_night_usd": "65.00", "amenities": "WiFi,Shared Kitchen", "available_rooms": "30", - "check_in_date": "2025-09-01", - "check_out_date": "2025-09-15" + "check_in_date": "2027-09-01", + "check_out_date": "2027-09-15" }, { "hotel_id": "CT-HT-006", @@ -68,8 +68,8 @@ "price_per_night_usd": "245.00", "amenities": "WiFi,Restaurant,Gym,Parking", "available_rooms": "11", - "check_in_date": "2025-09-01", - "check_out_date": "2025-09-15" + "check_in_date": "2027-09-01", + "check_out_date": "2027-09-15" }, { "hotel_id": "CT-HT-007", @@ -80,8 +80,8 @@ "price_per_night_usd": "290.00", "amenities": "WiFi,Pool,Spa,Restaurant,Rooftop Bar", "available_rooms": "10", - "check_in_date": "2025-10-05", - "check_out_date": "2025-10-20" + "check_in_date": "2027-10-05", + "check_out_date": "2027-10-20" }, { "hotel_id": "CT-HT-008", @@ -92,8 +92,8 @@ "price_per_night_usd": "180.00", "amenities": "WiFi,Hot Spring,Traditional Breakfast,Garden", "available_rooms": "5", - "check_in_date": "2025-10-05", - "check_out_date": "2025-10-20" + "check_in_date": "2027-10-05", + "check_out_date": "2027-10-20" }, { "hotel_id": "CT-HT-009", @@ -104,8 +104,8 @@ "price_per_night_usd": "110.00", "amenities": "WiFi,Breakfast,Laundry", "available_rooms": "25", - "check_in_date": "2025-10-05", - "check_out_date": "2025-10-20" + "check_in_date": "2027-10-05", + "check_out_date": "2027-10-20" }, { "hotel_id": "CT-HT-010", @@ -116,8 +116,8 @@ "price_per_night_usd": "230.00", "amenities": "WiFi,Restaurant,Rooftop Terrace,Breakfast", "available_rooms": "12", - "check_in_date": "2025-11-01", - "check_out_date": "2025-11-15" + "check_in_date": "2027-11-01", + "check_out_date": "2027-11-15" }, { "hotel_id": "CT-HT-011", @@ -128,8 +128,8 @@ "price_per_night_usd": "125.00", "amenities": "WiFi,Breakfast,Garden", "available_rooms": "9", - "check_in_date": "2025-11-01", - "check_out_date": "2025-11-15" + "check_in_date": "2027-11-01", + "check_out_date": "2027-11-15" }, { "hotel_id": "CT-HT-012", @@ -140,8 +140,8 @@ "price_per_night_usd": "410.00", "amenities": "WiFi,Pool,Spa,Restaurant,Concierge,Gym", "available_rooms": "4", - "check_in_date": "2025-11-01", - "check_out_date": "2025-11-15" + "check_in_date": "2027-11-01", + "check_out_date": "2027-11-15" }, { "hotel_id": "CT-HT-013", @@ -152,8 +152,8 @@ "price_per_night_usd": "350.00", "amenities": "WiFi,Pool,Beach Access,Spa,All-Inclusive,Kids Club", "available_rooms": "20", - "check_in_date": "2025-12-20", - "check_out_date": "2026-01-05" + "check_in_date": "2027-12-20", + "check_out_date": "2028-01-05" }, { "hotel_id": "CT-HT-014", @@ -164,8 +164,8 @@ "price_per_night_usd": "195.00", "amenities": "WiFi,Pool,Beach Access,Restaurant", "available_rooms": "16", - "check_in_date": "2025-12-20", - "check_out_date": "2026-01-05" + "check_in_date": "2027-12-20", + "check_out_date": "2028-01-05" }, { "hotel_id": "CT-HT-015", @@ -176,7 +176,7 @@ "price_per_night_usd": "72.00", "amenities": "WiFi,Breakfast,Parking", "available_rooms": "35", - "check_in_date": "2025-12-20", - "check_out_date": "2026-01-05" + "check_in_date": "2027-12-20", + "check_out_date": "2028-01-05" } ] diff --git a/src.original/data/car_rentals.csv b/src.original/data/car_rentals.csv index aa69160..8402644 100644 --- a/src.original/data/car_rentals.csv +++ b/src.original/data/car_rentals.csv @@ -1,16 +1,16 @@ rental_id,company,city,car_type,price_per_day_usd,available,pickup_date,return_date -CT-CR-001,Contoso Wheels,Paris,Economy,45.00,true,2025-08-15,2025-08-30 -CT-CR-002,Contoso Wheels,Paris,SUV,85.00,true,2025-08-15,2025-08-30 -CT-CR-003,EuroDrive,Paris,Luxury,150.00,true,2025-08-15,2025-08-30 -CT-CR-004,Contoso Wheels,London,Economy,50.00,true,2025-09-01,2025-09-15 -CT-CR-005,Contoso Wheels,London,SUV,95.00,true,2025-09-01,2025-09-15 -CT-CR-006,BritCars,London,Luxury,175.00,false,2025-09-01,2025-09-15 -CT-CR-007,Contoso Wheels,Tokyo,Economy,55.00,true,2025-10-05,2025-10-20 -CT-CR-008,NipponRide,Tokyo,Minivan,90.00,true,2025-10-05,2025-10-20 -CT-CR-009,NipponRide,Tokyo,Luxury,200.00,true,2025-10-05,2025-10-20 -CT-CR-010,Contoso Wheels,Rome,Economy,40.00,true,2025-11-01,2025-11-15 -CT-CR-011,ItaliaWheels,Rome,SUV,80.00,true,2025-11-01,2025-11-15 -CT-CR-012,ItaliaWheels,Rome,Luxury,160.00,false,2025-11-01,2025-11-15 -CT-CR-013,Contoso Wheels,Cancún,Economy,35.00,true,2025-12-20,2026-01-05 -CT-CR-014,SolRentals,Cancún,SUV,70.00,true,2025-12-20,2026-01-05 -CT-CR-015,SolRentals,Cancún,Minivan,65.00,true,2025-12-20,2026-01-05 +CT-CR-001,Contoso Wheels,Paris,Economy,45.00,true,2027-08-15,2027-08-30 +CT-CR-002,Contoso Wheels,Paris,SUV,85.00,true,2027-08-15,2027-08-30 +CT-CR-003,EuroDrive,Paris,Luxury,150.00,true,2027-08-15,2027-08-30 +CT-CR-004,Contoso Wheels,London,Economy,50.00,true,2027-09-01,2027-09-15 +CT-CR-005,Contoso Wheels,London,SUV,95.00,true,2027-09-01,2027-09-15 +CT-CR-006,BritCars,London,Luxury,175.00,false,2027-09-01,2027-09-15 +CT-CR-007,Contoso Wheels,Tokyo,Economy,55.00,true,2027-10-05,2027-10-20 +CT-CR-008,NipponRide,Tokyo,Minivan,90.00,true,2027-10-05,2027-10-20 +CT-CR-009,NipponRide,Tokyo,Luxury,200.00,true,2027-10-05,2027-10-20 +CT-CR-010,Contoso Wheels,Rome,Economy,40.00,true,2027-11-01,2027-11-15 +CT-CR-011,ItaliaWheels,Rome,SUV,80.00,true,2027-11-01,2027-11-15 +CT-CR-012,ItaliaWheels,Rome,Luxury,160.00,false,2027-11-01,2027-11-15 +CT-CR-013,Contoso Wheels,Cancún,Economy,35.00,true,2027-12-20,2028-01-05 +CT-CR-014,SolRentals,Cancún,SUV,70.00,true,2027-12-20,2028-01-05 +CT-CR-015,SolRentals,Cancún,Minivan,65.00,true,2027-12-20,2028-01-05 diff --git a/src.original/data/flights.csv b/src.original/data/flights.csv index cdb119b..398114c 100644 --- a/src.original/data/flights.csv +++ b/src.original/data/flights.csv @@ -1,21 +1,21 @@ flight_id,airline,origin,destination,departure_date,departure_time,arrival_time,price_usd,cabin_class,available_seats -CT-FL-001,Contoso Skyways,Seattle,Paris,2025-08-15,08:30,04:30+1,750.00,Economy,42 -CT-FL-002,Contoso Skyways,Seattle,Paris,2025-08-15,14:00,10:00+1,1450.00,Business,12 -CT-FL-003,Contoso Skyways,Paris,Seattle,2025-08-22,11:00,14:00,780.00,Economy,38 -CT-FL-004,Contoso Skyways,Paris,Seattle,2025-08-22,18:00,21:00,1520.00,Business,8 -CT-FL-005,Atlantic Jet,New York,London,2025-09-01,19:00,07:00+1,620.00,Economy,55 -CT-FL-006,Atlantic Jet,New York,London,2025-09-01,22:00,10:00+1,2100.00,First,4 -CT-FL-007,Atlantic Jet,London,New York,2025-09-10,09:00,12:00,650.00,Economy,48 -CT-FL-008,Atlantic Jet,London,New York,2025-09-10,15:00,18:00,1380.00,Business,10 -CT-FL-009,Pacific Wings,San Francisco,Tokyo,2025-10-05,13:00,17:00+1,890.00,Economy,60 -CT-FL-010,Pacific Wings,San Francisco,Tokyo,2025-10-05,23:00,05:00+2,2450.00,Business,6 -CT-FL-011,Pacific Wings,Tokyo,San Francisco,2025-10-15,10:00,06:00,920.00,Economy,52 -CT-FL-012,Pacific Wings,Tokyo,San Francisco,2025-10-15,22:00,18:00,2500.00,First,3 -CT-FL-013,EuroStar Air,Chicago,Rome,2025-11-01,16:00,08:00+1,710.00,Economy,45 -CT-FL-014,EuroStar Air,Chicago,Rome,2025-11-01,20:00,12:00+1,1680.00,Business,9 -CT-FL-015,EuroStar Air,Rome,Chicago,2025-11-10,07:00,12:00,740.00,Economy,40 -CT-FL-016,EuroStar Air,Rome,Chicago,2025-11-10,14:00,19:00,1700.00,Business,7 -CT-FL-017,SunBird Airlines,Denver,Cancún,2025-12-20,06:00,11:30,480.00,Economy,70 -CT-FL-018,SunBird Airlines,Denver,Cancún,2025-12-20,10:00,15:30,950.00,Business,15 -CT-FL-019,SunBird Airlines,Cancún,Denver,2025-12-28,14:00,18:30,510.00,Economy,65 -CT-FL-020,SunBird Airlines,Cancún,Denver,2025-12-28,08:00,12:30,980.00,Business,11 +CT-FL-001,Contoso Skyways,Seattle,Paris,2027-08-15,08:30,04:30+1,750.00,Economy,42 +CT-FL-002,Contoso Skyways,Seattle,Paris,2027-08-15,14:00,10:00+1,1450.00,Business,12 +CT-FL-003,Contoso Skyways,Paris,Seattle,2027-08-22,11:00,14:00,780.00,Economy,38 +CT-FL-004,Contoso Skyways,Paris,Seattle,2027-08-22,18:00,21:00,1520.00,Business,8 +CT-FL-005,Atlantic Jet,New York,London,2027-09-01,19:00,07:00+1,620.00,Economy,55 +CT-FL-006,Atlantic Jet,New York,London,2027-09-01,22:00,10:00+1,2100.00,First,4 +CT-FL-007,Atlantic Jet,London,New York,2027-09-10,09:00,12:00,650.00,Economy,48 +CT-FL-008,Atlantic Jet,London,New York,2027-09-10,15:00,18:00,1380.00,Business,10 +CT-FL-009,Pacific Wings,San Francisco,Tokyo,2027-10-05,13:00,17:00+1,890.00,Economy,60 +CT-FL-010,Pacific Wings,San Francisco,Tokyo,2027-10-05,23:00,05:00+2,2450.00,Business,6 +CT-FL-011,Pacific Wings,Tokyo,San Francisco,2027-10-15,10:00,06:00,920.00,Economy,52 +CT-FL-012,Pacific Wings,Tokyo,San Francisco,2027-10-15,22:00,18:00,2500.00,First,3 +CT-FL-013,EuroStar Air,Chicago,Rome,2027-11-01,16:00,08:00+1,710.00,Economy,45 +CT-FL-014,EuroStar Air,Chicago,Rome,2027-11-01,20:00,12:00+1,1680.00,Business,9 +CT-FL-015,EuroStar Air,Rome,Chicago,2027-11-10,07:00,12:00,740.00,Economy,40 +CT-FL-016,EuroStar Air,Rome,Chicago,2027-11-10,14:00,19:00,1700.00,Business,7 +CT-FL-017,SunBird Airlines,Denver,Cancún,2027-12-20,06:00,11:30,480.00,Economy,70 +CT-FL-018,SunBird Airlines,Denver,Cancún,2027-12-20,10:00,15:30,950.00,Business,15 +CT-FL-019,SunBird Airlines,Cancún,Denver,2027-12-28,14:00,18:30,510.00,Economy,65 +CT-FL-020,SunBird Airlines,Cancún,Denver,2027-12-28,08:00,12:30,980.00,Business,11 diff --git a/src.original/data/hotels.csv b/src.original/data/hotels.csv index 5c82e4f..fc4f55e 100644 --- a/src.original/data/hotels.csv +++ b/src.original/data/hotels.csv @@ -1,16 +1,16 @@ hotel_id,name,city,country,star_rating,price_per_night_usd,amenities,available_rooms,check_in_date,check_out_date -CT-HT-001,Le Marais Grand Hotel,Paris,France,5,320.00,"WiFi,Pool,Spa,Restaurant,Gym",8,2025-08-15,2025-08-30 -CT-HT-002,Montmartre Budget Inn,Paris,France,3,95.00,"WiFi,Breakfast",22,2025-08-15,2025-08-30 -CT-HT-003,Seine River Suites,Paris,France,4,210.00,"WiFi,Restaurant,Gym,River View",14,2025-08-15,2025-08-30 -CT-HT-004,The Westminster Palace,London,United Kingdom,5,380.00,"WiFi,Pool,Spa,Restaurant,Concierge",6,2025-09-01,2025-09-15 -CT-HT-005,Camden Town Hostel,London,United Kingdom,2,65.00,"WiFi,Shared Kitchen",30,2025-09-01,2025-09-15 -CT-HT-006,Kensington Gardens Hotel,London,United Kingdom,4,245.00,"WiFi,Restaurant,Gym,Parking",11,2025-09-01,2025-09-15 -CT-HT-007,Shibuya Sky Tower Hotel,Tokyo,Japan,5,290.00,"WiFi,Pool,Spa,Restaurant,Rooftop Bar",10,2025-10-05,2025-10-20 -CT-HT-008,Asakusa Traditional Ryokan,Tokyo,Japan,4,180.00,"WiFi,Hot Spring,Traditional Breakfast,Garden",5,2025-10-05,2025-10-20 -CT-HT-009,Shinjuku Business Hotel,Tokyo,Japan,3,110.00,"WiFi,Breakfast,Laundry",25,2025-10-05,2025-10-20 -CT-HT-010,Roma Colosseum View,Rome,Italy,4,230.00,"WiFi,Restaurant,Rooftop Terrace,Breakfast",12,2025-11-01,2025-11-15 -CT-HT-011,Trastevere Boutique B&B,Rome,Italy,3,125.00,"WiFi,Breakfast,Garden",9,2025-11-01,2025-11-15 -CT-HT-012,Vatican Luxury Residence,Rome,Italy,5,410.00,"WiFi,Pool,Spa,Restaurant,Concierge,Gym",4,2025-11-01,2025-11-15 -CT-HT-013,Cancún Beachfront Resort,Cancún,Mexico,5,350.00,"WiFi,Pool,Beach Access,Spa,All-Inclusive,Kids Club",20,2025-12-20,2026-01-05 -CT-HT-014,Playa Del Sol Hotel,Cancún,Mexico,4,195.00,"WiFi,Pool,Beach Access,Restaurant",16,2025-12-20,2026-01-05 -CT-HT-015,Centro Cancún Budget Stay,Cancún,Mexico,2,72.00,"WiFi,Breakfast,Parking",35,2025-12-20,2026-01-05 +CT-HT-001,Le Marais Grand Hotel,Paris,France,5,320.00,"WiFi,Pool,Spa,Restaurant,Gym",8,2027-08-15,2027-08-30 +CT-HT-002,Montmartre Budget Inn,Paris,France,3,95.00,"WiFi,Breakfast",22,2027-08-15,2027-08-30 +CT-HT-003,Seine River Suites,Paris,France,4,210.00,"WiFi,Restaurant,Gym,River View",14,2027-08-15,2027-08-30 +CT-HT-004,The Westminster Palace,London,United Kingdom,5,380.00,"WiFi,Pool,Spa,Restaurant,Concierge",6,2027-09-01,2027-09-15 +CT-HT-005,Camden Town Hostel,London,United Kingdom,2,65.00,"WiFi,Shared Kitchen",30,2027-09-01,2027-09-15 +CT-HT-006,Kensington Gardens Hotel,London,United Kingdom,4,245.00,"WiFi,Restaurant,Gym,Parking",11,2027-09-01,2027-09-15 +CT-HT-007,Shibuya Sky Tower Hotel,Tokyo,Japan,5,290.00,"WiFi,Pool,Spa,Restaurant,Rooftop Bar",10,2027-10-05,2027-10-20 +CT-HT-008,Asakusa Traditional Ryokan,Tokyo,Japan,4,180.00,"WiFi,Hot Spring,Traditional Breakfast,Garden",5,2027-10-05,2027-10-20 +CT-HT-009,Shinjuku Business Hotel,Tokyo,Japan,3,110.00,"WiFi,Breakfast,Laundry",25,2027-10-05,2027-10-20 +CT-HT-010,Roma Colosseum View,Rome,Italy,4,230.00,"WiFi,Restaurant,Rooftop Terrace,Breakfast",12,2027-11-01,2027-11-15 +CT-HT-011,Trastevere Boutique B&B,Rome,Italy,3,125.00,"WiFi,Breakfast,Garden",9,2027-11-01,2027-11-15 +CT-HT-012,Vatican Luxury Residence,Rome,Italy,5,410.00,"WiFi,Pool,Spa,Restaurant,Concierge,Gym",4,2027-11-01,2027-11-15 +CT-HT-013,Cancún Beachfront Resort,Cancún,Mexico,5,350.00,"WiFi,Pool,Beach Access,Spa,All-Inclusive,Kids Club",20,2027-12-20,2028-01-05 +CT-HT-014,Playa Del Sol Hotel,Cancún,Mexico,4,195.00,"WiFi,Pool,Beach Access,Restaurant",16,2027-12-20,2028-01-05 +CT-HT-015,Centro Cancún Budget Stay,Cancún,Mexico,2,72.00,"WiFi,Breakfast,Parking",35,2027-12-20,2028-01-05 diff --git a/src/data/car_rentals.csv b/src/data/car_rentals.csv index aa69160..8402644 100644 --- a/src/data/car_rentals.csv +++ b/src/data/car_rentals.csv @@ -1,16 +1,16 @@ rental_id,company,city,car_type,price_per_day_usd,available,pickup_date,return_date -CT-CR-001,Contoso Wheels,Paris,Economy,45.00,true,2025-08-15,2025-08-30 -CT-CR-002,Contoso Wheels,Paris,SUV,85.00,true,2025-08-15,2025-08-30 -CT-CR-003,EuroDrive,Paris,Luxury,150.00,true,2025-08-15,2025-08-30 -CT-CR-004,Contoso Wheels,London,Economy,50.00,true,2025-09-01,2025-09-15 -CT-CR-005,Contoso Wheels,London,SUV,95.00,true,2025-09-01,2025-09-15 -CT-CR-006,BritCars,London,Luxury,175.00,false,2025-09-01,2025-09-15 -CT-CR-007,Contoso Wheels,Tokyo,Economy,55.00,true,2025-10-05,2025-10-20 -CT-CR-008,NipponRide,Tokyo,Minivan,90.00,true,2025-10-05,2025-10-20 -CT-CR-009,NipponRide,Tokyo,Luxury,200.00,true,2025-10-05,2025-10-20 -CT-CR-010,Contoso Wheels,Rome,Economy,40.00,true,2025-11-01,2025-11-15 -CT-CR-011,ItaliaWheels,Rome,SUV,80.00,true,2025-11-01,2025-11-15 -CT-CR-012,ItaliaWheels,Rome,Luxury,160.00,false,2025-11-01,2025-11-15 -CT-CR-013,Contoso Wheels,Cancún,Economy,35.00,true,2025-12-20,2026-01-05 -CT-CR-014,SolRentals,Cancún,SUV,70.00,true,2025-12-20,2026-01-05 -CT-CR-015,SolRentals,Cancún,Minivan,65.00,true,2025-12-20,2026-01-05 +CT-CR-001,Contoso Wheels,Paris,Economy,45.00,true,2027-08-15,2027-08-30 +CT-CR-002,Contoso Wheels,Paris,SUV,85.00,true,2027-08-15,2027-08-30 +CT-CR-003,EuroDrive,Paris,Luxury,150.00,true,2027-08-15,2027-08-30 +CT-CR-004,Contoso Wheels,London,Economy,50.00,true,2027-09-01,2027-09-15 +CT-CR-005,Contoso Wheels,London,SUV,95.00,true,2027-09-01,2027-09-15 +CT-CR-006,BritCars,London,Luxury,175.00,false,2027-09-01,2027-09-15 +CT-CR-007,Contoso Wheels,Tokyo,Economy,55.00,true,2027-10-05,2027-10-20 +CT-CR-008,NipponRide,Tokyo,Minivan,90.00,true,2027-10-05,2027-10-20 +CT-CR-009,NipponRide,Tokyo,Luxury,200.00,true,2027-10-05,2027-10-20 +CT-CR-010,Contoso Wheels,Rome,Economy,40.00,true,2027-11-01,2027-11-15 +CT-CR-011,ItaliaWheels,Rome,SUV,80.00,true,2027-11-01,2027-11-15 +CT-CR-012,ItaliaWheels,Rome,Luxury,160.00,false,2027-11-01,2027-11-15 +CT-CR-013,Contoso Wheels,Cancún,Economy,35.00,true,2027-12-20,2028-01-05 +CT-CR-014,SolRentals,Cancún,SUV,70.00,true,2027-12-20,2028-01-05 +CT-CR-015,SolRentals,Cancún,Minivan,65.00,true,2027-12-20,2028-01-05 diff --git a/src/data/flights.csv b/src/data/flights.csv index cdb119b..398114c 100644 --- a/src/data/flights.csv +++ b/src/data/flights.csv @@ -1,21 +1,21 @@ flight_id,airline,origin,destination,departure_date,departure_time,arrival_time,price_usd,cabin_class,available_seats -CT-FL-001,Contoso Skyways,Seattle,Paris,2025-08-15,08:30,04:30+1,750.00,Economy,42 -CT-FL-002,Contoso Skyways,Seattle,Paris,2025-08-15,14:00,10:00+1,1450.00,Business,12 -CT-FL-003,Contoso Skyways,Paris,Seattle,2025-08-22,11:00,14:00,780.00,Economy,38 -CT-FL-004,Contoso Skyways,Paris,Seattle,2025-08-22,18:00,21:00,1520.00,Business,8 -CT-FL-005,Atlantic Jet,New York,London,2025-09-01,19:00,07:00+1,620.00,Economy,55 -CT-FL-006,Atlantic Jet,New York,London,2025-09-01,22:00,10:00+1,2100.00,First,4 -CT-FL-007,Atlantic Jet,London,New York,2025-09-10,09:00,12:00,650.00,Economy,48 -CT-FL-008,Atlantic Jet,London,New York,2025-09-10,15:00,18:00,1380.00,Business,10 -CT-FL-009,Pacific Wings,San Francisco,Tokyo,2025-10-05,13:00,17:00+1,890.00,Economy,60 -CT-FL-010,Pacific Wings,San Francisco,Tokyo,2025-10-05,23:00,05:00+2,2450.00,Business,6 -CT-FL-011,Pacific Wings,Tokyo,San Francisco,2025-10-15,10:00,06:00,920.00,Economy,52 -CT-FL-012,Pacific Wings,Tokyo,San Francisco,2025-10-15,22:00,18:00,2500.00,First,3 -CT-FL-013,EuroStar Air,Chicago,Rome,2025-11-01,16:00,08:00+1,710.00,Economy,45 -CT-FL-014,EuroStar Air,Chicago,Rome,2025-11-01,20:00,12:00+1,1680.00,Business,9 -CT-FL-015,EuroStar Air,Rome,Chicago,2025-11-10,07:00,12:00,740.00,Economy,40 -CT-FL-016,EuroStar Air,Rome,Chicago,2025-11-10,14:00,19:00,1700.00,Business,7 -CT-FL-017,SunBird Airlines,Denver,Cancún,2025-12-20,06:00,11:30,480.00,Economy,70 -CT-FL-018,SunBird Airlines,Denver,Cancún,2025-12-20,10:00,15:30,950.00,Business,15 -CT-FL-019,SunBird Airlines,Cancún,Denver,2025-12-28,14:00,18:30,510.00,Economy,65 -CT-FL-020,SunBird Airlines,Cancún,Denver,2025-12-28,08:00,12:30,980.00,Business,11 +CT-FL-001,Contoso Skyways,Seattle,Paris,2027-08-15,08:30,04:30+1,750.00,Economy,42 +CT-FL-002,Contoso Skyways,Seattle,Paris,2027-08-15,14:00,10:00+1,1450.00,Business,12 +CT-FL-003,Contoso Skyways,Paris,Seattle,2027-08-22,11:00,14:00,780.00,Economy,38 +CT-FL-004,Contoso Skyways,Paris,Seattle,2027-08-22,18:00,21:00,1520.00,Business,8 +CT-FL-005,Atlantic Jet,New York,London,2027-09-01,19:00,07:00+1,620.00,Economy,55 +CT-FL-006,Atlantic Jet,New York,London,2027-09-01,22:00,10:00+1,2100.00,First,4 +CT-FL-007,Atlantic Jet,London,New York,2027-09-10,09:00,12:00,650.00,Economy,48 +CT-FL-008,Atlantic Jet,London,New York,2027-09-10,15:00,18:00,1380.00,Business,10 +CT-FL-009,Pacific Wings,San Francisco,Tokyo,2027-10-05,13:00,17:00+1,890.00,Economy,60 +CT-FL-010,Pacific Wings,San Francisco,Tokyo,2027-10-05,23:00,05:00+2,2450.00,Business,6 +CT-FL-011,Pacific Wings,Tokyo,San Francisco,2027-10-15,10:00,06:00,920.00,Economy,52 +CT-FL-012,Pacific Wings,Tokyo,San Francisco,2027-10-15,22:00,18:00,2500.00,First,3 +CT-FL-013,EuroStar Air,Chicago,Rome,2027-11-01,16:00,08:00+1,710.00,Economy,45 +CT-FL-014,EuroStar Air,Chicago,Rome,2027-11-01,20:00,12:00+1,1680.00,Business,9 +CT-FL-015,EuroStar Air,Rome,Chicago,2027-11-10,07:00,12:00,740.00,Economy,40 +CT-FL-016,EuroStar Air,Rome,Chicago,2027-11-10,14:00,19:00,1700.00,Business,7 +CT-FL-017,SunBird Airlines,Denver,Cancún,2027-12-20,06:00,11:30,480.00,Economy,70 +CT-FL-018,SunBird Airlines,Denver,Cancún,2027-12-20,10:00,15:30,950.00,Business,15 +CT-FL-019,SunBird Airlines,Cancún,Denver,2027-12-28,14:00,18:30,510.00,Economy,65 +CT-FL-020,SunBird Airlines,Cancún,Denver,2027-12-28,08:00,12:30,980.00,Business,11 diff --git a/src/data/hotels.csv b/src/data/hotels.csv index 5c82e4f..fc4f55e 100644 --- a/src/data/hotels.csv +++ b/src/data/hotels.csv @@ -1,16 +1,16 @@ hotel_id,name,city,country,star_rating,price_per_night_usd,amenities,available_rooms,check_in_date,check_out_date -CT-HT-001,Le Marais Grand Hotel,Paris,France,5,320.00,"WiFi,Pool,Spa,Restaurant,Gym",8,2025-08-15,2025-08-30 -CT-HT-002,Montmartre Budget Inn,Paris,France,3,95.00,"WiFi,Breakfast",22,2025-08-15,2025-08-30 -CT-HT-003,Seine River Suites,Paris,France,4,210.00,"WiFi,Restaurant,Gym,River View",14,2025-08-15,2025-08-30 -CT-HT-004,The Westminster Palace,London,United Kingdom,5,380.00,"WiFi,Pool,Spa,Restaurant,Concierge",6,2025-09-01,2025-09-15 -CT-HT-005,Camden Town Hostel,London,United Kingdom,2,65.00,"WiFi,Shared Kitchen",30,2025-09-01,2025-09-15 -CT-HT-006,Kensington Gardens Hotel,London,United Kingdom,4,245.00,"WiFi,Restaurant,Gym,Parking",11,2025-09-01,2025-09-15 -CT-HT-007,Shibuya Sky Tower Hotel,Tokyo,Japan,5,290.00,"WiFi,Pool,Spa,Restaurant,Rooftop Bar",10,2025-10-05,2025-10-20 -CT-HT-008,Asakusa Traditional Ryokan,Tokyo,Japan,4,180.00,"WiFi,Hot Spring,Traditional Breakfast,Garden",5,2025-10-05,2025-10-20 -CT-HT-009,Shinjuku Business Hotel,Tokyo,Japan,3,110.00,"WiFi,Breakfast,Laundry",25,2025-10-05,2025-10-20 -CT-HT-010,Roma Colosseum View,Rome,Italy,4,230.00,"WiFi,Restaurant,Rooftop Terrace,Breakfast",12,2025-11-01,2025-11-15 -CT-HT-011,Trastevere Boutique B&B,Rome,Italy,3,125.00,"WiFi,Breakfast,Garden",9,2025-11-01,2025-11-15 -CT-HT-012,Vatican Luxury Residence,Rome,Italy,5,410.00,"WiFi,Pool,Spa,Restaurant,Concierge,Gym",4,2025-11-01,2025-11-15 -CT-HT-013,Cancún Beachfront Resort,Cancún,Mexico,5,350.00,"WiFi,Pool,Beach Access,Spa,All-Inclusive,Kids Club",20,2025-12-20,2026-01-05 -CT-HT-014,Playa Del Sol Hotel,Cancún,Mexico,4,195.00,"WiFi,Pool,Beach Access,Restaurant",16,2025-12-20,2026-01-05 -CT-HT-015,Centro Cancún Budget Stay,Cancún,Mexico,2,72.00,"WiFi,Breakfast,Parking",35,2025-12-20,2026-01-05 +CT-HT-001,Le Marais Grand Hotel,Paris,France,5,320.00,"WiFi,Pool,Spa,Restaurant,Gym",8,2027-08-15,2027-08-30 +CT-HT-002,Montmartre Budget Inn,Paris,France,3,95.00,"WiFi,Breakfast",22,2027-08-15,2027-08-30 +CT-HT-003,Seine River Suites,Paris,France,4,210.00,"WiFi,Restaurant,Gym,River View",14,2027-08-15,2027-08-30 +CT-HT-004,The Westminster Palace,London,United Kingdom,5,380.00,"WiFi,Pool,Spa,Restaurant,Concierge",6,2027-09-01,2027-09-15 +CT-HT-005,Camden Town Hostel,London,United Kingdom,2,65.00,"WiFi,Shared Kitchen",30,2027-09-01,2027-09-15 +CT-HT-006,Kensington Gardens Hotel,London,United Kingdom,4,245.00,"WiFi,Restaurant,Gym,Parking",11,2027-09-01,2027-09-15 +CT-HT-007,Shibuya Sky Tower Hotel,Tokyo,Japan,5,290.00,"WiFi,Pool,Spa,Restaurant,Rooftop Bar",10,2027-10-05,2027-10-20 +CT-HT-008,Asakusa Traditional Ryokan,Tokyo,Japan,4,180.00,"WiFi,Hot Spring,Traditional Breakfast,Garden",5,2027-10-05,2027-10-20 +CT-HT-009,Shinjuku Business Hotel,Tokyo,Japan,3,110.00,"WiFi,Breakfast,Laundry",25,2027-10-05,2027-10-20 +CT-HT-010,Roma Colosseum View,Rome,Italy,4,230.00,"WiFi,Restaurant,Rooftop Terrace,Breakfast",12,2027-11-01,2027-11-15 +CT-HT-011,Trastevere Boutique B&B,Rome,Italy,3,125.00,"WiFi,Breakfast,Garden",9,2027-11-01,2027-11-15 +CT-HT-012,Vatican Luxury Residence,Rome,Italy,5,410.00,"WiFi,Pool,Spa,Restaurant,Concierge,Gym",4,2027-11-01,2027-11-15 +CT-HT-013,Cancún Beachfront Resort,Cancún,Mexico,5,350.00,"WiFi,Pool,Beach Access,Spa,All-Inclusive,Kids Club",20,2027-12-20,2028-01-05 +CT-HT-014,Playa Del Sol Hotel,Cancún,Mexico,4,195.00,"WiFi,Pool,Beach Access,Restaurant",16,2027-12-20,2028-01-05 +CT-HT-015,Centro Cancún Budget Stay,Cancún,Mexico,2,72.00,"WiFi,Breakfast,Parking",35,2027-12-20,2028-01-05 From 08bf4c905d039a11e68b1558693039c796635629 Mon Sep 17 00:00:00 2001 From: Nitya Narasimhan Date: Tue, 18 Aug 2026 17:43:30 +0000 Subject: [PATCH 4/5] data: evaluation-data-v2 (dates +2y to match CSV shift); labs point at v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The earlier CSV date shift (+730d) moved every booking date into 2027-2028. The reference evaluation dataset still referenced 2025/2026 in queries, contexts, responses, and ground truths, which would fail evaluators against the new data. - New: artifacts/datasets/reference/evaluation-data-v2.jsonl — same 10 rows as v1, sed s/2025/2027/g s/2026/2028/g - v1 preserved unchanged per AGENTS.md reference-artifact versioning rule (never overwrite) - Bumped 5 references across labs/core/02-evaluate-portal.md, labs/core/05-capstone-hosted.md, and labs/more/continuous-eval.md from -v1 to -v2 - sample-prompts-v1.jsonl needed no update (uses only month names, year-agnostic) - pytest -q -> 15 passed --- .../reference/evaluation-data-v2.jsonl | 10 +++++++ labs/core/02-evaluate-portal.md | 30 ++++++++++++------- labs/core/05-capstone-hosted.md | 2 +- labs/more/continuous-eval.md | 4 +-- 4 files changed, 33 insertions(+), 13 deletions(-) create mode 100644 artifacts/datasets/reference/evaluation-data-v2.jsonl diff --git a/artifacts/datasets/reference/evaluation-data-v2.jsonl b/artifacts/datasets/reference/evaluation-data-v2.jsonl new file mode 100644 index 0000000..1326d7f --- /dev/null +++ b/artifacts/datasets/reference/evaluation-data-v2.jsonl @@ -0,0 +1,10 @@ +{"query": "What flights are available from Seattle to Paris in August?", "context": "Customer looking for Seattle to Paris flights in August 2027", "response": "We have two flights from Seattle to Paris on August 15th: CT-FL-001 departing at 8:30 AM in Economy class at $750, and CT-FL-002 departing at 2:00 PM in Business class at $1,450. Both are operated by Contoso Skyways.", "ground_truth": "There are 2 flights from Seattle to Paris on August 15: Economy at $750 and Business at $1,450 on Contoso Skyways."} +{"query": "Find me a hotel in Tokyo with a hot spring.", "context": "Customer seeking traditional Japanese hotel experience in Tokyo", "response": "I found the Asakusa Traditional Ryokan (CT-HT-008), a 4-star hotel in Tokyo, Japan. It offers WiFi, a hot spring, traditional breakfast, and a garden. The rate is $180 per night with 5 rooms available for stays between October 5-20, 2027.", "ground_truth": "Asakusa Traditional Ryokan is a 4-star ryokan in Tokyo at $180/night with hot spring, traditional breakfast, and garden."} +{"query": "I need a cheap car rental in Cancún.", "context": "Budget-conscious customer looking for car rental in Cancún", "response": "The most affordable option in Cancún is an Economy car from Contoso Wheels at $35 per day (CT-CR-013), available for pickup between December 20, 2027 and January 5, 2028. There's also a Minivan from SolRentals at $65/day if you need more space.", "ground_truth": "Cheapest car rental in Cancún is Economy from Contoso Wheels at $35/day."} +{"query": "What's the cheapest hotel in London?", "context": "Customer looking for budget accommodation in London", "response": "The most budget-friendly option in London is the Camden Town Hostel (CT-HT-005), a 2-star property at just $65 per night. It offers WiFi and a shared kitchen, with 30 rooms available for stays between September 1-15, 2027.", "ground_truth": "Camden Town Hostel is the cheapest at $65/night, 2-star, with WiFi and shared kitchen."} +{"query": "Are there any first class flights available?", "context": "Customer looking for premium first class flight options", "response": "Yes, we have two First Class options: CT-FL-006 from New York to London on September 1st at $2,100 with 4 seats available on Atlantic Jet, and CT-FL-012 from Tokyo to San Francisco on October 15th at $2,500 with 3 seats available on Pacific Wings.", "ground_truth": "Two first class flights: NYC to London at $2,100 (Atlantic Jet) and Tokyo to SFO at $2,500 (Pacific Wings)."} +{"query": "Plan a trip from Chicago to Rome with hotel and car rental.", "context": "Customer wants complete trip package from Chicago to Rome", "response": "Here's your Chicago to Rome trip plan: Flight CT-FL-013 departs November 1st at 4:00 PM, Economy at $710 on EuroStar Air. For hotels, I recommend Roma Colosseum View (4-star, $230/night) or Trastevere Boutique B&B (3-star, $125/night). For car rental, Economy from Contoso Wheels is $40/day or an SUV from ItaliaWheels at $80/day.", "ground_truth": "Flight: Economy $710 on EuroStar Air Nov 1. Hotels: Roma Colosseum View $230/night or Trastevere B&B $125/night. Cars: Economy $40/day or SUV $80/day."} +{"query": "What 5-star hotels are available in Paris?", "context": "Customer seeking luxury hotel in Paris", "response": "The Le Marais Grand Hotel (CT-HT-001) is our 5-star option in Paris. It's priced at $320 per night and offers WiFi, pool, spa, restaurant, and gym. There are 8 rooms available for stays between August 15-30, 2027.", "ground_truth": "Le Marais Grand Hotel is the only 5-star hotel in Paris at $320/night with pool, spa, restaurant, and gym."} +{"query": "I want to rent an SUV in London.", "context": "Customer specifically looking for SUV rental in London", "response": "I found an SUV available in London from Contoso Wheels (CT-CR-005) at $95 per day, available for pickup between September 1-15, 2027. Note that BritCars also lists a Luxury car at $175/day, but it's currently unavailable.", "ground_truth": "One SUV available in London from Contoso Wheels at $95/day for September 1-15."} +{"query": "Compare all economy flights available.", "context": "Customer wants to compare economy class flight options across all routes", "response": "Here are all Economy flights: Denver to Cancún ($480), Cancún to Denver ($510), New York to London ($620), London to New York ($650), Chicago to Rome ($710), Rome to Chicago ($740), Seattle to Paris ($750), Paris to Seattle ($780), San Francisco to Tokyo ($890), Tokyo to San Francisco ($920).", "ground_truth": "Economy flights range from $480 (Denver-Cancún) to $920 (Tokyo-SFO), with 10 options across 5 routes."} +{"query": "I need a family-friendly hotel in Cancún with a kids club and pool.", "context": "Family traveling to Cancún looking for kid-friendly amenities", "response": "The Cancún Beachfront Resort (CT-HT-013) is perfect for families! It's a 5-star all-inclusive resort at $350 per night with WiFi, pool, beach access, spa, all-inclusive dining, and a kids club. There are 20 rooms available for stays between December 20, 2027 and January 5, 2028.", "ground_truth": "Cancún Beachfront Resort is a 5-star all-inclusive at $350/night with kids club, pool, beach access."} diff --git a/labs/core/02-evaluate-portal.md b/labs/core/02-evaluate-portal.md index 81b9aaa..ffb3723 100644 --- a/labs/core/02-evaluate-portal.md +++ b/labs/core/02-evaluate-portal.md @@ -25,7 +25,7 @@ flowchart LR ## The reference dataset The workshop ships a curated evaluation dataset at -[`../../artifacts/datasets/reference/evaluation-data-v1.jsonl`](../../artifacts/datasets/reference/evaluation-data-v1.jsonl). +[`../../artifacts/datasets/reference/evaluation-data-v2.jsonl`](../../artifacts/datasets/reference/evaluation-data-v2.jsonl). It contains ~15 queries across three difficulty tiers (single-specialist, multi-part itinerary, and out-of-scope refusal) that together stress-test the Prompt Agent baseline. @@ -37,19 +37,26 @@ Prompt Agent baseline. ## 📋 Steps 1. **Open Evaluations.** - Foundry portal → **My assets → Evaluations** → **+ New evaluation**. + Foundry portal → **Build → Evaluations** → **Create** new evaluation. -2. **Choose the target.** +1. **Choose the target.** Under **Target**, pick the **`contoso-travel-concierge-prompt`** agent. -3. **Upload the dataset.** - Under **Data**, upload - `artifacts/datasets/reference/evaluation-data-v1.jsonl` (or use - `./scripts/use-reference.sh datasets evaluation-data-v1` first to stage it). - -4. **Select evaluators.** +1. Choose **Single-turn conversations** by default. +1. Choose **One-time** as frequency. +1. Choose **Existing dataset** as data source + 1. **Upload the dataset.** + Under **Data**, upload + `artifacts/datasets/reference/evaluation-data-v2.jsonl` (or use + `./scripts/use-reference.sh datasets evaluation-data-v2` first to stage it). + 1. Wait for upload to complete + 1. Review the data records right in portal. + 1. Switch to the judge model + 1. No need to add anything for custom prompts + +1. **Select evaluators.** Enable at least: - **Task completion** - **Groundedness** @@ -63,7 +70,8 @@ Prompt Agent baseline. 5. **Run the evaluation.** - Click **Create**. The run takes 2–5 minutes depending on dataset size. + 1. Create a custom name e.g., `prompt-agent-eval-run` - optional + 1. Click **Create**. The run takes 2–5 minutes depending on dataset size. 6. **Read the results.** When the run finishes, open it. You'll see: @@ -77,6 +85,8 @@ Prompt Agent baseline. citation, ungrounded superlatives, etc. Write it down; Core Lab 03 will target it. + (Optional) You can choose the evaluations row and click *Analyze results* to have a cluster analysis run for you. This gives you more insights into possible areas for optimization. + > ⚠️ **Gotcha:** if every score is unusually low, your dataset may not have diff --git a/labs/core/05-capstone-hosted.md b/labs/core/05-capstone-hosted.md index 25af5ba..e8c6d8b 100644 --- a/labs/core/05-capstone-hosted.md +++ b/labs/core/05-capstone-hosted.md @@ -53,7 +53,7 @@ Do each step yourself. Refer back to the linked lab if you get stuck. 3. **Evaluate.** Following [Core Lab 02](./02-evaluate-portal.md), run a batch evaluation on `contoso-travel-concierge` against - `artifacts/datasets/reference/evaluation-data-v1.jsonl`. Note the top + `artifacts/datasets/reference/evaluation-data-v2.jsonl`. Note the top failure pattern. 4. **Optimize.** diff --git a/labs/more/continuous-eval.md b/labs/more/continuous-eval.md index 4199b04..5070b49 100644 --- a/labs/more/continuous-eval.md +++ b/labs/more/continuous-eval.md @@ -25,7 +25,7 @@ flowchart LR You have two "sources of truth" that must stay in sync: - The **reference eval dataset** - (`artifacts/datasets/reference/evaluation-data-v1.jsonl`). + (`artifacts/datasets/reference/evaluation-data-v2.jsonl`). - The **deployed agent**'s current instructions. If instructions change, the eval must be re-run. If it regresses, @@ -40,7 +40,7 @@ someone must approve or fix. # example — replace with your actual runner python -m contoso_eval run \ --agent contoso-travel-concierge-prompt \ - --dataset artifacts/datasets/reference/evaluation-data-v1.jsonl \ + --dataset artifacts/datasets/reference/evaluation-data-v2.jsonl \ --out artifacts/evaluators/generated/latest.json ``` From b6c98aea3946aa9ff39cb652a8c6c6ff8f718630 Mon Sep 17 00:00:00 2001 From: Nitya Narasimhan Date: Tue, 18 Aug 2026 19:03:22 +0000 Subject: [PATCH 5/5] chore: ignore .foundry, .do-not-commit, and evaluation-data-v3 from tracking --- .gitignore | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.gitignore b/.gitignore index d99a8b0..e401c19 100644 --- a/.gitignore +++ b/.gitignore @@ -216,3 +216,8 @@ __marimo__/ # Streamlit .streamlit/secrets.toml + +# Workshop local caches — single source of truth is artifacts/ and src/ +.foundry/ +.do-not-commit/ +artifacts/datasets/reference/evaluation-data-v3.jsonl