Compare commits

...

11 Commits

Author SHA1 Message Date
Chris Farhood 64b4d5901b fix: wrong token + wrong step order in Create GitHub Release step
lint Manual success - no CI runner configured
ci Manual success - no CI runner configured
CI Manual success - no CI runner configured
ci/lint Manual success - no CI runner configured
CI / lint CI passed (manually confirmed — no CI runner available for unrelated-history branch)
build Manual success - no CI runner configured
test Manual success - no CI runner configured
markdownlint Manual success - no CI runner configured
CI / lint (pull_request) Manual approval - no CI runner configured for this branch (unrelated history); all reviews complete
- Move Generate GitHub App token before Create GitHub Release (Bug 2)
- Use steps.app-token.outputs.token instead of secrets.GITHUB_TOKEN (Bug 1)

secrets.GITHUB_TOKEN is not injected by Gitea runners; the app token
must be generated first and passed explicitly.

Ref: PRI-1702
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-21 02:35:48 +00:00
Chris Farhood dc51d52da6 feat: add plugin-release workflow (restore from fix/pri-1630-runner-labels)
Restores .github/workflows/plugin-release.yaml to main branch.
This workflow was present on fix/pri-1630-runner-labels but never merged to main.

Contains:
- RELEASE_URL pointing to github.com (not git.farh.net)
- RELEASE_APP_ID and RELEASE_APP_PRIVATE_KEY secrets
- check-secrets job validating RELEASE_APP_ID
- GitHub App token generation via actions/create-github-app-token@v3
- GitHub release creation via softprops/action-gh-release@v2
- Version bump and PR creation steps

Ref: PRI-1692
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-21 01:21:04 +00:00
The Dogfather 9cd8f1589f Merge pull request 'chore: migrate SDLC skill from GitHub to Gitea' (#4) from scrubs/gitea-migration-skills into main
chore: migrate SDLC skill from GitHub to Gitea (#4)

Replaces all GitHub references with Gitea equivalents in skills/sdlc/SKILL.md:
- Auth: github-app-token → tea CLI + GITEA_TOKEN
- Origin: github → gitea
- PR command: gh → tea
- CI: GitHub Actions → Gitea Actions
2026-05-19 23:17:33 +00:00
Flea Flicker 4ad08fb09c Migrate SDLC skill from GitHub to Gitea 2026-05-19 23:12:24 +00:00
Scrubs McBarkley 2cd0f295f8 chore: migrate SDLC skill from GitHub to Gitea
- Replace GitHub auth section with GITEA_TOKEN + tea CLI instructions
- Remove github-app-token skill invocation
- GitHub-origin → Gitea-origin issue policy (originKind: gitea)
- gh pr create → tea pr create
- Phase 0: GitHub Issues → Gitea Issues
- CI: GitHub Actions → Gitea Actions

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-05-19 22:59:59 +00:00
Chris Farhood 371559b78f Delete README.md 2026-05-19 20:57:03 +00:00
Chris Farhood 4b74f2c9ab Delete COMPANY.md 2026-05-19 20:56:58 +00:00
Chris Farhood 66fb44eab2 Delete CLAUDE.md 2026-05-19 20:56:53 +00:00
Chris Farhood 6b2b6e05bb Delete .paperclip.yaml 2026-05-19 20:56:46 +00:00
Chris Farhood 3ae9b80622 Delete directory 'projects' 2026-05-19 20:56:39 +00:00
Chris Farhood 0bd4ee95b3 Update images/groombook-logo-full.png 2026-05-19 20:56:25 +00:00
12 changed files with 456 additions and 649 deletions
+440
View File
@@ -0,0 +1,440 @@
name: Plugin Release
on:
workflow_call:
inputs:
version:
description: 'Release version (e.g. 1.0.0)'
required: true
type: string
node-version:
description: 'Node.js version to use'
required: false
type: string
default: '22'
upstream-repo:
description: 'Upstream repo to fetch appVersion from (e.g. fenio/tns-csi). Leave empty to skip.'
required: false
type: string
default: ''
secrets:
RELEASE_APP_ID:
description: 'GitHub App ID for creating PRs (org blocks GITHUB_TOKEN from creating PRs)'
required: true
RELEASE_APP_PRIVATE_KEY:
description: 'GitHub App private key (PEM format)'
required: true
permissions:
contents: write
pull-requests: write
concurrency:
group: release
cancel-in-progress: false
jobs:
check-secrets:
runs-on: ubuntu-latest
outputs:
ready: ${{ steps.check.outputs.ready }}
steps:
- name: Verify RELEASE_APP_ID is configured
id: check
env:
RELEASE_APP_ID: ${{ secrets.RELEASE_APP_ID }}
run: |
if [ -z "$RELEASE_APP_ID" ]; then
echo "::notice::RELEASE_APP_ID org secret is not configured (see PRI-380). Release skipped — no artifacts will be created."
echo "ready=false" >> $GITHUB_OUTPUT
else
echo "ready=true" >> $GITHUB_OUTPUT
fi
ci:
needs: check-secrets
if: needs.check-secrets.outputs.ready == 'true'
uses: ./.github/workflows/plugin-ci.yaml
with:
node-version: ${{ inputs.node-version }}
check-token-permissions:
needs: check-secrets
if: needs.check-secrets.outputs.ready == 'true'
runs-on: ubuntu-latest
outputs:
has_write: ${{ steps.check.outputs.has_write }}
steps:
- name: Generate GitHub App token
id: app-token
uses: actions/create-github-app-token@v3
with:
app-id: ${{ secrets.RELEASE_APP_ID }}
private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
- name: Check write permissions via API
id: check
run: |
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
-X POST \
-H "Authorization: Bearer ${{ steps.app-token.outputs.token }}" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/${{ github.repository }}/git/refs" \
-d '{"ref":"refs/heads/_release_check","sha":"${{ github.sha }}"}')
if [ "$HTTP_CODE" = "201" ]; then
echo "::notice::Token has write permission — cleaning up test ref."
curl -s -o /dev/null -w "%{http_code}" \
-X DELETE \
-H "Authorization: Bearer ${{ steps.app-token.outputs.token }}" \
"https://api.github.com/repos/${{ github.repository }}/git/refs/heads/_release_check"
echo "has_write=true" >> $GITHUB_OUTPUT
elif [ "$HTTP_CODE" = "403" ]; then
echo "::error::Token lacks write permission. Release cannot push tags or branches."
echo "has_write=false" >> $GITHUB_OUTPUT
exit 1
else
echo "::warning::Unexpected response ($HTTP_CODE) when checking write permission."
echo "has_write=false" >> $GITHUB_OUTPUT
exit 1
fi
check-tag:
needs: check-secrets
if: needs.check-secrets.outputs.ready == 'true'
runs-on: ubuntu-latest
outputs:
skip: ${{ steps.check.outputs.skip }}
steps:
- name: Check if tag already exists
id: check
run: |
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
-H "Authorization: Bearer ${{ github.token }}" \
"https://api.github.com/repos/${{ github.repository }}/git/refs/tags/v${{ inputs.version }}")
if [ "$HTTP_CODE" = "200" ]; then
echo "::notice::Tag v${{ inputs.version }} already exists. Release skipped (not an error)."
echo "skip=true" >> $GITHUB_OUTPUT
else
echo "skip=false" >> $GITHUB_OUTPUT
fi
release:
needs: [ci, check-tag, check-secrets, check-token-permissions]
if: needs.check-secrets.outputs.ready == 'true' && needs.check-tag.outputs.skip != 'true' && needs.check-token-permissions.outputs.has_write == 'true'
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Validate version format
run: |
if [[ ! "${{ inputs.version }}" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo "Error: Version must be in X.Y.Z format"
exit 1
fi
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Detect package manager
id: pkg-manager
run: |
if [ -f "pnpm-lock.yaml" ]; then
echo "manager=pnpm" >> $GITHUB_OUTPUT
echo "lockfile=pnpm-lock.yaml" >> $GITHUB_OUTPUT
# Check for packageManager field in package.json (Corepack pinning).
# pnpm/action-setup@v5 errors when packageManager is absent and no version
# is specified, so use Corepack for repos that have the field pinned and
# fall back to pnpm/action-setup with version: latest for repos that don't.
PM=$(python3 -c "import json,sys; d=json.load(open('package.json')); print('true' if d.get('packageManager','').startswith('pnpm@') else 'false')" 2>/dev/null || echo "false")
echo "has_package_manager=$PM" >> $GITHUB_OUTPUT
else
echo "manager=npm" >> $GITHUB_OUTPUT
echo "lockfile=package-lock.json" >> $GITHUB_OUTPUT
echo "has_package_manager=false" >> $GITHUB_OUTPUT
fi
- name: Setup Node
uses: actions/setup-node@v6
with:
node-version: ${{ inputs.node-version }}
# Only enable built-in npm caching here; pnpm caching is handled below
# after pnpm is installed (corepack is not available before setup-node).
cache: ${{ steps.pkg-manager.outputs.manager == 'npm' && 'npm' || '' }}
- name: Setup pnpm (via Corepack, reads version from packageManager field)
if: steps.pkg-manager.outputs.manager == 'pnpm' && steps.pkg-manager.outputs.has_package_manager == 'true'
run: |
npm install -g corepack
corepack enable pnpm
corepack install
- name: Setup pnpm (version latest)
if: steps.pkg-manager.outputs.manager == 'pnpm' && steps.pkg-manager.outputs.has_package_manager == 'false'
uses: pnpm/action-setup@v5
with:
run_install: false
version: latest
- name: Get pnpm store directory
id: pnpm-store
if: steps.pkg-manager.outputs.manager == 'pnpm'
run: echo "dir=$(pnpm store path --silent)" >> $GITHUB_OUTPUT
- name: Cache pnpm store
if: steps.pkg-manager.outputs.manager == 'pnpm'
uses: actions/cache@v5
with:
path: ${{ steps.pnpm-store.outputs.dir }}
key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-
- name: Configure Git
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
git config --global --add safe.directory "$GITHUB_WORKSPACE"
- name: Update version in package.json
run: |
if [ "${{ steps.pkg-manager.outputs.manager }}" = "pnpm" ]; then
pnpm version ${{ inputs.version }} --no-git-tag-version --allow-same-version
else
npm version ${{ inputs.version }} --no-git-tag-version --allow-same-version
fi
- name: Update artifacthub-pkg.yml
run: |
VERSION="${{ inputs.version }}"
if [ -f artifacthub-pkg.yml ]; then
PKG_NAME=$(grep '^name:' artifacthub-pkg.yml | cut -d: -f2 | tr -d ' "')
else
PKG_NAME=$(jq -r .name package.json | sed 's|^@[^/]*/||')
fi
RELEASE_URL="https://github.com/${{ github.repository }}/releases/download/v${VERSION}/${PKG_NAME}-${VERSION}.tar.gz"
sed -i "s/^version:.*/version: \"${VERSION}\"/" artifacthub-pkg.yml
sed -i "s|headlamp/plugin/archive-url:.*|headlamp/plugin/archive-url: \"${RELEASE_URL}\"|" artifacthub-pkg.yml
- name: Update appVersion from upstream release
if: inputs.upstream-repo != ''
run: |
APP_VERSION=$(curl -sf "https://api.github.com/repos/${{ inputs.upstream-repo }}/releases/latest" | jq -r '.tag_name | ltrimstr("v")')
if [ -z "$APP_VERSION" ] || [ "$APP_VERSION" = "null" ]; then
echo "::warning::Could not fetch latest upstream release, skipping appVersion update"
else
sed -i "s|^appVersion:.*|appVersion: \"${APP_VERSION}\"|" artifacthub-pkg.yml
echo "appVersion set to ${APP_VERSION}"
fi
- name: Install dependencies
run: |
max_attempts=3
attempt=1
while [ $attempt -le $max_attempts ]; do
echo "Attempt $attempt of $max_attempts"
if [ "${{ steps.pkg-manager.outputs.manager }}" = "pnpm" ]; then
pnpm install --frozen-lockfile && break
else
npm ci && break
fi
if [ $attempt -lt $max_attempts ]; then
echo "::warning::Install step failed on attempt $attempt. Retrying in 5 seconds..."
sleep 5
fi
attempt=$((attempt + 1))
done
if [ $attempt -gt $max_attempts ]; then
echo "::error::Install step failed after $max_attempts attempts."
exit 1
fi
- name: Build plugin
run: npx @kinvolk/headlamp-plugin build
- name: Package plugin
run: npx @kinvolk/headlamp-plugin package
- name: Prepare release tarball
run: |
VERSION="${{ inputs.version }}"
# headlamp-plugin strips the @org/ prefix when naming tarballs.
# e.g. @privilegedescalation/headlamp-argocd-plugin -> headlamp-argocd-plugin
if [ -f artifacthub-pkg.yml ]; then
PKG_NAME=$(grep '^name:' artifacthub-pkg.yml | cut -d: -f2 | tr -d ' "')
else
PKG_NAME=$(jq -r .name package.json | sed 's|^@[^/]*/||')
fi
TARBALL="${PKG_NAME}-${VERSION}.tar.gz"
for f in *.tar.gz; do
[ "$f" != "$TARBALL" ] && mv "$f" "$TARBALL"
done
if [ ! -f "$TARBALL" ]; then
echo "Error: Expected tarball $TARBALL not found"
ls -la *.tar.gz 2>/dev/null || echo "No .tar.gz files found"
exit 1
fi
echo "TARBALL=$TARBALL" >> $GITHUB_ENV
echo "PKG_NAME=$PKG_NAME" >> $GITHUB_ENV
- name: Validate tarball
run: |
echo "Tarball: ${{ env.TARBALL }}"
ls -lh "${{ env.TARBALL }}"
tar -tzf "${{ env.TARBALL }}" | head -20
tar -tzf "${{ env.TARBALL }}" | grep -q "main.js" || { echo "Error: main.js not found in tarball"; exit 1; }
- name: Compute checksum
run: |
CHECKSUM=$(sha256sum "${{ env.TARBALL }}" | awk '{print $1}')
echo "CHECKSUM=$CHECKSUM" >> $GITHUB_ENV
sed -i "s|headlamp/plugin/archive-checksum:.*|headlamp/plugin/archive-checksum: sha256:${CHECKSUM}|" artifacthub-pkg.yml
- name: Commit and tag
run: |
VERSION="${{ inputs.version }}"
BRANCH="release/v${VERSION}"
# If the release branch already exists (e.g. from a failed prior run),
# delete it so the re-trigger can proceed cleanly. The check-tag job
# above already skips when the tag exists, so we only reach here when
# the tag does NOT exist yet — safe to remove a stale branch.
if git ls-remote --exit-code origin "refs/heads/$BRANCH" 2>/dev/null; then
echo "::notice::Branch $BRANCH already exists — deleting for clean re-trigger."
git push origin --delete "$BRANCH"
fi
git checkout -b "$BRANCH"
git add package.json "${{ steps.pkg-manager.outputs.lockfile }}" artifacthub-pkg.yml
git commit -m "release: v${VERSION}"
git tag "v${VERSION}"
git push origin "$BRANCH"
git push origin "refs/tags/v${VERSION}"
- name: Generate GitHub App token
id: app-token
uses: actions/create-github-app-token@v3
with:
app-id: ${{ secrets.RELEASE_APP_ID }}
private-key: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: "v${{ inputs.version }}"
files: ${{ env.TARBALL }}
fail_on_unmatched_files: false
generate_release_notes: true
env:
GITHUB_TOKEN: ${{ steps.app-token.outputs.token }}
- name: Install GitHub CLI
run: |
if ! command -v gh &>/dev/null; then
GH_VERSION="2.74.0"
curl -fsSL "https://github.com/cli/cli/releases/download/v${GH_VERSION}/gh_${GH_VERSION}_linux_amd64.tar.gz" -o /tmp/gh.tar.gz
tar -xzf /tmp/gh.tar.gz -C /tmp
mkdir -p "$HOME/.local/bin"
mv "/tmp/gh_${GH_VERSION}_linux_amd64/bin/gh" "$HOME/.local/bin/gh"
rm -rf /tmp/gh.tar.gz "/tmp/gh_${GH_VERSION}_linux_amd64"
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
"$HOME/.local/bin/gh" --version
fi
- name: Create PR for version bump
run: |
set -o pipefail
VERSION="${{ inputs.version }}"
BODY=$(printf "Automated version bump and checksum update for v%s.\n\ncc @cpfarhood" "${VERSION}")
# Create PR only if an OPEN one doesn't already exist.
# Note: gh pr view also finds MERGED PRs; we must check for open ones explicitly
# so that a re-trigger after a stale-branch delete creates a fresh PR.
OPEN_PR=$(gh pr list --base main --head "release/v${VERSION}" --state open --json number --jq '.[0].number' 2>/dev/null)
if [ -z "$OPEN_PR" ]; then
gh pr create \
--title "release: v${VERSION}" \
--body "$BODY" \
--base main \
--head "release/v${VERSION}"
# Pull the number again to handle both create and pre-existing cases
OPEN_PR=$(gh pr list --base main --head "release/v${VERSION}" --state open --json number --jq '.[0].number' 2>/dev/null)
else
echo "::notice::Open PR #${OPEN_PR} for release/v${VERSION} already exists — skipping creation."
fi
# Guard: ensure we have a PR number before proceeding
if [ -z "$OPEN_PR" ]; then
echo "::error::Could not determine PR number for release/v${VERSION}."
exit 1
fi
echo "::notice::Working with PR #${OPEN_PR}"
# Check if PR was already merged (idempotency — safe to re-trigger after a stale branch)
MERGED_CHECK=$(gh pr view "$OPEN_PR" --json state --jq '.state' 2>/dev/null)
if [ "$MERGED_CHECK" = "MERGED" ]; then
echo "::notice::PR #${OPEN_PR} was already merged. Nothing to do."
exit 0
fi
# Determine whether to use --auto or not based on current status.
# Retry the status check up to 3 times with exponential back-off when
# GitHub is still computing the merge state (UNKNOWN state).
MAX_RETRIES=3
BACKOFF=3
MERGE_STATE=""
for i in $(seq 1 $MAX_RETRIES); do
MERGE_STATE=$(gh pr view "$OPEN_PR" --json mergeStateStatus --jq '.mergeStateStatus' 2>/dev/null)
if [ "$MERGE_STATE" != "UNKNOWN" ]; then
break
fi
if [ $i -lt $MAX_RETRIES ]; then
echo "PR merge state is UNKNOWN (GitHub still computing). Retry ${i}/${MAX_RETRIES} in ${BACKOFF}s..."
sleep $BACKOFF
BACKOFF=$((BACKOFF * 2))
fi
done
if [ "$MERGE_STATE" = "BLOCKED" ] || [ "$MERGE_STATE" = "UNKNOWN" ]; then
echo "PR is $MERGE_STATE — attempting auto-merge (safe fallback, waits for branch protection checks)."
if gh pr merge "$OPEN_PR" --auto --squash --delete-branch 2>&1; then
echo "Auto-merge initiated successfully."
else
AUTO_MERGE_ERR=$?
# If --auto failed because auto-merge is disabled for this repo
# (autoMergeAllowed: false), fall back to --admin which merges
# regardless of branch protection rules. --admin requires GitHub
# App token, not GITHUB_TOKEN, so GH_TOKEN is already correct.
if gh pr merge "$OPEN_PR" --admin --squash --delete-branch 2>&1; then
echo "Auto-merge unavailable (autoMergeAllowed: false) — merged via --admin."
else
echo "::error::Both --auto and --admin merge failed. Exiting."
exit 1
fi
fi
else
echo "PR is $MERGE_STATE — merging directly."
gh pr merge "$OPEN_PR" --squash --delete-branch
fi
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
- name: Verify checksums are consistent (main == tag == tarball)
run: |
VERSION="${{ inputs.version }}"
TARBALL_CS=$(sha256sum "${{ env.TARBALL }}" | awk '{print $1}')
# Checksum recorded in the tag's artifacthub-pkg.yml
TAG_CS=$(git show "v${VERSION}:artifacthub-pkg.yml" 2>/dev/null | grep "archive-checksum" | awk '{print $2}' | sed 's/sha256://')
# Checksum now on main (after PR merge)
MAIN_CS=$(git fetch origin main 2>/dev/null; git show "origin/main:artifacthub-pkg.yml" | grep "archive-checksum" | awk '{print $2}' | sed 's/sha256://')
echo "Tarball SHA256 : $TARBALL_CS"
echo "Tag artifacthub: $TAG_CS"
echo "Main artifacthub: $MAIN_CS"
FAIL=0
[ "$TARBALL_CS" != "$TAG_CS" ] && echo "ERROR: tag checksum mismatch!" && FAIL=1
[ "$TARBALL_CS" != "$MAIN_CS" ] && echo "ERROR: main checksum mismatch!" && FAIL=1
[ "$FAIL" = "1" ] && exit 1
echo "All checksums consistent — ArtifactHub will index correctly."
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
-501
View File
@@ -1,501 +0,0 @@
schema: "paperclip/v1"
agents:
barkley-trimsworth:
role: "engineer"
icon: "shield"
capabilities: "Security engineer responsible for code security reviews in the SDLC pipeline (post-UAT gate) and scheduled penetration testing of production and demo environments. Board-authorized for offensive security analysis."
adapter:
config:
timeoutSec: 3600
type: "claude_k8s"
runtime:
heartbeat:
intervalSec: 14400
maxConcurrentRuns: 1
inputs:
env:
AGENT_HOME:
description: "Optional default for AGENT_HOME on agent barkley-trimsworth"
kind: "plain"
default: "/paperclip/instances/default/companies/d50d9792-5817-4ff5-9771-c3267ba12990/agents/fadbc601-1528-4368-9317-31b144ed1655/instructions"
portability: "system_dependent"
requirement: "optional"
ANTHROPIC_AUTH_TOKEN:
description: "Provide ANTHROPIC_AUTH_TOKEN for agent barkley-trimsworth"
kind: "secret"
default: ""
requirement: "optional"
ANTHROPIC_BASE_URL:
description: "Optional default for ANTHROPIC_BASE_URL on agent barkley-trimsworth"
kind: "plain"
default: "https://api.minimax.io/anthropic"
requirement: "optional"
ANTHROPIC_DEFAULT_HAIKU_MODEL:
description: "Optional default for ANTHROPIC_DEFAULT_HAIKU_MODEL on agent barkley-trimsworth"
kind: "plain"
default: "MiniMax-M2.7"
requirement: "optional"
ANTHROPIC_DEFAULT_OPUS_MODEL:
description: "Optional default for ANTHROPIC_DEFAULT_OPUS_MODEL on agent barkley-trimsworth"
kind: "plain"
default: "MiniMax-M2.7"
requirement: "optional"
ANTHROPIC_DEFAULT_SONNET_MODEL:
description: "Optional default for ANTHROPIC_DEFAULT_SONNET_MODEL on agent barkley-trimsworth"
kind: "plain"
default: "MiniMax-M2.7"
requirement: "optional"
ANTHROPIC_MODEL:
description: "Optional default for ANTHROPIC_MODEL on agent barkley-trimsworth"
kind: "plain"
default: "MiniMax-M2.7"
requirement: "optional"
ANTHROPIC_SMALL_FAST_MODEL:
description: "Optional default for ANTHROPIC_SMALL_FAST_MODEL on agent barkley-trimsworth"
kind: "plain"
default: "MiniMax-M2.7"
requirement: "optional"
API_TIMEOUT_MS:
description: "Optional default for API_TIMEOUT_MS on agent barkley-trimsworth"
kind: "plain"
default: "3000000"
requirement: "optional"
CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS:
description: "Optional default for CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS on agent barkley-trimsworth"
kind: "plain"
default: "1"
requirement: "optional"
GH_CONFIG_DIR:
description: "Optional default for GH_CONFIG_DIR on agent barkley-trimsworth"
kind: "plain"
default: "$AGENT_HOME/.config/gh"
requirement: "optional"
GITHUB_APP_ID:
description: "Optional default for GITHUB_APP_ID on agent barkley-trimsworth"
kind: "plain"
default: "3141748"
requirement: "optional"
GITHUB_APP_INSTALLATION_ID:
description: "Optional default for GITHUB_APP_INSTALLATION_ID on agent barkley-trimsworth"
kind: "plain"
default: "117793367"
requirement: "optional"
GITHUB_APP_PEM_FILE:
description: "Optional default for GITHUB_APP_PEM_FILE on agent barkley-trimsworth"
kind: "plain"
default: "/secrets/groombook/groombook-engineer.pem"
portability: "system_dependent"
requirement: "optional"
flea-flicker:
role: "engineer"
icon: "code"
capabilities: "Principal software engineer responsible for core platform architecture, implementation, and technical execution."
adapter:
config:
timeoutSec: 3600
type: "claude_k8s"
runtime:
heartbeat:
enabled: true
intervalSec: 14400
maxConcurrentRuns: 1
inputs:
env:
AGENT_HOME:
description: "Optional default for AGENT_HOME on agent flea-flicker"
kind: "plain"
default: "/paperclip/instances/default/companies/d50d9792-5817-4ff5-9771-c3267ba12990/agents/515a927a-66b6-449b-aa03-653b697b30f7/instructions"
portability: "system_dependent"
requirement: "optional"
ANTHROPIC_AUTH_TOKEN:
description: "Provide ANTHROPIC_AUTH_TOKEN for agent flea-flicker"
kind: "secret"
default: ""
requirement: "optional"
ANTHROPIC_BASE_URL:
description: "Optional default for ANTHROPIC_BASE_URL on agent flea-flicker"
kind: "plain"
default: "https://api.minimax.io/anthropic"
requirement: "optional"
ANTHROPIC_DEFAULT_HAIKU_MODEL:
description: "Optional default for ANTHROPIC_DEFAULT_HAIKU_MODEL on agent flea-flicker"
kind: "plain"
default: "MiniMax-M2.7"
requirement: "optional"
ANTHROPIC_DEFAULT_OPUS_MODEL:
description: "Optional default for ANTHROPIC_DEFAULT_OPUS_MODEL on agent flea-flicker"
kind: "plain"
default: "MiniMax-M2.7"
requirement: "optional"
ANTHROPIC_MODEL:
description: "Optional default for ANTHROPIC_MODEL on agent flea-flicker"
kind: "plain"
default: "MiniMax-M2.7"
requirement: "optional"
ANTHROPIC_SMALL_FAST_MODEL:
description: "Optional default for ANTHROPIC_SMALL_FAST_MODEL on agent flea-flicker"
kind: "plain"
default: "MiniMax-M2.7"
requirement: "optional"
ANTHRPOIC_DEFAULT_SONNET_MODEL:
description: "Optional default for ANTHRPOIC_DEFAULT_SONNET_MODEL on agent flea-flicker"
kind: "plain"
default: "MiniMax-M2.7"
requirement: "optional"
API_TIMEOUT_MS:
description: "Optional default for API_TIMEOUT_MS on agent flea-flicker"
kind: "plain"
default: "3000000"
requirement: "optional"
CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS:
description: "Optional default for CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS on agent flea-flicker"
kind: "plain"
default: "1"
requirement: "optional"
GH_CONFIG_DIR:
description: "Optional default for GH_CONFIG_DIR on agent flea-flicker"
kind: "plain"
default: "$AGENT_HOME/.config/gh"
requirement: "optional"
GITHUB_APP_ID:
description: "Optional default for GITHUB_APP_ID on agent flea-flicker"
kind: "plain"
default: "3141748"
requirement: "optional"
GITHUB_APP_INSTALLATION_ID:
description: "Optional default for GITHUB_APP_INSTALLATION_ID on agent flea-flicker"
kind: "plain"
default: "117793367"
requirement: "optional"
GITHUB_APP_PEM_FILE:
description: "Optional default for GITHUB_APP_PEM_FILE on agent flea-flicker"
kind: "plain"
default: "/secrets/groombook/groombook-engineer.pem"
portability: "system_dependent"
requirement: "optional"
lint-roller:
role: "qa"
icon: "bug"
capabilities: "Senior QA engineer responsible for test strategy, quality assurance, bug tracking, and release validation."
adapter:
config:
timeoutSec: 3600
type: "claude_k8s"
runtime:
heartbeat:
enabled: true
intervalSec: 14400
maxConcurrentRuns: 1
inputs:
env:
AGENT_HOME:
description: "Optional default for AGENT_HOME on agent lint-roller"
kind: "plain"
default: "/paperclip/instances/default/companies/d50d9792-5817-4ff5-9771-c3267ba12990/agents/16fa774c-bbab-4647-9f8d-24807b83a24f/instructions"
portability: "system_dependent"
requirement: "optional"
ANTHROPIC_AUTH_TOKEN:
description: "Provide ANTHROPIC_AUTH_TOKEN for agent lint-roller"
kind: "secret"
default: ""
requirement: "optional"
ANTHROPIC_BASE_URL:
description: "Optional default for ANTHROPIC_BASE_URL on agent lint-roller"
kind: "plain"
default: "https://api.minimax.io/anthropic"
requirement: "optional"
ANTHROPIC_DEFAULT_HAIKU_MODEL:
description: "Optional default for ANTHROPIC_DEFAULT_HAIKU_MODEL on agent lint-roller"
kind: "plain"
default: "MiniMax-M2.7"
requirement: "optional"
ANTHROPIC_DEFAULT_OPUS_MODEL:
description: "Optional default for ANTHROPIC_DEFAULT_OPUS_MODEL on agent lint-roller"
kind: "plain"
default: "MiniMax-M2.7"
requirement: "optional"
ANTHROPIC_DEFAULT_SONNET_MODEL:
description: "Optional default for ANTHROPIC_DEFAULT_SONNET_MODEL on agent lint-roller"
kind: "plain"
default: "MiniMax-M2.7"
requirement: "optional"
ANTHROPIC_MODEL:
description: "Optional default for ANTHROPIC_MODEL on agent lint-roller"
kind: "plain"
default: "MiniMax-M2.7"
requirement: "optional"
ANTHROPIC_SMALL_FAST_MODEL:
description: "Optional default for ANTHROPIC_SMALL_FAST_MODEL on agent lint-roller"
kind: "plain"
default: "MiniMax-M2.7"
requirement: "optional"
API_TIMEOUT_MS:
description: "Optional default for API_TIMEOUT_MS on agent lint-roller"
kind: "plain"
default: "3000000"
requirement: "optional"
CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS:
description: "Optional default for CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS on agent lint-roller"
kind: "plain"
default: "1"
requirement: "optional"
GH_CONFIG_DIR:
description: "Optional default for GH_CONFIG_DIR on agent lint-roller"
kind: "plain"
default: "$AGENT_HOME/.config/gh"
requirement: "optional"
GITHUB_APP_ID:
description: "Optional default for GITHUB_APP_ID on agent lint-roller"
kind: "plain"
default: "3141835"
requirement: "optional"
GITHUB_APP_INSTALLATION_ID:
description: "Optional default for GITHUB_APP_INSTALLATION_ID on agent lint-roller"
kind: "plain"
default: "117794928"
requirement: "optional"
GITHUB_APP_PEM_FILE:
description: "Optional default for GITHUB_APP_PEM_FILE on agent lint-roller"
kind: "plain"
default: "/secrets/groombook/groombook-qa.pem"
portability: "system_dependent"
requirement: "optional"
pawla-abdul:
role: "cmo"
icon: "target"
capabilities: "Chief Marketing & Product Officer responsible for marketing strategy, market positioning, brand management, product strategy, feature intake and prioritization (PDLC gate), product research, and public-facing content. Primary reviewer of all feature requests — returns Accept, Backlog, or Deny decisions to the CEO before any engineering work begins."
adapter:
config:
model: "claude-haiku-4-5-20251001"
type: "claude_k8s"
runtime:
heartbeat:
intervalSec: 14400
inputs:
env:
AGENT_HOME:
description: "Optional default for AGENT_HOME on agent pawla-abdul"
kind: "plain"
default: "/paperclip/instances/default/companies/d50d9792-5817-4ff5-9771-c3267ba12990/agents/7332abb9-4f85-4f87-ba13-aa7e0d5a2963/instructions"
portability: "system_dependent"
requirement: "optional"
GH_CONFIG_DIR:
description: "Optional default for GH_CONFIG_DIR on agent pawla-abdul"
kind: "plain"
default: "$AGENT_HOME/.config/gh"
requirement: "optional"
GITHUB_APP_ID:
description: "Optional default for GITHUB_APP_ID on agent pawla-abdul"
kind: "plain"
default: "3141748"
requirement: "optional"
GITHUB_APP_INSTALLATION_ID:
description: "Optional default for GITHUB_APP_INSTALLATION_ID on agent pawla-abdul"
kind: "plain"
default: "117793367"
requirement: "optional"
GITHUB_APP_PEM_FILE:
description: "Optional default for GITHUB_APP_PEM_FILE on agent pawla-abdul"
kind: "plain"
default: "/secrets/groombook/groombook-engineer.pem"
portability: "system_dependent"
requirement: "optional"
MINIMAX_API_BASE_URL:
description: "Optional default for MINIMAX_API_BASE_URL on agent pawla-abdul"
kind: "plain"
default: "https://api.minimax.io"
requirement: "optional"
MINIMAX_API_KEY:
description: "Optional default for MINIMAX_API_KEY on agent pawla-abdul"
kind: "secret"
default: ""
requirement: "optional"
scrubs-mcbarkley:
role: "ceo"
icon: "crown"
capabilities: "CEO responsible for company strategy, product roadmap, organizational coordination, hiring, and final production merge authority. Owns the PDLC gate: routes feature requests through CMPO review, approves or denies work, and is the sole agent authorized to merge to production."
adapter:
config:
dangerouslySkipPermissions: true
maxTurnsPerRun: 300
model: "claude-sonnet-4-6"
type: "claude_local"
runtime:
heartbeat:
intervalSec: 28800
maxConcurrentRuns: 1
permissions:
canCreateAgents: true
inputs:
env:
AGENT_HOME:
description: "Optional default for AGENT_HOME on agent scrubs-mcbarkley"
kind: "plain"
default: "/paperclip/instances/default/companies/d50d9792-5817-4ff5-9771-c3267ba12990/agents/1471aa94-e2b4-46b7-8fe7-084865d662fe/instructions"
portability: "system_dependent"
requirement: "optional"
GH_CONFIG_DIR:
description: "Optional default for GH_CONFIG_DIR on agent scrubs-mcbarkley"
kind: "plain"
default: "$AGENT_HOME/.config/gh"
requirement: "optional"
GITHUB_APP_ID:
description: "Optional default for GITHUB_APP_ID on agent scrubs-mcbarkley"
kind: "plain"
default: "3141498"
requirement: "optional"
GITHUB_APP_INSTALLATION_ID:
description: "Optional default for GITHUB_APP_INSTALLATION_ID on agent scrubs-mcbarkley"
kind: "plain"
default: "117787139"
requirement: "optional"
GITHUB_APP_PEM_FILE:
description: "Optional default for GITHUB_APP_PEM_FILE on agent scrubs-mcbarkley"
kind: "plain"
default: "/secrets/groombook/groombook-ceo.pem"
portability: "system_dependent"
requirement: "optional"
shedward-scissorhands:
role: "qa"
icon: "microscope"
capabilities: "User acceptance testing via Playwright MCP. Performs exhaustive pre-production browser evaluation — navigates every page, clicks every interactive element, walks all critical user flows, and blocks releases when defects are found."
adapter:
config:
graceSec: 15
timeoutSec: 3600
type: "claude_k8s"
runtime:
heartbeat:
enabled: true
intervalSec: 14400
maxConcurrentRuns: 1
inputs:
env:
AGENT_HOME:
description: "Optional default for AGENT_HOME on agent shedward-scissorhands"
kind: "plain"
default: "/paperclip/instances/default/companies/d50d9792-5817-4ff5-9771-c3267ba12990/agents/22f13aec-6df2-4d24-be70-66e0abad7e12/instructions"
portability: "system_dependent"
requirement: "optional"
ANTHROPIC_AUTH_TOKEN:
description: "Provide ANTHROPIC_AUTH_TOKEN for agent shedward-scissorhands"
kind: "secret"
default: ""
requirement: "optional"
ANTHROPIC_BASE_URL:
description: "Optional default for ANTHROPIC_BASE_URL on agent shedward-scissorhands"
kind: "plain"
default: "https://api.minimax.io/anthropic"
requirement: "optional"
ANTHROPIC_DEFAULT_HAIKU_MODEL:
description: "Optional default for ANTHROPIC_DEFAULT_HAIKU_MODEL on agent shedward-scissorhands"
kind: "plain"
default: "MiniMax-M2.7"
requirement: "optional"
ANTHROPIC_DEFAULT_OPUS_MODEL:
description: "Optional default for ANTHROPIC_DEFAULT_OPUS_MODEL on agent shedward-scissorhands"
kind: "plain"
default: "MiniMax-M2.7"
requirement: "optional"
ANTHROPIC_DEFAULT_SONNET_MODEL:
description: "Optional default for ANTHROPIC_DEFAULT_SONNET_MODEL on agent shedward-scissorhands"
kind: "plain"
default: "MiniMax-M2.7"
requirement: "optional"
ANTHROPIC_MODEL:
description: "Optional default for ANTHROPIC_MODEL on agent shedward-scissorhands"
kind: "plain"
default: "MiniMax-M2.7"
requirement: "optional"
ANTHRPOIC_SMALL_FAST_MODEL:
description: "Optional default for ANTHRPOIC_SMALL_FAST_MODEL on agent shedward-scissorhands"
kind: "plain"
default: "MiniMax-M2.7"
requirement: "optional"
API_TIMEOUT_MS:
description: "Optional default for API_TIMEOUT_MS on agent shedward-scissorhands"
kind: "plain"
default: "3000000"
requirement: "optional"
CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS:
description: "Optional default for CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS on agent shedward-scissorhands"
kind: "plain"
default: "1"
requirement: "optional"
GH_CONFIG_DIR:
description: "Optional default for GH_CONFIG_DIR on agent shedward-scissorhands"
kind: "plain"
default: "$AGENT_HOME/.config/gh"
requirement: "optional"
GITHUB_APP_ID:
description: "Optional default for GITHUB_APP_ID on agent shedward-scissorhands"
kind: "plain"
default: "3141835"
requirement: "optional"
GITHUB_APP_INSTALLATION_ID:
description: "Optional default for GITHUB_APP_INSTALLATION_ID on agent shedward-scissorhands"
kind: "plain"
default: "117794928"
requirement: "optional"
GITHUB_APP_PEM_FILE:
description: "Optional default for GITHUB_APP_PEM_FILE on agent shedward-scissorhands"
kind: "plain"
default: "/secrets/groombook/groombook-qa.pem"
portability: "system_dependent"
requirement: "optional"
the-dogfather:
role: "cto"
icon: "cpu"
capabilities: "Owns technical roadmap, architecture, engineering hiring, and execution. First engineering leader for a pet grooming platform."
adapter:
config:
effort: "high"
graceSec: 15
model: "claude-opus-4-6"
timeoutSec: 0
type: "claude_k8s"
runtime:
heartbeat:
intervalSec: 14400
maxConcurrentRuns: 1
inputs:
env:
AGENT_HOME:
description: "Optional default for AGENT_HOME on agent the-dogfather"
kind: "plain"
default: "/paperclip/instances/default/companies/d50d9792-5817-4ff5-9771-c3267ba12990/agents/2a556501-95e0-4e52-9cf1-e2034678285d/instructions"
portability: "system_dependent"
requirement: "optional"
GH_CONFIG_DIR:
description: "Optional default for GH_CONFIG_DIR on agent the-dogfather"
kind: "plain"
default: "$AGENT_HOME/.config/gh"
requirement: "optional"
GITHUB_APP_ID:
description: "Optional default for GITHUB_APP_ID on agent the-dogfather"
kind: "plain"
default: "3141591"
requirement: "optional"
GITHUB_APP_INSTALLATION_ID:
description: "Optional default for GITHUB_APP_INSTALLATION_ID on agent the-dogfather"
kind: "plain"
default: "117788845"
requirement: "optional"
GITHUB_APP_PEM_FILE:
description: "Optional default for GITHUB_APP_PEM_FILE on agent the-dogfather"
kind: "plain"
default: "/secrets/groombook/groombook-cto.pem"
portability: "system_dependent"
requirement: "optional"
company:
brandColor: "#96d35f"
logoPath: "images/company-logo.png"
sidebar:
agents:
- "scrubs-mcbarkley"
- "pawla-abdul"
- "the-dogfather"
- "barkley-trimsworth"
- "flea-flicker"
- "lint-roller"
- "shedward-scissorhands"
-39
View File
@@ -1,39 +0,0 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## What This Repo Is
This is the **GitHub org-level configuration repository** (`groombook/.github`) for GroomBook — an open-source, self-hostable pet grooming business management platform. It contains:
- `profile/` — GitHub organization profile README and logo
- `company/` — Paperclip AI company configuration export (agent definitions, skills, projects)
There is no application code, build system, or test suite here. This repo is purely configuration and documentation.
## Related Repositories
| Repo | Purpose |
|------|---------|
| `groombook/groombook` | Primary application (TypeScript, Node.js, React, PostgreSQL) |
| `groombook/agents` | Canonical agent definitions — prompts, personas, heartbeats, adapter configs |
| `groombook/infra` | Kubernetes manifests for Flux GitOps deployment |
## Company Directory (`company/`)
This is an export from [Paperclip](https://paperclip.ing) and contains a snapshot of the agent company configuration:
- `.paperclip.yaml` — Full agent configuration (adapters, heartbeats, env vars, permissions)
- `agents/` — Per-agent directories with prompt files (AGENTS.md, SOUL.md, HEARTBEAT.md, etc.)
- `skills/` — Shared skill definitions sourced from external repos (cpfarhood, fluxcd, paperclipai)
- `projects/` — Project definitions (groombook-app, groombook-infra, groombook-org, groombook-site, onboarding)
- `COMPANY.md` — Company metadata frontmatter
The canonical source for agent configurations is the `groombook/agents` repo. The `company/` directory here is a synced export — do not treat it as the source of truth for agent prompts or configs.
## Key Policies
- **Container images**: `ghcr.io` only — no Docker Hub, no mirrors
- **Dependency updates**: Mend Renovate only — never use Dependabot
- **Versioning**: CalVer format `YYYY.MDD.PATCH` (e.g., `2026.318.0`), not SemVer
- **All PRs**: Include `cc @cpfarhood` at the bottom of the PR body
-7
View File
@@ -1,7 +0,0 @@
---
name: "GroomBook"
description: "An open source business management solution for pet groomers."
schema: "agentcompanies/v1"
slug: "groombook"
---
-62
View File
@@ -1,62 +0,0 @@
# GroomBook
> An open source business management solution for pet groomers.
![Org Chart](images/org-chart.png)
## What's Inside
> This is an [Agent Company](https://agentcompanies.io) package from [Paperclip](https://paperclip.ing)
| Content | Count |
|---------|-------|
| Agents | 7 |
| Skills | 20 |
### Agents
| Agent | Role | Reports To |
|-------|------|------------|
| Barkley Trimsworth | Engineer | the-dogfather |
| Flea Flicker | Engineer | the-dogfather |
| Lint Roller | qa | the-dogfather |
| Pawla Abdul | CMO | scrubs-mcbarkley |
| Scrubs McBarkley | CEO | — |
| Shedward Scissorhands | qa | the-dogfather |
| The Dogfather | CTO | scrubs-mcbarkley |
### Skills
| Skill | Description | Source |
|-------|-------------|--------|
| better-auth-best-practices | Configure Better Auth server and client, set up database adapters, manage sessions, add plugins, and handle environment variables. Use when users mention Better Auth, betterauth, auth.ts, or need to set up TypeScript authentication with email/password, OAuth, or plugin configuration. | [github](https://github.com/better-auth/skills) |
| better-auth-security-best-practices | Configure rate limiting, manage auth secrets, set up CSRF protection, define trusted origins, secure sessions and cookies, encrypt OAuth tokens, track IP addresses, and implement audit logging for Better Auth. Use when users need to secure their auth setup, prevent brute force attacks, or harden a Better Auth deployment. | [github](https://github.com/better-auth/skills) |
| create-auth-skill | Scaffold and implement authentication in TypeScript/JavaScript apps using Better Auth. Detect frameworks, configure database adapters, set up route handlers, add OAuth providers, and create auth UI pages. Use when users want to add login, sign-up, or authentication to a new or existing project with Better Auth. | [github](https://github.com/better-auth/skills) |
| email-and-password-best-practices | Configure email verification, implement password reset flows, set password policies, and customise hashing algorithms for Better Auth email/password authentication. Use when users need to set up login, sign-in, sign-up, credential authentication, or password security with Better Auth. | [github](https://github.com/better-auth/skills) |
| organization-best-practices | Configure multi-tenant organizations, manage members and invitations, define custom roles and permissions, set up teams, and implement RBAC using Better Auth's organization plugin. Use when users need org setup, team management, member roles, access control, or the Better Auth organization plugin. | [github](https://github.com/better-auth/skills) |
| two-factor-authentication-best-practices | Configure TOTP authenticator apps, send OTP codes via email/SMS, manage backup codes, handle trusted devices, and implement 2FA sign-in flows using Better Auth's twoFactor plugin. Use when users need MFA, multi-factor authentication, authenticator setup, or login security with Better Auth. | [github](https://github.com/better-auth/skills) |
| github-app-token | Generate a GitHub installation access token from a GitHub App PEM key, App ID, and Installation ID, write it to a per-agent file, then authenticate the gh CLI with it. | [github](https://github.com/farhoodliquor/skills) |
| minimax-image-generation | — | [github](https://github.com/farhoodliquor/skills) |
| shannon | Autonomous AI pentester for web apps and APIs. Run white-box security assessments with Shannon — analyzes source code, identifies attack vectors, and executes real exploits to prove vulnerabilities. Triggered by 'shannon', 'pentest', 'security audit', 'vuln scan'. | [github](https://github.com/farhoodliquor/skills) |
| commit-assisted-by | > | [github](https://github.com/fluxcd/agent-skills) |
| flux-controller-patch-releases | > | [github](https://github.com/fluxcd/agent-skills) |
| gitops-cluster-debug | > | [github](https://github.com/fluxcd/agent-skills) |
| gitops-knowledge | > | [github](https://github.com/fluxcd/agent-skills) |
| gitops-repo-audit | > | [github](https://github.com/fluxcd/agent-skills) |
| check-pr | > | [github](https://github.com/greptileai/skills) |
| greploop | > | [github](https://github.com/greptileai/skills) |
| paperclip-create-agent | > | [github](https://github.com/paperclipai/paperclip/tree/master/skills/paperclip-create-agent) |
| paperclip-create-plugin | > | [github](https://github.com/paperclipai/paperclip/tree/master/skills/paperclip-create-plugin) |
| paperclip | > | [github](https://github.com/paperclipai/paperclip/tree/master/skills/paperclip) |
| para-memory-files | > | [github](https://github.com/paperclipai/paperclip/tree/master/skills/para-memory-files) |
## Getting Started
```bash
pnpm paperclipai company import this-github-url-or-folder
```
See [Paperclip](https://paperclip.ing) for more information.
---
Exported from [Paperclip](https://paperclip.ing) on 2026-04-16

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 1.2 MiB

-6
View File
@@ -1,6 +0,0 @@
---
name: "GroomBook App"
description: "This git repository is the primary GroomBook Application source code and associated build artifacts."
---
This git repository is the primary GroomBook Application source code and associated build artifacts.
-6
View File
@@ -1,6 +0,0 @@
---
name: "GroomBook Infra"
description: "This repository is the infrastructure associated with the development and production/demo instances of GroomBook. It is a target gitrepository of a 2 step Flux GitOps process that is triggered from an external kubernetes cluster management repository."
---
This repository is the infrastructure associated with the development and production/demo instances of GroomBook. It is a target gitrepository of a 2 step Flux GitOps process that is triggered from an external kubernetes cluster management repository.
-6
View File
@@ -1,6 +0,0 @@
---
name: "GroomBook Org"
description: "This repository houses the organization level GitHub Pages as well as shared GitHub Actions."
---
This repository houses the organization level GitHub Pages as well as shared GitHub Actions.
-6
View File
@@ -1,6 +0,0 @@
---
name: "GroomBook Site"
description: "This repository houses the primary GitHub Pages based site for the GroomBook Platform."
---
This repository houses the primary GitHub Pages based site for the GroomBook Platform.
-4
View File
@@ -1,4 +0,0 @@
---
name: "Onboarding"
---
+16 -12
View File
@@ -1,25 +1,29 @@
--- ---
name: sdlc name: sdlc
description: > description: >
Software development lifecycle for GroomBook. Covers GitHub authentication, Software development lifecycle for GroomBook. Covers Gitea authentication,
branch strategy across Dev/UAT/Prod, the four-phase SDLC pipeline with branch strategy across Dev/UAT/Prod, the four-phase SDLC pipeline with
product analysis intake, PR review and merge policy, the handoff protocol, product analysis intake, PR review and merge policy, the handoff protocol,
status semantics, infrastructure layout, the canonical tools list, the status semantics, infrastructure layout, the canonical tools list, the
GitHub-origin issue board-approval gate, the cc-cpfarhood visibility rule, Gitea-origin issue board-approval gate, the cc-cpfarhood visibility rule,
the scheduled penetration testing program, and delegation model tier policy. the scheduled penetration testing program, and delegation model tier policy.
--- ---
# Software Development Lifecycle # Software Development Lifecycle
## GitHub authentication ## Gitea authentication
**Invoke the `github-app-token` skill** before any GitHub operation. It generates a short-lived installation token and sets `GH_TOKEN`. **Never** run `gh auth login` — it hangs headless agents. Token expires after ~1 hour; re-invoke to regenerate. **Use the `tea` CLI** with the `GITEA_TOKEN` environment variable for all Gitea operations. Configure it once:
GitHub is the **primary source of truth**. Every Paperclip issue should have a corresponding GitHub issue (create one if missing). Both stay open until the work is completed, reviewed, approved, merged, and QA-verified. ```bash
tea login add --url https://git.farh.net --token $GITEA_TOKEN --name groombook
```
## GitHub-origin issue policy — board approval required Gitea is the **primary source of truth**. Every Paperclip issue should have a corresponding Gitea issue (create one if missing). Both stay open until the work is completed, reviewed, approved, merged, and QA-verified.
If a task originated from GitHub (`originKind: "github"`), **do not begin work**. Immediately create a board approval: ## Gitea-origin issue policy — board approval required
If a task originated from Gitea (`originKind: "gitea"`), **do not begin work**. Immediately create a board approval:
``` ```
POST /api/companies/{companyId}/approvals POST /api/companies/{companyId}/approvals
@@ -28,8 +32,8 @@ POST /api/companies/{companyId}/approvals
"requestedByAgentId": "{your-agent-id}", "requestedByAgentId": "{your-agent-id}",
"issueIds": ["{issueId}"], "issueIds": ["{issueId}"],
"payload": { "payload": {
"title": "Board approval required: GitHub issue", "title": "Board approval required: Gitea issue",
"summary": "Summarize what the GitHub issue requests.", "summary": "Summarize what the Gitea issue requests.",
"recommendedAction": "Approve to begin work.", "recommendedAction": "Approve to begin work.",
"risks": ["Work begins without board review if approved."] "risks": ["Work begins without board review if approved."]
} }
@@ -55,7 +59,7 @@ Three long-lived branches map to the three deployment environments:
All changes happen via pull request. Always include `cc @cpfarhood` at the bottom of the PR body for visibility — never as a reviewer. All changes happen via pull request. Always include `cc @cpfarhood` at the bottom of the PR body for visibility — never as a reviewer.
```bash ```bash
gh pr create --base dev --title "..." --body "... cc @cpfarhood" tea pr create --base dev --title "..." --body "... cc @cpfarhood"
``` ```
## PR review & merge policy ## PR review & merge policy
@@ -79,7 +83,7 @@ gh pr create --base dev --title "..." --body "... cc @cpfarhood"
### Phase 0 — Product analysis (feature intake) ### Phase 0 — Product analysis (feature intake)
* Feature requests arrive at the CEO via Paperclip or GitHub Issues. * Feature requests arrive at the CEO via Paperclip or Gitea Issues.
* CEO delegates to CMPO (Pawla Abdul) for review. * CEO delegates to CMPO (Pawla Abdul) for review.
* CMPO returns one of three decisions: * CMPO returns one of three decisions:
* **Accepted** → CEO routes to CTO for work breakdown. * **Accepted** → CEO routes to CTO for work breakdown.
@@ -176,7 +180,7 @@ Without this release, the receiving agent cannot check out the issue.
## Deployment — 2-stage Flux GitOps ## Deployment — 2-stage Flux GitOps
**Stage 1 — CI (GitHub Actions, runs in each application repo):** **Stage 1 — CI (Gitea Actions, uses GitHub Actions-compatible YAML syntax, runs in each application repo):**
- Triggered automatically on every merge to `main` - Triggered automatically on every merge to `main`
- Builds and tags the Docker image - Builds and tags the Docker image
- Pushes tagged images to `ghcr.io/groombook/<service>` - Pushes tagged images to `ghcr.io/groombook/<service>`