---
name: step-00-dependencies
description: Pre-flight dependency check - verify NuGet packages and runtime assembly resolution
next_step: steps/step-01-compile.md
---

# Step 0: Dependency Pre-Flight Check

## BLOCKING - Must pass before proceeding to compilation

### 1. Locate the solution file

```bash
ls *.sln 2>/dev/null || find . -maxdepth 2 -name "*.sln" -type f
```

Store as `{solution_file}`.

### 2. Restore packages with diagnostic output

```bash
dotnet restore {SolutionFile} --verbosity normal 2>&1
```

**Parse the output for these NuGet warnings:**

| Warning Code | Meaning | Action |
|-------------|---------|--------|
| `NU1603` | Package version resolved to different version than requested | Version mismatch -- verify package versions in .csproj |
| `NU1605` | Downgrade detected | Package version conflict -- update to consistent version |
| `NU1608` | Package version outside dependency constraint | Incompatible dependency versions |
| `NU1701` | Package restored using fallback target framework | Potential runtime incompatibility |
| `NU1902` | Package version range could not be satisfied | Missing package source |

**If ANY NU1603/NU1605/NU1608 warnings are found:**
- List each warning with the affected package name and versions
- Suggest fix command: `dotnet add {ProjectFile} package {PackageName} --version {CorrectVersion}`
- This is a WARNING (proceed with caution, may cause runtime errors)

### 3. Quick startup smoke test (runtime assembly validation)

> **CRITICAL:** This step catches errors that `dotnet build` alone misses.
> A successful build does NOT guarantee all assemblies are resolvable at runtime.
> Example: `FileNotFoundException: Could not load file or assembly 'X'` only appears at runtime.

```bash
# Find the API project
API_PROJECT=$(ls src/*Api*/*.csproj 2>/dev/null | head -1)

if [ -n "$API_PROJECT" ]; then
  # Build first (quick, no restore)
  dotnet build "$API_PROJECT" --no-restore --verbosity quiet 2>&1

  # Start the API and capture output
  dotnet run --project "$API_PROJECT" --urls "http://localhost:5098" > /tmp/ss-dep-check.log 2>&1 &
  STARTUP_PID=$!

  # Wait up to 10 seconds for either: process exits (crash) or health responds (success)
  STARTUP_OK=false
  for i in $(seq 1 10); do
    # Check if process is still alive
    if ! kill -0 $STARTUP_PID 2>/dev/null; then
      # Process died - read the output for error classification
      echo "API STARTUP CRASH DETECTED"
      cat /tmp/ss-dep-check.log
      break
    fi

    # Check if health endpoint responds
    HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:5098/health 2>/dev/null)
    if [ "$HTTP_CODE" != "000" ]; then
      STARTUP_OK=true
      break
    fi
    sleep 1
  done

  # Cleanup
  kill $STARTUP_PID 2>/dev/null
  wait $STARTUP_PID 2>/dev/null
  rm -f /tmp/ss-dep-check.log
fi
```

### 4. Classify startup errors (if crash detected)

If the API process crashed, read the output and classify:

| Error Pattern | Classification | Fix Command |
|--------------|----------------|-------------|
| `FileNotFoundException: Could not load file or assembly '{Name}, Version={V}'` | **MISSING_PACKAGE** | `dotnet add {ApiProject} package {Name} --version {V.Major}.{V.Minor}.{V.Patch}` |
| `FileNotFoundException: Could not load file or assembly '{Name}'` (no version) | **MISSING_ASSEMBLY** | Check .csproj references and `PrivateAssets` settings |
| `TypeLoadException: Could not load type '{Type}' from assembly '{Asm}'` | **VERSION_MISMATCH** | `dotnet add {ApiProject} package {Asm} --version {CorrectVersion}` |
| `MissingMethodException: Method not found: '{Method}'` | **VERSION_MISMATCH** | Update package to matching version |
| `InvalidOperationException: Unable to resolve service for type '{Type}'` | **MISSING_DI** | Add `services.AddScoped<{Interface}, {Implementation}>()` in DI setup |
| `InvalidOperationException: The ConnectionString property has not been initialized` | **MISSING_CONFIG** | Add connection string to `appsettings.json` |

**For MISSING_PACKAGE specifically:**
1. Extract the assembly name from the error (text between quotes after "file or assembly")
2. The NuGet package name is usually identical to the assembly name (e.g., `Microsoft.Extensions.Http.Resilience`)
3. Extract the version: `Version=X.X.X.X` -> take first 3 segments as NuGet version
4. Provide exact fix: `dotnet add {ApiProject} package {PackageName} --version {Major.Minor.Patch}`
5. **If assembly starts with `SmartStack.`**: this is a framework bug in SmartStack.csproj, not a client project issue

### 5. Evaluate result

| Scenario | Action |
|----------|--------|
| No warnings, startup OK | PASS -> proceed to step 1 (compile) |
| Warnings only, startup OK | WARNING -> display warnings, proceed to step 1 |
| Startup crash with classified error | **FAIL** -> display classification + fix command, **STOP** |
| Startup crash with unclassified error | **FAIL** -> display full output, **STOP** for investigation |

### 6. Store state

```
{dependency_check_result} = PASS | WARNING | FAIL
{dependency_warnings} = list of warnings (if any)
{startup_error_class} = classification (if crash detected)
{startup_fix_command} = suggested fix command (if crash detected)
```
