CI/CD validation

Every PR runs contract validation (including icon policy checks) and uploads a JSON artifact that SurfaceOps can ingest. Minimal workflow:

- run: pnpm install --frozen-lockfile
- run: pnpm examples:build-manifest
- run: pnpm examples:test-edge
- run: node tools/interfacectl/packages/interfacectl-cli/dist/index.js validate \
        --workspace-root . \
        --contract ./contracts/surfaces.web.contract.json \
        --format json \
        --exit-codes v2 \
        --out ./artifacts/interfacectl-report.json

# Icon policy outcomes in CI/CD time:
# icon.source-disallowed + policy=warn   => warning visibility, exit 0
# icon.source-disallowed + policy=strict => blocking error, exit 20

CI/CD time is authoritative for icon-source policy. `icon.source-disallowed` stays non-blocking in warn mode and becomes blocking in strict mode, while artifacts remain available for SurfaceOps review.