virtual-agent 0.1.0

Virtual Agent — the user-facing profile-management facade over awp: where profiles live, how they are saved, edited, updated and shared. awp stays the runtime; this crate owns the custody layer.
Documentation
# crates.io publication for virtual-agent, gated on the same verification
# gate as local development (`scripts/verify.sh`).
#
# Trigger: push a version tag (`git tag v0.1.0 && git push origin v0.1.0`)
# after the matching Cargo.toml version.
#
# Credentials: crates.io Trusted Publishing — the crate allowlists this
# repo+workflow; the auth action exchanges the job's OIDC token for a
# scoped short-lived crates.io token. No stored secret.
name: publish

on:
  push:
    tags: ["v*"]

permissions:
  contents: read
  id-token: write

jobs:
  verify:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
      - uses: dtolnay/rust-toolchain@b725eda525362e7cf34af9a7243cac1e3f01a7ec # stable
        with:
          components: rustfmt, clippy
      - run: scripts/verify.sh

  publish:
    needs: verify
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
      - uses: dtolnay/rust-toolchain@b725eda525362e7cf34af9a7243cac1e3f01a7ec # stable
      - uses: rust-lang/crates-io-auth-action@c6f97d42243bad5fab37ca0427f495c86d5b1a18 # v1.0.5
        id: auth
      - name: Publish
        env:
          CARGO_REGISTRY_TOKEN: ${{ steps.auth.outputs.token }}
        run: |
          set -euo pipefail
          log="/tmp/publish-virtual-agent.log"
          for attempt in 1 2 3 4 5; do
            if cargo publish -p virtual-agent --token "$CARGO_REGISTRY_TOKEN" 2>&1 | tee "$log"; then
              exit 0
            fi
            if grep -qi 'already uploaded\|already exists' "$log"; then
              echo "virtual-agent already published — skipping"
              exit 0
            fi
            sleep 30
          done
          echo "::error::could not publish virtual-agent"
          exit 1