feat/ml-integration #2

Merged
Snider merged 81 commits from feat/ml-integration into dev 2026-02-16 06:19:10 +00:00
67 changed files with 118 additions and 2794 deletions
Showing only changes of commit 4dcd168cd4 - Show all commits

View file

@ -30,7 +30,7 @@ core/
package domain
import (
"github.com/host-uk/core/pkg/cli"
"forge.lthn.ai/core/cli/pkg/cli"
"github.com/spf13/cobra"
)
@ -53,7 +53,7 @@ func NewNameCmd() *cobra.Command {
## CLI Output Helpers
```go
import "github.com/host-uk/core/pkg/cli"
import "forge.lthn.ai/core/cli/pkg/cli"
cli.Success("Operation completed") // Green check
cli.Warning("Something to note") // Yellow warning

View file

@ -1,7 +1,7 @@
# Issue 258: Smart Test Detection
## Original Issue
<https://github.com/host-uk/core/issues/258>
<https://forge.lthn.ai/core/cli/issues/258>
## Summary
Make `core test` smart — detect changed Go files and run only relevant tests.

View file

@ -1,58 +0,0 @@
name: Bug Report
description: Report a problem with the core CLI
title: "[Bug]: "
labels: ["bug", "triage"]
body:
- type: markdown
attributes:
value: |
Thanks for reporting! Please fill out the details below.
- type: dropdown
id: os
attributes:
label: Operating System
options:
- macOS
- Windows
- Linux (Ubuntu/Debian)
- Linux (Other)
validations:
required: true
- type: input
id: command
attributes:
label: Command
description: Which command failed?
placeholder: "e.g., core dev work, core php test"
validations:
required: true
- type: input
id: version
attributes:
label: Version
description: Output of `core version`
placeholder: "e.g., core v0.1.0"
- type: textarea
id: description
attributes:
label: What happened?
description: Describe the issue
validations:
required: true
- type: textarea
id: expected
attributes:
label: Expected behaviour
description: What should have happened?
- type: textarea
id: logs
attributes:
label: Error output
description: Paste any error messages
render: shell

View file

@ -1,8 +0,0 @@
blank_issues_enabled: true
contact_links:
- name: Host UK Documentation
url: https://github.com/host-uk/core-devops
about: Setup guides and workspace documentation
- name: Discussions
url: https://github.com/orgs/host-uk/discussions
about: Ask questions and share ideas

View file

@ -1,58 +0,0 @@
name: Feature Request
description: Suggest a new feature or enhancement
title: "[Feature]: "
labels: ["enhancement"]
body:
- type: markdown
attributes:
value: |
Thanks for the suggestion! Please describe your idea below.
- type: dropdown
id: area
attributes:
label: Area
options:
- dev commands (work, commit, push, pull)
- php commands (test, lint, stan)
- GitHub integration (issues, reviews, ci)
- New command
- Documentation
- Other
validations:
required: true
- type: textarea
id: problem
attributes:
label: Problem or use case
description: What problem does this solve?
validations:
required: true
- type: textarea
id: solution
attributes:
label: Proposed solution
description: How would you like it to work?
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: Alternatives considered
description: Any other approaches you've thought about?
- type: dropdown
id: complexity
attributes:
label: Estimated complexity
description: How much work do you think this requires?
options:
- "Small - Quick fix, single file, < 1 hour"
- "Medium - Multiple files, few hours to a day"
- "Large - Significant changes, multiple days"
- "Unknown - Not sure"
validations:
required: false

View file

@ -1,24 +0,0 @@
version: 2
updates:
- package-ecosystem: "gomod"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
labels:
- "type:dependencies"
- "priority:low"
commit-message:
prefix: "deps(go):"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
labels:
- "type:dependencies"
- "priority:low"
commit-message:
prefix: "deps(actions):"

View file

@ -1,10 +0,0 @@
name: Agent Verification
on:
issues:
types: [labeled]
jobs:
verify:
uses: host-uk/.github/.github/workflows/agent-verify.yml@main
secrets: inherit

View file

@ -1,92 +0,0 @@
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_dispatch
name: "Alpha Release: Manual"
on:
workflow_dispatch:
permissions:
contents: write
id-token: write
attestations: write
env:
NEXT_VERSION: "0.0.4"
jobs:
build:
strategy:
matrix:
include:
- os: ubuntu-latest
platform: linux/amd64
- os: ubuntu-latest
platform: linux/arm64
- os: macos-latest
platform: darwin/universal
- os: windows-latest
platform: windows/amd64
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v6
- name: Build
uses: host-uk/build@v3
with:
build-name: core
build-platform: ${{ matrix.platform }}
build: true
package: true
sign: false
release:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Download artifacts
uses: actions/download-artifact@v7
with:
path: dist
merge-multiple: true
- name: Prepare release files
run: |
mkdir -p release
cp dist/* release/ 2>/dev/null || true
ls -la release/
- name: Create alpha release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
VERSION="v${{ env.NEXT_VERSION }}-alpha.${{ github.run_number }}"
gh release create "$VERSION" \
--title "Alpha: $VERSION" \
--notes "Canary build from dev branch.
**Version:** $VERSION
**Commit:** ${{ github.sha }}
**Built:** $(date -u +'%Y-%m-%d %H:%M:%S UTC')
**Run:** ${{ github.run_id }}
## Channel: Alpha (Canary)
This is an automated pre-release for early testing.
- Systems and early adopters can test breaking changes
- Quality scoring determines promotion to beta
- Use stable releases for production
## Installation
\`\`\`bash
# macOS/Linux
curl -fsSL https://github.com/host-uk/core/releases/download/$VERSION/core-linux-amd64 -o core
chmod +x core && sudo mv core /usr/local/bin/
\`\`\`
" \
--prerelease \
--target dev \
release/*

View file

@ -1,93 +0,0 @@
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#push
name: "Alpha Release: Push"
on:
push:
branches: [dev]
permissions:
contents: write
id-token: write
attestations: write
env:
NEXT_VERSION: "0.0.4"
jobs:
build:
strategy:
matrix:
include:
- os: ubuntu-latest
platform: linux/amd64
- os: ubuntu-latest
platform: linux/arm64
- os: macos-latest
platform: darwin/universal
- os: windows-latest
platform: windows/amd64
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v6
- name: Build
uses: host-uk/build@v3
with:
build-name: core
build-platform: ${{ matrix.platform }}
build: true
package: true
sign: false
release:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Download artifacts
uses: actions/download-artifact@v7
with:
path: dist
merge-multiple: true
- name: Prepare release files
run: |
mkdir -p release
cp dist/* release/ 2>/dev/null || true
ls -la release/
- name: Create alpha release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
VERSION="v${{ env.NEXT_VERSION }}-alpha.${{ github.run_number }}"
gh release create "$VERSION" \
--title "Alpha: $VERSION" \
--notes "Canary build from dev branch.
**Version:** $VERSION
**Commit:** ${{ github.sha }}
**Built:** $(date -u +'%Y-%m-%d %H:%M:%S UTC')
**Run:** ${{ github.run_id }}
## Channel: Alpha (Canary)
This is an automated pre-release for early testing.
- Systems and early adopters can test breaking changes
- Quality scoring determines promotion to beta
- Use stable releases for production
## Installation
\`\`\`bash
# macOS/Linux
curl -fsSL https://github.com/host-uk/core/releases/download/$VERSION/core-linux-amd64 -o core
chmod +x core && sudo mv core /usr/local/bin/
\`\`\`
" \
--prerelease \
--target dev \
release/*

View file

@ -1,500 +0,0 @@
name: Alpha Release
on:
push:
branches: [dev]
workflow_dispatch:
permissions:
contents: write
id-token: write
attestations: write
env:
# Next version - update when releasing
NEXT_VERSION: "0.0.4"
jobs:
build:
strategy:
matrix:
include:
- os: ubuntu-latest
goos: linux
goarch: amd64
- os: ubuntu-latest
goos: linux
goarch: arm64
- os: macos-latest
goos: darwin
goarch: arm64
- os: windows-latest
goos: windows
goarch: amd64
runs-on: ${{ matrix.os }}
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
steps:
- uses: actions/checkout@v6
# GUI build disabled until build action supports Wails v3
# - name: Wails Build Action
# uses: host-uk/build@v4.0.0
# with:
# build-name: core
# build-platform: ${{ matrix.goos }}/${{ matrix.goarch }}
# build: true
# package: true
# sign: false
- name: Setup Go
uses: host-uk/build/actions/setup/go@v4.0.0
with:
go-version: "1.25"
- name: Build CLI
shell: bash
run: |
EXT=""
if [ "$GOOS" = "windows" ]; then EXT=".exe"; fi
BINARY="core${EXT}"
ARCHIVE_PREFIX="core-${GOOS}-${GOARCH}"
APP_VERSION="${{ env.NEXT_VERSION }}-alpha.${{ github.run_number }}"
go build -ldflags "-s -w -X github.com/host-uk/core/pkg/cli.AppVersion=${APP_VERSION}" -o "./bin/${BINARY}" .
# Create tar.gz for Homebrew (non-Windows)
if [ "$GOOS" != "windows" ]; then
tar czf "./bin/${ARCHIVE_PREFIX}.tar.gz" -C ./bin "${BINARY}"
fi
# Create zip for Scoop (Windows)
if [ "$GOOS" = "windows" ]; then
cd ./bin && zip "${ARCHIVE_PREFIX}.zip" "${BINARY}" && cd ..
fi
# Rename raw binary to platform-specific name for release
mv "./bin/${BINARY}" "./bin/${ARCHIVE_PREFIX}${EXT}"
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: core-${{ matrix.goos }}-${{ matrix.goarch }}
path: ./bin/core-*
build-ide:
strategy:
matrix:
include:
- os: macos-latest
goos: darwin
goarch: arm64
- os: ubuntu-latest
goos: linux
goarch: amd64
- os: windows-latest
goos: windows
goarch: amd64
runs-on: ${{ matrix.os }}
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
defaults:
run:
working-directory: internal/core-ide
steps:
- uses: actions/checkout@v6
- name: Setup Go
uses: host-uk/build/actions/setup/go@v4.0.0
with:
go-version: "1.25"
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
- name: Install Wails CLI
run: go install github.com/wailsapp/wails/v3/cmd/wails3@latest
- name: Install frontend dependencies
working-directory: internal/core-ide/frontend
run: npm ci
- name: Generate bindings
run: wails3 generate bindings -f '-tags production' -clean=false -ts -i
- name: Build frontend
working-directory: internal/core-ide/frontend
run: npm run build
- name: Install Linux dependencies
if: matrix.goos == 'linux'
run: |
sudo apt-get update
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev
- name: Build IDE
shell: bash
run: |
EXT=""
if [ "$GOOS" = "windows" ]; then EXT=".exe"; fi
BINARY="core-ide${EXT}"
ARCHIVE_PREFIX="core-ide-${GOOS}-${GOARCH}"
BUILD_FLAGS="-tags production -trimpath -buildvcs=false"
if [ "$GOOS" = "windows" ]; then
# Windows: no CGO, use windowsgui linker flag
export CGO_ENABLED=0
LDFLAGS="-w -s -H windowsgui"
# Generate Windows syso resource
cd build
wails3 generate syso -arch ${GOARCH} -icon windows/icon.ico -manifest windows/wails.exe.manifest -info windows/info.json -out ../wails_windows_${GOARCH}.syso
cd ..
elif [ "$GOOS" = "darwin" ]; then
export CGO_ENABLED=1
export CGO_CFLAGS="-mmacosx-version-min=10.15"
export CGO_LDFLAGS="-mmacosx-version-min=10.15"
export MACOSX_DEPLOYMENT_TARGET="10.15"
LDFLAGS="-w -s"
else
export CGO_ENABLED=1
LDFLAGS="-w -s"
fi
go build ${BUILD_FLAGS} -ldflags="${LDFLAGS}" -o "./bin/${BINARY}"
# Clean up syso files
rm -f *.syso
# Package
if [ "$GOOS" = "darwin" ]; then
# Create .app bundle
mkdir -p "./bin/Core IDE.app/Contents/"{MacOS,Resources}
cp build/darwin/icons.icns "./bin/Core IDE.app/Contents/Resources/"
cp "./bin/${BINARY}" "./bin/Core IDE.app/Contents/MacOS/"
cp build/darwin/Info.plist "./bin/Core IDE.app/Contents/"
codesign --force --deep --sign - "./bin/Core IDE.app"
tar czf "./bin/${ARCHIVE_PREFIX}.tar.gz" -C ./bin "Core IDE.app"
elif [ "$GOOS" = "windows" ]; then
cd ./bin && zip "${ARCHIVE_PREFIX}.zip" "${BINARY}" && cd ..
else
tar czf "./bin/${ARCHIVE_PREFIX}.tar.gz" -C ./bin "${BINARY}"
fi
# Rename raw binary
mv "./bin/${BINARY}" "./bin/${ARCHIVE_PREFIX}${EXT}"
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: core-ide-${{ matrix.goos }}-${{ matrix.goarch }}
path: internal/core-ide/bin/core-ide-*
release:
needs: [build, build-ide]
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- uses: actions/checkout@v6
- name: Set version
id: version
run: echo "version=v${{ env.NEXT_VERSION }}-alpha.${{ github.run_number }}" >> "$GITHUB_OUTPUT"
- name: Download artifacts
uses: actions/download-artifact@v7
with:
path: dist
merge-multiple: true
- name: Prepare release files
run: |
mkdir -p release
cp dist/* release/ 2>/dev/null || true
ls -la release/
- name: Create alpha release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
VERSION: ${{ steps.version.outputs.version }}
run: |
gh release create "$VERSION" \
--title "Alpha: $VERSION" \
--notes "Canary build from dev branch.
**Version:** $VERSION
**Commit:** ${{ github.sha }}
**Built:** $(date -u +'%Y-%m-%d %H:%M:%S UTC')
**Run:** ${{ github.run_id }}
## Channel: Alpha (Canary)
This is an automated pre-release for early testing.
- Systems and early adopters can test breaking changes
- Quality scoring determines promotion to beta
- Use stable releases for production
## Installation
\`\`\`bash
# Homebrew (macOS/Linux)
brew install host-uk/tap/core
# Scoop (Windows)
scoop bucket add host-uk https://github.com/host-uk/scoop-bucket
scoop install core
# Direct download (example: Linux amd64)
curl -fsSL https://github.com/host-uk/core/releases/download/$VERSION/core-linux-amd64 -o core
chmod +x core && sudo mv core /usr/local/bin/
\`\`\`
" \
--prerelease \
--target dev \
release/*
update-tap:
needs: release
runs-on: ubuntu-latest
steps:
- name: Download artifacts
uses: actions/download-artifact@v7
with:
path: dist
merge-multiple: true
- name: Generate checksums
run: |
cd dist
for f in *.tar.gz; do
sha256sum "$f" | awk '{print $1}' > "${f}.sha256"
done
echo "=== Checksums ==="
cat *.sha256
- name: Update Homebrew formula
env:
GH_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
VERSION: ${{ needs.release.outputs.version }}
run: |
# Strip leading 'v' for formula version
FORMULA_VERSION="${VERSION#v}"
# Read checksums
DARWIN_ARM64=$(cat dist/core-darwin-arm64.tar.gz.sha256)
LINUX_AMD64=$(cat dist/core-linux-amd64.tar.gz.sha256)
LINUX_ARM64=$(cat dist/core-linux-arm64.tar.gz.sha256)
# Clone tap repo (configure auth for push)
gh repo clone host-uk/homebrew-tap /tmp/tap -- --depth=1
cd /tmp/tap
git remote set-url origin "https://x-access-token:${GH_TOKEN}@github.com/host-uk/homebrew-tap.git"
cd -
mkdir -p /tmp/tap/Formula
# Write formula
cat > /tmp/tap/Formula/core.rb << FORMULA
# typed: false
# frozen_string_literal: true
class Core < Formula
desc "Host UK development CLI"
homepage "https://github.com/host-uk/core"
version "${FORMULA_VERSION}"
license "EUPL-1.2"
on_macos do
url "https://github.com/host-uk/core/releases/download/${VERSION}/core-darwin-arm64.tar.gz"
sha256 "${DARWIN_ARM64}"
end
on_linux do
if Hardware::CPU.arm?
url "https://github.com/host-uk/core/releases/download/${VERSION}/core-linux-arm64.tar.gz"
sha256 "${LINUX_ARM64}"
else
url "https://github.com/host-uk/core/releases/download/${VERSION}/core-linux-amd64.tar.gz"
sha256 "${LINUX_AMD64}"
end
end
def install
bin.install "core"
end
test do
system "\#{bin}/core", "--version"
end
end
FORMULA
# Remove leading whitespace from heredoc
sed -i 's/^ //' /tmp/tap/Formula/core.rb
# Read IDE checksums (may not exist if build-ide failed)
IDE_DARWIN_ARM64=$(cat dist/core-ide-darwin-arm64.tar.gz.sha256 2>/dev/null || echo "")
IDE_LINUX_AMD64=$(cat dist/core-ide-linux-amd64.tar.gz.sha256 2>/dev/null || echo "")
# Write core-ide Formula (Linux binary)
if [ -n "${IDE_LINUX_AMD64}" ]; then
cat > /tmp/tap/Formula/core-ide.rb << FORMULA
# typed: false
# frozen_string_literal: true
class CoreIde < Formula
desc "Host UK desktop development environment"
homepage "https://github.com/host-uk/core"
version "${FORMULA_VERSION}"
license "EUPL-1.2"
on_linux do
url "https://github.com/host-uk/core/releases/download/${VERSION}/core-ide-linux-amd64.tar.gz"
sha256 "${IDE_LINUX_AMD64}"
end
def install
bin.install "core-ide"
end
end
FORMULA
sed -i 's/^ //' /tmp/tap/Formula/core-ide.rb
fi
# Write core-ide Cask (macOS .app bundle)
if [ -n "${IDE_DARWIN_ARM64}" ]; then
mkdir -p /tmp/tap/Casks
cat > /tmp/tap/Casks/core-ide.rb << CASK
cask "core-ide" do
version "${FORMULA_VERSION}"
sha256 "${IDE_DARWIN_ARM64}"
url "https://github.com/host-uk/core/releases/download/${VERSION}/core-ide-darwin-arm64.tar.gz"
name "Core IDE"
desc "Host UK desktop development environment"
homepage "https://github.com/host-uk/core"
app "Core IDE.app"
end
CASK
sed -i 's/^ //' /tmp/tap/Casks/core-ide.rb
fi
cd /tmp/tap
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add .
git diff --cached --quiet && echo "No changes to tap" && exit 0
git commit -m "Update core to ${FORMULA_VERSION}"
git push
update-scoop:
needs: release
runs-on: ubuntu-latest
steps:
- name: Download artifacts
uses: actions/download-artifact@v7
with:
path: dist
merge-multiple: true
- name: Generate checksums
run: |
cd dist
for f in *.zip; do
[ -f "$f" ] || continue
sha256sum "$f" | awk '{print $1}' > "${f}.sha256"
done
echo "=== Checksums ==="
cat *.sha256 2>/dev/null || echo "No zip checksums"
- name: Update Scoop manifests
env:
GH_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
VERSION: ${{ needs.release.outputs.version }}
run: |
# Strip leading 'v' for manifest version
MANIFEST_VERSION="${VERSION#v}"
# Read checksums
WIN_AMD64=$(cat dist/core-windows-amd64.zip.sha256 2>/dev/null || echo "")
IDE_WIN_AMD64=$(cat dist/core-ide-windows-amd64.zip.sha256 2>/dev/null || echo "")
# Clone scoop bucket
gh repo clone host-uk/scoop-bucket /tmp/scoop -- --depth=1
cd /tmp/scoop
git remote set-url origin "https://x-access-token:${GH_TOKEN}@github.com/host-uk/scoop-bucket.git"
# Write core.json manifest
cat > core.json << 'MANIFEST'
{
"version": "VERSION_PLACEHOLDER",
"description": "Host UK development CLI",
"homepage": "https://github.com/host-uk/core",
"license": "EUPL-1.2",
"architecture": {
"64bit": {
"url": "URL_PLACEHOLDER",
"hash": "HASH_PLACEHOLDER",
"bin": "core.exe"
}
},
"checkver": "github",
"autoupdate": {
"architecture": {
"64bit": {
"url": "https://github.com/host-uk/core/releases/download/v$version/core-windows-amd64.zip"
}
}
}
}
MANIFEST
sed -i "s|VERSION_PLACEHOLDER|${MANIFEST_VERSION}|g" core.json
sed -i "s|URL_PLACEHOLDER|https://github.com/host-uk/core/releases/download/${VERSION}/core-windows-amd64.zip|g" core.json
sed -i "s|HASH_PLACEHOLDER|${WIN_AMD64}|g" core.json
sed -i 's/^ //' core.json
# Write core-ide.json manifest
if [ -n "${IDE_WIN_AMD64}" ]; then
cat > core-ide.json << 'MANIFEST'
{
"version": "VERSION_PLACEHOLDER",
"description": "Host UK desktop development environment",
"homepage": "https://github.com/host-uk/core",
"license": "EUPL-1.2",
"architecture": {
"64bit": {
"url": "URL_PLACEHOLDER",
"hash": "HASH_PLACEHOLDER",
"bin": "core-ide.exe"
}
},
"checkver": "github",
"autoupdate": {
"architecture": {
"64bit": {
"url": "https://github.com/host-uk/core/releases/download/v$version/core-ide-windows-amd64.zip"
}
}
}
}
MANIFEST
sed -i "s|VERSION_PLACEHOLDER|${MANIFEST_VERSION}|g" core-ide.json
sed -i "s|URL_PLACEHOLDER|https://github.com/host-uk/core/releases/download/${VERSION}/core-ide-windows-amd64.zip|g" core-ide.json
sed -i "s|HASH_PLACEHOLDER|${IDE_WIN_AMD64}|g" core-ide.json
sed -i 's/^ //' core-ide.json
fi
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add .
git diff --cached --quiet && echo "No changes to scoop bucket" && exit 0
git commit -m "Update core to ${MANIFEST_VERSION}"
git push

View file

@ -1,113 +0,0 @@
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#issues
name: "Auto Label: Issue Created/Edited"
on:
issues:
types: [opened, edited]
permissions:
issues: write
jobs:
label:
runs-on: ubuntu-latest
steps:
- name: Auto-label based on content
uses: actions/github-script@v8
with:
script: |
const issue = context.payload.issue;
const title = issue.title.toLowerCase();
const body = (issue.body || '').toLowerCase();
const content = title + ' ' + body;
const labelsToAdd = [];
// Type labels based on title prefix
if (title.includes('[bug]')) {
labelsToAdd.push('bug');
} else if (title.includes('[feature]') || title.includes('feat(') || title.includes('feat:')) {
labelsToAdd.push('enhancement');
} else if (title.includes('[docs]') || title.includes('docs(') || title.includes('docs:')) {
labelsToAdd.push('documentation');
}
// Project labels based on content
if (content.includes('core dev') || content.includes('core work') || content.includes('core commit') || content.includes('core push')) {
labelsToAdd.push('project:core-cli');
}
if (content.includes('core php') || content.includes('composer') || content.includes('pest') || content.includes('phpstan')) {
labelsToAdd.push('project:core-php');
}
// Language labels
if (content.includes('.go') || content.includes('golang') || content.includes('go mod')) {
labelsToAdd.push('go');
}
// Priority detection
if (content.includes('critical') || content.includes('urgent') || content.includes('breaking')) {
labelsToAdd.push('priority:high');
}
// Agent labels
if (content.includes('agent') || content.includes('ai ') || content.includes('claude') || content.includes('agentic')) {
labelsToAdd.push('agentic');
}
// Complexity - from template dropdown or heuristics
if (body.includes('small - quick fix')) {
labelsToAdd.push('complexity:small');
labelsToAdd.push('good first issue');
} else if (body.includes('medium - multiple files')) {
labelsToAdd.push('complexity:medium');
} else if (body.includes('large - significant')) {
labelsToAdd.push('complexity:large');
} else if (!body.includes('unknown - not sure')) {
// Heuristic complexity detection
const checklistCount = (body.match(/- \[ \]/g) || []).length;
const codeBlocks = (body.match(/```/g) || []).length / 2;
const sections = (body.match(/^##/gm) || []).length;
const fileRefs = (body.match(/\.(go|php|js|ts|yml|yaml|json|md)\b/g) || []).length;
const complexKeywords = ['refactor', 'rewrite', 'migration', 'breaking change', 'across repos', 'architecture'];
const simpleKeywords = ['simple', 'quick fix', 'typo', 'minor', 'trivial'];
const hasComplexKeyword = complexKeywords.some(k => content.includes(k));
const hasSimpleKeyword = simpleKeywords.some(k => content.includes(k));
let score = checklistCount * 2 + codeBlocks + sections + fileRefs;
score += hasComplexKeyword ? 5 : 0;
score -= hasSimpleKeyword ? 3 : 0;
if (hasSimpleKeyword || score <= 2) {
labelsToAdd.push('complexity:small');
labelsToAdd.push('good first issue');
} else if (score <= 6) {
labelsToAdd.push('complexity:medium');
} else {
labelsToAdd.push('complexity:large');
}
}
// Apply labels if any detected
if (labelsToAdd.length > 0) {
// Filter to only existing labels
const existingLabels = await github.rest.issues.listLabelsForRepo({
owner: context.repo.owner,
repo: context.repo.repo,
per_page: 100
});
const validLabels = existingLabels.data.map(l => l.name);
const filteredLabels = labelsToAdd.filter(l => validLabels.includes(l));
if (filteredLabels.length > 0) {
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
labels: filteredLabels
});
console.log(`Added labels: ${filteredLabels.join(', ')}`);
}
}

View file

@ -1,54 +0,0 @@
name: Auto Merge
on:
pull_request:
types: [opened, reopened, ready_for_review]
permissions:
contents: write
pull-requests: write
env:
GH_REPO: ${{ github.repository }}
jobs:
merge:
runs-on: ubuntu-latest
if: github.event.pull_request.draft == false
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Enable auto-merge
uses: actions/github-script@v7
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const author = context.payload.pull_request.user.login;
const association = context.payload.pull_request.author_association;
// Trusted bot accounts (act as org members)
const trustedBots = ['google-labs-jules[bot]'];
const isTrustedBot = trustedBots.includes(author);
// Check author association from webhook payload
const trusted = ['MEMBER', 'OWNER', 'COLLABORATOR'];
if (!isTrustedBot && !trusted.includes(association)) {
core.info(`${author} is ${association} — skipping auto-merge`);
return;
}
try {
await exec.exec('gh', [
'pr', 'merge', process.env.PR_NUMBER,
'--auto',
'--merge',
'-R', `${context.repo.owner}/${context.repo.repo}`
]);
core.info(`Auto-merge enabled for #${process.env.PR_NUMBER}`);
} catch (error) {
core.error(`Failed to enable auto-merge: ${error.message}`);
throw error;
}

View file

@ -1,10 +0,0 @@
name: Auto Project
on:
issues:
types: [opened, labeled]
jobs:
project:
uses: host-uk/.github/.github/workflows/auto-project.yml@main
secrets: inherit

View file

@ -1,309 +0,0 @@
# BugSETI Release Workflow
# Builds for all platforms and creates GitHub releases
name: "BugSETI Release"
on:
push:
tags:
- 'bugseti-v*.*.*' # Stable: bugseti-v1.0.0
- 'bugseti-v*.*.*-beta.*' # Beta: bugseti-v1.0.0-beta.1
- 'bugseti-nightly-*' # Nightly: bugseti-nightly-20260205
permissions:
contents: write
env:
APP_NAME: bugseti
WAILS_VERSION: "3"
jobs:
# Determine release channel from tag
prepare:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
channel: ${{ steps.version.outputs.channel }}
prerelease: ${{ steps.version.outputs.prerelease }}
steps:
- name: Determine version and channel
id: version
env:
TAG: ${{ github.ref_name }}
run: |
if [[ "$TAG" == bugseti-nightly-* ]]; then
VERSION="${TAG#bugseti-}"
CHANNEL="nightly"
PRERELEASE="true"
elif [[ "$TAG" == *-beta.* ]]; then
VERSION="${TAG#bugseti-v}"
CHANNEL="beta"
PRERELEASE="true"
else
VERSION="${TAG#bugseti-v}"
CHANNEL="stable"
PRERELEASE="false"
fi
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
echo "channel=${CHANNEL}" >> "$GITHUB_OUTPUT"
echo "prerelease=${PRERELEASE}" >> "$GITHUB_OUTPUT"
echo "Tag: $TAG"
echo "Version: $VERSION"
echo "Channel: $CHANNEL"
echo "Prerelease: $PRERELEASE"
build:
needs: prepare
strategy:
fail-fast: false
matrix:
include:
# macOS ARM64 (Apple Silicon)
- os: macos-latest
goos: darwin
goarch: arm64
ext: ""
archive: tar.gz
# macOS AMD64 (Intel)
- os: macos-13
goos: darwin
goarch: amd64
ext: ""
archive: tar.gz
# Linux AMD64
- os: ubuntu-latest
goos: linux
goarch: amd64
ext: ""
archive: tar.gz
# Linux ARM64
- os: ubuntu-24.04-arm
goos: linux
goarch: arm64
ext: ""
archive: tar.gz
# Windows AMD64
- os: windows-latest
goos: windows
goarch: amd64
ext: ".exe"
archive: zip
runs-on: ${{ matrix.os }}
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
VERSION: ${{ needs.prepare.outputs.version }}
CHANNEL: ${{ needs.prepare.outputs.channel }}
defaults:
run:
working-directory: cmd/bugseti
steps:
- uses: actions/checkout@v6
- name: Setup Go
uses: host-uk/build/actions/setup/go@v4.0.0
with:
go-version: "1.25"
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
- name: Install Wails CLI
run: go install github.com/wailsapp/wails/v3/cmd/wails3@latest
- name: Install frontend dependencies
working-directory: cmd/bugseti/frontend
run: npm ci
- name: Generate bindings
run: wails3 generate bindings -f '-tags production' -clean=false -ts -i
- name: Build frontend
working-directory: cmd/bugseti/frontend
run: npm run build
- name: Install Linux dependencies
if: matrix.goos == 'linux'
run: |
sudo apt-get update
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev libayatana-appindicator3-dev
- name: Build BugSETI
shell: bash
env:
EXT: ${{ matrix.ext }}
ARCHIVE: ${{ matrix.archive }}
COMMIT_SHA: ${{ github.sha }}
run: |
BINARY="${APP_NAME}${EXT}"
ARCHIVE_PREFIX="${APP_NAME}-${GOOS}-${GOARCH}"
BUILD_FLAGS="-tags production -trimpath -buildvcs=false"
# Version injection via ldflags
LDFLAGS="-s -w"
LDFLAGS="${LDFLAGS} -X github.com/host-uk/core/internal/bugseti.Version=${VERSION}"
LDFLAGS="${LDFLAGS} -X github.com/host-uk/core/internal/bugseti.Channel=${CHANNEL}"
LDFLAGS="${LDFLAGS} -X github.com/host-uk/core/internal/bugseti.Commit=${COMMIT_SHA}"
LDFLAGS="${LDFLAGS} -X github.com/host-uk/core/internal/bugseti.BuildTime=$(date -u +%Y-%m-%dT%H:%M:%SZ)"
if [ "$GOOS" = "windows" ]; then
export CGO_ENABLED=0
LDFLAGS="${LDFLAGS} -H windowsgui"
# Generate Windows syso resource
cd build
wails3 generate syso -arch ${GOARCH} -icon windows/icon.ico -manifest windows/wails.exe.manifest -info windows/info.json -out ../wails_windows_${GOARCH}.syso 2>/dev/null || true
cd ..
elif [ "$GOOS" = "darwin" ]; then
export CGO_ENABLED=1
export CGO_CFLAGS="-mmacosx-version-min=10.15"
export CGO_LDFLAGS="-mmacosx-version-min=10.15"
export MACOSX_DEPLOYMENT_TARGET="10.15"
else
export CGO_ENABLED=1
fi
mkdir -p bin
go build ${BUILD_FLAGS} -ldflags="${LDFLAGS}" -o "./bin/${BINARY}"
# Clean up syso files
rm -f *.syso
# Package based on platform
if [ "$GOOS" = "darwin" ]; then
# Create .app bundle
mkdir -p "./bin/BugSETI.app/Contents/"{MacOS,Resources}
cp build/darwin/icons.icns "./bin/BugSETI.app/Contents/Resources/" 2>/dev/null || true
cp "./bin/${BINARY}" "./bin/BugSETI.app/Contents/MacOS/"
cp build/darwin/Info.plist "./bin/BugSETI.app/Contents/"
codesign --force --deep --sign - "./bin/BugSETI.app" 2>/dev/null || true
tar czf "./bin/${ARCHIVE_PREFIX}.tar.gz" -C ./bin "BugSETI.app"
elif [ "$GOOS" = "windows" ]; then
cd ./bin && zip "${ARCHIVE_PREFIX}.zip" "${BINARY}" && cd ..
else
tar czf "./bin/${ARCHIVE_PREFIX}.tar.gz" -C ./bin "${BINARY}"
fi
# Rename raw binary for individual download
mv "./bin/${BINARY}" "./bin/${ARCHIVE_PREFIX}${EXT}"
# Generate checksum
cd ./bin
sha256sum "${ARCHIVE_PREFIX}.${ARCHIVE}" > "${ARCHIVE_PREFIX}.${ARCHIVE}.sha256"
sha256sum "${ARCHIVE_PREFIX}${EXT}" > "${ARCHIVE_PREFIX}${EXT}.sha256"
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: bugseti-${{ matrix.goos }}-${{ matrix.goarch }}
path: |
cmd/bugseti/bin/bugseti-*
retention-days: 7
release:
needs: [prepare, build]
runs-on: ubuntu-latest
env:
TAG_NAME: ${{ github.ref_name }}
VERSION: ${{ needs.prepare.outputs.version }}
CHANNEL: ${{ needs.prepare.outputs.channel }}
PRERELEASE: ${{ needs.prepare.outputs.prerelease }}
REPO: ${{ github.repository }}
steps:
- uses: actions/checkout@v6
- name: Download all artifacts
uses: actions/download-artifact@v7
with:
path: dist
merge-multiple: true
- name: List release files
run: |
echo "=== Release files ==="
ls -la dist/
echo "=== Checksums ==="
cat dist/*.sha256
- name: Create release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Determine release title
if [ "$CHANNEL" = "nightly" ]; then
TITLE="BugSETI Nightly (${VERSION})"
elif [ "$CHANNEL" = "beta" ]; then
TITLE="BugSETI v${VERSION} (Beta)"
else
TITLE="BugSETI v${VERSION}"
fi
# Create release notes
cat > release-notes.md << EOF
## BugSETI ${VERSION}
**Channel:** ${CHANNEL}
### Downloads
| Platform | Architecture | Binary | Archive |
|----------|-------------|--------|---------|
| macOS | ARM64 (Apple Silicon) | [bugseti-darwin-arm64](https://github.com/${REPO}/releases/download/${TAG_NAME}/bugseti-darwin-arm64) | [tar.gz](https://github.com/${REPO}/releases/download/${TAG_NAME}/bugseti-darwin-arm64.tar.gz) |
| macOS | AMD64 (Intel) | [bugseti-darwin-amd64](https://github.com/${REPO}/releases/download/${TAG_NAME}/bugseti-darwin-amd64) | [tar.gz](https://github.com/${REPO}/releases/download/${TAG_NAME}/bugseti-darwin-amd64.tar.gz) |
| Linux | AMD64 | [bugseti-linux-amd64](https://github.com/${REPO}/releases/download/${TAG_NAME}/bugseti-linux-amd64) | [tar.gz](https://github.com/${REPO}/releases/download/${TAG_NAME}/bugseti-linux-amd64.tar.gz) |
| Linux | ARM64 | [bugseti-linux-arm64](https://github.com/${REPO}/releases/download/${TAG_NAME}/bugseti-linux-arm64) | [tar.gz](https://github.com/${REPO}/releases/download/${TAG_NAME}/bugseti-linux-arm64.tar.gz) |
| Windows | AMD64 | [bugseti-windows-amd64.exe](https://github.com/${REPO}/releases/download/${TAG_NAME}/bugseti-windows-amd64.exe) | [zip](https://github.com/${REPO}/releases/download/${TAG_NAME}/bugseti-windows-amd64.zip) |
### Checksums (SHA256)
\`\`\`
$(cat dist/*.sha256)
\`\`\`
---
*BugSETI - Distributed Bug Fixing, like SETI@home but for code*
EOF
# Build release command
RELEASE_ARGS=(
--title "$TITLE"
--notes-file release-notes.md
)
if [ "$PRERELEASE" = "true" ]; then
RELEASE_ARGS+=(--prerelease)
fi
# Create the release
gh release create "$TAG_NAME" \
"${RELEASE_ARGS[@]}" \
dist/*
# Scheduled nightly builds
nightly:
if: github.event_name == 'schedule'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Create nightly tag
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
DATE=$(date -u +%Y%m%d)
TAG="bugseti-nightly-${DATE}"
# Delete existing nightly tag for today if it exists
gh release delete "$TAG" --yes 2>/dev/null || true
git push origin ":refs/tags/$TAG" 2>/dev/null || true
# Create new tag
git tag "$TAG"
git push origin "$TAG"

View file

@ -1,41 +0,0 @@
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_dispatch
name: "CI: Manual"
on:
workflow_dispatch:
env:
CORE_VERSION: dev
jobs:
qa:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version-file: 'go.mod'
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev
- name: Build core CLI
run: |
go build -ldflags "-X github.com/host-uk/core/pkg/cli.AppVersion=${{ env.CORE_VERSION }}" -o /usr/local/bin/core .
core --version
- name: Generate code
run: go generate ./internal/cmd/updater/...
- name: Run QA
# Skip lint until golangci-lint supports Go 1.25
run: core go qa --skip=lint
- name: Verify build
run: |
core build --targets=linux/amd64 --ci
dist/linux_amd64/core --version

View file

@ -1,42 +0,0 @@
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request
name: "CI: Pull Request"
on:
pull_request:
branches: [dev, main]
env:
CORE_VERSION: dev
jobs:
qa:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version-file: 'go.mod'
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev
- name: Build core CLI
run: |
go build -ldflags "-X github.com/host-uk/core/pkg/cli.AppVersion=${{ env.CORE_VERSION }}" -o /usr/local/bin/core .
core --version
- name: Generate code
run: go generate ./internal/cmd/updater/...
- name: Run QA
# Skip lint until golangci-lint supports Go 1.25
run: core go qa --skip=lint
- name: Verify build
run: |
core build --targets=linux/amd64 --ci
dist/linux_amd64/core --version

View file

@ -1,42 +0,0 @@
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#push
name: "CI: Push"
on:
push:
branches: [dev, main]
env:
CORE_VERSION: dev
jobs:
qa:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version-file: 'go.mod'
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev
- name: Build core CLI
run: |
go build -ldflags "-X github.com/host-uk/core/pkg/cli.AppVersion=${{ env.CORE_VERSION }}" -o /usr/local/bin/core .
core --version
- name: Generate code
run: go generate ./internal/cmd/updater/...
- name: Run QA
# Skip lint until golangci-lint supports Go 1.25
run: core go qa --skip=lint
- name: Verify build
run: |
core build --targets=linux/amd64 --ci
dist/linux_amd64/core --version

View file

@ -1,49 +0,0 @@
name: CI
on:
push:
branches: [dev, main]
pull_request:
branches: [dev, main]
workflow_dispatch:
permissions:
contents: read
env:
CORE_VERSION: dev
jobs:
qa:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version-file: 'go.mod'
- name: Install system dependencies
run: |
sudo apt-get update
# Try 4.1 first (Ubuntu 22.04+), fall back to 4.0 (Ubuntu 20.04)
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev || \
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev
- name: Build core CLI
run: |
go build -ldflags "-X github.com/host-uk/core/pkg/cli.AppVersion=${{ env.CORE_VERSION }}" -o /usr/local/bin/core .
core --version
- name: Generate code
run: go generate ./internal/cmd/updater/...
- name: Run QA
# Skip lint until golangci-lint supports Go 1.25
run: core go qa --skip=lint
- name: Verify build
run: |
core build --targets=linux/amd64 --ci
dist/linux_amd64/core --version

View file

@ -1,32 +0,0 @@
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request
name: "CodeQL: Pull Request"
on:
pull_request:
branches: [dev, main]
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Initialize CodeQL
uses: github/codeql-action/init@v4
with:
languages: go
- name: Autobuild
uses: github/codeql-action/autobuild@v4
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4
with:
category: "/language:go"

View file

@ -1,32 +0,0 @@
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#push
name: "CodeQL: Push"
on:
push:
branches: [dev, main]
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Initialize CodeQL
uses: github/codeql-action/init@v4
with:
languages: go
- name: Autobuild
uses: github/codeql-action/autobuild@v4
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4
with:
category: "/language:go"

View file

@ -1,32 +0,0 @@
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#schedule
name: "CodeQL: Schedule"
on:
schedule:
- cron: "0 6 * * 1"
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Initialize CodeQL
uses: github/codeql-action/init@v4
with:
languages: go
- name: Autobuild
uses: github/codeql-action/autobuild@v4
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4
with:
category: "/language:go"

View file

@ -1,30 +0,0 @@
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request
name: "Code Scanning: Pull Request"
on:
pull_request:
branches: ["dev"]
jobs:
CodeQL:
runs-on: ubuntu-latest
permissions:
security-events: write
actions: read
contents: read
steps:
- name: "Checkout Repository"
uses: actions/checkout@v6
- name: "Initialize CodeQL"
uses: github/codeql-action/init@v4
with:
languages: go,javascript,typescript
- name: "Autobuild"
uses: github/codeql-action/autobuild@v4
- name: "Perform CodeQL Analysis"
uses: github/codeql-action/analyze@v4

View file

@ -1,30 +0,0 @@
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#push
name: "Code Scanning: Push"
on:
push:
branches: ["dev"]
jobs:
CodeQL:
runs-on: ubuntu-latest
permissions:
security-events: write
actions: read
contents: read
steps:
- name: "Checkout Repository"
uses: actions/checkout@v6
- name: "Initialize CodeQL"
uses: github/codeql-action/init@v4
with:
languages: go,javascript,typescript
- name: "Autobuild"
uses: github/codeql-action/autobuild@v4
- name: "Perform CodeQL Analysis"
uses: github/codeql-action/analyze@v4

View file

@ -1,30 +0,0 @@
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#schedule
name: "Code Scanning: Schedule"
on:
schedule:
- cron: "0 2 * * 1-5"
jobs:
CodeQL:
runs-on: ubuntu-latest
permissions:
security-events: write
actions: read
contents: read
steps:
- name: "Checkout Repository"
uses: actions/checkout@v6
- name: "Initialize CodeQL"
uses: github/codeql-action/init@v4
with:
languages: go,javascript,typescript
- name: "Autobuild"
uses: github/codeql-action/autobuild@v4
- name: "Perform CodeQL Analysis"
uses: github/codeql-action/analyze@v4

View file

@ -1,46 +0,0 @@
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_dispatch
name: "Coverage: Manual"
on:
workflow_dispatch:
env:
CORE_VERSION: dev
jobs:
coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version-file: 'go.mod'
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev
- name: Build core CLI
run: |
go build -ldflags "-X github.com/host-uk/core/pkg/cli.AppVersion=${{ env.CORE_VERSION }}" -o /usr/local/bin/core .
core --version
- name: Generate code
run: go generate ./internal/cmd/updater/...
- name: Run coverage
run: core go cov
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
- name: Upload coverage report
uses: actions/upload-artifact@v6
with:
name: coverage-report
path: coverage.txt

View file

@ -1,47 +0,0 @@
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request
name: "Coverage: Pull Request"
on:
pull_request:
branches: [dev, main]
env:
CORE_VERSION: dev
jobs:
coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version-file: 'go.mod'
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev
- name: Build core CLI
run: |
go build -ldflags "-X github.com/host-uk/core/pkg/cli.AppVersion=${{ env.CORE_VERSION }}" -o /usr/local/bin/core .
core --version
- name: Generate code
run: go generate ./internal/cmd/updater/...
- name: Run coverage
run: core go cov
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
- name: Upload coverage report
uses: actions/upload-artifact@v6
with:
name: coverage-report
path: coverage.txt

View file

@ -1,47 +0,0 @@
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#push
name: "Coverage: Push"
on:
push:
branches: [dev, main]
env:
CORE_VERSION: dev
jobs:
coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version-file: 'go.mod'
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev
- name: Build core CLI
run: |
go build -ldflags "-X github.com/host-uk/core/pkg/cli.AppVersion=${{ env.CORE_VERSION }}" -o /usr/local/bin/core .
core --version
- name: Generate code
run: go generate ./internal/cmd/updater/...
- name: Run coverage
run: core go cov
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
- name: Upload coverage report
uses: actions/upload-artifact@v6
with:
name: coverage-report
path: coverage.txt

View file

@ -1,54 +0,0 @@
name: Coverage
on:
push:
branches: [dev, main]
pull_request:
branches: [dev, main]
workflow_dispatch:
permissions:
contents: read
env:
CORE_VERSION: dev
jobs:
coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Set up Go
uses: actions/setup-go@v6
with:
go-version-file: 'go.mod'
- name: Install system dependencies
run: |
sudo apt-get update
# Try 4.1 first (Ubuntu 22.04+), fall back to 4.0 (Ubuntu 20.04)
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev || \
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev
- name: Build core CLI
run: |
go build -ldflags "-X github.com/host-uk/core/pkg/cli.AppVersion=${{ env.CORE_VERSION }}" -o /usr/local/bin/core .
core --version
- name: Generate code
run: go generate ./internal/cmd/updater/...
- name: Run coverage
run: core go cov --output coverage.txt --threshold 40 --branch-threshold 35
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
- name: Upload coverage report
uses: actions/upload-artifact@v6
with:
name: coverage-report
path: coverage.txt

View file

@ -1,89 +0,0 @@
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_dispatch
name: "PR Build: Manual"
on:
workflow_dispatch:
inputs:
pr_number:
description: 'PR number to build'
required: true
type: number
permissions:
contents: write
pull-requests: read
env:
NEXT_VERSION: "0.0.4"
jobs:
build:
strategy:
matrix:
include:
- os: ubuntu-latest
platform: linux/amd64
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v6
- name: Build
uses: host-uk/build@v3
with:
build-name: core
build-platform: ${{ matrix.platform }}
build: true
package: true
sign: false
draft-release:
needs: build
runs-on: ubuntu-latest
env:
PR_NUM: ${{ inputs.pr_number }}
PR_SHA: ${{ github.sha }}
steps:
- uses: actions/checkout@v6
- name: Download artifacts
uses: actions/download-artifact@v7
with:
path: dist
merge-multiple: true
- name: Prepare release files
run: |
mkdir -p release
cp dist/* release/ 2>/dev/null || true
ls -la release/
- name: Create draft release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
TAG="v${{ env.NEXT_VERSION }}.pr.${PR_NUM}.bid.${{ github.run_id }}"
# Delete existing draft for this PR if it exists
gh release delete "$TAG" -y 2>/dev/null || true
git push origin ":refs/tags/$TAG" 2>/dev/null || true
gh release create "$TAG" \
--title "Draft: PR #${PR_NUM}" \
--notes "Draft build for PR #${PR_NUM}.
**Version:** $TAG
**PR:** #${PR_NUM}
**Commit:** ${PR_SHA}
**Built:** $(date -u +'%Y-%m-%d %H:%M:%S UTC')
**Run:** ${{ github.run_id }}
## Channel: Draft
This is a draft build for testing PR changes before merge.
Not intended for production use.
Build artifacts available for download and testing.
" \
--draft \
--prerelease \
release/*

View file

@ -1,89 +0,0 @@
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request
name: "PR Build: Pull Request"
on:
pull_request:
types: [opened, synchronize, reopened]
permissions:
contents: write
pull-requests: read
env:
NEXT_VERSION: "0.0.4"
jobs:
build:
# Only build if PR is from the same repo (not forks)
if: github.event.pull_request.head.repo.full_name == github.repository
strategy:
matrix:
include:
- os: ubuntu-latest
platform: linux/amd64
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Build
uses: host-uk/build@v3
with:
build-name: core
build-platform: ${{ matrix.platform }}
build: true
package: true
sign: false
draft-release:
needs: build
runs-on: ubuntu-latest
env:
PR_NUM: ${{ github.event.pull_request.number }}
PR_SHA: ${{ github.event.pull_request.head.sha }}
steps:
- uses: actions/checkout@v6
- name: Download artifacts
uses: actions/download-artifact@v7
with:
path: dist
merge-multiple: true
- name: Prepare release files
run: |
mkdir -p release
cp dist/* release/ 2>/dev/null || true
ls -la release/
- name: Create draft release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
TAG="v${{ env.NEXT_VERSION }}.pr.${PR_NUM}.bid.${{ github.run_id }}"
# Delete existing draft for this PR if it exists
gh release delete "$TAG" -y 2>/dev/null || true
git push origin ":refs/tags/$TAG" 2>/dev/null || true
gh release create "$TAG" \
--title "Draft: PR #${PR_NUM}" \
--notes "Draft build for PR #${PR_NUM}.
**Version:** $TAG
**PR:** #${PR_NUM}
**Commit:** ${PR_SHA}
**Built:** $(date -u +'%Y-%m-%d %H:%M:%S UTC')
**Run:** ${{ github.run_id }}
## Channel: Draft
This is a draft build for testing PR changes before merge.
Not intended for production use.
Build artifacts available for download and testing.
" \
--draft \
--prerelease \
release/*

View file

@ -1,113 +0,0 @@
name: PR Build
on:
pull_request:
types: [opened, synchronize, reopened]
workflow_dispatch:
inputs:
pr_number:
description: 'PR number to build'
required: true
type: number
permissions:
contents: write
pull-requests: read
env:
# Next version - update when releasing
NEXT_VERSION: "0.0.4"
jobs:
build:
# Only build if PR is from the same repo (not forks) or manually triggered
if: github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'workflow_dispatch'
strategy:
matrix:
include:
- os: ubuntu-latest
goos: linux
goarch: amd64
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
# GUI build disabled until build action supports Wails v3
# - name: Wails Build Action
# uses: host-uk/build@v4.0.0
# with:
# build-name: core
# build-platform: ${{ matrix.goos }}/${{ matrix.goarch }}
# build: true
# package: true
# sign: false
- name: Setup Go
uses: host-uk/build/actions/setup/go@v4.0.0
with:
go-version: "1.25"
- name: Build CLI
run: go build -o ./bin/core .
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: core-${{ matrix.goos }}-${{ matrix.goarch }}
path: ./bin/core
draft-release:
needs: build
runs-on: ubuntu-latest
env:
# Safe: PR number is numeric, not user-controlled string
PR_NUM: ${{ github.event.pull_request.number || inputs.pr_number }}
PR_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
steps:
- uses: actions/checkout@v6
- name: Download artifacts
uses: actions/download-artifact@v7
with:
path: dist
merge-multiple: true
- name: Prepare release files
run: |
mkdir -p release
cp dist/* release/ 2>/dev/null || true
ls -la release/
- name: Create draft release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
# Use dots for build metadata (semver v1 compatible)
TAG="v${{ env.NEXT_VERSION }}.pr.${PR_NUM}.bid.${{ github.run_id }}"
# Delete existing draft for this PR if it exists
gh release delete "$TAG" -y 2>/dev/null || true
git push origin ":refs/tags/$TAG" 2>/dev/null || true
gh release create "$TAG" \
--title "Draft: PR #${PR_NUM}" \
--notes "Draft build for PR #${PR_NUM}.
**Version:** $TAG
**PR:** #${PR_NUM}
**Commit:** ${PR_SHA}
**Built:** $(date -u +'%Y-%m-%d %H:%M:%S UTC')
**Run:** ${{ github.run_id }}
## Channel: Draft
This is a draft build for testing PR changes before merge.
Not intended for production use.
Build artifacts available for download and testing.
" \
--draft \
--prerelease \
release/*

View file

@ -1,45 +0,0 @@
name: PR Gate
on:
pull_request_target:
types: [opened, synchronize, reopened, labeled]
permissions:
contents: read
pull-requests: read
jobs:
org-gate:
runs-on: ubuntu-latest
steps:
- name: Check org membership or approval label
uses: actions/github-script@v7
with:
script: |
const author = context.payload.pull_request.user.login;
const association = context.payload.pull_request.author_association;
// Trusted accounts
const trustedAuthors = ['google-labs-jules[bot]', 'Snider'];
if (trustedAuthors.includes(author)) {
core.info(`${author} is trusted — gate passed`);
return;
}
// Check author association
const trustedAssociations = ['MEMBER', 'OWNER', 'COLLABORATOR'];
if (trustedAssociations.includes(association)) {
core.info(`${author} is ${association} — gate passed`);
return;
}
// Check for external-approved label
const labels = context.payload.pull_request.labels.map(l => l.name);
if (labels.includes('external-approved')) {
core.info('external-approved label present — gate passed');
return;
}
core.setFailed(
`External PR from ${author} requires an org member to add the "external-approved" label before merge.`
);

View file

@ -1,454 +0,0 @@
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#push
name: "Release: Tag Push"
on:
push:
tags:
- 'v*.*.*'
permissions:
contents: write
jobs:
build:
strategy:
matrix:
include:
- os: ubuntu-latest
goos: linux
goarch: amd64
- os: ubuntu-latest
goos: linux
goarch: arm64
- os: macos-latest
goos: darwin
goarch: arm64
- os: windows-latest
goos: windows
goarch: amd64
runs-on: ${{ matrix.os }}
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
steps:
- uses: actions/checkout@v6
- name: Setup Go
uses: host-uk/build/actions/setup/go@v4.0.0
with:
go-version: "1.25"
- name: Build CLI
shell: bash
run: |
EXT=""
if [ "$GOOS" = "windows" ]; then EXT=".exe"; fi
BINARY="core${EXT}"
ARCHIVE_PREFIX="core-${GOOS}-${GOARCH}"
APP_VERSION="${GITHUB_REF_NAME#v}"
go build -ldflags "-s -w -X github.com/host-uk/core/pkg/cli.AppVersion=${APP_VERSION}" -o "./bin/${BINARY}" .
# Create tar.gz for Homebrew (non-Windows)
if [ "$GOOS" != "windows" ]; then
tar czf "./bin/${ARCHIVE_PREFIX}.tar.gz" -C ./bin "${BINARY}"
fi
# Create zip for Scoop (Windows)
if [ "$GOOS" = "windows" ]; then
cd ./bin && zip "${ARCHIVE_PREFIX}.zip" "${BINARY}" && cd ..
fi
# Rename raw binary to platform-specific name for release
mv "./bin/${BINARY}" "./bin/${ARCHIVE_PREFIX}${EXT}"
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: core-${{ matrix.goos }}-${{ matrix.goarch }}
path: ./bin/core-*
build-ide:
strategy:
matrix:
include:
- os: macos-latest
goos: darwin
goarch: arm64
- os: ubuntu-latest
goos: linux
goarch: amd64
- os: windows-latest
goos: windows
goarch: amd64
runs-on: ${{ matrix.os }}
env:
GOOS: ${{ matrix.goos }}
GOARCH: ${{ matrix.goarch }}
defaults:
run:
working-directory: internal/core-ide
steps:
- uses: actions/checkout@v6
- name: Setup Go
uses: host-uk/build/actions/setup/go@v4.0.0
with:
go-version: "1.25"
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
- name: Install Wails CLI
run: go install github.com/wailsapp/wails/v3/cmd/wails3@latest
- name: Install frontend dependencies
working-directory: internal/core-ide/frontend
run: npm ci
- name: Generate bindings
run: wails3 generate bindings -f '-tags production' -clean=false -ts -i
- name: Build frontend
working-directory: internal/core-ide/frontend
run: npm run build
- name: Install Linux dependencies
if: matrix.goos == 'linux'
run: |
sudo apt-get update
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev
- name: Build IDE
shell: bash
run: |
EXT=""
if [ "$GOOS" = "windows" ]; then EXT=".exe"; fi
BINARY="core-ide${EXT}"
ARCHIVE_PREFIX="core-ide-${GOOS}-${GOARCH}"
BUILD_FLAGS="-tags production -trimpath -buildvcs=false"
if [ "$GOOS" = "windows" ]; then
# Windows: no CGO, use windowsgui linker flag
export CGO_ENABLED=0
LDFLAGS="-w -s -H windowsgui"
# Generate Windows syso resource
cd build
wails3 generate syso -arch ${GOARCH} -icon windows/icon.ico -manifest windows/wails.exe.manifest -info windows/info.json -out ../wails_windows_${GOARCH}.syso
cd ..
elif [ "$GOOS" = "darwin" ]; then
export CGO_ENABLED=1
export CGO_CFLAGS="-mmacosx-version-min=10.15"
export CGO_LDFLAGS="-mmacosx-version-min=10.15"
export MACOSX_DEPLOYMENT_TARGET="10.15"
LDFLAGS="-w -s"
else
export CGO_ENABLED=1
LDFLAGS="-w -s"
fi
go build ${BUILD_FLAGS} -ldflags="${LDFLAGS}" -o "./bin/${BINARY}"
# Clean up syso files
rm -f *.syso
# Package
if [ "$GOOS" = "darwin" ]; then
# Create .app bundle
mkdir -p "./bin/Core IDE.app/Contents/"{MacOS,Resources}
cp build/darwin/icons.icns "./bin/Core IDE.app/Contents/Resources/"
cp "./bin/${BINARY}" "./bin/Core IDE.app/Contents/MacOS/"
cp build/darwin/Info.plist "./bin/Core IDE.app/Contents/"
codesign --force --deep --sign - "./bin/Core IDE.app"
tar czf "./bin/${ARCHIVE_PREFIX}.tar.gz" -C ./bin "Core IDE.app"
elif [ "$GOOS" = "windows" ]; then
cd ./bin && zip "${ARCHIVE_PREFIX}.zip" "${BINARY}" && cd ..
else
tar czf "./bin/${ARCHIVE_PREFIX}.tar.gz" -C ./bin "${BINARY}"
fi
# Rename raw binary
mv "./bin/${BINARY}" "./bin/${ARCHIVE_PREFIX}${EXT}"
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: core-ide-${{ matrix.goos }}-${{ matrix.goarch }}
path: internal/core-ide/bin/core-ide-*
release:
needs: [build, build-ide]
runs-on: ubuntu-latest
outputs:
version: ${{ steps.version.outputs.version }}
steps:
- uses: actions/checkout@v6
- name: Set version
id: version
run: echo "version=${{ github.ref_name }}" >> "$GITHUB_OUTPUT"
- name: Download artifacts
uses: actions/download-artifact@v7
with:
path: dist
merge-multiple: true
- name: Prepare release files
run: |
mkdir -p release
cp dist/* release/ 2>/dev/null || true
ls -la release/
- name: Create release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAG_NAME: ${{ github.ref_name }}
run: |
gh release create "$TAG_NAME" \
--title "Release $TAG_NAME" \
--generate-notes \
release/*
update-tap:
needs: release
runs-on: ubuntu-latest
steps:
- name: Download artifacts
uses: actions/download-artifact@v7
with:
path: dist
merge-multiple: true
- name: Generate checksums
run: |
cd dist
for f in *.tar.gz; do
sha256sum "$f" | awk '{print $1}' > "${f}.sha256"
done
echo "=== Checksums ==="
cat *.sha256
- name: Update Homebrew formula
env:
GH_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
VERSION: ${{ needs.release.outputs.version }}
run: |
# Strip leading 'v' for formula version
FORMULA_VERSION="${VERSION#v}"
# Read checksums
DARWIN_ARM64=$(cat dist/core-darwin-arm64.tar.gz.sha256)
LINUX_AMD64=$(cat dist/core-linux-amd64.tar.gz.sha256)
LINUX_ARM64=$(cat dist/core-linux-arm64.tar.gz.sha256)
# Clone tap repo (configure auth for push)
gh repo clone host-uk/homebrew-tap /tmp/tap -- --depth=1
cd /tmp/tap
git remote set-url origin "https://x-access-token:${GH_TOKEN}@github.com/host-uk/homebrew-tap.git"
cd -
mkdir -p /tmp/tap/Formula
# Write formula
cat > /tmp/tap/Formula/core.rb << FORMULA
# typed: false
# frozen_string_literal: true
class Core < Formula
desc "Host UK development CLI"
homepage "https://github.com/host-uk/core"
version "${FORMULA_VERSION}"
license "EUPL-1.2"
on_macos do
url "https://github.com/host-uk/core/releases/download/${VERSION}/core-darwin-arm64.tar.gz"
sha256 "${DARWIN_ARM64}"
end
on_linux do
if Hardware::CPU.arm?
url "https://github.com/host-uk/core/releases/download/${VERSION}/core-linux-arm64.tar.gz"
sha256 "${LINUX_ARM64}"
else
url "https://github.com/host-uk/core/releases/download/${VERSION}/core-linux-amd64.tar.gz"
sha256 "${LINUX_AMD64}"
end
end
def install
bin.install "core"
end
test do
system "\#{bin}/core", "--version"
end
end
FORMULA
# Remove leading whitespace from heredoc
sed -i 's/^ //' /tmp/tap/Formula/core.rb
# Read IDE checksums (may not exist if build-ide failed)
IDE_DARWIN_ARM64=$(cat dist/core-ide-darwin-arm64.tar.gz.sha256 2>/dev/null || echo "")
IDE_LINUX_AMD64=$(cat dist/core-ide-linux-amd64.tar.gz.sha256 2>/dev/null || echo "")
# Write core-ide Formula (Linux binary)
if [ -n "${IDE_LINUX_AMD64}" ]; then
cat > /tmp/tap/Formula/core-ide.rb << FORMULA
# typed: false
# frozen_string_literal: true
class CoreIde < Formula
desc "Host UK desktop development environment"
homepage "https://github.com/host-uk/core"
version "${FORMULA_VERSION}"
license "EUPL-1.2"
on_linux do
url "https://github.com/host-uk/core/releases/download/${VERSION}/core-ide-linux-amd64.tar.gz"
sha256 "${IDE_LINUX_AMD64}"
end
def install
bin.install "core-ide"
end
end
FORMULA
sed -i 's/^ //' /tmp/tap/Formula/core-ide.rb
fi
# Write core-ide Cask (macOS .app bundle)
if [ -n "${IDE_DARWIN_ARM64}" ]; then
mkdir -p /tmp/tap/Casks
cat > /tmp/tap/Casks/core-ide.rb << CASK
cask "core-ide" do
version "${FORMULA_VERSION}"
sha256 "${IDE_DARWIN_ARM64}"
url "https://github.com/host-uk/core/releases/download/${VERSION}/core-ide-darwin-arm64.tar.gz"
name "Core IDE"
desc "Host UK desktop development environment"
homepage "https://github.com/host-uk/core"
app "Core IDE.app"
end
CASK
sed -i 's/^ //' /tmp/tap/Casks/core-ide.rb
fi
cd /tmp/tap
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add .
git diff --cached --quiet && echo "No changes to tap" && exit 0
git commit -m "Update core to ${FORMULA_VERSION}"
git push
update-scoop:
needs: release
runs-on: ubuntu-latest
steps:
- name: Download artifacts
uses: actions/download-artifact@v7
with:
path: dist
merge-multiple: true
- name: Generate checksums
run: |
cd dist
for f in *.zip; do
[ -f "$f" ] || continue
sha256sum "$f" | awk '{print $1}' > "${f}.sha256"
done
echo "=== Checksums ==="
cat *.sha256 2>/dev/null || echo "No zip checksums"
- name: Update Scoop manifests
env:
GH_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
VERSION: ${{ needs.release.outputs.version }}
run: |
# Strip leading 'v' for manifest version
MANIFEST_VERSION="${VERSION#v}"
# Read checksums
WIN_AMD64=$(cat dist/core-windows-amd64.zip.sha256 2>/dev/null || echo "")
IDE_WIN_AMD64=$(cat dist/core-ide-windows-amd64.zip.sha256 2>/dev/null || echo "")
# Clone scoop bucket
gh repo clone host-uk/scoop-bucket /tmp/scoop -- --depth=1
cd /tmp/scoop
git remote set-url origin "https://x-access-token:${GH_TOKEN}@github.com/host-uk/scoop-bucket.git"
# Write core.json manifest
cat > core.json << 'MANIFEST'
{
"version": "VERSION_PLACEHOLDER",
"description": "Host UK development CLI",
"homepage": "https://github.com/host-uk/core",
"license": "EUPL-1.2",
"architecture": {
"64bit": {
"url": "URL_PLACEHOLDER",
"hash": "HASH_PLACEHOLDER",
"bin": "core.exe"
}
},
"checkver": "github",
"autoupdate": {
"architecture": {
"64bit": {
"url": "https://github.com/host-uk/core/releases/download/v$version/core-windows-amd64.zip"
}
}
}
}
MANIFEST
sed -i "s|VERSION_PLACEHOLDER|${MANIFEST_VERSION}|g" core.json
sed -i "s|URL_PLACEHOLDER|https://github.com/host-uk/core/releases/download/${VERSION}/core-windows-amd64.zip|g" core.json
sed -i "s|HASH_PLACEHOLDER|${WIN_AMD64}|g" core.json
sed -i 's/^ //' core.json
# Write core-ide.json manifest
if [ -n "${IDE_WIN_AMD64}" ]; then
cat > core-ide.json << 'MANIFEST'
{
"version": "VERSION_PLACEHOLDER",
"description": "Host UK desktop development environment",
"homepage": "https://github.com/host-uk/core",
"license": "EUPL-1.2",
"architecture": {
"64bit": {
"url": "URL_PLACEHOLDER",
"hash": "HASH_PLACEHOLDER",
"bin": "core-ide.exe"
}
},
"checkver": "github",
"autoupdate": {
"architecture": {
"64bit": {
"url": "https://github.com/host-uk/core/releases/download/v$version/core-ide-windows-amd64.zip"
}
}
}
}
MANIFEST
sed -i "s|VERSION_PLACEHOLDER|${MANIFEST_VERSION}|g" core-ide.json
sed -i "s|URL_PLACEHOLDER|https://github.com/host-uk/core/releases/download/${VERSION}/core-ide-windows-amd64.zip|g" core-ide.json
sed -i "s|HASH_PLACEHOLDER|${IDE_WIN_AMD64}|g" core-ide.json
sed -i 's/^ //' core-ide.json
fi
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add .
git diff --cached --quiet && echo "No changes to scoop bucket" && exit 0
git commit -m "Update core to ${MANIFEST_VERSION}"
git push

View file

@ -9,9 +9,9 @@ steps:
- go mod download
- >-
go build
-ldflags "-X github.com/host-uk/core/pkg/cli.AppVersion=ci
-X github.com/host-uk/core/pkg/cli.BuildCommit=${CI_COMMIT_SHA:0:7}
-X github.com/host-uk/core/pkg/cli.BuildDate=$(date -u +%Y%m%d)"
-ldflags "-X forge.lthn.ai/core/cli/pkg/cli.AppVersion=ci
-X forge.lthn.ai/core/cli/pkg/cli.BuildCommit=${CI_COMMIT_SHA:0:7}
-X forge.lthn.ai/core/cli/pkg/cli.BuildDate=$(date -u +%Y%m%d)"
-o ./bin/core .
- ./bin/core --version

View file

@ -1,14 +1,14 @@
# Core
[![codecov](https://codecov.io/gh/host-uk/core/branch/dev/graph/badge.svg)](https://codecov.io/gh/host-uk/core)
[![Go Test Coverage](https://github.com/host-uk/core/actions/workflows/coverage.yml/badge.svg)](https://github.com/host-uk/core/actions/workflows/coverage.yml)
[![Code Scanning](https://github.com/host-uk/core/actions/workflows/codescan.yml/badge.svg)](https://github.com/host-uk/core/actions/workflows/codescan.yml)
[![Go Test Coverage](https://forge.lthn.ai/core/cli/actions/workflows/coverage.yml/badge.svg)](https://forge.lthn.ai/core/cli/actions/workflows/coverage.yml)
[![Code Scanning](https://forge.lthn.ai/core/cli/actions/workflows/codescan.yml/badge.svg)](https://forge.lthn.ai/core/cli/actions/workflows/codescan.yml)
[![Go Version](https://img.shields.io/github/go-mod/go-version/host-uk/core)](https://go.dev/)
[![License](https://img.shields.io/badge/License-EUPL--1.2-blue.svg)](https://opensource.org/licenses/EUPL-1.2)
Core is a Web3 Framework, written in Go using Wails.io to replace Electron and the bloat of browsers that, at their core, still live in their mum's basement.
- Repo: https://github.com/host-uk/core
- Repo: https://forge.lthn.ai/core/cli
## Vision
@ -26,7 +26,7 @@ Core is an **opinionated Web3 desktop application framework** providing:
```bash
# 1. Install Core
go install github.com/host-uk/core/cmd/core@latest
go install forge.lthn.ai/core/cli/cmd/core@latest
# 2. Verify environment
core doctor
@ -44,7 +44,7 @@ For more details, see the [User Guide](docs/user-guide.md).
## Framework Quick Start (Go)
```go
import core "github.com/host-uk/core/pkg/framework/core"
import core "forge.lthn.ai/core/cli/pkg/framework/core"
app, err := core.New(
core.WithServiceLock(),
@ -210,7 +210,7 @@ app.RegisterService(application.NewService(coreService)) // Only Core is regist
**Currently exposed** (see `cmd/core-gui/public/bindings/`):
```typescript
// From frontend:
import { ACTION, Config, Service } from './bindings/github.com/host-uk/core/pkg/core'
import { ACTION, Config, Service } from './bindings/forge.lthn.ai/core/cli/pkg/core'
ACTION(msg) // Broadcast IPC message
Config() // Get config service reference
@ -259,7 +259,7 @@ Sub-services are accessed via Core's **IPC/ACTION system**, not direct Wails bin
```typescript
// Frontend calls Core.ACTION() with typed messages
import { ACTION } from './bindings/github.com/host-uk/core/pkg/core'
import { ACTION } from './bindings/forge.lthn.ai/core/cli/pkg/core'
// Open a window
ACTION({ action: "display.open_window", name: "settings", options: { Title: "Settings", Width: 800 } })

View file

@ -15,7 +15,7 @@ vars:
SEMVER_PRERELEASE:
sh: '[ "{{.SEMVER_COMMITS}}" = "0" ] && echo "" || echo "dev.{{.SEMVER_COMMITS}}"'
# ldflags
PKG: "github.com/host-uk/core/pkg/cli"
PKG: "forge.lthn.ai/core/cli/pkg/cli"
LDFLAGS_BASE: >-
-X {{.PKG}}.AppVersion={{.SEMVER_VERSION}}
-X {{.PKG}}.BuildCommit={{.SEMVER_COMMIT}}

View file

@ -19,7 +19,7 @@ BugSETI is a system tray application that helps developers contribute to open so
```bash
# Clone the repository
git clone https://github.com/host-uk/core.git
git clone https://forge.lthn.ai/core/cli.git
cd core
# Build BugSETI

View file

@ -12,7 +12,7 @@ description: |
it pulls OSS issues from GitHub, AI prepares context,
you fix bugs, and it auto-submits PRs.
vendor: "Lethean"
homepage: "https://github.com/host-uk/core"
homepage: "https://forge.lthn.ai/core/cli"
license: "MIT"
contents:

View file

@ -186,7 +186,7 @@
<div class="flex items-center gap-6 text-sm">
<a href="#how-it-works" class="text-lethean-400 hover:text-lethean-200 transition-colors link-underline">How it works</a>
<a href="#ecosystem" class="text-lethean-400 hover:text-lethean-200 transition-colors link-underline">Ecosystem</a>
<a href="https://github.com/host-uk/core" target="_blank" rel="noopener" class="text-lethean-400 hover:text-lethean-200 transition-colors link-underline">GitHub</a>
<a href="https://forge.lthn.ai/core/cli" target="_blank" rel="noopener" class="text-lethean-400 hover:text-lethean-200 transition-colors link-underline">GitHub</a>
<a href="#join" class="inline-flex items-center gap-1.5 px-4 py-1.5 rounded-md bg-cyan-400/10 text-cyan-400 border border-cyan-400/20 hover:bg-cyan-400/20 hover:border-cyan-400/30 transition-all text-sm font-medium">
Get BugSETI
</a>
@ -249,7 +249,7 @@
Download BugSETI
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7l5 5m0 0l-5 5m5-5H6"/></svg>
</a>
<a href="https://github.com/host-uk/core" target="_blank" rel="noopener" class="inline-flex items-center gap-2 px-6 py-3 rounded-lg border border-lethean-600/50 text-lethean-300 font-medium text-sm hover:bg-lethean-800/50 hover:border-lethean-500/50 transition-all">
<a href="https://forge.lthn.ai/core/cli" target="_blank" rel="noopener" class="inline-flex items-center gap-2 px-6 py-3 rounded-lg border border-lethean-600/50 text-lethean-300 font-medium text-sm hover:bg-lethean-800/50 hover:border-lethean-500/50 transition-all">
<svg class="w-4 h-4" fill="currentColor" viewBox="0 0 24 24"><path d="M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385.6.105.825-.255.825-.57 0-.285-.015-1.23-.015-2.235-3.015.555-3.795-.735-4.035-1.41-.135-.345-.72-1.41-1.23-1.695-.42-.225-1.02-.78-.015-.795.945-.015 1.62.87 1.845 1.23 1.08 1.815 2.805 1.305 3.495.99.105-.78.42-1.305.765-1.605-2.67-.3-5.46-1.335-5.46-5.925 0-1.305.465-2.385 1.23-3.225-.12-.3-.54-1.53.12-3.18 0 0 1.005-.315 3.3 1.23.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23.66 1.65.24 2.88.12 3.18.765.84 1.23 1.905 1.23 3.225 0 4.605-2.805 5.625-5.475 5.925.435.375.81 1.095.81 2.22 0 1.605-.015 2.895-.015 3.3 0 .315.225.69.825.57A12.02 12.02 0 0024 12c0-6.63-5.37-12-12-12z"/></svg>
View Source
</a>
@ -518,13 +518,13 @@
<!-- Download buttons -->
<div class="flex flex-col sm:flex-row items-center justify-center gap-3 mb-12">
<a href="https://github.com/host-uk/core/releases" target="_blank" rel="noopener" class="w-full sm:w-auto inline-flex items-center justify-center gap-2 px-6 py-3.5 rounded-lg bg-lethean-800 border border-lethean-600/40 text-lethean-200 font-medium text-sm hover:bg-lethean-700 hover:border-lethean-500/50 transition-all">
<a href="https://forge.lthn.ai/core/cli/releases" target="_blank" rel="noopener" class="w-full sm:w-auto inline-flex items-center justify-center gap-2 px-6 py-3.5 rounded-lg bg-lethean-800 border border-lethean-600/40 text-lethean-200 font-medium text-sm hover:bg-lethean-700 hover:border-lethean-500/50 transition-all">
<span class="text-lg">🐧</span> Linux
</a>
<a href="https://github.com/host-uk/core/releases" target="_blank" rel="noopener" class="w-full sm:w-auto inline-flex items-center justify-center gap-2 px-6 py-3.5 rounded-lg bg-lethean-800 border border-lethean-600/40 text-lethean-200 font-medium text-sm hover:bg-lethean-700 hover:border-lethean-500/50 transition-all">
<a href="https://forge.lthn.ai/core/cli/releases" target="_blank" rel="noopener" class="w-full sm:w-auto inline-flex items-center justify-center gap-2 px-6 py-3.5 rounded-lg bg-lethean-800 border border-lethean-600/40 text-lethean-200 font-medium text-sm hover:bg-lethean-700 hover:border-lethean-500/50 transition-all">
<span class="text-lg">🍎</span> macOS
</a>
<a href="https://github.com/host-uk/core/releases" target="_blank" rel="noopener" class="w-full sm:w-auto inline-flex items-center justify-center gap-2 px-6 py-3.5 rounded-lg bg-lethean-800 border border-lethean-600/40 text-lethean-200 font-medium text-sm hover:bg-lethean-700 hover:border-lethean-500/50 transition-all">
<a href="https://forge.lthn.ai/core/cli/releases" target="_blank" rel="noopener" class="w-full sm:w-auto inline-flex items-center justify-center gap-2 px-6 py-3.5 rounded-lg bg-lethean-800 border border-lethean-600/40 text-lethean-200 font-medium text-sm hover:bg-lethean-700 hover:border-lethean-500/50 transition-all">
<span class="text-lg">🪟</span> Windows
</a>
</div>
@ -533,7 +533,7 @@
<div class="gradient-border rounded-lg overflow-hidden max-w-md mx-auto">
<div class="bg-lethean-900 rounded-lg px-5 py-3 font-mono text-sm text-left">
<span class="text-lethean-500"># or build from source</span><br>
<span class="text-cyan-400">$</span> <span class="text-lethean-300">git clone https://github.com/host-uk/core</span><br>
<span class="text-cyan-400">$</span> <span class="text-lethean-300">git clone https://forge.lthn.ai/core/cli</span><br>
<span class="text-cyan-400">$</span> <span class="text-lethean-300">cd core && go build ./cmd/bugseti</span>
</div>
</div>

View file

@ -26,8 +26,8 @@ core dev work --status
repos:
- name: core
path: ./core
url: https://github.com/host-uk/core
url: https://forge.lthn.ai/core/cli
- name: core-php
path: ./core-php
url: https://github.com/host-uk/core-php
url: https://forge.lthn.ai/core/cli-php
```

View file

@ -32,7 +32,7 @@ core go mod graph | dot -Tpng -o deps.png
## Output
```
github.com/host-uk/core github.com/stretchr/testify@v1.11.1
forge.lthn.ai/core/cli github.com/stretchr/testify@v1.11.1
github.com/stretchr/testify@v1.11.1 github.com/davecgh/go-spew@v1.1.2
github.com/stretchr/testify@v1.11.1 github.com/pmezard/go-difflib@v1.0.1
...

View file

@ -23,7 +23,7 @@ Unified interface for Go/PHP development, multi-repo management, and deployment.
## Installation
```bash
go install github.com/host-uk/core/cmd/core@latest
go install forge.lthn.ai/core/cli/cmd/core@latest
```
Verify: `core doctor`

View file

@ -21,7 +21,7 @@ It is both. The Core Framework (`pkg/core`) is a library for building Go desktop
The recommended way is via Go:
```bash
go install github.com/host-uk/core/cmd/core@latest
go install forge.lthn.ai/core/cli/cmd/core@latest
```
Ensure your Go bin directory is in your PATH. See [Getting Started](getting-started.md) for more options.

View file

@ -25,7 +25,7 @@ Optional (for specific features):
```bash
# Install latest release
go install github.com/host-uk/core/cmd/core@latest
go install forge.lthn.ai/core/cli/cmd/core@latest
# Verify installation
core doctor
@ -39,21 +39,21 @@ export PATH="$PATH:$(go env GOPATH)/bin"
### Option 2: Download Binary
Download pre-built binaries from [GitHub Releases](https://github.com/host-uk/core/releases):
Download pre-built binaries from [GitHub Releases](https://forge.lthn.ai/core/cli/releases):
```bash
# macOS (Apple Silicon)
curl -Lo core https://github.com/host-uk/core/releases/latest/download/core-darwin-arm64
curl -Lo core https://forge.lthn.ai/core/cli/releases/latest/download/core-darwin-arm64
chmod +x core
sudo mv core /usr/local/bin/
# macOS (Intel)
curl -Lo core https://github.com/host-uk/core/releases/latest/download/core-darwin-amd64
curl -Lo core https://forge.lthn.ai/core/cli/releases/latest/download/core-darwin-amd64
chmod +x core
sudo mv core /usr/local/bin/
# Linux (x86_64)
curl -Lo core https://github.com/host-uk/core/releases/latest/download/core-linux-amd64
curl -Lo core https://forge.lthn.ai/core/cli/releases/latest/download/core-linux-amd64
chmod +x core
sudo mv core /usr/local/bin/
```
@ -62,7 +62,7 @@ sudo mv core /usr/local/bin/
```bash
# Clone repository
git clone https://github.com/host-uk/core.git
git clone https://forge.lthn.ai/core/cli.git
cd core
# Build with Task (recommended)
@ -181,7 +181,7 @@ core doctor
core <command> --help
# Full documentation
https://github.com/host-uk/core/tree/main/docs
https://forge.lthn.ai/core/cli/tree/main/docs
```
## See Also

View file

@ -6,10 +6,10 @@ Core is a unified CLI for the host-uk ecosystem - build, release, and deploy Go,
```bash
# Via Go (recommended)
go install github.com/host-uk/core/cmd/core@latest
go install forge.lthn.ai/core/cli/cmd/core@latest
# Or download binary from releases
curl -Lo core https://github.com/host-uk/core/releases/latest/download/core-$(go env GOOS)-$(go env GOARCH)
curl -Lo core https://forge.lthn.ai/core/cli/releases/latest/download/core-$(go env GOOS)-$(go env GOARCH)
chmod +x core && sudo mv core /usr/local/bin/
# Verify

View file

@ -364,7 +364,7 @@ import (
"log"
"time"
"github.com/host-uk/core/pkg/webview"
"forge.lthn.ai/core/cli/pkg/webview"
)
func main() {
@ -424,7 +424,7 @@ import (
"log"
"time"
"github.com/host-uk/core/pkg/webview"
"forge.lthn.ai/core/cli/pkg/webview"
)
func main() {

View file

@ -47,8 +47,8 @@ Here is the technical documentation for the Core framework packages.
* **Framework Integration**: The `Service` struct embeds `framework.ServiceRuntime`, utilizing the Actor pattern (Queries and Tasks) to allow dynamic log level adjustment at runtime without restarting the application.
### 4. Dependencies
* `github.com/host-uk/core/pkg/io`: Used by `rotation.go` to handle file operations (renaming, deleting, writing) abstractly.
* `github.com/host-uk/core/pkg/framework`: Used by `service.go` to hook into the application lifecycle and message bus.
* `forge.lthn.ai/core/cli/pkg/io`: Used by `rotation.go` to handle file operations (renaming, deleting, writing) abstractly.
* `forge.lthn.ai/core/cli/pkg/framework`: Used by `service.go` to hook into the application lifecycle and message bus.
* Standard Lib: `errors`, `fmt`, `os`, `sync`, `time`.
### 5. Test Coverage Notes
@ -88,8 +88,8 @@ Here is the technical documentation for the Core framework packages.
### 4. Dependencies
* `github.com/spf13/viper`: Core logic for map merging and unmarshalling.
* `gopkg.in/yaml.v3`: For marshalling data when saving.
* `github.com/host-uk/core/pkg/io`: For reading/writing config files.
* `github.com/host-uk/core/pkg/framework/core`: For service integration and error handling.
* `forge.lthn.ai/core/cli/pkg/io`: For reading/writing config files.
* `forge.lthn.ai/core/cli/pkg/framework/core`: For service integration and error handling.
### 5. Test Coverage Notes
* **Precedence**: Verify that Environment variables override File values.
@ -122,7 +122,7 @@ Here is the technical documentation for the Core framework packages.
### 4. Dependencies
* Standard Lib: `io`, `io/fs`, `os`, `path/filepath`, `strings`, `time`.
* `github.com/host-uk/core/pkg/io/local`: (Implied) The concrete implementation for OS disk access.
* `forge.lthn.ai/core/cli/pkg/io/local`: (Implied) The concrete implementation for OS disk access.
### 5. Test Coverage Notes
* **Mock fidelity**: The `MockMedium` must behave exactly like the OS. E.g., `Rename` should fail if the source doesn't exist; `Delete` should fail if a directory is not empty.
@ -198,10 +198,10 @@ Here is the technical documentation for the Core framework packages.
4. Server validates signature against User Public Key.
### 4. Dependencies
* `github.com/host-uk/core/pkg/io`: For user database storage.
* `github.com/host-uk/core/pkg/crypt/lthn`: (Implied) Specific password hashing.
* `github.com/host-uk/core/pkg/crypt/pgp`: (Implied) OpenPGP operations.
* `github.com/host-uk/core/pkg/framework/core`: Error handling.
* `forge.lthn.ai/core/cli/pkg/io`: For user database storage.
* `forge.lthn.ai/core/cli/pkg/crypt/lthn`: (Implied) Specific password hashing.
* `forge.lthn.ai/core/cli/pkg/crypt/pgp`: (Implied) OpenPGP operations.
* `forge.lthn.ai/core/cli/pkg/framework/core`: Error handling.
### 5. Test Coverage Notes
* **Flow Verification**: Full integration test simulating a client: Register -> Get Challenge -> Decrypt/Sign (Mock Client) -> Validate -> Get Token.

View file

@ -60,9 +60,9 @@ The `cli` package is a comprehensive application runtime and UI framework design
### 4. Dependencies
- `github.com/spf13/cobra`: The underlying command routing engine.
- `github.com/host-uk/core/pkg/framework`: The dependency injection and service lifecycle container.
- `github.com/host-uk/core/pkg/i18n`: For translation and semantic grammar generation.
- `github.com/host-uk/core/pkg/log`: For structured logging.
- `forge.lthn.ai/core/cli/pkg/framework`: The dependency injection and service lifecycle container.
- `forge.lthn.ai/core/cli/pkg/i18n`: For translation and semantic grammar generation.
- `forge.lthn.ai/core/cli/pkg/log`: For structured logging.
- `golang.org/x/term`: For TTY detection.
### 5. Test Coverage Notes
@ -162,8 +162,8 @@ The `workspace` package implements the `core.Workspace` interface, providing iso
- **Key Management**: Delegates actual key generation to the core's `Crypt()` service but manages the storage of the resulting keys within the workspace layout.
### 4. Dependencies
- `github.com/host-uk/core/pkg/framework/core`: Interfaces.
- `github.com/host-uk/core/pkg/io`: File system abstraction (`io.Medium`).
- `forge.lthn.ai/core/cli/pkg/framework/core`: Interfaces.
- `forge.lthn.ai/core/cli/pkg/io`: File system abstraction (`io.Medium`).
- `crypt` service (Runtime dependency): Required for `CreateWorkspace`.
### 5. Test Coverage Notes

View file

@ -87,8 +87,8 @@ type Builder interface {
### 4. Dependencies
* `archive/tar`, `archive/zip`, `compress/gzip`: Standard library for archiving.
* `github.com/Snider/Borg/pkg/compress`: External dependency for XZ compression support.
* `github.com/host-uk/core/pkg/io`: Internal interface for filesystem abstraction.
* `github.com/host-uk/core/pkg/config`: Internal centralized configuration loading.
* `forge.lthn.ai/core/cli/pkg/io`: Internal interface for filesystem abstraction.
* `forge.lthn.ai/core/cli/pkg/config`: Internal centralized configuration loading.
### 5. Test Coverage Notes
* **Mocking IO**: Tests must implement a mock `io.Medium` to simulate file existence (`Detect`) and write operations (`Archive`) without touching the disk.
@ -158,7 +158,7 @@ type RunOptions struct {
### 4. Dependencies
* `os/exec`: Essential for spawning the hypervisor processes.
* `embed`: For built-in templates.
* `github.com/host-uk/core/pkg/io`: Filesystem access for state and logs.
* `forge.lthn.ai/core/cli/pkg/io`: Filesystem access for state and logs.
### 5. Test Coverage Notes
* **Process Management**: Difficult to test `Run` in standard CI. Mocking `exec.Command` or the `Hypervisor` interface is required.
@ -224,7 +224,7 @@ func (r *Runner) RunParallel(ctx context.Context, specs []RunSpec) (*RunAllResul
### 4. Dependencies
* `os/exec`: The underlying execution engine.
* `github.com/host-uk/core/pkg/framework`: Creates the `ServiceRuntime` and provides the IPC/Action bus.
* `forge.lthn.ai/core/cli/pkg/framework`: Creates the `ServiceRuntime` and provides the IPC/Action bus.
### 5. Test Coverage Notes
* **Concurrency**: The `Runner` needs tests for race conditions during parallel execution.
@ -286,7 +286,7 @@ type JobHandler interface {
* **Journaling**: Writes `jsonl` (JSON Lines) files partitioned by repository and date (`baseDir/owner/repo/YYYY-MM-DD.jsonl`), ensuring an append-only audit trail.
### 4. Dependencies
* `github.com/host-uk/core/pkg/log`: Internal logging.
* `forge.lthn.ai/core/cli/pkg/log`: Internal logging.
* `encoding/json`: For journal serialization.
### 5. Test Coverage Notes

View file

@ -72,7 +72,7 @@ func NewService(opts ServiceOptions) func(*framework.Core) (any, error)
### Dependencies
* `os/exec`: For invoking git commands.
* `github.com/host-uk/core/pkg/framework`: For service registration and message passing types.
* `forge.lthn.ai/core/cli/pkg/framework`: For service registration and message passing types.
### Test Coverage Notes
* **Mocking**: Testing requires abstracting `exec.Command`. Since this package calls `exec.CommandContext` directly, tests likely require overriding a package-level variable or using a "fake exec" pattern during test initialization.
@ -135,7 +135,7 @@ func (repo *Repo) IsGitRepo() bool
### Dependencies
* `gopkg.in/yaml.v3`: For parsing `repos.yaml`.
* `github.com/host-uk/core/pkg/io`: For filesystem abstraction (`io.Medium`).
* `forge.lthn.ai/core/cli/pkg/io`: For filesystem abstraction (`io.Medium`).
### Test Coverage Notes
* **Circular Dependencies**: Critical test cases must define a registry with `A->B->A` dependencies to ensure `TopologicalOrder` returns a clear error and doesn't stack overflow.
@ -197,7 +197,7 @@ func (c *Client) ListUserRepos(...)
### Dependencies
* `code.gitea.io/sdk/gitea` (for `pkg/gitea`)
* `codeberg.org/mvdkleijn/forgejo-sdk` (for `pkg/forge`)
* `github.com/host-uk/core/pkg/config`: For persistent auth storage.
* `forge.lthn.ai/core/cli/pkg/config`: For persistent auth storage.
### Test Coverage Notes
* **Draft Status**: The raw HTTP patch in `pkg/forge` needs integration testing against a real instance or a high-fidelity HTTP mock to ensure payload format matches Forgejo's API expectation.
@ -250,8 +250,8 @@ func IncrementVersion(current string) string
* **SDK Generation**: Includes a specialized sub-pipeline (`RunSDK`) that handles OpenAPI diffing and client generation.
### Dependencies
* `github.com/host-uk/core/pkg/build`: For compiling artifacts.
* `github.com/host-uk/core/pkg/release/publishers`: Interface definitions for publishing targets.
* `forge.lthn.ai/core/cli/pkg/build`: For compiling artifacts.
* `forge.lthn.ai/core/cli/pkg/release/publishers`: Interface definitions for publishing targets.
* `golang.org/x/text`: For title casing in changelogs.
### Test Coverage Notes

View file

@ -51,8 +51,8 @@ func ListAgents(cfg *config.Config) (map[string]AgentConfig, error)
* **Defaults Handling**: `LoadAgents` applies specific logic defaults (e.g., default queue directories, default models like "sonnet") to ensure the system works with minimal configuration.
### 4. Dependencies
* `github.com/host-uk/core/pkg/config`: For reading/writing the persistent configuration state.
* `github.com/host-uk/core/pkg/jobrunner/handlers`: To map local config structs to the runtime types used by the job dispatch system.
* `forge.lthn.ai/core/cli/pkg/config`: For reading/writing the persistent configuration state.
* `forge.lthn.ai/core/cli/pkg/jobrunner/handlers`: To map local config structs to the runtime types used by the job dispatch system.
### 5. Test Coverage Notes
* **Configuration Persistence**: Tests should verify that `SaveAgent` correctly updates the underlying config file and that `LoadAgents` retrieves it accurately.

View file

@ -58,7 +58,7 @@ type TaskResult struct { Changed, Failed bool; Msg, Stdout string; ... }
* **SSH Abstraction**: `ssh.go` wraps `golang.org/x/crypto/ssh` to handle connection pooling, key management, and `sudo` escalation (become).
### 4. Dependencies
* `github.com/host-uk/core/pkg/log`: structured logging.
* `forge.lthn.ai/core/cli/pkg/log`: structured logging.
* `golang.org/x/crypto/ssh`: Underlying SSH transport.
* `gopkg.in/yaml.v3`: YAML parsing.
@ -129,7 +129,7 @@ Re-exports `Core`, `Option`, `Message`, `Startable`, `Stoppable`, and constructo
Purely structural; contains type aliases and variable assignments to expose the internal `core` package.
### 4. Dependencies
* `github.com/host-uk/core/pkg/framework/core`
* `forge.lthn.ai/core/cli/pkg/framework/core`
### 5. Test Coverage Notes
No logic to test directly; coverage belongs in `pkg/framework/core`.

View file

@ -40,7 +40,7 @@ package mypackage
import (
"sync"
"github.com/host-uk/core/pkg/framework"
"forge.lthn.ai/core/cli/pkg/framework"
)
// Service provides mypackage functionality with Core integration.
@ -120,7 +120,7 @@ import (
"sync"
"sync/atomic"
"github.com/host-uk/core/pkg/framework"
"forge.lthn.ai/core/cli/pkg/framework"
)
// Global default service

View file

@ -5,7 +5,7 @@ The `pkg/i18n` package provides internationalisation and localisation for Go CLI
## Quick Start
```go
import "github.com/host-uk/core/pkg/i18n"
import "forge.lthn.ai/core/cli/pkg/i18n"
func main() {
// Initialise with embedded locales

View file

@ -15,7 +15,7 @@
**Files:**
- Create: `go.work`
**Context:** The repo has two real modules — the root (`github.com/host-uk/core`) and core-ide (`github.com/host-uk/core/internal/core-ide`). Without a workspace, core-ide can't import `pkg/jobrunner` from the root module during local development without fragile `replace` directives. A `go.work` file makes cross-module imports resolve locally, keeps each module's `go.mod` clean, and lets CI build each variant independently.
**Context:** The repo has two real modules — the root (`forge.lthn.ai/core/cli`) and core-ide (`forge.lthn.ai/core/cli/internal/core-ide`). Without a workspace, core-ide can't import `pkg/jobrunner` from the root module during local development without fragile `replace` directives. A `go.work` file makes cross-module imports resolve locally, keeps each module's `go.mod` clean, and lets CI build each variant independently.
**Step 1: Create the workspace file**
@ -580,7 +580,7 @@ import (
"fmt"
"time"
"github.com/host-uk/core/pkg/log"
"forge.lthn.ai/core/cli/pkg/log"
)
// PollerConfig configures the job runner poller.
@ -732,7 +732,7 @@ func (p *Poller) AddHandler(h JobHandler) {
_ = fmt.Sprintf // ensure fmt imported for future use
```
Wait — remove that last line. The `fmt` import is only needed if used. Let me correct: the implementation above doesn't use `fmt` directly, so remove it from imports. The `log` package import path is `github.com/host-uk/core/pkg/log`.
Wait — remove that last line. The `fmt` import is only needed if used. Let me correct: the implementation above doesn't use `fmt` directly, so remove it from imports. The `log` package import path is `forge.lthn.ai/core/cli/pkg/log`.
**Step 4: Run tests**
@ -755,7 +755,7 @@ git commit -m "feat(jobrunner): add Poller with multi-source dispatch and journa
- Create: `pkg/jobrunner/github/signals.go`
- Test: `pkg/jobrunner/github/source_test.go`
**Context:** This package lives in the root go.mod (`github.com/host-uk/core`), NOT in the core-ide module. It uses `oauth2` and the GitHub REST API (same pattern as `internal/cmd/updater/github.go`). Uses conditional requests (ETag/If-None-Match) to conserve rate limit.
**Context:** This package lives in the root go.mod (`forge.lthn.ai/core/cli`), NOT in the core-ide module. It uses `oauth2` and the GitHub REST API (same pattern as `internal/cmd/updater/github.go`). Uses conditional requests (ETag/If-None-Match) to conserve rate limit.
**Step 1: Write the test**
@ -769,7 +769,7 @@ import (
"net/http/httptest"
"testing"
"github.com/host-uk/core/pkg/jobrunner"
"forge.lthn.ai/core/cli/pkg/jobrunner"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@ -856,7 +856,7 @@ import (
"strings"
"time"
"github.com/host-uk/core/pkg/jobrunner"
"forge.lthn.ai/core/cli/pkg/jobrunner"
)
// ghIssue is the minimal structure from GitHub Issues API.
@ -985,8 +985,8 @@ import (
"os"
"strings"
"github.com/host-uk/core/pkg/jobrunner"
"github.com/host-uk/core/pkg/log"
"forge.lthn.ai/core/cli/pkg/jobrunner"
"forge.lthn.ai/core/cli/pkg/log"
"golang.org/x/oauth2"
)
@ -1176,7 +1176,7 @@ import (
"net/http/httptest"
"testing"
"github.com/host-uk/core/pkg/jobrunner"
"forge.lthn.ai/core/cli/pkg/jobrunner"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@ -1259,7 +1259,7 @@ import (
"net/http"
"time"
"github.com/host-uk/core/pkg/jobrunner"
"forge.lthn.ai/core/cli/pkg/jobrunner"
)
// PublishDraft marks a draft PR as ready for review.
@ -1355,7 +1355,7 @@ import (
"net/http/httptest"
"testing"
"github.com/host-uk/core/pkg/jobrunner"
"forge.lthn.ai/core/cli/pkg/jobrunner"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@ -1438,7 +1438,7 @@ import (
"net/http"
"time"
"github.com/host-uk/core/pkg/jobrunner"
"forge.lthn.ai/core/cli/pkg/jobrunner"
)
// SendFixCommand comments on a PR to request a fix.
@ -1559,7 +1559,7 @@ import (
"os/exec"
"time"
"github.com/host-uk/core/pkg/jobrunner"
"forge.lthn.ai/core/cli/pkg/jobrunner"
)
type EnableAutoMerge struct{}
@ -1657,7 +1657,7 @@ import (
"net/http/httptest"
"testing"
"github.com/host-uk/core/pkg/jobrunner"
"forge.lthn.ai/core/cli/pkg/jobrunner"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@ -1758,7 +1758,7 @@ import (
"net/http"
"time"
"github.com/host-uk/core/pkg/jobrunner"
"forge.lthn.ai/core/cli/pkg/jobrunner"
)
// ResolveThreads resolves all unresolved review threads on a PR.
@ -1918,16 +1918,16 @@ git commit -m "feat(jobrunner): add resolve_threads handler with GraphQL"
**Context:** core-ide currently always creates a Wails app. We need to branch: headless starts the poller + MCP bridge directly; desktop mode keeps the existing Wails app with poller as an optional service.
Note: core-ide has its own `go.mod` (`github.com/host-uk/core/internal/core-ide`). The jobrunner package lives in the root module. We need to add the root module as a dependency of core-ide, OR move the handler wiring into the root module. **Simplest approach:** core-ide imports `github.com/host-uk/core/pkg/jobrunner` — this requires adding the root module as a dependency in core-ide's go.mod.
Note: core-ide has its own `go.mod` (`forge.lthn.ai/core/cli/internal/core-ide`). The jobrunner package lives in the root module. We need to add the root module as a dependency of core-ide, OR move the handler wiring into the root module. **Simplest approach:** core-ide imports `forge.lthn.ai/core/cli/pkg/jobrunner` — this requires adding the root module as a dependency in core-ide's go.mod.
**Step 1: Update core-ide go.mod**
Run: `cd /Users/snider/Code/host-uk/core/internal/core-ide && go get github.com/host-uk/core/pkg/jobrunner`
Run: `cd /Users/snider/Code/host-uk/core/internal/core-ide && go get forge.lthn.ai/core/cli/pkg/jobrunner`
If this fails because the package isn't published yet, use a `replace` directive temporarily:
```
replace github.com/host-uk/core => ../..
replace forge.lthn.ai/core/cli => ../..
```
Then `go mod tidy`.
@ -2020,7 +2020,7 @@ git commit -m "feat(core-ide): register job handlers as MCP tools"
```go
// In startHeadless(), before starting poller:
updaterSvc, err := updater.NewUpdateService(updater.UpdateServiceConfig{
RepoURL: "https://github.com/host-uk/core",
RepoURL: "https://forge.lthn.ai/core/cli",
Channel: "alpha",
CheckOnStartup: updater.CheckAndUpdateOnStartup,
})

View file

@ -81,8 +81,8 @@ import (
"context"
"fmt"
ragcmd "github.com/host-uk/core/internal/cmd/rag"
"github.com/host-uk/core/pkg/rag"
ragcmd "forge.lthn.ai/core/cli/internal/cmd/rag"
"forge.lthn.ai/core/cli/pkg/rag"
"github.com/modelcontextprotocol/go-sdk/mcp"
)
@ -368,7 +368,7 @@ import (
"fmt"
"time"
"github.com/host-uk/core/pkg/ai"
"forge.lthn.ai/core/cli/pkg/ai"
"github.com/modelcontextprotocol/go-sdk/mcp"
)
@ -608,9 +608,9 @@ import (
"os/signal"
"syscall"
"github.com/host-uk/core/pkg/cli"
"github.com/host-uk/core/pkg/i18n"
"github.com/host-uk/core/pkg/mcp"
"forge.lthn.ai/core/cli/pkg/cli"
"forge.lthn.ai/core/cli/pkg/i18n"
"forge.lthn.ai/core/cli/pkg/mcp"
)
func init() {
@ -695,7 +695,7 @@ Modify `internal/variants/full.go` to add:
```go
import (
// ... existing imports ...
_ "github.com/host-uk/core/internal/cmd/mcpcmd"
_ "forge.lthn.ai/core/cli/internal/cmd/mcpcmd"
)
```

View file

@ -18,7 +18,7 @@ export PATH="$PATH:$(go env GOPATH)/bin"
source ~/.bashrc # or ~/.zshrc
```
### "go: module github.com/host-uk/core: no matching versions"
### "go: module forge.lthn.ai/core/cli: no matching versions"
**Cause:** Go module proxy hasn't cached the latest version yet.
@ -26,7 +26,7 @@ source ~/.bashrc # or ~/.zshrc
```bash
# Bypass proxy
GOPROXY=direct go install github.com/host-uk/core/cmd/core@latest
GOPROXY=direct go install forge.lthn.ai/core/cli/cmd/core@latest
```
---
@ -340,7 +340,7 @@ This verifies all required tools are installed and configured.
If you've found a bug:
1. Check existing issues: https://github.com/host-uk/core/issues
1. Check existing issues: https://forge.lthn.ai/core/cli/issues
2. Create a new issue with:
- Core version (`core --version`)
- OS and architecture (`go env GOOS GOARCH`)

View file

@ -173,7 +173,7 @@ jobs:
go-version: '1.23'
- name: Install Core
run: go install github.com/host-uk/core/cmd/core@latest
run: go install forge.lthn.ai/core/cli/cmd/core@latest
- name: Build
run: core build --ci

View file

@ -2,9 +2,6 @@ go 1.25.5
use (
.
./cmd/bugseti
./cmd/core-app
./cmd/core-ide
./internal/bugseti
./internal/bugseti/updater
./internal/core-ide

View file

@ -1,6 +1,6 @@
[Unit]
Description=Core IDE Job Runner (Headless Mode)
Documentation=https://github.com/host-uk/core
Documentation=https://forge.lthn.ai/core/cli
After=network-online.target
Wants=network-online.target

View file

@ -1,6 +1,6 @@
[Unit]
Description=Core IDE Job Runner (User Mode)
Documentation=https://github.com/host-uk/core
Documentation=https://forge.lthn.ai/core/cli
After=network-online.target
Wants=network-online.target

View file

@ -2,7 +2,7 @@ site_name: Core Framework
site_url: https://core.help
site_description: 'A Web3 Framework for building Go desktop applications with Wails v3'
site_author: 'Snider'
repo_url: 'https://github.com/host-uk/core'
repo_url: 'https://forge.lthn.ai/core/cli'
repo_name: 'host-uk/core'
theme:

View file

@ -201,7 +201,7 @@ else
# Install from releases
ARCH=$(dpkg --print-architecture)
CORE_URL="https://github.com/host-uk/core/releases/latest/download/core-linux-${ARCH}"
CORE_URL="https://forge.lthn.ai/core/cli/releases/latest/download/core-linux-${ARCH}"
curl -fsSL "$CORE_URL" -o /tmp/core
chmod +x /tmp/core
@ -220,7 +220,7 @@ if [[ -z "${SKIP_GUI:-}" ]]; then
log_info "Installing core-ide..."
ARCH=$(dpkg --print-architecture)
IDE_URL="https://github.com/host-uk/core/releases/latest/download/core-ide-linux-${ARCH}.deb"
IDE_URL="https://forge.lthn.ai/core/cli/releases/latest/download/core-ide-linux-${ARCH}.deb"
curl -fsSL "$IDE_URL" -o /tmp/core-ide.deb
sudo dpkg -i /tmp/core-ide.deb || sudo apt-get install -f -y

View file

@ -491,7 +491,7 @@ In `pkg/build/config.go`, add to the `BuildConfig` struct:
```go
// Add import
import "github.com/host-uk/core/pkg/build/signing"
import "forge.lthn.ai/core/cli/pkg/build/signing"
// Add to BuildConfig struct after Targets field:
// Sign contains code signing configuration.
@ -590,7 +590,7 @@ import (
"fmt"
"runtime"
"github.com/host-uk/core/pkg/build"
"forge.lthn.ai/core/cli/pkg/build"
)
// SignBinaries signs macOS binaries in the artifacts list.
@ -727,7 +727,7 @@ buildCmd.Action(func() error {
Add to imports:
```go
"github.com/host-uk/core/pkg/build/signing"
"forge.lthn.ai/core/cli/pkg/build/signing"
```
**Step 4: Add signing after build, before archive**
@ -820,7 +820,7 @@ import (
"runtime"
"testing"
"github.com/host-uk/core/pkg/build"
"forge.lthn.ai/core/cli/pkg/build"
)
func TestSignBinaries_Good_SkipsNonDarwin(t *testing.T) {

View file

@ -19,17 +19,17 @@
**Step 1: Create go.mod**
```go
module github.com/host-uk/core/pkg/devops
module forge.lthn.ai/core/cli/pkg/devops
go 1.25
require (
github.com/host-uk/core/pkg/container v0.0.0
forge.lthn.ai/core/cli/pkg/container v0.0.0
golang.org/x/crypto v0.32.0
gopkg.in/yaml.v3 v3.0.1
)
replace github.com/host-uk/core/pkg/container => ../container
replace forge.lthn.ai/core/cli/pkg/container => ../container
```
**Step 2: Create devops.go with core types**
@ -45,7 +45,7 @@ import (
"path/filepath"
"runtime"
"github.com/host-uk/core/pkg/container"
"forge.lthn.ai/core/cli/pkg/container"
)
// DevOps manages the portable development environment.
@ -744,7 +744,7 @@ import (
"path/filepath"
"time"
"github.com/host-uk/core/pkg/devops/sources"
"forge.lthn.ai/core/cli/pkg/devops/sources"
)
// ImageManager handles image downloads and updates.
@ -1786,7 +1786,7 @@ import (
"strings"
"github.com/charmbracelet/lipgloss"
"github.com/host-uk/core/pkg/devops"
"forge.lthn.ai/core/cli/pkg/devops"
"github.com/leaanthony/clir"
)

View file

@ -19,7 +19,7 @@
**Step 1: Create go.mod for sdk package**
```go
module github.com/host-uk/core/pkg/sdk
module forge.lthn.ai/core/cli/pkg/sdk
go 1.25
@ -1390,7 +1390,7 @@ Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>"
// Add to sdk.go, replacing the stub Generate method
import (
"github.com/host-uk/core/pkg/sdk/generators"
"forge.lthn.ai/core/cli/pkg/sdk/generators"
)
// Generate generates SDKs for all configured languages.
@ -1494,7 +1494,7 @@ import (
"os"
"github.com/charmbracelet/lipgloss"
"github.com/host-uk/core/pkg/sdk"
"forge.lthn.ai/core/cli/pkg/sdk"
"github.com/leaanthony/clir"
)

View file

@ -108,7 +108,7 @@ import (
"context"
"fmt"
"github.com/host-uk/core/pkg/sdk"
"forge.lthn.ai/core/cli/pkg/sdk"
)
// SDKRelease holds the result of an SDK release.