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
1 change: 0 additions & 1 deletion .githooks/pre-commit
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#!/bin/sh
set -eu
dotnet run --project eng/ArcForges.Repository -- check
git diff --cached --check
6 changes: 2 additions & 4 deletions .githooks/pre-push
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
#!/bin/sh
set -eu
dotnet restore ArcNotes.slnx --locked-mode
dotnet format ArcNotes.slnx --verify-no-changes --no-restore
dotnet build ArcNotes.slnx -c Release --no-restore
dotnet test --project tests/ArcForges.ArcNotes.Tests/ArcForges.ArcNotes.Tests.csproj -c Release --no-build
# Build and test explicitly once when the change requires them; never on every push.
git diff --check
56 changes: 16 additions & 40 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,6 @@ jobs:
rid: win-arm64
- os: ubuntu-24.04
rid: linux-x64
- os: macos-15-intel
rid: osx-x64
- os: macos-15
rid: osx-arm64
defaults:
run:
shell: bash
Expand All @@ -53,17 +49,24 @@ jobs:
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y clang zlib1g-dev libx11-6 libice6 libsm6 libfontconfig1 xvfb fonts-dejavu-core
sudo apt-get install -y clang zlib1g-dev
- run: dotnet restore ArcNotes.slnx --locked-mode
- run: dotnet format ArcNotes.slnx --verify-no-changes --no-restore
- name: Check formatting once
if: runner.os == 'Linux'
run: dotnet format ArcNotes.slnx --verify-no-changes --no-restore
- run: dotnet build ArcNotes.slnx -c Release --no-restore
- run: dotnet run --project eng/ArcForges.Repository -c Release --no-build -- verify-assemblies
- run: dotnet run --project eng/ArcForges.Repository -c Release --no-build -- check
- name: Run verify-assemblies once
if: runner.os == 'Linux'
run: dotnet run --project eng/ArcForges.Repository -c Release --no-build -- verify-assemblies
- name: Run check once
if: runner.os == 'Linux'
run: dotnet run --project eng/ArcForges.Repository -c Release --no-build -- check
- name: Set immutable version
id: version
run: dotnet run --project eng/ArcForges.Repository -c Release --no-build -- version
- name: Run deterministic tests
run: dotnet test --project tests/ArcForges.ArcNotes.Tests/ArcForges.ArcNotes.Tests.csproj -c Release --no-build
- name: Run offline unit tests once
if: runner.os == 'Linux'
run: dotnet test --project tests/ArcForges.ArcNotes.Tests/ArcForges.ArcNotes.Tests.csproj -c Release --no-build --filter-not-class '*.TransportTests'
- name: Compile Native AOT executable
env:
PACKAGE_VERSION: ${{ steps.version.outputs.version }}
Expand All @@ -74,16 +77,7 @@ jobs:
PACKAGE_VERSION: ${{ steps.version.outputs.version }}
TARGET_RID: ${{ matrix.rid }}
run: dotnet run --project eng/ArcForges.Repository -c Release --no-build -- prepare "$TARGET_RID" "$PACKAGE_VERSION"
- name: Run native UI and live Cloud checks
env:
TARGET_RID: ${{ matrix.rid }}
run: |
if [ "$RUNNER_OS" = "Linux" ]; then
xvfb-run -a dotnet run --project eng/ArcForges.Repository -c Release --no-build -- smoke "$TARGET_RID"
else
dotnet run --project eng/ArcForges.Repository -c Release --no-build -- smoke "$TARGET_RID"
fi
- name: Pack the verified native directory
- name: Pack the compiled native directory
env:
PACKAGE_VERSION: ${{ steps.version.outputs.version }}
TARGET_RID: ${{ matrix.rid }}
Expand Down Expand Up @@ -191,24 +185,6 @@ jobs:
test "$QUALITY" = success
test "$CODEQL" = success
if [ "$EVENT" = pull_request ]; then test "$DEPENDENCIES" = success; else test "$DEPENDENCIES" = skipped; fi
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
persist-credentials: false
- uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68 # v6
with:
global-json-file: global.json
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
pattern: arcnotes-candidate-*-${{ github.run_id }}-${{ github.run_attempt }}
path: artifacts/download
- run: dotnet restore eng/ArcForges.Repository --locked-mode
- run: dotnet build eng/ArcForges.Repository -c Release --no-restore
- id: version
run: dotnet run --project eng/ArcForges.Repository -c Release --no-build -- version
- name: Rehearse the complete release verification before merge
env:
PACKAGE_VERSION: ${{ steps.version.outputs.version }}
run: dotnet run --project eng/ArcForges.Repository -c Release --no-build -- verify artifacts/download "$PACKAGE_VERSION" "$GITHUB_SHA"

release:
name: Publish portable release
Expand Down Expand Up @@ -237,7 +213,7 @@ jobs:
- run: dotnet build eng/ArcForges.Repository -c Release --no-restore
- id: version
run: dotnet run --project eng/ArcForges.Repository -c Release --no-build -- version
- name: Verify immutable candidates
- name: Check candidate integrity once at publication handoff
env:
PACKAGE_VERSION: ${{ steps.version.outputs.version }}
run: dotnet run --project eng/ArcForges.Repository -c Release --no-build -- verify artifacts/download "$PACKAGE_VERSION" "$GITHUB_SHA"
Expand All @@ -250,7 +226,7 @@ jobs:
tag="v$PACKAGE_VERSION"
gh release create "$tag" --target "$GITHUB_SHA" --title "ArcNotes $PACKAGE_VERSION" --draft --prerelease --notes-file docs/release-notes.md
mapfile -d '' assets < <(find artifacts/download -type f \( -name '*.zip' -o -name '*.tar.gz' -o -name '*.sha256' \) -print0)
test "${#assets[@]}" = 10
test "${#assets[@]}" = 6
gh release upload "$tag" "${assets[@]}"
tar --exclude='*.zip' --exclude='*.tar.gz' --exclude='*.sha256' -czf artifacts/arcnotes-verification.tar.gz -C artifacts/download .
gh release upload "$tag" artifacts/arcnotes-verification.tar.gz
Expand Down
11 changes: 8 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
- Keep this repository a C# desktop consumer. Use published, exact NuGet dependencies and committed locks. Do not add sibling source references or submodules.
- Keep AGPL-3.0-only headers and the existing licence. Do not import reference code under incompatible terms.
- Preserve Native AOT, normal TLS validation, `/api` routing, RPC deadlines, cancellation and user-visible failures. No fake success, credential in a desktop binary, blanket trimming suppression or automatic application retries.
- Keep the production entry point offline until a user action. Live smoke testing is explicit and must exercise the native UI action and published client.
- Run the checks in `CONTRIBUTING.md`. Never describe a local test, cross-compile or mock as a hosted native or live service test.
- PRs validate; only successful main pushes publish all five verified candidates. Do not merge a PR unless the user requests it.
- Keep the production entry point offline until a user action. Runtime tests are explicit local opt-in only when the affected behavior needs them and the existing environment supports them.
- Follow the [accepted CI and local validation policy](https://github.com/ArcForges/ArcForges-Design/blob/47db6670a727317939b91245e8c0b288834acf99/docs/assurance/ci-and-local-validation-policy.md). No macOS CI, device/emulator/GUI/browser E2E, live service or installed-package consumer execution is permitted in any hosted workflow or nested default build/publish command.
- CI compiles and packages Windows x64/ARM64 and Linux x64. Run platform-independent static checks and offline unit tests once. Preserve dependency locks, necessary signing, source/licence provenance and one candidate integrity check at the publication handoff.
- Do not routinely download published assets, compare their hashes/members or run another installation/runtime verification cycle. A concrete integrity defect or explicit user request is required for a scoped diagnostic download.
- Validate only affected behavior once. Do not install or reinstall vcpkg, SDKs, emulators or toolchains to expand coverage. Hooks must not rebuild or test implicitly. Serialize CPU-heavy local work and reuse existing caches.
- Never describe unrun local/macOS/runtime checks as passed. Historical evidence is not a command to repeat it. Documentation-only changes need consistency review, not product builds.
- Use the normal network; no proxy 7890, other proxy configuration, wsl.exe or WSL wrappers. Stop and report the exact failing operation on a network failure without retries.
- Use retained worktrees/branches and PR titles prefixed with the current work package/substep. Review the full latest PR head and merge only after applicable reduced CI succeeds when merging is user-authorized. Post-merge checks stop after expected commit, required publication result and clean primary fast-forward; do not begin another validation cycle.
9 changes: 4 additions & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,16 @@ Use a branch/worktree and open a pull request. Keep one coherent change per PR a

```sh
dotnet restore ArcNotes.slnx --locked-mode
dotnet run --project eng/ArcForges.Repository -- hooks
dotnet run --project eng/ArcForges.Repository -- check
dotnet format ArcNotes.slnx --verify-no-changes --no-restore
dotnet build ArcNotes.slnx -c Release --no-restore
dotnet test --project tests/ArcForges.ArcNotes.Tests/ArcForges.ArcNotes.Tests.csproj -c Release --no-build
dotnet run --project eng/ArcForges.Repository -c Release --no-build -- check
dotnet test --project tests/ArcForges.ArcNotes.Tests/ArcForges.ArcNotes.Tests.csproj -c Release --no-build --filter-not-class '*.TransportTests'
```

`dotnet format ArcNotes.slnx --no-restore` fixes C# formatting. Hooks are local to the checkout using Git worktree configuration. Pre-commit checks text and whitespace; pre-push restores locked dependencies, builds and runs deterministic tests. Hosted CI is authoritative even if hooks are not installed. Hooks do not call the live backend.
`dotnet format ArcNotes.slnx --no-restore` fixes C# formatting. Hooks are local to the checkout using Git worktree configuration. Pre-commit and pre-push check Git whitespace only. Run the relevant commands above explicitly once for source changes; documentation-only changes need consistency review. CI repeats no GUI/live/runtime scenarios and runs offline unit checks on one Linux host.

Change direct dependency versions only in `Directory.Packages.props`. After an intentional dependency change, run `dotnet restore ArcNotes.slnx --force-evaluate -p:RestoreLockedMode=false`, inspect every lock diff, and rerun locked restore and validation. Updating an SDK also requires refreshing implicit runtime/compiler entries in locks. Do not hand-edit content hashes or disable audit/locked restore to make a bot PR green.

Review upstream licence changes when updating dependencies. `third-party/` preserves primary licence texts missing from NuGet packages, with pinned source commits and hashes. Update those records if the corresponding upstream terms change; preserve their bytes. Native package notices embedded by upstream are collected automatically during staging.

Native release/live validation is described in [development](docs/development.md). No secrets are required for Hello. Do not place credentials or personal data in fixtures, logs or screenshots. Report security issues privately using [SECURITY](SECURITY.md).
Optional local native and loopback transport validation is described in [development](docs/development.md); it is not a CI or publication prerequisite. No secrets are required for Hello. Do not place credentials or personal data in fixtures, logs or screenshots. Report security issues privately using [SECURITY](SECURITY.md).
9 changes: 4 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Install .NET SDK **10.0.401** and the native build prerequisites in [development
```sh
dotnet restore ArcNotes.slnx --locked-mode
dotnet build ArcNotes.slnx -c Release --no-restore
dotnet test --project tests/ArcForges.ArcNotes.Tests/ArcForges.ArcNotes.Tests.csproj -c Release --no-build
dotnet test --project tests/ArcForges.ArcNotes.Tests/ArcForges.ArcNotes.Tests.csproj -c Release --no-build --filter-not-class '*.TransportTests'
dotnet run --project src/ArcForges.ArcNotes
dotnet run --project eng/ArcForges.Repository -- hooks
```
Expand All @@ -20,17 +20,16 @@ The UI, application state and repository tool are C#. Avalonia/Skia supply packa

## Downloads and automation

Each successful main push publishes a prerelease `v0.1.0-ci.<run>.<attempt>` to [GitHub Releases](https://github.com/ArcForges/ArcNotes/releases). PRs build and test the same five Native AOT targets but never publish a release:
Each successful main push publishes a prerelease `v0.1.0-ci.<run>.<attempt>` to [GitHub Releases](https://github.com/ArcForges/ArcNotes/releases). PRs compile the same three Windows/Linux Native AOT targets and run offline checks but never publish a release:

| Platform | Archive |
| --- | --- |
| Windows x64 / ARM64 | Portable ZIP; extract everything and run `ArcNotes.exe` |
| Linux x64 | Portable tar.gz; extract everything and run `./ArcNotes` in an X11/XWayland desktop |
| macOS Intel / Apple Silicon | tar.gz containing `ArcNotes.app` and notices |

Keep all files together. These self-contained builds do not require a .NET installation. They are development distributions: Windows binaries are unsigned and macOS bundles are ad-hoc signed, not Developer ID signed or notarized. No installer, app-store identity or OS trust claim is included. Linux system libraries are listed in [development](docs/development.md). Source for a release is its exact Git tag/commit.
Keep all files together. These self-contained builds do not require a .NET installation. They are development distributions: Windows binaries are unsigned. Automated releases do not contain macOS builds; local macOS source support remains available without CI or release claims. No installer, app-store identity or OS trust claim is included. Linux system libraries are listed in [development](docs/development.md). Source for a release is its exact Git tag/commit.

CI verifies the native window, UI action, live greeting, Unicode/boundaries, gRPC status and backend revision on each native host before packaging. `--smoke-live --evidence <absolute-path.json>` is an explicit network-using validation mode that closes the window afterward; it is not normal startup. See [release mechanics](docs/releasing.md) and [bootstrap plan/evidence](docs/bootstrap-plan.md).
CI performs compilation, packaging, offline unit/static checks and security scanning. It does not launch packaged applications, native UI or live Cloud requests. Runtime smoke is an explicit local-only command when needed; no post-publication asset download or runtime cycle is required. See [release mechanics](docs/releasing.md) and the [validation policy](https://github.com/ArcForges/ArcForges-Design/blob/47db6670a727317939b91245e8c0b288834acf99/docs/assurance/ci-and-local-validation-policy.md).

## Contribute and report issues

Expand Down
2 changes: 2 additions & 0 deletions docs/bootstrap-plan.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# ArcNotes desktop Hello bootstrap

> Historical bootstrap record. Its five-platform/live-test release procedure has been superseded by the [CI and local validation policy](https://github.com/ArcForges/ArcForges-Design/blob/47db6670a727317939b91245e8c0b288834acf99/docs/assurance/ci-and-local-validation-policy.md) and [current release mechanics](releasing.md). Retain the original account below as history; do not execute it as current instructions.

## Source and bounded scope

Copy the complete tracked ArcChat foundation at [merged commit 818ca61b106eb373de94622125a9a54e5a3644d5](https://github.com/ArcForges/ArcChat/commit/818ca61b106eb373de94622125a9a54e5a3644d5), then adapt product identity for ArcNotes (knowledge management). The target started at 9a9de616040622760aa1b8dd213d6310c9996539 with only the same AGPL licence. This is a Hello bootstrap, not implementation of the product's full business workflows.
Expand Down
14 changes: 8 additions & 6 deletions docs/build-identity.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@ format, storage, capability, policy or extension version is invented for this
foundation. Explicit absent states name their later responsible work packages.
There is no first-party native ABI in this application.

Preparation executes the actual Native AOT candidate offline and compares its
report with independently obtained Git/run/release and restored dependency inputs.
The report is included in each portable archive. Archive verification reads it
and rejects even rehashed metadata changes. Existing native UI/live Cloud checks
remain required on all five native CI hosts. The `verify-assemblies` command reads
the actual PE metadata of the app, core, tests and repository tool after compilation.
The repository tool statically reads actual app/core/test/tool PE metadata once.
Preparation writes `build-identity.json` from the reviewed Git/run/release, restored
dependency and committed source inputs without launching the AOT app. This packaged
build-input receipt is not runtime execution evidence. The app's explicit local
`--build-info` command remains available for relevant support diagnostics.
Publication checks candidate identity and legal/source integrity once. CI has three
Windows/Linux compilation targets, no macOS/UI/live execution and no routine public
archive download or runtime verification cycle.

Tests mutate each of the nine distinct source kinds, check deterministic output,
and reject missing/unknown axes, aliases, duplicate subjects, malformed versions,
Expand Down
Loading
Loading