Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/instructions/vs-code-designer.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ Each test runs in its own fresh VS Code session to avoid workspace-switch conten
| 4.5 | designerViewExtended.test.ts | Parallel branches + run-after (ADO #10109401) |
| 4.6 | keyboardNavigation.test.ts | Ctrl+Up/Down + Ctrl+Alt+P / Ctrl+Shift+P hotkey contract |
| 4.7 | dataMapper.test.ts, demo, smoke, standalone | Data Mapper + generic tests |
| 4.11 | bundleCdnHealth.test.ts | CDN integrity headers probe (`Content-Length` / `Content-MD5` on the Workflows extension bundle). Pure Mocha — no VS Code session. |

### Shared Helper Modules

Expand Down Expand Up @@ -193,9 +194,10 @@ $env:E2E_MODE = "newtestsonly" # Phases 4.3-4.6 only (requires prior
$env:E2E_MODE = "conversiononly" # Phases 4.8a-e only (requires prior 4.1 manifest)
$env:E2E_MODE = "conversioncreateonly" # Phase 4.8b only (builds own legacy fixture)
$env:E2E_MODE = "nonlogicappstartup" # Phase 4.0 only
$env:E2E_MODE = "bundleintegrityonly" # Phase 4.11 — pure-Mocha CDN integrity probe (no VS Code)

# CI matrix shard modes (each runs on its own GitHub Actions runner):
$env:E2E_MODE = "independentonly" # 4.0 + 4.8b — no Phase 4.1 dep
$env:E2E_MODE = "independentonly" # 4.0 + 4.8b + 4.11 — no Phase 4.1 dep
$env:E2E_MODE = "createplusdesigner" # 4.1 → 4.2, 4.7
$env:E2E_MODE = "createplusnewtests" # 4.1 → 4.3, 4.4, 4.5, 4.6
$env:E2E_MODE = "createplusconversion" # 4.1 → 4.8a, 4.8c, 4.8d, 4.8e
Expand Down
153 changes: 126 additions & 27 deletions .github/workflows/vscode-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,6 @@ jobs:
key: la-runtime-deps-${{ runner.os }}-v1
restore-keys: |
la-runtime-deps-${{ runner.os }}-
save-always: true

- name: Run fixtures scenario (p41a-fixtures)
run: |
Expand All @@ -214,13 +213,47 @@ jobs:
node apps/vs-code-designer/src/test/ui/run-e2e.js
env:
LA_E2E_SCENARIO: p41a-fixtures
LA_E2E_STRICT_DEPENDENCY_VALIDATION: '1'
NODE_OPTIONS: --max-old-space-size=4096
# Node's os.tmpdir() honors TMPDIR/TMP/TEMP on Linux; setting TEMP
# pins workspace + manifest creation under $RUNNER_TEMP/la-e2e-test
# so the artifact upload below has a stable, scoped path.
TEMP: ${{ runner.temp }}
TMPDIR: ${{ runner.temp }}

- name: Verify Logic Apps extension bundle sidecar
run: |
BUNDLE_ROOT="${HOME}/.azure-functions-core-tools/Functions/ExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle.Workflows"
node - "$BUNDLE_ROOT" <<'NODE'
const fs = require('fs');
const path = require('path');
const root = process.argv[2];
if (!fs.existsSync(root)) {
throw new Error(`Bundle root missing: ${root}`);
}
const versions = fs.readdirSync(root)
.filter((name) => /^\d+\.\d+\.\d+/.test(name) && fs.statSync(path.join(root, name)).isDirectory())
.sort((a, b) => b.localeCompare(a, undefined, { numeric: true }));
if (versions.length === 0) {
throw new Error(`No bundle version folders under ${root}`);
}
const bundleDir = path.join(root, versions[0]);
const sidecarPath = path.join(bundleDir, '.bundle-source-md5');
if (!fs.existsSync(sidecarPath)) {
throw new Error(`Bundle sidecar missing: ${sidecarPath}`);
}
const sidecar = JSON.parse(fs.readFileSync(sidecarPath, 'utf8'));
if (!sidecar || typeof sidecar.sourceMd5 !== 'string' || typeof sidecar.contentHash !== 'string') {
throw new Error(`Bundle sidecar missing sourceMd5/contentHash: ${sidecarPath}`);
}
const entries = fs.readdirSync(bundleDir).filter((name) => name !== '.bundle-source-md5');
if (entries.length === 0) {
throw new Error(`Bundle directory has no extracted content: ${bundleDir}`);
}
console.log(`Bundle verified: ${bundleDir}`);
console.log(`Sidecar: ${sidecarPath}`);
NODE

- name: Verify fixtures manifest exists
run: |
MANIFEST="${RUNNER_TEMP}/la-e2e-test/created-workspaces.json"
Expand All @@ -236,6 +269,12 @@ jobs:
run: |
tar -czf workspace-fixtures.tar.gz -C "${RUNNER_TEMP}" la-e2e-test

- name: Tar Logic Apps extension bundle
run: |
tar -czf logic-apps-extension-bundle.tar.gz \
-C "${HOME}/.azure-functions-core-tools/Functions/ExtensionBundles" \
Microsoft.Azure.Functions.ExtensionBundle.Workflows

- name: Upload workspace fixtures artifact
uses: actions/upload-artifact@v4
with:
Expand All @@ -244,6 +283,14 @@ jobs:
retention-days: 1
if-no-files-found: error

- name: Upload Logic Apps extension bundle artifact
uses: actions/upload-artifact@v4
with:
name: logic-apps-extension-bundle-${{ github.sha }}
path: logic-apps-extension-bundle.tar.gz
retention-days: 1
if-no-files-found: error

- name: Upload fixture screenshots on failure
uses: actions/upload-artifact@v4
if: failure()
Expand All @@ -263,31 +310,71 @@ jobs:
strategy:
fail-fast: false
matrix:
scenario:
# Independent / no-workspace (don't need fixtures artifact)
- p40-nonlogicapp
- p48b-conversioncreate
include:
# Independent / no-workspace (don't need fixtures or bundle artifacts)
- scenario: p40-nonlogicapp
use_workspace_fixtures: false
use_bundle_artifact: false
- scenario: p48b-conversioncreate
use_workspace_fixtures: false
use_bundle_artifact: false
# Full 12-shape behavior validation — self-creates its own workspaces,
# so it doesn't consume the fixtures artifact either.
- p41b-createworkspace-behavior
# so it doesn't consume the fixtures artifact, but it still consumes
# the setup-fixtures bundle artifact and runs bundle preflight.
- scenario: p41b-createworkspace-behavior
use_workspace_fixtures: false
use_bundle_artifact: true
# Designer lifecycle (consume fixtures from setup-fixtures)
- p42-standard
- p42-customcode
- p42-rulesengine
- scenario: p42-standard
use_workspace_fixtures: true
use_bundle_artifact: true
- scenario: p42-customcode
use_workspace_fixtures: true
use_bundle_artifact: true
- scenario: p42-rulesengine
use_workspace_fixtures: true
use_bundle_artifact: true
# Runtime-touching consumer tests (consume fixtures)
- p43-inlinejavascript
- p43-customcode
- p43-rulesengine
- p44-statelessvariables
- p45-designerviewextended
- p46-keyboardnav
- scenario: p43-inlinejavascript
use_workspace_fixtures: true
use_bundle_artifact: true
- scenario: p43-customcode
use_workspace_fixtures: true
use_bundle_artifact: true
- scenario: p43-rulesengine
use_workspace_fixtures: true
use_bundle_artifact: true
- scenario: p44-statelessvariables
use_workspace_fixtures: true
use_bundle_artifact: true
- scenario: p45-designerviewextended
use_workspace_fixtures: true
use_bundle_artifact: true
- scenario: p46-keyboardnav
use_workspace_fixtures: true
use_bundle_artifact: true
# Multi-designer + dataMapper suite (manifest-multi)
- p47-suite
- scenario: p47-suite
use_workspace_fixtures: true
use_bundle_artifact: true
# Conversion suite
- p48a-conversionno
- p48c-multipledesigners
- p48d-conversionyes
- p48e-conversionsubfolder
- scenario: p48a-conversionno
use_workspace_fixtures: true
use_bundle_artifact: true
- scenario: p48c-multipledesigners
use_workspace_fixtures: true
use_bundle_artifact: true
- scenario: p48d-conversionyes
use_workspace_fixtures: true
use_bundle_artifact: true
- scenario: p48e-conversionsubfolder
use_workspace_fixtures: true
use_bundle_artifact: true
# Bundle on-disk repair / integrity gate (Phase 14 code path).
# Consumes the standard/Stateful fixture from setup-fixtures.
- scenario: p412-bundlerepair
use_workspace_fixtures: true
use_bundle_artifact: true

steps:
- name: Checkout
Expand Down Expand Up @@ -342,19 +429,16 @@ jobs:
- name: Extract build artifacts
run: tar -xzf extension-build.tar.gz

# Scenarios that self-create their workspaces skip the fixtures download:
# - p40-nonlogicapp (plain folder, no workspace)
# - p48b-conversioncreate (builds its own legacy fixture)
# - p41b-createworkspace-behavior (full 12-shape wizard run)
# Scenarios that self-create their workspaces set use_workspace_fixtures=false.
- name: Download workspace fixtures artifact
if: matrix.scenario != 'p40-nonlogicapp' && matrix.scenario != 'p48b-conversioncreate' && matrix.scenario != 'p41b-createworkspace-behavior'
if: matrix.use_workspace_fixtures == true
uses: actions/download-artifact@v4
with:
name: workspace-fixtures-${{ github.sha }}
path: .

- name: Extract workspace fixtures into $RUNNER_TEMP
if: matrix.scenario != 'p40-nonlogicapp' && matrix.scenario != 'p48b-conversioncreate' && matrix.scenario != 'p41b-createworkspace-behavior'
if: matrix.use_workspace_fixtures == true
run: |
mkdir -p "${RUNNER_TEMP}"
tar -xzf workspace-fixtures.tar.gz -C "${RUNNER_TEMP}"
Expand All @@ -365,6 +449,20 @@ jobs:
cat "${RUNNER_TEMP}/la-e2e-test/created-workspaces.json"
fi

- name: Download Logic Apps extension bundle artifact
if: matrix.use_bundle_artifact == true
uses: actions/download-artifact@v4
with:
name: logic-apps-extension-bundle-${{ github.sha }}
path: .

- name: Extract Logic Apps extension bundle
if: matrix.use_bundle_artifact == true
run: |
mkdir -p "${HOME}/.azure-functions-core-tools/Functions/ExtensionBundles"
tar -xzf logic-apps-extension-bundle.tar.gz -C "${HOME}/.azure-functions-core-tools/Functions/ExtensionBundles"
find "${HOME}/.azure-functions-core-tools/Functions/ExtensionBundles/Microsoft.Azure.Functions.ExtensionBundle.Workflows" -maxdepth 2 -type f -name '.bundle-source-md5' -print

- name: Install system dependencies for virtual display
run: |
sudo apt-get update
Expand Down Expand Up @@ -399,6 +497,7 @@ jobs:
env:
# Per-scenario matrix: each shard runs exactly one scenarios[] entry.
LA_E2E_SCENARIO: ${{ matrix.scenario }}
LA_E2E_BUNDLE_PREFLIGHT: ${{ matrix.use_bundle_artifact && '1' || '0' }}
NODE_OPTIONS: --max-old-space-size=4096
# Pin os.tmpdir() so the bootstrapper finds the manifest the
# setup-fixtures job uploaded (same RUNNER_TEMP layout).
Expand Down
10 changes: 6 additions & 4 deletions .squad/knowledge/INDEX.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ Read this first on **every** task. Open any file whose triggers match the task d

| If the task involves… | Read these |
|---|---|
| **Opening or updating ANY pull request body** | **`.github/pull_request_template.md` (lowercase filename — exists at repo root in `.github/`, do NOT improvise sections, do NOT skip)** **+** [review-patterns.md](review-patterns.md) ("PR body must conform…") |
| `git`, worktrees, branches, repo setup, syncing agents | [session-learnings.md](session-learnings.md) **+ run `git config --get-regexp '^alias\.'`** (custom aliases: `git new <branch>`, `git agents`, `git sync-agents`, `git unhide-agents`, `git ap`) **+** [ci-patterns.md](ci-patterns.md) (worktree off-main vs off-feature, stacked PRs from forks) |
| Pull request lifecycle, pushing, CI checks, failing workflows, retries | [ci-patterns.md](ci-patterns.md) |
| PR comments, reviewer feedback, addressing review threads | [review-patterns.md](review-patterns.md) |
| Opening or updating a PR body, `AI PR Validation` bot failures, `needs-pr-update` label | [review-patterns.md](review-patterns.md) ("PR body must conform to .github/pull_request_template.md…") **+** `.github/pull_request_template.md` |
| `AI PR Validation` bot failures, `needs-pr-update` label | [review-patterns.md](review-patterns.md) ("PR body must conform to .github/pull_request_template.md…") **+** `.github/pull_request_template.md` |
| Squad routing, agent prompts, playbooks, charters | [agent-improvements.md](agent-improvements.md) |
| VS Code extension E2E (ExTester), `run-e2e.js`, designer/run/debug tests | [vscode-e2e-testing.md](vscode-e2e-testing.md) **+** `apps/vs-code-designer/src/test/ui/SKILL.md` |
| Functions runtime readiness, `:7071` probes, `listCallbackUrl`, `waitForRuntimeReady`, "runtime not ready" flakes | [runtime-readiness-probes.md](runtime-readiness-probes.md) |
Expand All @@ -21,9 +22,10 @@ Read this first on **every** task. Open any file whose triggers match the task d

## Hard Rules

1. **Never run a raw `git` command before checking aliases.** Repo-specific aliases (e.g., `git new` for worktrees) encode conventions that raw git won't enforce.
2. **Never skip this index because a task "looks trivial."** Trivial-looking tasks (worktree creation, single test runs, one-line scripts) are where repo conventions get missed.
3. **When a knowledge file disagrees with a generic best practice, the knowledge file wins** — it reflects repo-specific evidence.
1. **Before opening or editing any PR body**, read `.github/pull_request_template.md` (lowercase filename) at the repo root and use its exact section structure. Do NOT improvise. The fork and the `Azure/LogicAppsUX` upstream both ship the same template.
2. **Never run a raw `git` command before checking aliases.** Repo-specific aliases (e.g., `git new` for worktrees) encode conventions that raw git won't enforce.
3. **Never skip this index because a task "looks trivial."** Trivial-looking tasks (worktree creation, single test runs, one-line scripts) are where repo conventions get missed.
4. **When a knowledge file disagrees with a generic best practice, the knowledge file wins** — it reflects repo-specific evidence.

## Maintenance

Expand Down
13 changes: 7 additions & 6 deletions .squad/knowledge/review-patterns.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@ Curated patterns for PR comments, reviewer feedback, and final summaries. Add en
- Why it matters: PR #9164 hit this on initial open — the `release-scribe`-style PR body shipped without ticking Commit Type, Risk Level, or Test Plan E2E boxes and without a `## Contributors` section, so AI PR Validation flagged 3 sections ❌ + 2 ⚠️. Rewriting the body to match `.github/pull_request_template.md` and applying `risk:medium` cleared all 8 sections to ✅. The bot re-runs on `pull_request_target.types: [edited, labeled, unlabeled]` so a single `gh pr edit --body-file ... --add-label risk:<level> --remove-label needs-pr-update` triggers a fresh validation pass.
- Pattern (release-scribe and pr-orchestrator):
1. Read `.github/pull_request_template.md` before authoring any PR body — do NOT improvise sections.
2. Tick exactly one `Commit Type` and exactly one `Risk Level` checkbox. The PR title prefix (`fix:`, `feat:`, `perf:`, `test:`, `ci:`, `docs:`, `chore:`) must match the single ticked commit type.
3. Apply the matching repo label (`risk:low` / `risk:medium` / `risk:high`) in the same `gh pr edit` call.
4. Include a literal `## Contributors` section listing `@user` mentions — a trailing `Co-authored-by:` git trailer alone does NOT satisfy this requirement.
5. Tick the Test Plan boxes that actually apply. If the diff adds a `*.spec.ts(x)` file under a test folder, "Unit tests added/updated" must be ticked. Cite CI run IDs and per-shard wall-times when CI evidence exists.
6. Remove `needs-pr-update` in the same edit operation.
7. Wait ~5-7 minutes for the bot to re-validate and verify all sections show ✅ before declaring the body work complete.
2. **Preserve every section, every comment hint, and every checkbox from the template verbatim.** Tick only the ones that apply; leave the rest as `- [ ]`. Never delete unticked checkbox rows or section comments — reviewers expect the full grid.
3. Tick exactly one `Commit Type` and exactly one `Risk Level` checkbox. The PR title prefix (`fix:`, `feat:`, `perf:`, `test:`, `ci:`, `docs:`, `chore:`) must match the single ticked commit type.
4. Apply the matching repo label (`risk:low` / `risk:medium` / `risk:high`) in the same `gh pr edit` call.
5. Include a literal `## Contributors` section listing `@user` mentions — a trailing `Co-authored-by:` git trailer alone does NOT satisfy this requirement.
6. Tick the Test Plan boxes that actually apply. If the diff adds a `*.spec.ts(x)` file under a test folder, "Unit tests added/updated" must be ticked. Cite CI run IDs and per-shard wall-times when CI evidence exists.
7. Remove `needs-pr-update` in the same edit operation.
8. Wait ~5-7 minutes for the bot to re-validate and verify all sections show ✅ before declaring the body work complete.
- Source: PR #9164 AI PR Validation bot iterations; `.github/workflows/pr-ai-validation.yml`; `.github/pull_request_template.md`.
- Applies to: `release-scribe`, `pr-orchestrator`, `chief-engineer`, `pr-comment-triage`.
- Status: verified.
Expand Down
4 changes: 3 additions & 1 deletion apps/vs-code-designer/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ Each test runs in its own fresh VS Code session to avoid workspace-switch conten
| 4.5 | designerViewExtended.test.ts | Parallel branches + run-after (ADO #10109401) |
| 4.6 | keyboardNavigation.test.ts | Ctrl+Up/Down + Ctrl+Alt+P / Ctrl+Shift+P hotkey contract |
| 4.7 | dataMapper.test.ts, demo, smoke, standalone | Data Mapper + generic tests |
| 4.11 | bundleCdnHealth.test.ts | CDN integrity headers probe (`Content-Length` / `Content-MD5` on the Workflows extension bundle). Pure Mocha — no VS Code session. |

### Shared Helper Modules

Expand Down Expand Up @@ -193,9 +194,10 @@ $env:E2E_MODE = "newtestsonly" # Phases 4.3-4.6 only (requires prior
$env:E2E_MODE = "conversiononly" # Phases 4.8a-e only (requires prior 4.1 manifest)
$env:E2E_MODE = "conversioncreateonly" # Phase 4.8b only (builds own legacy fixture)
$env:E2E_MODE = "nonlogicappstartup" # Phase 4.0 only
$env:E2E_MODE = "bundleintegrityonly" # Phase 4.11 — pure-Mocha CDN integrity probe (no VS Code)

# CI matrix shard modes (each runs on its own GitHub Actions runner):
$env:E2E_MODE = "independentonly" # 4.0 + 4.8b — no Phase 4.1 dep
$env:E2E_MODE = "independentonly" # 4.0 + 4.8b + 4.11 — no Phase 4.1 dep
$env:E2E_MODE = "createplusdesigner" # 4.1 → 4.2, 4.7
$env:E2E_MODE = "createplusnewtests" # 4.1 → 4.3, 4.4, 4.5, 4.6
$env:E2E_MODE = "createplusconversion" # 4.1 → 4.8a, 4.8c, 4.8d, 4.8e
Expand Down
Loading
Loading