Say the version the build actually is, in the two places anyone reads it #83
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # ============================================================ | |
| # HashCortX — continuous integration | |
| # | |
| # This repository has no frontend test suite, and `src/` is served | |
| # unbundled, so nothing catches a syntax error in a JavaScript file | |
| # before it reaches a user: the browser stops executing that script | |
| # and every feature after it silently disappears. | |
| # | |
| # So the gate is deliberately modest and entirely honest about what | |
| # it proves: the JavaScript parses, the Rust compiles, and the Rust | |
| # tests pass. It does NOT prove the app works. Only running it does. | |
| # | |
| # The release pipeline is a separate concern — see docs/future/build.yml. | |
| # ============================================================ | |
| name: CI | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| workflow_dispatch: | |
| # A second push to the same branch cancels the first — no point burning | |
| # minutes on a commit that has already been superseded. | |
| concurrency: | |
| group: ci-${{ github.ref }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| jobs: | |
| javascript: | |
| name: Scripts parse and the Permission Guard behaves | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| # Every file the app actually loads. Vendored libraries under | |
| # src/js/vendor/ are third-party minified builds and are checked | |
| # too — a corrupt vendor file breaks the app just as thoroughly. | |
| - name: Syntax-check every loaded script | |
| run: npm run check:syntax | |
| # Loads the real guard.js and asserts what it refuses, what it asks | |
| # about, and what it lets through unprompted. It is the only thing | |
| # between a language model and the user's disk. | |
| - name: Permission Guard checks | |
| run: npm run check:guard | |
| # Retrieval fails quietly — nothing crashes when ranking gets worse, the | |
| # answers just start missing the point. These pin the ordering rules. | |
| - name: Knowledge-base retrieval checks | |
| run: npm run check:rag | |
| # What the model actually sees of a long agent run. | |
| - name: Agent context-budgeting checks | |
| run: npm run check:agent | |
| # Export bugs are invisible until someone opens the file a week later. | |
| - name: Export formatting checks | |
| run: npm run check:export | |
| # Batching must never reorder a write past a read. | |
| - name: Agent loop policy checks | |
| run: npm run check:policy | |
| # Clipped text and wrapped labels are invisible until someone | |
| # screenshots the app. These catch the two CSS mistakes that cause them. | |
| - name: Layout checks | |
| run: npm run check:layout | |
| # Battery bugs never announce themselves — nothing fails, the laptop is | |
| # just warm. These pin what stops when nobody is looking. | |
| - name: Idle power checks | |
| run: npm run check:power | |
| # Which files may reach the machine at all. Turns ARCHITECTURE.md rule 1 | |
| # from prose into something that fails the build. | |
| - name: Native surface checks | |
| run: npm run check:native | |
| # HashMeterAi reports this log as measured. That only holds if every | |
| # path records, and records real counts. | |
| - name: Usage-log checks | |
| run: npm run check:usage | |
| # getElementById returns null rather than throwing, so a control removed | |
| # from the markup silently disables the code that reads it. This makes | |
| # every such lookup a written-down decision instead of a surprise. | |
| - name: Element-lookup checks | |
| run: npm run check:dom | |
| # The diff is what a user reads before deciding whether to keep a change | |
| # the agent already made. One that drops a line is worse than none. | |
| - name: Diff checks | |
| run: npm run check:diff | |
| # Undo decides whether a user's file gets written over. The case that | |
| # matters is the one where nothing usable was saved: it has to refuse | |
| # rather than write emptiness and report success. | |
| - name: Undo checks | |
| run: npm run check:undo | |
| # Chunking has to cover the whole document. It did not, and half of every | |
| # file added to the knowledge base was dropped without a sign. | |
| - name: Knowledge-base chunking checks | |
| run: npm run check:rag-store | |
| # Where a language model may send the agent's fetch tool. This gate | |
| # shipped with no tests at all. | |
| - name: Fetch-address checks | |
| run: npm run check:url-safety | |
| # How much of a fetched page the model is given, and whether it is told | |
| # when there is more. A page cut without saying so is answered from its | |
| # introduction. | |
| - name: Page-text checks | |
| run: npm run check:page-text | |
| # A provider endpoint outside connect-src is not a crash — it is a | |
| # blocked request the app reports as the provider being unreachable. | |
| - name: Cloud provider checks | |
| run: npm run check:providers | |
| # A vendored library that arrives without a file it imports parses fine | |
| # and fails only when the feature is opened. three.js ships as two files | |
| # and only one was copied, which took 3D Forge out entirely. | |
| - name: Module-import checks | |
| run: npm run check:imports | |
| # The link sanitiser decides which links in a model's reply are safe to | |
| # click, and an agent may be quoting a page it fetched. | |
| - name: Markdown safety checks | |
| run: npm run check:markdown | |
| # How the conversation is described to each provider. Wrong here is not | |
| # an error — it is a request that is accepted and answered badly. | |
| - name: Agent request-shape checks | |
| run: npm run check:shape | |
| # Reading a model's identifier: which provider, what to call it, roughly | |
| # how capable it is. A tier read too low sends a hard question to a small | |
| # model, and the user blames the answer. | |
| - name: Model-identifier checks | |
| run: npm run check:model-names | |
| # A fact extracted badly is repeated back for as long as it survives, and | |
| # one that never ranks makes the model deny knowing what it was told. | |
| - name: Memory checks | |
| run: npm run check:memory | |
| rust: | |
| name: Rust — ${{ matrix.label }} | |
| runs-on: ${{ matrix.os }} | |
| # All three platforms, because for the entire life of this project only | |
| # macOS was ever built. A dependency table header had quietly made chrono, | |
| # dirs and shellexpand macOS-only, so the crate did not compile on Linux or | |
| # Windows at all and nothing noticed. A matrix is the only thing that keeps | |
| # that honest — the alternative is finding out from a user. | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| # 24.04, not 22.04, and the reason is linking rather than preference. | |
| # ort downloads a prebuilt ONNX Runtime that wants glibc 2.38+ (the | |
| # __isoc23_* string functions) and libstdc++ 13+ (_M_replace_cold). | |
| # 22.04 ships glibc 2.35 and GCC 11, so `cargo check` passed — it does | |
| # not link — and `cargo test` failed with a wall of undefined symbols. | |
| - os: ubuntu-24.04 | |
| label: Linux | |
| - os: macos-latest | |
| label: macOS | |
| - os: windows-latest | |
| label: Windows | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: clippy | |
| - uses: swatinem/rust-cache@v2 | |
| with: | |
| workspaces: './src-tauri -> target' | |
| key: ${{ matrix.label }} | |
| # Tauri needs the system webview and its -sys crates' headers even to | |
| # type-check. This is the full Tauri v2 Linux prerequisite list, not the | |
| # shorter one docs/future/build.yml carries: that one predates v2, names | |
| # libappindicator3-dev (v2 wants the ayatana fork), and omits libxdo-dev | |
| # and libssl-dev, whose -sys crates then fail to build. | |
| # macOS and Windows ship their webview with the OS and need none of this. | |
| - name: Install Linux system dependencies | |
| if: runner.os == 'Linux' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y \ | |
| build-essential \ | |
| pkg-config \ | |
| curl wget file \ | |
| libwebkit2gtk-4.1-dev \ | |
| libayatana-appindicator3-dev \ | |
| librsvg2-dev \ | |
| libxdo-dev \ | |
| libssl-dev \ | |
| libdbus-1-dev \ | |
| patchelf | |
| # Every cargo step on Unix goes through the annotator so a failure is | |
| # readable from the checks API without admin rights on the repository. | |
| # See the script's header for why that matters. | |
| - name: cargo check | |
| if: runner.os != 'Windows' | |
| run: scripts/ci/run-and-annotate.sh "cargo check (${{ matrix.label }})" cargo check --manifest-path src-tauri/Cargo.toml --all-targets | |
| - name: cargo test | |
| if: runner.os != 'Windows' | |
| run: scripts/ci/run-and-annotate.sh "cargo test (${{ matrix.label }})" cargo test --manifest-path src-tauri/Cargo.toml | |
| # Windows has no bash by default for the annotator wrapper, and its logs | |
| # are readable from the run page anyway. Run cargo directly there. | |
| - name: cargo check (Windows) | |
| if: runner.os == 'Windows' | |
| run: cargo check --manifest-path src-tauri/Cargo.toml --all-targets | |
| - name: cargo test (Windows) | |
| if: runner.os == 'Windows' | |
| run: cargo test --manifest-path src-tauri/Cargo.toml | |
| # The security code is where a warning is most worth reading, so | |
| # clippy runs — but it does not fail the build yet, because the | |
| # existing code has never been linted and a red CI that everyone | |
| # learns to ignore is worse than no CI. | |
| - name: cargo clippy (advisory) | |
| continue-on-error: true | |
| run: cargo clippy --manifest-path src-tauri/Cargo.toml --all-targets |