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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions .github/workflows/installer-smoke-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,19 @@ jobs:
sleep 1
done
exit 1
- name: Install CLI and dashboard
- name: Install CLI
env:
ARCHDEV_RELEASE_BASE_URL: http://127.0.0.1:8123
ARCHDEV_VERSION: 0.31.0
HOME: ${{ runner.temp }}/home
SHELL: /bin/${{ matrix.shell_name }}
ARCHDEV_INSTALL_DIR: ${{ runner.temp }}/home/.local/bin
run: |
mkdir -p "$HOME"
mkdir -p "$HOME" "$ARCHDEV_INSTALL_DIR"
touch "$ARCHDEV_INSTALL_DIR/archdev-dashboard"
./install.sh
test "$("$HOME/.local/bin/archdev" --version)" = 0.31.0
test -x "$HOME/.local/bin/archdev-dashboard"
test ! -e "$HOME/.local/bin/archdev-dashboard"
test -f "$HOME/${{ matrix.completion_file }}"
- name: Stop fixture server
if: always()
Expand All @@ -70,14 +71,15 @@ jobs:
$server = Start-Process python -ArgumentList "-m", "http.server", "8123", "--bind", "127.0.0.1" -WorkingDirectory "$env:RUNNER_TEMP\release" -PassThru
$server.Id | Set-Content "$env:RUNNER_TEMP\server.pid"
Start-Sleep -Seconds 2
- name: Install CLI and dashboard
- name: Install CLI
shell: pwsh
run: |
New-Item -ItemType Directory -Path "$env:RUNNER_TEMP\bin" -Force | Out-Null
New-Item -ItemType File -Path "$env:RUNNER_TEMP\bin\archdev-dashboard.exe" -Force | Out-Null
./install.ps1 -Version 0.31.0 -BaseUrl http://127.0.0.1:8123 -InstallDir "$env:RUNNER_TEMP\bin" -SkipPathUpdate
$cliVersion = & "$env:RUNNER_TEMP\bin\archdev.exe" --version
if ($cliVersion.Trim() -ne "0.31.0") { throw "archdev.exe version mismatch" }
$sidecarVersion = & "$env:RUNNER_TEMP\bin\archdev-dashboard.exe" --version
if ($sidecarVersion.Trim() -ne "0.31.0") { throw "archdev-dashboard.exe is not runnable" }
if (Test-Path "$env:RUNNER_TEMP\bin\archdev-dashboard.exe") { throw "retired archdev-dashboard.exe was installed" }
- name: Stop fixture server
if: always()
shell: pwsh
Expand Down
40 changes: 34 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,40 @@ curl -fsSL https://raw.githubusercontent.com/ArchAstro/archdev/main/install.sh |
irm https://raw.githubusercontent.com/ArchAstro/archdev/main/install.ps1 | iex
```

The release archive installs both `archdev` and its `archdev-dashboard`
sidecar. The Unix installer also configures Bash, Zsh, or Fish completions for
the active shell.
The release archive installs `archdev`. The Unix installer also configures
Bash, Zsh, or Fish completions for the active shell.

## Install one domain as an agent skill

ArchDev's domain skills are independently installable. Each skill bootstraps a
compatible ArchDev CLI on first use and configures only the capability it owns.

| Skill | Use it for | ArchDev login | Local runner |
| --- | --- | --- | --- |
| `tasks` | Plans, dependencies, claims, and fenced completion | Required for shared Tasks | Not installed |
| `jobs` | Exact-commit pipelines, logs, retries, and repository automation | Not required | Installed only by `jobs setup` |

Install a skill for your machine:

```bash
npx skills add ArchAstro/archdev --skill tasks --global --yes
npx skills add ArchAstro/archdev --skill jobs --global --yes
```

Or omit `--global` to install into the current repository:

```bash
npx skills add ArchAstro/archdev --skill tasks --yes
npx skills add ArchAstro/archdev --skill jobs --yes
```

The Tasks skill never runs umbrella setup or installs the Jobs runner. The Jobs
skill does not log in or configure a model provider; it runs `jobs setup` only
when durable local automation is requested.

## Repository scope

This repository owns public distribution: installers, release metadata, and
downloadable binaries. ArchDev's source and release build stay in firstlanding.
Report installation and packaging problems with a GitHub issue here.
This repository owns public distribution: installers, skills, release metadata,
and downloadable binaries. ArchDev's source and release build stay in
firstlanding. Report installation and packaging problems with a GitHub issue
here.
11 changes: 5 additions & 6 deletions install.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,10 @@ try {
$ActualHash = (Get-FileHash $ArchivePath -Algorithm SHA256).Hash
if ($ActualHash.ToLowerInvariant() -ne $ExpectedHash.ToLowerInvariant()) { throw "Checksum mismatch for $AssetName" }
Expand-Archive -Path $ArchivePath -DestinationPath $ExtractDir -Force
foreach ($Name in @("archdev.exe", "archdev-dashboard.exe")) {
$Source = Join-Path $ExtractDir $Name
if (-not (Test-Path $Source)) { throw "Archive is missing $Name" }
Copy-Item $Source (Join-Path $InstallDir $Name) -Force
}
$Source = Join-Path $ExtractDir "archdev.exe"
if (-not (Test-Path $Source)) { throw "Archive is missing archdev.exe" }
Copy-Item $Source (Join-Path $InstallDir "archdev.exe") -Force
Remove-Item (Join-Path $InstallDir "archdev-dashboard.exe") -Force -ErrorAction SilentlyContinue
if (-not $SkipPathUpdate) {
$CurrentUserPath = [Environment]::GetEnvironmentVariable("Path", "User")
$Entries = if ($CurrentUserPath) { $CurrentUserPath -split ';' } else { @() }
Expand All @@ -69,7 +68,7 @@ try {
}
}
if (-not $SkipVerify) { & (Join-Path $InstallDir "archdev.exe") --version }
Write-Host "Installed archdev and archdev-dashboard to $InstallDir"
Write-Host "Installed archdev to $InstallDir"
} finally {
Remove-Item $TempRoot -Recurse -Force -ErrorAction SilentlyContinue
}
14 changes: 7 additions & 7 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ set -euo pipefail
OWNER="ArchAstro"
REPO="archdev"
BINARY_NAME="archdev"
SIDECAR_NAME="archdev-dashboard"
INSTALL_DIR="${ARCHDEV_INSTALL_DIR:-}"
REQUESTED_VERSION="${ARCHDEV_VERSION:-latest}"
RELEASE_BASE_URL="${ARCHDEV_RELEASE_BASE_URL:-}"
Expand Down Expand Up @@ -112,7 +111,6 @@ asset_url=${ASSET_URL}
checksum_url=${CHECKSUM_URL}
install_dir=${INSTALL_DIR}
binary_path=${INSTALL_DIR}/${BINARY_NAME}
sidecar_path=${INSTALL_DIR}/${SIDECAR_NAME}
EOF
exit 0
fi
Expand Down Expand Up @@ -146,10 +144,12 @@ fi

mkdir -p "$EXTRACT_DIR"
tar -xzf "$ASSET_PATH" -C "$EXTRACT_DIR"
for executable in "$BINARY_NAME" "$SIDECAR_NAME"; do
[[ -f "$EXTRACT_DIR/$executable" ]] || { printf 'Archive is missing %s\n' "$executable" >&2; exit 1; }
install -m 0755 "$EXTRACT_DIR/$executable" "$INSTALL_DIR/$executable"
done
[[ -f "$EXTRACT_DIR/$BINARY_NAME" ]] || {
printf 'Archive is missing %s\n' "$BINARY_NAME" >&2
exit 1
}
install -m 0755 "$EXTRACT_DIR/$BINARY_NAME" "$INSTALL_DIR/$BINARY_NAME"
rm -f "$INSTALL_DIR/archdev-dashboard"

append_once() {
local file="$1" line="$2"
Expand Down Expand Up @@ -198,4 +198,4 @@ fi
if [[ "$SKIP_VERIFY" != true ]]; then
"$INSTALL_DIR/$BINARY_NAME" --version
fi
printf 'Installed %s and %s to %s\n' "$BINARY_NAME" "$SIDECAR_NAME" "$INSTALL_DIR"
printf 'Installed %s to %s\n' "$BINARY_NAME" "$INSTALL_DIR"
8 changes: 2 additions & 6 deletions scripts/create-unix-fixtures.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,8 @@ if [ "\${1:-}" = "--version" ]; then printf '%s\n' '$VERSION'; exit 0; fi
if [ "\${1:-}" = "completion" ]; then printf '# completion for %s\n' "\${2:-unknown}"; exit 0; fi
exit 0
EOF
cat >"$fixture/archdev-dashboard" <<'EOF'
#!/usr/bin/env sh
exit 0
EOF
chmod +x "$fixture/archdev" "$fixture/archdev-dashboard"
tar -C "$fixture" -czf "$OUTPUT_DIR/archdev-$target.tar.gz" archdev archdev-dashboard
chmod +x "$fixture/archdev"
tar -C "$fixture" -czf "$OUTPUT_DIR/archdev-$target.tar.gz" archdev
rm -rf "$fixture"
done
(
Expand Down
3 changes: 1 addition & 2 deletions scripts/create-windows-fixtures.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ foreach ($Arch in @("arm64", "x64")) {
$Fixture = Join-Path ([IO.Path]::GetTempPath()) ("archdev-fixture-" + [Guid]::NewGuid().ToString("N"))
New-Item -ItemType Directory -Path $Fixture | Out-Null
Copy-Item $FixtureBinary (Join-Path $Fixture "archdev.exe")
Copy-Item (Join-Path $Fixture "archdev.exe") (Join-Path $Fixture "archdev-dashboard.exe")
Compress-Archive -Path (Join-Path $Fixture "archdev.exe"), (Join-Path $Fixture "archdev-dashboard.exe") -DestinationPath (Join-Path $OutputDir "archdev-windows-$Arch.zip")
Compress-Archive -Path (Join-Path $Fixture "archdev.exe") -DestinationPath (Join-Path $OutputDir "archdev-windows-$Arch.zip")
Remove-Item $Fixture -Recurse -Force
}
Remove-Item $FixtureBinaryRoot -Recurse -Force
Expand Down
141 changes: 141 additions & 0 deletions skills/jobs/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
---
name: jobs
description: Use when someone asks to run durable repository automation, execute a pipeline against an exact commit, inspect or retry a job, read persisted logs, manage the local runner, submit or sync a repository, automate review delivery, or recover conflicts through ArchDev Jobs.
---

# Jobs

ArchDev Jobs runs repository automation in isolated worktrees against exact
commits. Jobs is local: do not authenticate an ArchDev user or configure a model
provider unless a pipeline step independently requires one.

## Start

Resolve the absolute path of this loaded `SKILL.md` from the host's skill
inventory. Do not derive it from the current repository. Bootstrap ArchDev from
that directory.

Unix:

```sh
skill_file="/absolute/path/to/loaded/jobs/SKILL.md"
skill_dir="$(cd -P "$(dirname "$skill_file")" && pwd)"
archdev="$(bash "$skill_dir/scripts/bootstrap.sh")"
```

Windows PowerShell:

```powershell
$skillFile = 'C:\absolute\path\to\loaded\jobs\SKILL.md'
$skillDir = Split-Path -Parent (Resolve-Path -LiteralPath $skillFile)
$archdev = & powershell -NoProfile -File "$skillDir\scripts\bootstrap.ps1"
```

If bootstrap fails, report its error and point to the official ArchDev
installer. Run all repository commands from the intended Git checkout.

Inspect configuration and runner state before changing either:

```sh
"$archdev" check
"$archdev" --json jobs runner status
"$archdev" --json jobs list
```

A stopped or absent runner is not an authentication failure. These inspection
commands may return nonzero before first setup; when durable work was requested,
continue with `jobs setup`. Do not run `archdev auth login`, `archdev agents
setup`, provider login, or umbrella setup for Jobs.

## Choose foreground or durable execution

Use `--here` only when the user asked to run a pipeline immediately in the
current checkout. This can mutate the checkout and does not create durable job
history:

```sh
"$archdev" jobs run "<pipeline>" --here
```

For work that must survive the terminal, first enable local automation. This
installs or starts the per-user runner and registers the current repository; it
does not configure model access:

```sh
"$archdev" jobs setup
```

Commit the intended input before submission. A durable named run captures the
current committed `HEAD`, ignores later working-tree edits, and disables
automatic publication unless the pipeline explicitly publishes:

```sh
"$archdev" --json jobs run "<pipeline>"
```

Keep the returned job ID.

## Observe and control jobs

```sh
"$archdev" --json jobs show "<job-id>"
"$archdev" jobs logs "<job-id>"
"$archdev" --json jobs cancel "<job-id>"
"$archdev" --json jobs retry "<job-id>"
```

Retry only failed non-PR jobs. Pull-request retries belong to the PR watcher.
Cancellation can be asynchronous; re-read the job until it reaches a terminal
state rather than reporting success from the request alone.

Ordinary cleanup targets terminal jobs:

```sh
"$archdev" --json jobs clean --status succeeded failed cancelled
```

`jobs clean --all` stops the runner and can permanently delete active jobs and
owned artifacts. Run it only after explicit user approval of the exact cleanup.

## Runner lifecycle

Use the runner namespace instead of the deprecated `daemon` commands:

```sh
"$archdev" --json jobs runner doctor
"$archdev" jobs runner start
"$archdev" jobs runner stop
"$archdev" jobs runner uninstall
```

`runner uninstall` removes the native service but preserves repositories, job
history, reports, and project configuration. Run stop or uninstall only when the
user requested that local service change.

## Repository delivery

`jobs setup` normally enables the current repository. Use the explicit
repository lifecycle when diagnosing or scripting it:

```sh
"$archdev" jobs repo enable
"$archdev" jobs repo submit
"$archdev" jobs repo sync
"$archdev" jobs repo disable
```

`repo submit` sends committed `HEAD` to the private runner and can rebase the
submitted branch according to repository policy. Check `git status`, the
current branch, and the intended commit first. `repo sync` updates a clean
source checkout only when the recorded identity fences match.

For event-shaped diagnostics, submit only a payload whose schema the selected
binding expects:

```sh
"$archdev" --json jobs trigger one_off --payload '{"prompt":"Run the focused verification"}'
```

Never invent successful logs, publication, or settlement. Inspect the terminal
job, attempts, and persisted output. Do not expose private worktree paths,
credentials, or customer data in prompts, payloads, or reports.
73 changes: 73 additions & 0 deletions skills/jobs/scripts/bootstrap.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
$ErrorActionPreference = "Stop"

function Resolve-ArchDevPath([string]$Candidate) {
return (Resolve-Path -LiteralPath $Candidate).Path
}

function Install-ArchDev {
$installDir = if ($env:ARCHDEV_INSTALL_DIR) {
$env:ARCHDEV_INSTALL_DIR
} else {
Join-Path $env:LOCALAPPDATA "ArchDev\bin"
}
$requestedVersion = if ($env:ARCHDEV_VERSION) { $env:ARCHDEV_VERSION } else { "latest" }
$baseUrl = if ($env:ARCHDEV_RELEASE_BASE_URL) {
$env:ARCHDEV_RELEASE_BASE_URL.TrimEnd('/')
} elseif ($requestedVersion -eq "latest") {
"https://github.com/ArchAstro/archdev/releases/latest/download"
} else {
$tag = if ($requestedVersion.StartsWith("v")) { $requestedVersion } else { "v$requestedVersion" }
"https://github.com/ArchAstro/archdev/releases/download/$tag"
}
$architecture = switch ($env:PROCESSOR_ARCHITECTURE.ToLowerInvariant()) {
"amd64" { "x64" }
"arm64" { "arm64" }
default { throw "Unsupported architecture: $env:PROCESSOR_ARCHITECTURE" }
}
$asset = "archdev-windows-$architecture.zip"
$tempRoot = Join-Path ([IO.Path]::GetTempPath()) ("archdev-skill-" + [Guid]::NewGuid().ToString("N"))
$archive = Join-Path $tempRoot $asset
$checksums = Join-Path $tempRoot "SHA256SUMS"
$extract = Join-Path $tempRoot "extract"
try {
New-Item -ItemType Directory -Path $extract -Force | Out-Null
Invoke-WebRequest -Uri "$baseUrl/$asset" -OutFile $archive
Invoke-WebRequest -Uri "$baseUrl/SHA256SUMS" -OutFile $checksums
$expectedLine = Select-String -Path $checksums -Pattern ([Regex]::Escape($asset) + '$') | Select-Object -First 1
if (-not $expectedLine) { throw "Checksum missing for $asset" }
$expected = ($expectedLine.Line -split '\s+')[0]
$actual = (Get-FileHash $archive -Algorithm SHA256).Hash
if ($actual.ToLowerInvariant() -ne $expected.ToLowerInvariant()) {
throw "Checksum mismatch for $asset"
}
Expand-Archive -Path $archive -DestinationPath $extract -Force
$source = Join-Path $extract "archdev.exe"
if (-not (Test-Path -LiteralPath $source -PathType Leaf)) {
throw "Archive is missing archdev.exe"
}
New-Item -ItemType Directory -Path $installDir -Force | Out-Null
Copy-Item $source (Join-Path $installDir "archdev.exe") -Force
Remove-Item (Join-Path $installDir "archdev-dashboard.exe") -Force -ErrorAction SilentlyContinue
} finally {
Remove-Item $tempRoot -Recurse -Force -ErrorAction SilentlyContinue
}
return (Resolve-ArchDevPath (Join-Path $installDir "archdev.exe"))
}

$existing = Get-Command archdev -ErrorAction SilentlyContinue
$archdev = if ($existing) { Resolve-ArchDevPath $existing.Source } else { Install-ArchDev }

& $archdev jobs setup --help *> $null
if ($LASTEXITCODE -ne 0) {
[Console]::Error.WriteLine("Updating ArchDev because this version lacks the Jobs domain.")
$archdev = Install-ArchDev
}

if (-not (Test-Path -LiteralPath $archdev -PathType Leaf)) {
throw "ArchDev installation did not create an executable at $archdev"
}
& $archdev --version *> $null
if ($LASTEXITCODE -ne 0) { throw "ArchDev version verification failed" }
& $archdev jobs setup --help *> $null
if ($LASTEXITCODE -ne 0) { throw "Installed ArchDev does not provide the Jobs domain" }
Write-Output $archdev
Loading