Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .githooks/commit-msg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env sh
# Strips assistant attribution trailers from every commit message.
# Strips attribution trailers from every commit message.
#
# House rule: commits carry the owner's name and nothing else. Tooling that
# appends its own attribution is stripped here rather than caught in review,
Expand Down Expand Up @@ -30,7 +30,7 @@ rm -f "$tmp"
# message is true, and nothing else did either.
#
# **It warns and never blocks**, deliberately. A message legitimately names paths it does not
# touch the file a fix refers to, a path being explained, a command being quoted so a
# touch (the file a fix refers to, a path being explained, a command being quoted), so a
# blocking version would be wrong far more often than right. This exists to put the claim and
# the diff in front of the author at the moment of writing, not to arbitrate.
#
Expand Down Expand Up @@ -66,12 +66,12 @@ for tok in $(tr -c 'A-Za-z0-9_./-' ' ' < "$msg_file"); do
done

if [ -n "$missing" ]; then
echo "commit-msg: WARNING the message names paths that exist nowhere in the tree:" >&2
echo "commit-msg: WARNING: the message names paths that exist nowhere in the tree:" >&2
for m in $missing; do echo " $m" >&2; done
fi

if [ -n "$unstaged" ]; then
echo "commit-msg: NOTE the message names paths this commit does not touch:" >&2
echo "commit-msg: NOTE: the message names paths this commit does not touch:" >&2
for m in $unstaged; do echo " $m" >&2; done
echo " Fine when the message refers to a file; wrong when it claims to have" >&2
echo " changed one. This is the noisy tier and it is meant to be read, not obeyed." >&2
Expand Down
29 changes: 29 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# SPDX-FileCopyrightText: Sudo Apt Holdings LLC
# SPDX-License-Identifier: Apache-2.0
#
# Dependabot opens a pull request when a dependency has a security advisory or a newer
# release. A pull request is not an upgrade: VERSIONS.md is the pin list, and a version
# lands only after it is proposed in a slice's NOTES.md and approved (CLAUDE.md section 5).
# The value here is the alert arriving as a diff with the gate run against it.
version: 2
updates:
- package-ecosystem: mix
directory: /
schedule:
interval: weekly
open-pull-requests-limit: 5
commit-message:
prefix: "chore(deps)"
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
commit-message:
prefix: "chore(ci)"
- package-ecosystem: cargo
directory: /src-tauri
schedule:
interval: weekly
open-pull-requests-limit: 3
commit-message:
prefix: "chore(deps)"
15 changes: 11 additions & 4 deletions .github/workflows/gate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,23 @@ jobs:
MIX_ENV: test
TRINITY_DB: sqlite
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
fetch-depth: 0 # plan_check rule 8 reads the whole history

- uses: erlef/setup-beam@v1
# On a pull request the default checkout is a merge commit GitHub makes on the fly,
# authored by nobody and signed off by nobody. plan_check rule 8 refused it on the
# first pull request this repository ever had (run 35477492177). The branch head is
# what was written and signed, so that is what the gate reads. The ruleset's strict
# policy requires the branch to be current with main before it can merge, so the
# head is also what main will contain.
ref: ${{ github.event.pull_request.head.sha || github.sha }}

- uses: erlef/setup-beam@54075bcc5e249e4758d363f27d099f55d843f124 # v1.24.1
with:
version-file: .tool-versions
version-type: strict

- uses: actions/cache@v4
- uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: |
deps
Expand Down
55 changes: 34 additions & 21 deletions .github/workflows/package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,26 @@
name: package

# Corrected 2026-09-06, before this workflow had ever run. The push trigger was
# `branches: [main]`, so the one branch whose evidence depends on itthe slice branch was
# `branches: [main]`, so the one branch whose evidence depends on it, the slice branch, was
# the one branch it ignored, and pushing slice 001 produced no package run at all. Slice
# branches are where a packaging change is proven; main is where it has already been proven.
#
# Narrowed 2026-09-19. Between 2026-09-05 and 2026-09-07 this matrix ran 31 times on every
# push, 1 600 runner-minutes, most of them Windows and macOS, for a packaging path that
# slice 001 had already proven. It now runs when a slice or release tag is pushed, on a
# change to something packaging actually depends on, or by hand. A slice that touches
# packaging asks for the run with `workflow_dispatch` and cites the run id in its proof.
on:
push:
branches: [main, 'slice/**']
pull_request:
tags: ['slice/**', 'v*']
paths:
- mix.exs
- mix.lock
- config/**
- src-tauri/**
- rust-toolchain.toml
- .tool-versions
- .github/workflows/package.yml
workflow_dispatch:

jobs:
Expand All @@ -41,9 +54,9 @@ jobs:
artifact: desktop_windows_x86_64.exe

steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0

- uses: erlef/setup-beam@v1
- uses: erlef/setup-beam@54075bcc5e249e4758d363f27d099f55d843f124 # v1.24.1
with:
version-file: .tool-versions
version-type: strict
Expand All @@ -56,12 +69,12 @@ jobs:
shell: bash
run: echo "version=$(awk '$1=="zig"{print $2}' .tool-versions)" >> "$GITHUB_OUTPUT"

- uses: mlugg/setup-zig@v2
- uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # v2.2.1
with:
version: ${{ steps.zig.outputs.version }}

# The Rust version is not written here either: rustup reads rust-toolchain.toml, which
# is the pin (see NOTES.md D1 asdf has no rust plugin and ignores a rust line).
# is the pin (see NOTES.md D1: asdf has no rust plugin and ignores a rust line).
- name: Rust toolchain from rust-toolchain.toml
shell: bash
run: rustup show active-toolchain
Expand Down Expand Up @@ -103,7 +116,7 @@ jobs:
# * daisyui (https://github.com/saadeghi/daisyui.git - v5.5.20)
# lock mismatch: the dependency is out of date
#
# A second `mix deps.get` under MIX_ENV=prod did NOT fix it it reported "All
# A second `mix deps.get` under MIX_ENV=prod did NOT fix it: it reported "All
# dependencies have been fetched" and the release refused anyway, so the checkout on
# disk is what Mix disagrees with, not the environment. Both offenders are git
# `sparse` deps carrying `app: false, compile: false`; they exist for the asset build
Expand Down Expand Up @@ -139,7 +152,7 @@ jobs:

# Item 2 of the G4 decision. `src-tauri/` exists from slice 001's ex_tauri.install, so
# the shell is buildable in CI. This compiles the Rust window; it does not run it, and
# no job here claims a window opened a runner has no desktop session.
# no job here claims a window opened: a runner has no desktop session.
- name: Build the Tauri shell
shell: bash
run: cargo build --manifest-path src-tauri/Cargo.toml --locked
Expand All @@ -157,14 +170,14 @@ jobs:
# --no-halt is what makes the exit mean anything. Burrito launches the release as
# `-s elixir start_cli`, and the Elixir CLI halts when its command list is empty, so
# without --no-halt the binary exits 0 on its own and `--smoke` proves nothing.
- name: Smoke boots, serves, exits by itself, leaves nothing behind
- name: Smoke test: boots, serves, exits by itself, leaves nothing behind
if: runner.os != 'Windows'
shell: bash
run: |
set -euo pipefail
# Match OUR processes, not the machine's. The first version of this step diffed the
# whole `ps -eo pid,ppid,comm` table and failed on macOS because the runner's own
# daemons churn between the two samples mdworker_shared exiting, CloudTelemetry
# daemons churn between the two samples: mdworker_shared exiting, CloudTelemetry
# starting, and the `ps` process itself differing. The artifact had launched, served
# and exited cleanly; the assertion was wrong, not the binary. "No process of ours
# remains" is the claim AC7 actually makes.
Expand All @@ -179,7 +192,7 @@ jobs:
echo "--- ours, after ----"; cat ps-after.txt
diff ps-before.txt ps-after.txt

- name: Smoke Windows
- name: Smoke test on Windows
if: runner.os == 'Windows'
shell: pwsh
run: |
Expand Down Expand Up @@ -222,7 +235,7 @@ jobs:
done
test -n "${PORT:-}"
# Bounded. The first version of this loop had no limit and the Windows runner sat in
# it until the run was cancelled by hand a step that hangs reports nothing and
# it until the run was cancelled by hand: a step that hangs reports nothing and
# fails nothing, which is the same shape as a workflow that never fires.
ok=0
for _ in $(seq 1 600); do
Expand All @@ -238,11 +251,11 @@ jobs:
code=$(curl -sS -o /dev/null -w '%{http_code}' "http://127.0.0.1:$PORT/")
echo "HTTP $code on port $PORT"
echo "COLD_START_MS=$elapsed" | tee -a "$GITHUB_ENV"
echo "### ${{ matrix.name }} cold start to first HTTP 200: **${elapsed} ms**" >> "$GITHUB_STEP_SUMMARY"
echo "### ${{ matrix.name }}: cold start to first HTTP 200: **${elapsed} ms**" >> "$GITHUB_STEP_SUMMARY"
test "$code" = "200"
# Stopping it, and Windows needs its own verb. `kill` from Git-bash does not stop a
# native Windows process, so the backgrounded .exe outlived the step and the job hung
# long past the bounded loops above run 34078281292, cancelled by hand. `taskkill
# long past the bounded loops above: run 34078281292, cancelled by hand. `taskkill
# /T` takes the wrapper and its BEAM together, which on Windows is also the only
# thing that clears finding F1's orphan.
if [ "${{ runner.os }}" = "Windows" ]; then
Expand All @@ -251,19 +264,19 @@ jobs:
else
CHILD=$(pgrep -P "$PID" 2>/dev/null || true)
kill "$PID" || true
# The wrapper does not forward termination to the BEAM it launched finding F1,
# The wrapper does not forward termination to the BEAM it launched: finding F1,
# re-measured at G4 as an orphan still serving 200 past 7.6 s. Kill the child
# explicitly or the runner leaves it behind.
[ -n "$CHILD" ] && kill "$CHILD" 2>/dev/null || true
fi

- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: ${{ matrix.artifact }}
path: burrito_out/${{ matrix.artifact }}
if-no-files-found: error

- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
if: always()
with:
name: launch-log-${{ matrix.target }}
Expand All @@ -272,14 +285,14 @@ jobs:
serve.log
if-no-files-found: warn

# Line 10. Each job states, in its own summary, which of the two things it did and
# Line 10. Each job states, in its own summary, which of the two things it did, and
# every job here did the second one.
- name: State what this job did not prove
if: always()
shell: bash
run: |
{
echo "## ${{ matrix.name }} what this run does and does not establish"
echo "## ${{ matrix.name }}: what this run does and does not establish"
echo
echo "**Established:** the artifact builds on ${{ matrix.os }}; it launches and"
echo "reaches serving; under \`--no-halt --smoke\` it exits by itself and the"
Expand All @@ -291,7 +304,7 @@ jobs:
echo
echo "**Not established, and not claimed:** the shell was **built, never run.**"
echo "No native window was opened. This job smoked the **sidecar alone, with no"
echo "display** it did not run the shell under \`xvfb-run\` and it did not use a"
echo "display**: it did not run the shell under \`xvfb-run\` and it did not use a"
echo "desktop session, because this runner has none. No screenshot exists here;"
echo "the only screenshot of a real window in this project is the owner's, on"
echo "Linux, at slices/001-packaging-spike/proof/. First **paint** was not"
Expand Down
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ erl_crash.dump
# Desktop shell (slices 001, 100, 101)
# `mix ex_tauri.install` creates `src-tauri/`, not `tauri/`, so the rule this line replaces
# named a directory that has never existed. Corrected at slice 001 G4. Rust build output was
# never actually at risk the generator writes its own src-tauri/.gitignore carrying
# `/target/` but a rule that matches nothing is a claim that is not true.
# never actually at risk (the generator writes its own src-tauri/.gitignore carrying
# `/target/`), but a rule that matches nothing is a claim that is not true.
/src-tauri/target/
/priv/static/assets/
# Burrito's output: one packaged binary per target, tens of MB each. Slice 001 measures them
Expand Down
Loading
Loading