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 .github/workflows/agent-architecture-review.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
ANTHROPIC_BASE_URL: ${{ secrets.LITELLM_BASE_URL }}
ANTHROPIC_AUTH_TOKEN: ${{ secrets.LITELLM_MASTER_KEY }}
steps:
- uses: arndvs/sandcastle-hub/actions/agent-run@main
- uses: arndvs/ctrlshft-hub/actions/agent-run@main
with:
workflow: architecture-review
ref: main
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/agent-check-stale-prs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
ANTHROPIC_BASE_URL: ${{ secrets.LITELLM_BASE_URL }}
ANTHROPIC_AUTH_TOKEN: ${{ secrets.LITELLM_MASTER_KEY }}
steps:
- uses: arndvs/sandcastle-hub/actions/agent-run@main
- uses: arndvs/ctrlshft-hub/actions/agent-run@main
with:
workflow: check-stale-prs
ref: main
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/agent-fix-pr-feedback.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:

fix-pr-feedback:
if: github.event.label.name == 'agent:fix' && github.event.pull_request.head.repo.full_name == github.repository
uses: arndvs/sandcastle-hub/.github/workflows/reusable-fix-pr-feedback.yml@main
uses: arndvs/ctrlshft-hub/.github/workflows/reusable-fix-pr-feedback.yml@main
with:
pr-number: ${{ github.event.pull_request.number }}
secrets: inherit
2 changes: 1 addition & 1 deletion .github/workflows/agent-implement-issue.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ permissions:
jobs:
implement:
if: github.event.label.name == 'agent:implement'
uses: arndvs/sandcastle-hub/.github/workflows/reusable-implement-issue.yml@main
uses: arndvs/ctrlshft-hub/.github/workflows/reusable-implement-issue.yml@main
with:
issue-number: ${{ github.event.issue.number }}
issue-title: ${{ github.event.issue.title }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/agent-implement-prd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ permissions:
jobs:
implement-prd:
if: github.event.label.name == 'agent:implement-prd'
uses: arndvs/sandcastle-hub/.github/workflows/reusable-implement-prd.yml@main
uses: arndvs/ctrlshft-hub/.github/workflows/reusable-implement-prd.yml@main
with:
prd-number: ${{ github.event.issue.number }}
prd-title: ${{ github.event.issue.title }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/agent-keep-tests-tight.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ permissions:

jobs:
keep-tests-tight:
uses: arndvs/sandcastle-hub/.github/workflows/reusable-keep-tests-tight.yml@main
uses: arndvs/ctrlshft-hub/.github/workflows/reusable-keep-tests-tight.yml@main
secrets: inherit
2 changes: 1 addition & 1 deletion .github/workflows/agent-merge-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:

merge:
if: github.event.label.name == 'agent:merge' && github.event.pull_request.head.repo.full_name == github.repository
uses: arndvs/sandcastle-hub/.github/workflows/reusable-merge-pr.yml@main
uses: arndvs/ctrlshft-hub/.github/workflows/reusable-merge-pr.yml@main
with:
pr-number: ${{ github.event.pull_request.number }}
secrets: inherit
2 changes: 1 addition & 1 deletion .github/workflows/agent-plan-issue.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
run: |
gh issue edit "$ISSUE_NUMBER" --remove-label "agent:plan" -R ${{ github.repository }} || true
gh issue edit "$ISSUE_NUMBER" --add-label "agent:in-progress" -R ${{ github.repository }}
- uses: arndvs/sandcastle-hub/actions/agent-run@main
- uses: arndvs/ctrlshft-hub/actions/agent-run@main
with:
workflow: plan-issue
ref: main
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/agent-promote-queued.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
run: |
gh issue edit "$ISSUE_NUMBER" --remove-label "agent:promote" -R ${{ github.repository }} || true
gh issue edit "$ISSUE_NUMBER" --add-label "agent:in-progress" -R ${{ github.repository }}
- uses: arndvs/sandcastle-hub/actions/agent-run@main
- uses: arndvs/ctrlshft-hub/actions/agent-run@main
with:
workflow: promote-queued
ref: main
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/agent-repo-hygiene.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
ANTHROPIC_BASE_URL: ${{ secrets.LITELLM_BASE_URL }}
ANTHROPIC_AUTH_TOKEN: ${{ secrets.LITELLM_MASTER_KEY }}
steps:
- uses: arndvs/sandcastle-hub/actions/agent-run@main
- uses: arndvs/ctrlshft-hub/actions/agent-run@main
with:
workflow: repo-hygiene
ref: main
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/agent-review-issue.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
run: |
gh issue edit "$ISSUE_NUMBER" --remove-label "agent:review" -R ${{ github.repository }} || true
gh issue edit "$ISSUE_NUMBER" --add-label "agent:in-progress" -R ${{ github.repository }}
- uses: arndvs/sandcastle-hub/actions/agent-run@main
- uses: arndvs/ctrlshft-hub/actions/agent-run@main
with:
workflow: review-issue
ref: main
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/agent-update-branch.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:

update-branch:
if: github.event.label.name == 'agent:update-branch' && github.event.pull_request.head.repo.full_name == github.repository
uses: arndvs/sandcastle-hub/.github/workflows/reusable-update-branch.yml@main
uses: arndvs/ctrlshft-hub/.github/workflows/reusable-update-branch.yml@main
with:
pr-number: ${{ github.event.pull_request.number }}
branch: ${{ github.event.pull_request.head.ref }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/labels-sync.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
curl -fsSL \
-H "Authorization: Bearer $GH_TOKEN" \
-H "Accept: application/vnd.github.raw" \
"https://api.github.com/repos/arndvs/sandcastle-hub/contents/templates/labels.json?ref=main" \
"https://api.github.com/repos/arndvs/ctrlshft-hub/contents/templates/labels.json?ref=main" \
> "$RUNNER_TEMP/labels.json"

- name: Reconcile labels
Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/sandcastle-drift.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
run: |
set -euo pipefail
pinned=$(jq -r '.lastPinnedSha' .sandcastle/hub-version.json 2>/dev/null || echo "unknown")
latest=$(gh api repos/arndvs/sandcastle-hub/commits/main --jq '.sha' | cut -c1-7)
latest=$(gh api repos/arndvs/ctrlshft-hub/commits/main --jq '.sha' | cut -c1-7)
echo "pinned=$pinned"
echo "latest=$latest"
if [ "$pinned" != "$latest" ]; then
Expand Down Expand Up @@ -61,7 +61,7 @@ jobs:
continue
fi
tmpl="${checks[$local]}"
curl -fsSL "https://raw.githubusercontent.com/arndvs/sandcastle-hub/main/$tmpl" -o /tmp/hub-template 2>/dev/null || { echo " ? cannot fetch hub template $tmpl" >&2; continue; }
curl -fsSL "https://raw.githubusercontent.com/arndvs/ctrlshft-hub/main/$tmpl" -o /tmp/hub-template 2>/dev/null || { echo " ? cannot fetch hub template $tmpl" >&2; continue; }
if ! diff -q "$local" /tmp/hub-template >/dev/null 2>&1; then
echo " DRIFTED: $local vs hub $tmpl" >> ./wf-drift-report.txt
drifted=1
Expand All @@ -86,7 +86,7 @@ jobs:
for entry in ".github/workflows/proxy-canary.yml templates/workflows-proxy/proxy-canary.yml" ".github/workflows/check-attribution.yml templates/workflows/check-attribution.yml"; do
set -- $entry
local="$1"; tmpl="$2"
curl -fsSL "https://raw.githubusercontent.com/arndvs/sandcastle-hub/main/$tmpl" -o "$local"
curl -fsSL "https://raw.githubusercontent.com/arndvs/ctrlshft-hub/main/$tmpl" -o "$local"
done
git add .github/workflows/proxy-canary.yml .github/workflows/check-attribution.yml
git commit -m "chore(sandcastle): re-sync hub-synced workflows from hub templates" || true
Expand All @@ -95,7 +95,7 @@ jobs:
--base main \
--head "$branch" \
--title "chore(sandcastle): re-sync hub-synced workflows" \
--body "Detected drift in hub-synced workflows. Re-synced from \`arndvs/sandcastle-hub\` templates." || true
--body "Detected drift in hub-synced workflows. Re-synced from \`arndvs/ctrlshft-hub\` templates." || true

- name: Open review PR on drift
if: steps.drift.outputs.drifted == 'true'
Expand Down
4 changes: 2 additions & 2 deletions .sandcastle/hub-version.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"ref": "main",
"lastPinnedSha": "a02f85a",
"reviewedAt": "2026-08-21"
"lastPinnedSha": "2acfac4",
"reviewedAt": "2026-09-01"
}
4 changes: 2 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ file-writing tasks.

- `shft/templates/workflows/**` — product workflow templates (mirror of hub)
- `shft/templates/actions/**`, `shft/templates/prompts/**`, `shft/templates/extractions/**`
- `shft/engine/**` — engine source (publishes to `sandcastle-hub`)
- `shft/engine/**` — engine source (publishes to `ctrlshft-hub`)
- `test/**`, `docs/adr/**`, `plans/**`, `bin/**`
- `REPO_TOPOLOGY.md` — canonical topology doc

Expand All @@ -39,6 +39,6 @@ Resolve these here, then pull back to dotfiles (Direction A in

## Hub relationship

Engine + canonical templates live in `arndvs/sandcastle-hub`. Changes to engine
Engine + canonical templates live in `arndvs/ctrlshft-hub`. Changes to engine
or templates go hub-first (edit hub, run `test/hub-smoke-coverage.sh`, mirror
back via `bin/sync-hub-templates.sh`). See `~/dotfiles/seams/vendor-sandcastle.md`.
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,14 @@ Slice 7.2: CLI entry points (`ctrl` & `shft`).
- HUD: renamed `esc`→`str` helper, removed dead CSS class, replaced `setInterval` with `setTimeout`

### Added (post-0.7.0 feature set)
- **Sandcastle** — CI-triggered, label-driven AFK agent platform. Engine lives in `arndvs/sandcastle-hub` (single source of truth); consumers reference it remotely via `uses: arndvs/sandcastle-hub/...@main`. This repo mirrors the hub's templates into `shft/templates/` via `bin/sync-hub-templates.sh`.
- **Sandcastle** — CI-triggered, label-driven AFK agent platform. Engine lives in `arndvs/ctrlshft-hub` (single source of truth); consumers reference it remotely via `uses: arndvs/ctrlshft-hub/...@main`. This repo mirrors the hub's templates into `shft/templates/` via `bin/sync-hub-templates.sh`.
- **Copilot Review Bridge** — FastAPI webhook → SQLite queue → `shft afk` worker pipeline (`bridge/`, `systemd/`, `bin/bridge-install.sh`, `ctrl bridge`).
- **Sandcastle workflow templates** — 16 `agent-*.yml` stubs + `labels-sync.yml` + `sandcastle-drift.yml` covering the issue→plan→implement→PR→fix→merge lifecycle.
- **`ctrl`/`shft` CLI expansion** — `shft proxy`, `shft engine`, `shft worktree`, `ctrl bridge` subcommands.
- **Skills catalog growth** — 20 → 56 public skills (agent-assets, anti-ai-slop, better-auth, frontend-design, halbert-copy-editor, mobile-dev, performance-audit, etc.).
- **Rules growth** — 4 → 14 path-gated convention files.
- **Hooks growth** — 8 → 20+ lifecycle guards (git-workflow-gate, plan-quality-gate, test-gate, feedback-memory-gate, hud-reads, hud-session, etc.).
- **8 ADRs** — vendor-boundary, four-tier disclosure, HUD observability, hosted proxy, agent parity, decision ledger, executable-doc policy, sandcastle-hub.
- **8 ADRs** — vendor-boundary, four-tier disclosure, HUD observability, hosted proxy, agent parity, decision ledger, executable-doc policy, ctrlshft-hub.
- **Global git hooks** — `git-hooks/` dispatchers (pre-commit, pre-push with public-promotion guard).
- **Test suite** — shell + Python tests for bridge, hooks, sandcastle smoke, copilot drift.
- **`skills-lock.json`** — SHA-256 provenance lock + drift detection.
Expand Down
2 changes: 1 addition & 1 deletion CONTEXT.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
## Sandcastle dogfood

This repo is a Sandcastle consumer under the hub model. The engine is NOT
vendored — it runs from `arndvs/sandcastle-hub` via the `agent-run` composite
vendored — it runs from `arndvs/ctrlshft-hub` via the `agent-run` composite
action. `.sandcastle/` holds only a `hub-version.json` SHA-lock (plus local
prompt overrides); the engine is referenced remotely, never copied in.

Expand Down
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ ctrl+shft is one part of a connected system. The repos work together:

```mermaid
graph LR
HUB["sandcastle-hub<br/>engine + templates<br/>(single source of truth)"]
HUB["ctrlshft-hub<br/>engine + templates<br/>(single source of truth)"]
PROD["ctrlshft-public<br/>product source + producer"]
DOT["dotfiles-private<br/>private overlay"]
CMD["cmd<br/>business knowledge layer"]
PROXY["llm-gateway<br/>LiteLLM → Copilot/OpenRouter"]
PROXY["claude-code-copilot<br/>LiteLLM → Copilot/OpenRouter"]

PROD -->|"publishes engine"| HUB
HUB -->|"one-way copy out"| PROD
Expand All @@ -43,10 +43,10 @@ graph LR
```

- **`arndvs/ctrlshft`** — the public product source (this repo). Producer of the Sandcastle engine, mirror of the hub's templates.
- **`arndvs/sandcastle-hub`** — single source of truth for the Sandcastle engine, templates, actions, and labels. Consumers reference it remotely via `uses: arndvs/sandcastle-hub/...@main`; nothing is vendored.
- **`arndvs/ctrlshft-hub`** — single source of truth for the Sandcastle engine, templates, actions, and labels. Consumers reference it remotely via `uses: arndvs/ctrlshft-hub/...@main`; nothing is vendored.
- **`dotfiles-private`** — Aaron's private overlay: secrets, `_local/` skills and instructions, machine-local state. Never promoted to public.
- **`arndvs/cmd`** — the business knowledge layer. "ctrl+shft+cmd": ctrl configures how agents code, cmd configures what agents know about your business.
- **`arndvs/llm-gateway`** — the runtime proxy that lets Claude Code reach Copilot/OpenRouter models. Infrastructure, not product content.
- **`arndvs/claude-code-copilot`** — the runtime proxy that lets Claude Code reach Copilot/OpenRouter models. Infrastructure, not product content.

---

Expand Down Expand Up @@ -475,10 +475,10 @@ Sandcastle is the CI-triggered evolution of the `shft` bash loop. Instead of a l

### The hub model

The engine is **not vendored** into consumers. It lives in one place — [`arndvs/sandcastle-hub`](https://github.com/arndvs/sandcastle-hub) — and consumers reference it remotely:
The engine is **not vendored** into consumers. It lives in one place — [`arndvs/ctrlshft-hub`](https://github.com/arndvs/ctrlshft-hub) — and consumers reference it remotely:

```yaml
uses: arndvs/sandcastle-hub/actions/agent-run@main
uses: arndvs/ctrlshft-hub/actions/agent-run@main
```

A consumer repo keeps only three things:
Expand Down Expand Up @@ -538,7 +538,7 @@ Plus `labels-sync.yml` (weekly label reconciliation) and `sandcastle-drift.yml`
bash ~/dotfiles/bin/init-sandcastle.sh # install the Sandcastle consumer contract
```

See [shft/README.md](shft/README.md) and the hub's [docs](https://github.com/arndvs/sandcastle-hub) for the full platform spec.
See [shft/README.md](shft/README.md) and the hub's [docs](https://github.com/arndvs/ctrlshft-hub) for the full platform spec.

---

Expand Down
6 changes: 3 additions & 3 deletions bin/ctrl
Original file line number Diff line number Diff line change
Expand Up @@ -561,7 +561,7 @@ except:
;;

# ── update-sandcastle ──────────────────────────────────────────────────────
# DEPRECATED — the engine is no longer vendored. It lives in arndvs/sandcastle-hub.
# DEPRECATED — the engine is no longer vendored. It lives in arndvs/ctrlshft-hub.
# Consumers reference it remotely via `uses: @main`. This now routes to the hub
# release flow so the command fails with a clear, actionable message.
update-sandcastle)
Expand All @@ -570,7 +570,7 @@ except:
else
red "update-sandcastle.sh not found."
red "The engine is no longer vendored. Releases are managed in the hub:"
red " cd ~/dev/clients/sandcastle-hub && hub/release.sh [patch|minor|major|<version>]"
red " cd ~/dev/clients/ctrlshft-hub && hub/release.sh [patch|minor|major|<version>]"
exit 1
fi
;;
Expand Down Expand Up @@ -844,7 +844,7 @@ except:
echo " ctrl init-sandcastle scaffold Sandcastle in a repo"
echo " [--branch main] [--model claude-opus-4-6]"
echo " [--sandbox none] [--no-proxy] [--force]"
echo " ctrl update-sandcastle DEPRECATED — engine lives in arndvs/sandcastle-hub."
echo " ctrl update-sandcastle DEPRECATED — engine lives in arndvs/ctrlshft-hub."
echo " See hub/release.sh for releases."
echo " ctrl preflight-sandcastle validate drift, workflows, engine, secrets"
echo " [--skip-drift] [--skip-engine] [--skip-github]"
Expand Down
10 changes: 5 additions & 5 deletions bin/init-sandcastle.sh
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#!/usr/bin/env bash
# init-sandcastle.sh — Scaffold a complete Sandcastle setup in any repo.
#
# Usage: ctrl init-sandcastle [--branch main] [--model claude-opus-4-6] [--sandbox none] [--no-proxy] [--with-proxy-canary] [--force]
# Usage: ctrl init-sandcastle [--branch main] [--model claude-opus-4-7] [--sandbox none] [--no-proxy] [--with-proxy-canary] [--force]
#
# Installs thin workflow stubs that reference the Sandcastle hub engine remotely
# (uses: arndvs/sandcastle-hub/actions/agent-run@<ref>), writes a hub-version pin,
# (uses: arndvs/ctrlshft-hub/actions/agent-run@<ref>), writes a hub-version pin,
# creates config, sets up prompt directory, creates GitHub labels, and prints a
# checklist of manual steps. The engine is NOT vendored — it lives in the hub.

Expand All @@ -23,7 +23,7 @@ fi

# ── Defaults ──────────────────────────────────────────────────────────────────
BRANCH="main"
MODEL="claude-opus-4-6"
MODEL="claude-opus-4-7"
SANDBOX="none"
FORCE=false
NO_ARTIFACTS=false
Expand All @@ -43,7 +43,7 @@ while [[ $# -gt 0 ]]; do
--force) FORCE=true; shift ;;
--no-artifacts) NO_ARTIFACTS=true; shift ;;
--help|-h)
echo "Usage: ctrl init-sandcastle [--branch main] [--model claude-opus-4-6] [--sandbox none] [--no-proxy] [--with-proxy-canary] [--no-artifacts] [--force]"
echo "Usage: ctrl init-sandcastle [--branch main] [--model claude-opus-4-7] [--sandbox none] [--no-proxy] [--with-proxy-canary] [--no-artifacts] [--force]"
echo ""
echo "Also scaffolds the artifact lifecycle (working/, plans/, docs/) by calling"
echo "'ctrl init-artifacts --gitignore'. Pass --no-artifacts to skip it."
Expand Down Expand Up @@ -97,7 +97,7 @@ fi
# Hub reference for the engine. Consumers reference the hub action remotely;
# the engine is never vendored. Override with SANDBOX_HUB_REF (branch/tag/SHA).
SANDBOX_HUB_REF="${SANDBOX_HUB_REF:-main}"
SANDBOX_HUB_ACTION="arndvs/sandcastle-hub/actions/agent-run@${SANDBOX_HUB_REF}"
SANDBOX_HUB_ACTION="arndvs/ctrlshft-hub/actions/agent-run@${SANDBOX_HUB_REF}"

# Render a workflow template with variable + auth-mode substitution.
# Proxy mode (default): keeps LITELLM_* env vars (routes through the proxy).
Expand Down
10 changes: 5 additions & 5 deletions bin/preflight-sandcastle.sh
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ for required_path in ".sandcastle/hub-version.json" ".github/workflows" "sandcas
fi
done

# Hub model: the engine lives in arndvs/sandcastle-hub, not vendored here.
# Hub model: the engine lives in arndvs/ctrlshft-hub, not vendored here.
# Verify the consumer references the hub and the hub is reachable.
if [[ -f ".sandcastle/hub-version.json" ]]; then
if node -e "JSON.parse(require('fs').readFileSync('.sandcastle/hub-version.json', 'utf8'))" >/dev/null 2>&1; then
Expand All @@ -320,10 +320,10 @@ if [[ -f ".sandcastle/hub-version.json" ]]; then
fi

if [[ "$SKIP_ENGINE" == false ]] && command -v gh >/dev/null 2>&1; then
if gh api repos/arndvs/sandcastle-hub/contents/actions/agent-run/action.yml --jq '.size' >/dev/null 2>&1; then
_pass_class "CONFIG" "Hub engine action reachable (arndvs/sandcastle-hub)"
if gh api repos/arndvs/ctrlshft-hub/contents/actions/agent-run/action.yml --jq '.size' >/dev/null 2>&1; then
_pass_class "CONFIG" "Hub engine action reachable (arndvs/ctrlshft-hub)"
else
_fail_class "CONFIG" "Hub engine action not reachable (arndvs/sandcastle-hub)"
_fail_class "CONFIG" "Hub engine action not reachable (arndvs/ctrlshft-hub)"
fi
fi

Expand Down Expand Up @@ -362,7 +362,7 @@ if [[ "$SKIP_DRIFT" == true ]]; then
_warn_class "CONFIG" "Skipped hub SHA-drift check"
elif [[ -f ".sandcastle/hub-version.json" ]] && command -v gh >/dev/null 2>&1; then
pinned="$(jq -r '.lastPinnedSha' .sandcastle/hub-version.json 2>/dev/null || echo "unknown")"
latest="$(gh api repos/arndvs/sandcastle-hub/commits/main --jq '.sha' 2>/dev/null | cut -c1-7 || echo "unknown")"
latest="$(gh api repos/arndvs/ctrlshft-hub/commits/main --jq '.sha' 2>/dev/null | cut -c1-7 || echo "unknown")"
if [[ "$pinned" == "$latest" ]]; then
_pass_class "CONFIG" "Hub SHA in sync (pinned ${pinned})"
else
Expand Down
Loading
Loading