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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion RELEASE-server-only-risk.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Task D prepares public plugin version 0.49.7. This file records source work,
not a published artifact. Runtime A/B/C shipped in CLI 0.49.6; a CLI version
number alone does not establish that these skill changes are installed.

Canonical sources are root `archdev/`, `tasks/`, `tasks-execute/` and `plan-collab/`.
Canonical sources are root `archdev/`, `tasks/`, `tasks-execute/`, `tasks-audit/` and `plan-collab/`.
Firstlanding commit `9b708c4338` removed the duplicate embedded skill bundles;
both CLIs now install the public repository archive. Regenerate plugins with
`npm run build` in `tools/plugin-gen`; never edit generated copies.
Expand Down
1 change: 1 addition & 0 deletions catalog/archdev.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
{ "name": "archdev", "path": "archdev" },
{ "name": "tasks", "path": "tasks" },
{ "name": "tasks-execute", "path": "tasks-execute" },
{ "name": "tasks-audit", "path": "tasks-audit" },
{ "name": "plan-collab", "path": "plan-collab" },
{ "name": "shots", "path": "shots" }
],
Expand Down
366 changes: 366 additions & 0 deletions plugins/antigravity/skills/tasks-audit/SKILL.md

Large diffs are not rendered by default.

178 changes: 178 additions & 0 deletions plugins/antigravity/skills/tasks-audit/scripts/bootstrap.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
$ErrorActionPreference = "Stop"

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

function Install-ArchDev {
# Reviewed installer bytes; update the revision and digest together.
$installerUrl = "https://raw.githubusercontent.com/ArchAstro/archdev/a530d21dd04eaed5742b8ad7daf9140a3ee2ef0f/install.ps1"
$installerSha256 = "f767834cb5aeae252b9c37f427818906ee82f9a11a71b9d4fd0ba0cd2e8086e1"
$installDir = if ($env:ARCHDEV_INSTALL_DIR) {
$env:ARCHDEV_INSTALL_DIR
} else {
Join-Path $env:LOCALAPPDATA "ArchDev\bin"
}
$installerRoot = Join-Path ([IO.Path]::GetTempPath()) ("archdev-install-" + [Guid]::NewGuid().ToString("N"))
New-Item -ItemType Directory -Path $installerRoot -ErrorAction Stop | Out-Null
$installerPath = Join-Path $installerRoot "install.ps1"
try {
Invoke-WebRequest -Uri $installerUrl -OutFile $installerPath
$actualHash = (Get-FileHash -LiteralPath $installerPath -Algorithm SHA256).Hash
if ($actualHash -ne $installerSha256) {
throw "ArchDev installer SHA256 mismatch; refusing to execute downloaded content."
}
& $installerPath -InstallDir $installDir -BaseUrl "" -SkipPathUpdate -SkipVerify:$false *> $null
if (-not $?) { throw "ArchDev installer failed" }
} finally {
Remove-Item $installerRoot -Recurse -Force -ErrorAction SilentlyContinue
}
return (Resolve-ArchDevPath (Join-Path $installDir "archdev.exe"))
}

$minVersion = [Version]"0.49.6"

function Test-Version([string]$Binary) {
$raw = (& $Binary --version 2>$null | Select-Object -First 1) -replace "[^0-9.]", ""
try {
return ([Version]$raw -ge $minVersion)
} catch {
return $false
}
}

function Test-Tasks([string]$Binary) {
if (-not (Test-Version $Binary)) { return $false }
$helpText = & $Binary tasks review update --help 2>$null
if ($LASTEXITCODE -ne 0 -or (($helpText -join "`n") -notmatch "(?m)^Usage: archdev tasks review update ")) { return $false }
$inboxHelp = & $Binary tasks inbox --help 2>$null
if ($LASTEXITCODE -ne 0 -or (($inboxHelp -join "`n") -notmatch "(?m)^Usage: archdev tasks inbox ")) { return $false }
$answerHelp = & $Binary tasks answer --help 2>$null
if ($LASTEXITCODE -ne 0 -or (($answerHelp -join "`n") -notmatch "--expected-version")) { return $false }
# This capability marks the release with consent-safe hook self-heal.
$hookHelp = & $Binary repo hook setup --help 2>$null
return ($LASTEXITCODE -eq 0 -and (($hookHelp -join "`n") -match "--local"))
}

# A Homebrew install owns its copy. Installing another one elsewhere leaves two
# binaries that are upgraded separately, and whichever comes first on PATH wins.
# Homebrew exists only on macOS and Linux; Windows keeps the installer path.
$brewFormula = "archastro/tools/archdev"

# Resolves every symlink in the path, including directory links such as
# Homebrew's opt link. A dangling keg link still yields its Cellar path.
function Get-RealPath([string]$Path) {
$pending = [Collections.Generic.List[string]]::new()
$pending.AddRange([string[]]@([IO.Path]::GetFullPath($Path).Split("/") | Where-Object { $_ }))
$real = ""
$hops = 0
while ($pending.Count -gt 0) {
$part = $pending[0]
$pending.RemoveAt(0)
if ($part -eq ".") { continue }
if ($part -eq "..") {
$real = $real.Substring(0, [Math]::Max(0, $real.LastIndexOf("/")))
continue
}
$next = "$real/$part"
$item = Get-Item -LiteralPath $next -Force -ErrorAction SilentlyContinue
if ($item -and $item.LinkTarget -and $hops -lt 32) {
$hops++
if ($item.LinkTarget.StartsWith("/")) { $real = "" }
$pending.InsertRange(0, [string[]]@($item.LinkTarget.Split("/") | Where-Object { $_ }))
continue
}
$real = $next
}
return $real
}

# Test-Path accepts a dangling link; a removed keg leaves one behind.
function Test-LinkedFile([string]$Path) {
return (Test-Path -LiteralPath (Get-RealPath $Path) -PathType Leaf)
}

function Test-HomebrewArchDev([string]$Path) {
return ((Get-RealPath $Path) -like "*/Cellar/archdev/*")
}

function Get-Brew {
return (Get-Command brew -CommandType Application -ErrorAction SilentlyContinue | Select-Object -First 1)
}

# The Homebrew-managed archdev on PATH, else <brew --prefix>/bin/archdev when
# Homebrew links it there, even if another copy comes first on PATH.
function Find-HomebrewArchDev($Candidate) {
if ($env:OS -eq "Windows_NT") { return $null }
if ($Candidate -and (Test-HomebrewArchDev $Candidate)) { return $Candidate }
$brew = Get-Brew
if (-not $brew) { return $null }
$prefix = @(& $brew.Source --prefix 2>$null) | Select-Object -First 1
if ($LASTEXITCODE -ne 0 -or -not $prefix) { return $null }
$linked = Join-Path $prefix "bin/archdev"
if ((Get-Item -LiteralPath $linked -Force -ErrorAction SilentlyContinue) -and (Test-HomebrewArchDev $linked)) {
return $linked
}
return $null
}

# Repairs a Homebrew-managed archdev with Homebrew rather than a second copy:
# upgrade when it reports a too-old version; reinstall when the binary is
# missing, crashes, or a current version fails the capability probes, where
# upgrade would be a no-op.
function Update-HomebrewArchDev([string]$Binary) {
# The brew that owns this keg; another prefix's brew could install a second copy.
$real = Get-RealPath $Binary
$brew = $real.Substring(0, $real.IndexOf("/Cellar/archdev/")) + "/bin/brew"
if (-not (Test-Path -LiteralPath $brew -PathType Leaf)) {
throw "ArchDev at $Binary is managed by Homebrew, but $brew is missing. Run: brew upgrade $brewFormula. Not installing a second copy of ArchDev."
}
$version = $null
if (Test-LinkedFile $Binary) {
$raw = (& $Binary --version 2>$null | Select-Object -First 1) -replace "[^0-9.]", ""
try { $version = [Version]$raw } catch { $version = $null }
}
# Only a readable, too-old version needs an upgrade; anything else is broken.
$action = if ($version -and $version -lt $minVersion) { "upgrade" } else { "reinstall" }
[Console]::Error.WriteLine("Updating Homebrew-managed ArchDev at ${Binary}: brew $action $brewFormula")
# Callers read stdout as the archdev path, so brew's progress goes to stderr.
& $brew $action $brewFormula | ForEach-Object { [Console]::Error.WriteLine($_) }
if ($LASTEXITCODE -ne 0) {
throw "brew $action $brewFormula failed. ArchDev at $Binary is managed by Homebrew; not installing a second copy."
}
}

$existing = Get-Command archdev -ErrorAction SilentlyContinue
$candidate = if ($existing) { Resolve-ArchDevPath $existing.Source } else { $null }
$homebrewArchDev = Find-HomebrewArchDev $candidate
if ($homebrewArchDev) {
$archdev = $homebrewArchDev
if ($candidate -and $candidate -ne $archdev) {
[Console]::Error.WriteLine("Using Homebrew-managed ArchDev at $archdev; $candidate comes first on PATH.")
}
if (-not (Test-LinkedFile $archdev) -or -not (Test-Tasks $archdev)) {
Update-HomebrewArchDev $archdev
}
} else {
$archdev = if ($candidate) { $candidate } else { Install-ArchDev }
if (-not (Test-Tasks $archdev)) {
[Console]::Error.WriteLine("Updating ArchDev: task audits require 0.49.6+, tasks inbox and answer, web review commands, and consent-safe repository hook support.")
$archdev = Install-ArchDev
}
}

if ($homebrewArchDev -and -not (Test-LinkedFile $archdev)) {
throw "Homebrew did not leave an executable at $archdev; not installing a second copy."
}
if (-not (Test-Path -LiteralPath $archdev -PathType Leaf)) {
throw "ArchDev installer did not create an executable at $archdev"
}
& $archdev --version *> $null
if ($LASTEXITCODE -ne 0) { throw "ArchDev version verification failed" }
if (-not (Test-Tasks $archdev)) {
if ($homebrewArchDev) { throw "Homebrew-managed ArchDev at $archdev still fails the capability check after brew; not installing a second copy." }
throw "Installed ArchDev lacks tasks inbox/answer, Tasks web review commands, or consent-safe repository hook support on 0.49.6+"
}

# Tasks executable resolution does not authorize changing hook configuration.
Write-Output $archdev
201 changes: 201 additions & 0 deletions plugins/antigravity/skills/tasks-audit/scripts/bootstrap.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
#!/usr/bin/env bash

set -euo pipefail

installer_revision="a530d21dd04eaed5742b8ad7daf9140a3ee2ef0f"
installer_url="https://raw.githubusercontent.com/ArchAstro/archdev/${installer_revision}/install.sh"
installer_sha256="f838ca858f7db526cdf2a2697001ae1d404edf3df93617e525efa9d171be7e64"
install_dir="${ARCHDEV_INSTALL_DIR:-$HOME/.local/bin}"
min_version="0.49.6"

absolute_path() {
local candidate="$1"
local directory
directory="$(cd -P "$(dirname "$candidate")" && pwd)"
printf '%s/%s\n' "$directory" "$(basename "$candidate")"
}

install_archdev() (
# Keep downloaded code private and verify its reviewed bytes before execution.
umask 077
installer_file="$(mktemp "${TMPDIR:-/tmp}/archdev-installer.XXXXXX")" || {
printf 'Could not create a private ArchDev installer file.\n' >&2
exit 1
}
trap 'rm -f "$installer_file"' EXIT
trap 'exit 1' HUP INT TERM
if ! curl --fail --silent --show-error --location \
--proto '=https' --proto-redir '=https' \
--output "$installer_file" "$installer_url"; then
printf 'Could not download the pinned ArchDev installer.\n' >&2
exit 1
fi
if command -v sha256sum >/dev/null 2>&1; then
actual_sha256="$(sha256sum "$installer_file")" || {
printf 'Could not hash the ArchDev installer.\n' >&2
exit 1
}
elif command -v shasum >/dev/null 2>&1; then
actual_sha256="$(shasum -a 256 "$installer_file")" || {
printf 'Could not hash the ArchDev installer.\n' >&2
exit 1
}
else
printf 'ArchDev installer verification requires sha256sum or shasum.\n' >&2
exit 1
fi
if [[ "${actual_sha256%% *}" != "$installer_sha256" ]]; then
printf 'ArchDev installer SHA-256 mismatch; refusing to execute it.\n' >&2
exit 1
fi
if ! ARCHDEV_INSTALL_DIR="$install_dir" \
ARCHDEV_RELEASE_BASE_URL= \
ARCHDEV_INSTALL_SKIP_VERIFY=false \
ARCHDEV_INSTALL_SKIP_PATH_UPDATE=true \
ARCHDEV_INSTALL_SKIP_COMPLETIONS=true \
bash "$installer_file" >&2; then
printf 'Verified ArchDev installer failed.\n' >&2
exit 1
fi
)

version_ok() {
local raw version
raw="$("$1" --version 2>/dev/null | head -n 1)"
version="$(printf '%s' "$raw" | grep -Eo '[0-9]+\.[0-9]+\.[0-9]+' | head -n 1)"
[[ -n "$version" ]] || return 1
[[ "$(printf '%s\n%s\n' "$min_version" "$version" | sort -V | head -n 1)" == "$min_version" ]]
}

supports_tasks() {
version_ok "$1" &&
"$1" tasks review update --help 2>/dev/null | grep -F 'Usage: archdev tasks review update ' >/dev/null &&
# Auditing reads the human-attention inbox and answers paused Tasks.
"$1" tasks inbox --help 2>/dev/null | grep -F 'Usage: archdev tasks inbox ' >/dev/null &&
"$1" tasks answer --help 2>/dev/null | grep -F -- '--expected-version' >/dev/null &&
# This capability marks the release with consent-safe hook self-heal.
"$1" repo hook setup --help 2>/dev/null | grep -F -- '--local' >/dev/null
}

# A Homebrew install owns its copy. Installing another one elsewhere leaves two
# binaries that are upgraded separately, and whichever comes first on PATH wins.
brew_formula="archastro/tools/archdev"

# Follows symlinks one hop at a time; macOS before 12.3 has no readlink -f.
real_path() {
local path="$1" link hops=0 directory
while [[ -L "$path" && "$hops" -lt 32 ]]; do
link="$(readlink "$path")" || break
case "$link" in
/*) path="$link" ;;
*) path="$(dirname "$path")/$link" ;;
esac
hops=$((hops + 1))
done
# A dangling keg link still names its Cellar path.
directory="$(cd -P "$(dirname "$path")" 2>/dev/null && pwd)" || {
printf '%s\n' "$path"
return 0
}
printf '%s/%s\n' "$directory" "$(basename "$path")"
}

is_homebrew_archdev() {
case "$(real_path "$1")" in
*/Cellar/archdev/*) return 0 ;;
esac
return 1
}

# The Homebrew-managed archdev on PATH, else <brew --prefix>/bin/archdev when
# Homebrew links it there, even if another copy comes first on PATH.
find_homebrew_archdev() {
local candidate="$1" prefix
if [[ -n "$candidate" ]] && is_homebrew_archdev "$candidate"; then
# Keep the link path: an upgrade removes the versioned keg behind it.
printf '%s/%s\n' "$(cd "$(dirname "$candidate")" && pwd -L)" "$(basename "$candidate")"
return 0
fi
command -v brew >/dev/null 2>&1 || return 1
prefix="$(brew --prefix 2>/dev/null)" || return 1
[[ -n "$prefix" ]] || return 1
if [[ -e "$prefix/bin/archdev" || -L "$prefix/bin/archdev" ]] &&
is_homebrew_archdev "$prefix/bin/archdev"; then
printf '%s/bin/archdev\n' "$prefix"
return 0
fi
return 1
}

# Repairs a Homebrew-managed archdev with Homebrew rather than a second copy:
# upgrade when it reports a too-old version; reinstall when the binary is
# missing, crashes, or a current version fails the capability probes, where
# upgrade would be a no-op.
update_homebrew_archdev() {
local binary="$1" action=reinstall brew version=""
# The brew that owns this keg; another prefix's brew could install a second copy.
brew="$(real_path "$binary")"
brew="${brew%%/Cellar/archdev/*}/bin/brew"
if [[ ! -x "$brew" ]]; then
printf 'ArchDev at %s is managed by Homebrew, but %s is missing. Run: brew upgrade %s\n' "$binary" "$brew" "$brew_formula" >&2
printf 'Not installing a second copy of ArchDev.\n' >&2
return 1
fi
if [[ -x "$binary" ]]; then
version="$("$binary" --version 2>/dev/null | head -n 1 | grep -Eo '[0-9]+\.[0-9]+\.[0-9]+' | head -n 1 || true)"
fi
# Only a readable, too-old version needs an upgrade; anything else is broken.
if [[ -n "$version" ]] && ! version_ok "$binary"; then
action=upgrade
fi
printf 'Updating Homebrew-managed ArchDev at %s: brew %s %s\n' "$binary" "$action" "$brew_formula" >&2
if ! "$brew" "$action" "$brew_formula" >&2; then
printf 'brew %s %s failed. ArchDev at %s is managed by Homebrew; not installing a second copy.\n' "$action" "$brew_formula" "$binary" >&2
return 1
fi
}

candidate="$(command -v archdev 2>/dev/null || true)"
homebrew_archdev="$(find_homebrew_archdev "$candidate" || true)"
if [[ -n "$homebrew_archdev" ]]; then
executable="$homebrew_archdev"
if [[ -n "$candidate" && "$(absolute_path "$candidate")" != "$executable" ]]; then
printf 'Using Homebrew-managed ArchDev at %s; %s comes first on PATH.\n' "$executable" "$(absolute_path "$candidate")" >&2
fi
if ! supports_tasks "$executable"; then
update_homebrew_archdev "$executable" || exit 1
fi
else
if [[ -n "$candidate" ]]; then
executable="$(absolute_path "$candidate")"
else
install_archdev || exit 1
executable="$(absolute_path "$install_dir/archdev")"
fi
if ! supports_tasks "$executable"; then
printf 'Updating ArchDev: task audits require 0.49.6+, tasks inbox and answer, web review commands, and consent-safe repository hook support.\n' >&2
install_archdev || exit 1
executable="$(absolute_path "$install_dir/archdev")"
fi
fi

[[ -x "$executable" ]] || {
if [[ -n "$homebrew_archdev" ]]; then
printf 'Homebrew did not leave an executable at %s; not installing a second copy.\n' "$executable" >&2
else
printf 'ArchDev installer did not create an executable at %s\n' "$executable" >&2
fi
exit 1
}

"$executable" --version >&2
supports_tasks "$executable" || {
if [[ -n "$homebrew_archdev" ]]; then
printf 'Homebrew-managed ArchDev at %s still fails the capability check after brew; not installing a second copy.\n' "$executable" >&2
fi
printf 'Installed ArchDev lacks tasks inbox/answer, Tasks web review commands, or consent-safe repository hook support.\n' >&2
exit 1
}

# Executable resolution does not authorize changing hook configuration.
printf '%s\n' "$executable"
Loading
Loading