---
phase: 01-scaffold
plan: "02"
type: execute
wave: 1
depends_on: []
files_modified:
  - .github/workflows/PullRequestCI.yml
  - .github/workflows/MainDistributionPipeline.yml
  - .github/workflows/CodeQuality.yml
  - test/sql/semantic_views.test
  - Makefile
  - extension-ci-tools/
autonomous: true
requirements:
  - INFRA-02
  - INFRA-04

must_haves:
  truths:
    - "Pull requests to main or release/* run CI on Linux x86_64 only (fast feedback)"
    - "Pushes to main or release/* trigger a full 5-platform build matrix"
    - "CI includes a SQLLogicTest LOAD smoke test that fails if the extension ABI does not match the pinned DuckDB version"
    - "Code quality CI job runs rustfmt --check, clippy, cargo-deny, and coverage on every push and PR"
    - "The extension-ci-tools submodule is present and the Makefile includes it correctly"
  artifacts:
    - path: ".github/workflows/PullRequestCI.yml"
      provides: "PR CI — Linux x86_64 fast check only"
      contains: "PullRequestCI"
    - path: ".github/workflows/MainDistributionPipeline.yml"
      provides: "Full 5-platform build matrix on main and release branches"
      contains: "MainDistributionPipeline"
    - path: ".github/workflows/CodeQuality.yml"
      provides: "rustfmt, clippy, cargo-deny, coverage quality gates"
      contains: "CodeQuality"
    - path: "test/sql/semantic_views.test"
      provides: "SQLLogicTest LOAD smoke test (catches ABI mismatches)"
      contains: "require semantic_views"
    - path: "Makefile"
      provides: "Thin wrapper including extension-ci-tools makefiles"
      contains: "extension-ci-tools"
  key_links:
    - from: ".github/workflows/PullRequestCI.yml"
      to: "duckdb/extension-ci-tools reusable workflow"
      via: "uses: duckdb/extension-ci-tools/.github/workflows/_extension_distribution.yml@main"
      pattern: "_extension_distribution.yml"
    - from: ".github/workflows/MainDistributionPipeline.yml"
      to: "duckdb/extension-ci-tools reusable workflow"
      via: "uses: duckdb/extension-ci-tools/.github/workflows/_extension_distribution.yml@main"
      pattern: "_extension_distribution.yml"
    - from: "test/sql/semantic_views.test"
      to: "extension binary"
      via: "require semantic_views directive in SQLLogicTest runner"
      pattern: "require semantic_views"
    - from: "Makefile"
      to: "extension-ci-tools/makefiles/"
      via: "include extension-ci-tools/makefiles/..."
      pattern: "include.*extension-ci-tools"
---

<objective>
Set up the CI workflows and LOAD smoke test infrastructure. Three GitHub Actions workflows provide: fast PR CI (Linux x86_64 only), full 5-platform distribution build (main/release branches), and code quality gates. The SQLLogicTest smoke test file catches DuckDB ABI mismatches that `cargo test` cannot detect.

Purpose: CI is the enforcement mechanism for all platform compatibility and code quality requirements. Without it, the scaffold has no automated verification that the extension actually loads on target platforms.
Output: Three GitHub Actions workflow YAML files, a SQLLogicTest smoke test, and a correctly configured Makefile with the extension-ci-tools submodule wired in.
</objective>

<execution_context>
@/Users/paul/.claude/get-shit-done/workflows/execute-plan.md
@/Users/paul/.claude/get-shit-done/templates/summary.md
</execution_context>

<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/01-scaffold/01-RESEARCH.md
</context>

<tasks>

<task type="auto">
  <name>Task 1: Initialize extension-template-rs Makefile and submodule structure</name>
  <files>
    Makefile
    extension-ci-tools/
    .gitmodules
  </files>
  <action>
The project needs the `extension-ci-tools` git submodule and a Makefile that includes its makefiles. Without these, `make configure`, `make debug`, `make test_debug`, etc. do not work.

**Step 1: Fetch the extension-template-rs Makefile**

Fetch https://raw.githubusercontent.com/duckdb/extension-template-rs/main/Makefile to get the exact Makefile content from the official template. This Makefile includes the extension-ci-tools makefiles and defines targets like `configure`, `debug`, `release`, `test_debug`, `test_release`.

Write the fetched Makefile to `/Users/paul/Documents/Dev/Personal/duckdb-semantic-views/Makefile`, replacing any occurrences of the template extension name (`rusty_quack` or similar) with `semantic_views`.

**Step 2: Add extension-ci-tools as a git submodule**

```bash
cd /Users/paul/Documents/Dev/Personal/duckdb-semantic-views
git submodule add https://github.com/duckdb/extension-ci-tools.git extension-ci-tools
git submodule update --init --recursive
```

Per RESEARCH.md Pitfall 1: `extension-ci-tools` MUST be a git submodule — do NOT vendor or copy files manually. The Makefile uses `include` with relative paths that depend on the submodule structure.

**Step 3: Set the DuckDB version pin**

Verify that the Makefile sets `TARGET_DUCKDB_VERSION=v1.4.4` (or confirm the variable name used in the template). This is the version pin that the DuckDB version monitor workflow (plan 03) will update.

**Step 4: Run make configure**

```bash
cd /Users/paul/Documents/Dev/Personal/duckdb-semantic-views && make configure 2>&1
```

`make configure` downloads the pinned DuckDB binary locally. This is what `just setup` calls. Verify it completes without error — a successful configure proves the Makefile and submodule are wired correctly.

If `make configure` is slow (downloads a binary), proceed once it completes. This step is required before `make test_debug` will work in plan verification.
  </action>
  <verify>
    <automated>cd /Users/paul/Documents/Dev/Personal/duckdb-semantic-views && ls extension-ci-tools/makefiles/ 2>&1 | head -5</automated>
    <manual>Verify extension-ci-tools/makefiles/ directory is populated (not empty). Verify .gitmodules contains extension-ci-tools entry.</manual>
  </verify>
  <done>extension-ci-tools/ submodule is initialized and populated. .gitmodules contains the submodule entry. Makefile includes extension-ci-tools makefiles. `make configure` completes without error.</done>
</task>

<task type="auto">
  <name>Task 2: Create GitHub Actions workflows and LOAD smoke test</name>
  <files>
    .github/workflows/PullRequestCI.yml
    .github/workflows/MainDistributionPipeline.yml
    .github/workflows/CodeQuality.yml
    test/sql/semantic_views.test
  </files>
  <action>
Create the three GitHub Actions workflows and the SQLLogicTest smoke test file.

**Step 1: Create .github/workflows/PullRequestCI.yml**

Per RESEARCH.md Pattern 5 and locked decision (feature branches = Linux x86_64 only):

```yaml
name: Pull Request CI
on:
  pull_request:
    branches:
      - main
      - 'release/*'

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  linux-fast-check:
    name: Build and test (Linux x86_64)
    uses: duckdb/extension-ci-tools/.github/workflows/_extension_distribution.yml@main
    with:
      duckdb_version: v1.4.4
      ci_tools_version: main
      extension_name: semantic_views
      extra_toolchains: 'rust;python3'
      # Only Linux x86_64 for fast PR feedback — full matrix runs on main/release
      exclude_archs: 'wasm_mvp;wasm_eh;wasm_threads;linux_amd64_musl;linux_arm64;osx_amd64;osx_arm64;windows_amd64'
```

NOTE on `exclude_archs`: The exact architecture string identifiers must match what `extension-ci-tools` distribution matrix defines. After the submodule is initialized, verify the exact names by checking `extension-ci-tools/config/distribution_matrix.json`. Adjust the exclude list if any names differ. The goal is Linux x86_64 only — exclude everything else.

**Step 2: Create .github/workflows/MainDistributionPipeline.yml**

Per RESEARCH.md Pattern (last code example) and locked decision (main/release/* = full 5-platform):

```yaml
name: Main Extension Distribution Pipeline
on:
  push:
    branches:
      - main
      - 'release/*'
  workflow_dispatch:

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}-${{ github.head_ref || '' }}-${{ github.base_ref || '' }}-${{ github.ref != 'refs/heads/main' || github.sha }}
  cancel-in-progress: true

jobs:
  duckdb-stable-build:
    name: Build extension binaries (all platforms)
    uses: duckdb/extension-ci-tools/.github/workflows/_extension_distribution.yml@main
    with:
      duckdb_version: v1.4.4
      ci_tools_version: main
      extension_name: semantic_views
      extra_toolchains: 'rust;python3'
      # Include: Linux x86_64, Linux arm64, macOS x86_64, macOS arm64, Windows x86_64
      # Exclude: WASM targets and musl (not in target matrix)
      exclude_archs: 'wasm_mvp;wasm_eh;wasm_threads;linux_amd64_musl'
```

**Step 3: Create .github/workflows/CodeQuality.yml**

Per RESEARCH.md code example and locked decisions (cargo-llvm-cov for coverage, cargo-nextest, 80% threshold, cargo-deny):

```yaml
name: Code Quality
on:
  push:
    branches:
      - main
      - 'release/*'
  pull_request:

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

jobs:
  quality:
    name: Lint, format, and coverage
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install Rust stable
        uses: dtolnay/rust-toolchain@stable
        with:
          components: rustfmt, clippy

      - name: Check formatting (rustfmt)
        run: cargo fmt --check

      - name: Clippy (pedantic lints, deny warnings)
        run: cargo clippy -- -D warnings

      - name: cargo-deny (licenses + advisories)
        uses: EmbarkStudios/cargo-deny-action@v2

      - name: Install cargo-llvm-cov
        uses: taiki-e/install-action@cargo-llvm-cov

      - name: Install cargo-nextest
        uses: taiki-e/install-action@nextest

      - name: Coverage check (80% minimum)
        run: cargo llvm-cov nextest --fail-under-lines 80
```

NOTE on coverage: `cargo llvm-cov nextest` on a `cdylib` crate may require `--lib` or test harness config. If this command fails, try `cargo llvm-cov --lib nextest --fail-under-lines 80`. The open question from RESEARCH.md should be resolved empirically here — add a comment in the workflow noting the fallback command.

**Step 4: Create test/sql/semantic_views.test**

Create directory `/Users/paul/Documents/Dev/Personal/duckdb-semantic-views/test/sql/` and write the SQLLogicTest smoke test per RESEARCH.md Pattern 3:

```sql
# Smoke test: verify the extension loads via DuckDB's LOAD mechanism
# This catches ABI mismatches that cargo test cannot detect (INFRA-04)
# The 'require' directive causes the SQLLogicTest runner to LOAD the extension.
# If ABI doesn't match the pinned DuckDB CLI binary, this test fails.

require semantic_views

# Basic smoke: extension loaded and DuckDB is functional
query I
SELECT 42;
----
42
```

Per RESEARCH.md Pattern 3: The `require semantic_views` directive is the key — it causes the test runner to invoke `LOAD` on the built `.duckdb_extension` file. This exercises the DuckDB loading mechanism (ABI check, binary footer validation, symbol resolution) which `cargo test` never exercises.
  </action>
  <verify>
    <automated>cd /Users/paul/Documents/Dev/Personal/duckdb-semantic-views &amp;&amp; cat test/sql/semantic_views.test | grep "require semantic_views" &amp;&amp; ls .github/workflows/*.yml</automated>
    <manual>Verify three workflow YAML files exist in .github/workflows/. Verify test/sql/semantic_views.test contains "require semantic_views". Review PullRequestCI.yml to confirm exclude_archs lists match extension-ci-tools distribution matrix.</manual>
  </verify>
  <done>Three workflow YAML files exist (.github/workflows/PullRequestCI.yml, MainDistributionPipeline.yml, CodeQuality.yml). test/sql/semantic_views.test contains "require semantic_views". All YAML files are valid (yamllint or GitHub Actions syntax check).</done>
</task>

</tasks>

<verification>
After both tasks complete, run the following to confirm CI infrastructure is correct:

1. `ls /Users/paul/Documents/Dev/Personal/duckdb-semantic-views/extension-ci-tools/makefiles/` — directory is populated
2. `cat /Users/paul/Documents/Dev/Personal/duckdb-semantic-views/.gitmodules` — contains extension-ci-tools entry
3. `ls /Users/paul/Documents/Dev/Personal/duckdb-semantic-views/.github/workflows/` — shows three workflow files
4. `grep "require semantic_views" /Users/paul/Documents/Dev/Personal/duckdb-semantic-views/test/sql/semantic_views.test` — matches
5. `grep "exclude_archs" /Users/paul/Documents/Dev/Personal/duckdb-semantic-views/.github/workflows/PullRequestCI.yml` — shows extensive exclude list (Linux x86_64 only)
6. `grep "exclude_archs" /Users/paul/Documents/Dev/Personal/duckdb-semantic-views/.github/workflows/MainDistributionPipeline.yml` — shows only WASM/musl excluded (all 5 platforms included)
</verification>

<success_criteria>
- extension-ci-tools submodule is initialized and populated
- `make configure` completes without error (downloads pinned DuckDB binary)
- Three workflow YAML files exist with correct triggers (PR vs push to main/release/*)
- PullRequestCI.yml excludes all non-Linux-x86_64 platforms
- MainDistributionPipeline.yml includes all 5 target platforms (excludes only WASM/musl)
- CodeQuality.yml runs rustfmt, clippy, cargo-deny, and coverage with 80% threshold
- test/sql/semantic_views.test contains `require semantic_views` directive
</success_criteria>

<output>
After completion, create `.planning/phases/01-scaffold/01-02-SUMMARY.md` following the template at @/Users/paul/.claude/get-shit-done/templates/summary.md
</output>
