Skip to content

deploy: frontend rollback, stale-vector regen, single-source phrases - #22

Open
Ocean82 wants to merge 1 commit into
mainfrom
deploy-hardening
Open

deploy: frontend rollback, stale-vector regen, single-source phrases#22
Ocean82 wants to merge 1 commit into
mainfrom
deploy-hardening

Conversation

@Ocean82

@Ocean82 Ocean82 commented Aug 31, 2026

Copy link
Copy Markdown
Owner

Hardens the deploy pipeline. Three fixes plus verification.

1. Frontend rollback on failed health check

Previously a failed health check rolled back only the server (PM2), leaving the newly-mirrored frontend live against the old API. Extracted the build/mirror into mirror_frontend() and reused it in the rollback path so the SPA is rebuilt from PREV_COMMIT to match the rolled-back server. Also added the root npm ci the frontend rebuild needs. The frontend restore is non-fatal (loud WARN on failure) so it can't block the server rollback.

2. Stale intent-vectors.bin regeneration (binary format v2)

The precompute step only ran when the file was absent, so editing intent phrases shipped stale vectors. Now:

  • shared/intentPhrases.js computes an FNV-1a hash of the phrase set.
  • Writer embeds the hash in a new 16-byte v2 header.
  • Client rejects a binary whose hash no longer matches (falls back to runtime bootstrap) and rejects the old v1 format.
  • deploy.sh always runs model:precompute when the model is present; the script self-skips cheaply (header read, before ONNX load) when current.

3. Phrase-list drift (root-cause fix)

INTENT_PHRASES was duplicated across intentEmbeddings.ts and precompute-embeddings.mjs. Extracted to a single shared/intentPhrases.js imported by both, so drift is structurally impossible.

Verification

  • tsc --noEmit: passes (added shared/intentPhrases.d.ts for types)
  • vitest run src/ai/nlp: 145/145 pass, incl. rewritten v2 round-trip + stale-hash + parity tests
  • node --check on new JS: clean
  • bash -n scripts/deploy.sh: clean

Deploy note

The v2 bump means the first server deploy after merge regenerates intent-vectors.bin (existing v1 file is rejected). Until then the client falls back to the slower runtime bootstrap � safe degradation, not a breakage.

Summary by Sourcery

Harden deployment rollback and intent-vector freshness while establishing a single source of truth for intent phrases.

Bug Fixes:

  • Keep the frontend synchronized with the rolled-back server after failed deployment health checks.
  • Detect and reject stale or legacy intent-vector binaries, falling back safely to runtime initialization.

Enhancements:

  • Centralize intent phrases and add hash-based validation to prevent phrase-list and precomputed-vector drift.

Deployment:

  • Always verify and regenerate deployed intent vectors when the phrase set changes, while preserving a cheap no-op path for current vectors.

Tests:

  • Add coverage for version 2 intent-vector parsing, stale-hash rejection, format validation, round trips, and phrase-hash parity.

…-source phrases

- deploy.sh: extract mirror_frontend(); rebuild+remirror frontend from
  PREV_COMMIT on health-check rollback so the live SPA matches the API.
- intent-vectors.bin format v2: embed FNV-1a hash of the phrase set. Client
  rejects a binary whose hash no longer matches (falls back to runtime
  bootstrap); precompute self-skips when current, regenerates when stale.
- deploy.sh always runs model:precompute when the model is present (was gated
  on file absence, which shipped stale vectors after a phrase edit).
- Eliminate INTENT_PHRASES duplication: single source in shared/intentPhrases.js
  imported by both intentEmbeddings.ts and precompute-embeddings.mjs.
- Update intentVectorsBin.test.ts to v2 format; add stale-hash and parity tests.
Copilot AI lite review requested due to automatic review settings August 31, 2026 12:16

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@sourcery-ai

sourcery-ai Bot commented Aug 31, 2026

Copy link
Copy Markdown

Reviewer's Guide

Hardens deployment consistency by restoring the frontend alongside a rolled-back server, and hardens intent-vector artifacts with a shared phrase source, hash-validated v2 format, automatic stale regeneration, and comprehensive format tests.

Sequence diagram for deploy health-check rollback

sequenceDiagram
    participant Deploy as deploy.sh
    participant Git
    participant Server
    participant Frontend

    Deploy->>Frontend: mirror_frontend()
    Deploy->>Server: pm2 restart PM2_PROCESS
    Deploy->>Server: health check
    alt health check passes
        Deploy-->>Deploy: deployment completes
    else health check fails
        Deploy->>Git: git reset --hard PREV_COMMIT
        Deploy->>Server: npm ci
        Deploy->>Server: npm run build
        Deploy->>Server: pm2 restart PM2_PROCESS
        opt FRONTEND_MIRRORED = true
            Deploy->>Frontend: mirror_frontend()
        end
        Deploy-->>Deploy: die with rollback status
    end
Loading

Sequence diagram for stale intent-vector regeneration

sequenceDiagram
    participant Deploy as deploy.sh
    participant Precompute as model:precompute
    participant Binary as intent-vectors.bin
    participant Model as ONNX model

    Deploy->>Precompute: run_model_step npm run model:precompute
    Precompute->>Binary: read 16-byte v2 header
    alt version 2 and hash matches
        Precompute-->>Deploy: skip regeneration
    else missing, v1, or stale hash
        Precompute->>Model: load ONNX model
        Model-->>Precompute: embeddings
        Precompute->>Binary: write v2 header with phrasesHash and vectors
        Precompute-->>Deploy: regenerated artifact
    end
Loading

File-Level Changes

Change Details Files
Make frontend deployment reusable and restore it during server rollback.
  • Extract the Vite build and mirror logic into mirror_frontend().
  • Track whether the new frontend was mirrored and rebuild it after resetting to PREV_COMMIT when health checks fail.
  • Add root dependency installation before rebuilding the frontend; keep frontend rollback failures non-fatal but visible.
scripts/deploy.sh
Add phrase-set versioning to precomputed intent vectors and regenerate stale artifacts automatically.
  • Compute a deterministic FNV-1a phrase-set hash and store it in a new 16-byte v2 binary header.
  • Reject v1, incompatible, or hash-mismatched binaries so runtime bootstrap handles stale vectors.
  • Run precompute whenever the model exists, with a cheap header/hash check before loading ONNX.
shared/intentPhrases.js
shared/intentPhrases.d.ts
scripts/precompute-embeddings.mjs
src/ai/nlp/intentEmbeddings.ts
Eliminate duplicated intent phrase definitions and add binary-format regression coverage.
  • Move the phrase list into a shared ESM module consumed by runtime and precompute code.
  • Add TypeScript declarations for the shared JavaScript module.
  • Test v2 parsing, vector offsets, padding, version/dimension rejection, stale hashes, unavailable files, and hash parity.
shared/intentPhrases.js
shared/intentPhrases.d.ts
src/ai/nlp/intentEmbeddings.ts
scripts/precompute-embeddings.mjs
src/ai/nlp/__tests__/intentVectorsBin.test.ts

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai

coderabbitai Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 95d30d82-eff4-48c4-b916-e2b957f13c66


Comment @coderabbitai help to get the list of available commands.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've reviewed your changes and they look great!

Sourcery assessment

Needs a human reviewer. If the new deployment or rollback flow is wrong, it can leave a frontend/API version mismatch or cause a production outage, and the failed deployment may already have affected users before the script is reverted. Reverting the code restores the old behavior for future deploys, but it cannot undo an outage or inconsistent assets already served.


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants