Compare commits

..
1 Commits
Author SHA1 Message Date
sorokin.oleg.edu c812d49250 chore: update fork project and release URLs 2026-11-01 06:37:12 +03:00
9 changed files with 16 additions and 16 deletions
+3 -3
View File
@@ -12,7 +12,7 @@
<a href="https://learnharness.ai">Download</a> ·
<a href="#how-it-works">How it works</a> ·
<a href="docs/development.md">Documentation</a> ·
<a href="https://github.com/amosblomqvist/learnharness/issues">Issues</a> ·
<a href="https://git.sorokin-oleg-edu.xyz/sorokin.oleg.edu/learnharness/issues">Issues</a> ·
<a href="https://discord.gg/5tCHHQEB2e">Discord</a>
</p>
@@ -43,7 +43,7 @@ Future teaching sessions can read the graph instead of starting from scratch. Pr
## Download and get started
**[Download from learnharness.ai](https://learnharness.ai)** · [GitHub Releases](https://github.com/amosblomqvist/learnharness/releases)
**[Download from learnharness.ai](https://learnharness.ai)** · [Gitea Releases](https://git.sorokin-oleg-edu.xyz/sorokin.oleg.edu/learnharness/releases)
- **macOS (Apple Silicon):** signed and notarized DMG. Drag the app to Applications.
- **Windows (x64):** run the installer. It is currently unsigned; Windows may show an “unknown publisher” or SmartScreen warning.
@@ -72,7 +72,7 @@ npm test # deterministic, no LLM, no network
See the [development guide](docs/development.md), [architecture](docs/architecture.md), and [desktop release guide](docs/desktop-release.md).
Questions, bug reports, and feature requests: [GitHub Issues](https://github.com/amosblomqvist/learnharness/issues).
Questions, bug reports, and feature requests: [Gitea Issues](https://git.sorokin-oleg-edu.xyz/sorokin.oleg.edu/learnharness/issues).
## License
+1 -1
View File
@@ -15,7 +15,7 @@ Windows signing is deliberately disabled for this first release. SmartScreen may
The custom app bar stays on all three platforms. macOS keeps its left-side traffic lights; Windows/Linux use Electron's native right-side Window Controls Overlay, with CSS space reserved from the overlay's actual geometry. Windows/Linux hide the native menu until Alt is pressed. macOS keeps its system menu.
Icons are per-platform (2026-10-13): macOS compiles the Icon Composer document `build/icon.icon` via actool into `Assets.car` (macOS 26 Liquid Glass) plus a fallback icns that `scripts/after-pack.cjs` replaces with the hand-packed full-res `build/icon.icns` (actool's caps at 256px); Windows embeds `build/icon.ico` and Linux uses `build/icon.png`, both generated from the flat design (`build/icon-flat.svg`) by `node scripts/make-icons.mjs`. Building the mac icon needs **macOS 26+ and Xcode 26+** (`actool`): Xcode 26's asset compiler crashes on macOS 15 because its host frameworks lack required symbols. `desktop:dist` injects `DEVELOPER_DIR` locally; release packaging uses `macos-26` and selects Xcode via setup-xcode. The older-OS fallback icon remains included. Linux's desktop identity is `learnharness.desktop`. Public package-maintainer metadata uses the owner's GitHub no-reply address; support goes through [GitHub Issues](https://github.com/amosblomqvist/learnharness/issues).
Icons are per-platform (2026-10-13): macOS compiles the Icon Composer document `build/icon.icon` via actool into `Assets.car` (macOS 26 Liquid Glass) plus a fallback icns that `scripts/after-pack.cjs` replaces with the hand-packed full-res `build/icon.icns` (actool's caps at 256px); Windows embeds `build/icon.ico` and Linux uses `build/icon.png`, both generated from the flat design (`build/icon-flat.svg`) by `node scripts/make-icons.mjs`. Building the mac icon needs **macOS 26+ and Xcode 26+** (`actool`): Xcode 26's asset compiler crashes on macOS 15 because its host frameworks lack required symbols. `desktop:dist` injects `DEVELOPER_DIR` locally; release packaging uses `macos-26` and selects Xcode via setup-xcode. The older-OS fallback icon remains included. Linux's desktop identity is `learnharness.desktop`. Public package-maintainer metadata uses the owner's GitHub no-reply address; support goes through [Gitea Issues](https://git.sorokin-oleg-edu.xyz/sorokin.oleg.edu/learnharness/issues).
## Build pipeline
+2 -2
View File
@@ -1,7 +1,7 @@
# Gitea releases for this fork
The release destination is
https://git.sorokin-oleg-edu.xyz/replicated/learnharness.
https://git.sorokin-oleg-edu.xyz/sorokin.oleg.edu/learnharness.
Version **0.6.1 is Linux x64 AppImage-only**; follow the dedicated procedure below.
The historical **0.6.0 release targets Linux x64 and Windows x64**, with each platform built
and verified on its native operating system. The upstream GitHub workflow and three-platform packaging
@@ -12,7 +12,7 @@ Official fork packages use `electron-builder.gitea.yml`, which inherits the
upstream packaging and replaces its update origin with:
```
https://git.sorokin-oleg-edu.xyz/replicated/learnharness/releases/download/latest
https://git.sorokin-oleg-edu.xyz/sorokin.oleg.edu/learnharness/releases/download/latest
```
Gitea's `latest` alias resolves the most recent published, non-prerelease release.
+1 -1
View File
@@ -5,4 +5,4 @@ publish:
provider: generic
# Gitea resolves the latest published, non-prerelease release here.
# Drafts remain private and do not become an update before publication.
url: https://git.sorokin-oleg-edu.xyz/replicated/learnharness/releases/download/latest
url: https://git.sorokin-oleg-edu.xyz/sorokin.oleg.edu/learnharness/releases/download/latest
+1 -1
View File
@@ -6,7 +6,7 @@
"name": "Amos Blomqvist",
"email": "255718537+amosblomqvist@users.noreply.github.com"
},
"homepage": "https://github.com/amosblomqvist/learnharness",
"homepage": "https://git.sorokin-oleg-edu.xyz/sorokin.oleg.edu/learnharness",
"desktopName": "learnharness.desktop",
"description": "An agent harness for learning: adaptive teaching, practice, and a persistent knowledge graph.",
"type": "module",
+1 -1
View File
@@ -14,7 +14,7 @@ const require = createRequire(import.meta.url);
const yaml = require("js-yaml");
const ROOT = path.resolve(import.meta.dirname, "..");
export const SERVER = "https://git.sorokin-oleg-edu.xyz";
export const REPOSITORY = "replicated/learnharness";
export const REPOSITORY = "sorokin.oleg.edu/learnharness";
export const UPDATE_URL = `${SERVER}/${REPOSITORY}/releases/download/latest`;
const API = `${SERVER}/api/v1/repos/${REPOSITORY}`;
+1 -1
View File
@@ -166,7 +166,7 @@ describe("desktop packaging policy", () => {
const pkg = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
assert.equal(pkg.author.name, "Amos Blomqvist");
assert.equal(pkg.author.email, "255718537+amosblomqvist@users.noreply.github.com");
assert.equal(pkg.homepage, "https://github.com/amosblomqvist/learnharness");
assert.equal(pkg.homepage, "https://git.sorokin-oleg-edu.xyz/sorokin.oleg.edu/learnharness");
assert.equal(pkg.desktopName, "learnharness.desktop");
});
});
+5 -5
View File
@@ -26,7 +26,7 @@ async function fixture(name: string, appimageOnly = false, fixtureVersion = vers
test("Linux release inventory and Gitea feed match the current release scope", () => {
assert.deepEqual(names, ["LearnHarness-0.4.0-x86_64.AppImage", "LearnHarness-0.4.0-amd64.deb", "latest-linux.yml", "SHA256SUMS"]);
assert.equal(UPDATE_URL, "https://git.sorokin-oleg-edu.xyz/replicated/learnharness/releases/download/latest");
assert.equal(UPDATE_URL, "https://git.sorokin-oleg-edu.xyz/sorokin.oleg.edu/learnharness/releases/download/latest");
assert.throws(() => expectedLinuxAssets("0.4.0-preview"));
});
test("local verification checks actual installer bytes, updater hashes, sizes and checksum manifest", async () => {
@@ -61,7 +61,7 @@ test("empty files and arbitrary downloads cannot pass as installers", async () =
test("remote verification downloads and hashes every draft attachment, and refuses published or incomplete releases", async () => {
const directory = await fixture("remote");
const inventory = await verifyLocal(directory, version);
const assets = inventory.map((asset) => ({ ...asset, browser_download_url: `https://git.sorokin-oleg-edu.xyz/replicated/learnharness/releases/download/v0.4.0/${asset.name}` }));
const assets = inventory.map((asset) => ({ ...asset, browser_download_url: `https://git.sorokin-oleg-edu.xyz/sorokin.oleg.edu/learnharness/releases/download/v0.4.0/${asset.name}` }));
const release = { draft: true, prerelease: false, assets };
const request = async (input: URL | RequestInfo) => {
const url = input instanceof URL ? input : new URL(String(input));
@@ -184,10 +184,10 @@ function mockedReleaseCommand(directory: string, command: string, options: strin
const { version } = JSON.parse(await fs.readFile(${JSON.stringify(path.resolve(import.meta.dirname, "../package.json"))}, "utf8"));
const tag = "v" + version;
const server = "https://git.sorokin-oleg-edu.xyz";
const api = "/api/v1/repos/replicated/learnharness";
const api = "/api/v1/repos/sorokin.oleg.edu/learnharness";
const calls = { api: [], uploads: [], downloads: [], edits: [] };
const files = (await fs.readdir(directory)).filter(name => name.endsWith(".AppImage") || name.endsWith(".deb") || ["latest-linux.yml", "SHA256SUMS"].includes(name));
const assets = await Promise.all(files.map(async name => ({ name, size: (await fs.stat(path.join(directory, name))).size, browser_download_url: server + "/replicated/learnharness/releases/download/" + tag + "/" + name })));
const assets = await Promise.all(files.map(async name => ({ name, size: (await fs.stat(path.join(directory, name))).size, browser_download_url: server + "/sorokin.oleg.edu/learnharness/releases/download/" + tag + "/" + name })));
const release = { id: 1, tag_name: tag, draft: scenario !== "published", prerelease: scenario === "prerelease", assets: scenario === "new" ? [] : [...assets], html_url: server + "/draft" };
if (scenario === "missing-asset") release.assets.pop();
if (scenario === "duplicate-asset") release.assets.push(assets[0]);
@@ -228,7 +228,7 @@ function mockedReleaseCommand(directory: string, command: string, options: strin
return json(asset);
}
if (method === "GET" && url.pathname === api + "/releases/1") return json(release);
} else if (method === "GET" && url.pathname.startsWith("/replicated/learnharness/releases/download/" + tag + "/")) {
} else if (method === "GET" && url.pathname.startsWith("/sorokin.oleg.edu/learnharness/releases/download/" + tag + "/")) {
const name = decodeURIComponent(path.basename(url.pathname));
assert(files.includes(name), "download outside expected fixture");
calls.downloads.push(name);
+1 -1
View File
@@ -51,7 +51,7 @@ test("Gitea updater identity and release tooling are preserved", () => {
const config = source("electron-builder.gitea.yml");
assert.match(config, /extends: \.\/electron-builder\.yml/);
assert.match(config, /provider: generic/);
assert.match(config, /url: https:\/\/server2\.sorokin-oleg-edu\.xyz\/replicated\/learnharness\/releases\/download\/latest/);
assert.match(config, /url: https:\/\/git\.sorokin-oleg-edu\.xyz\/sorokin\.oleg\.edu\/learnharness\/releases\/download\/latest/);
assert.ok(tracked.has("scripts/gitea-release.mjs"));
});