feat(agent/plugins): create plugins/{core-go,core-php,infra} tree (RFC.plugin-restructure §1+§2)

plugins/ subtree created from scratch (no dappcore-go/dappcore-php
existed to rename). Per docs/RFC-AGENT-PLUGIN-RESTRUCTURE.md:

plugins/core-go/:
- .claude-plugin/plugin.json (name: core-go)
- README.md, marketplace.yaml, .mcp.json (calls core mcp serve)
- commands/{commit,qa,review,verify}.md
- skills/{core,core-go,go-agent}/SKILL.md (seeded from existing repo material)
- skills/api-endpoints/SKILL.md (NEW per ticket)
- agents/go-developer.md
- hook scripts referenced by commands

plugins/core-php/: same structure, php-developer agent + php-specific
api-endpoints skill.

plugins/infra/: plugin.json, README.md, marketplace.yaml, agents/infra-ops.md.

Manifests use core-* not dappcore-*. .mcp.json files call core mcp serve.
No dappcore-* names left.

Note: seed skills copied from existing repo material per ticket spec —
some upstream Host UK examples remain in copied skill docs. Future PR
can purge those if Host UK references are out of scope for the public
plugin marketplace.

Co-authored-by: Codex <noreply@openai.com>
Closes tasks.lthn.sh/view.php?id=234
This commit is contained in:
Snider 2026-04-25 20:04:50 +01:00
parent fbee790859
commit 55bc34c885
36 changed files with 2468 additions and 0 deletions

View file

@ -0,0 +1,18 @@
{
"name": "core-go",
"version": "0.1.0",
"description": "Claude plugin family for Core Go services, libraries, and tooling.",
"author": {
"name": "Lethean Community",
"email": "hello@lethean.io"
},
"homepage": "https://lthn.ai",
"repository": "https://forge.lthn.ai/core/agent.git",
"license": "EUPL-1.2",
"keywords": [
"claude",
"core",
"go",
"agent"
]
}

View file

@ -0,0 +1,9 @@
{
"mcpServers": {
"core": {
"type": "stdio",
"command": "core",
"args": ["mcp", "serve"]
}
}
}

View file

@ -0,0 +1,6 @@
# core-go
This plugin family covers Claude workflows for Core Go services and shared libraries.
It is the canonical home for Go-focused commands, agents, and skills in the Core ecosystem.
The scope includes service scaffolding, package conventions, QA, verification, and release support.
Marketplace metadata for this family is defined in `marketplace.yaml`.
Commands, agents, and skills here are seeded from the existing Claude and Codex plugin material in this repository.

View file

@ -0,0 +1,24 @@
---
name: go-developer
description: Go development agent for Core services and libraries. Derived from the existing core-go and go-agent skills.
tools: Bash, Read, Edit, MultiEdit, Grep, Glob, LS
model: sonnet
color: green
---
You are a Go developer working in the Core ecosystem.
## Working rules
- Follow the package and CLI conventions in `skills/core/SKILL.md` and `skills/core-go/SKILL.md`.
- Use the delivery loop in `skills/go-agent/SKILL.md` when the task requires autonomous implementation.
- Prefer `core go test`, `core go lint`, `core go fmt`, and `core build` over raw toolchain commands when the wrapper exists.
- Keep user-facing strings in UK English.
- Use the Good/Bad/Ugly test naming pattern described by the existing Go skill.
## Delivery standard
1. Read the package structure before adding new code.
2. Keep changes small, typed, and test-backed.
3. Fix the root cause, not just the failing symptom.
4. Run QA and verification before stopping.

View file

@ -0,0 +1,52 @@
---
name: commit
description: Generate a conventional commit message for staged changes
args: "[message]"
flags:
- --amend
hooks:
Before:
- hooks:
- type: command
command: "${CLAUDE_PLUGIN_ROOT}/scripts/smart-commit.sh"
---
# Smart Commit
Generate a conventional commit message for staged changes.
## Usage
Generate message automatically:
`/core-go:commit`
Provide a custom message:
`/core-go:commit "feat(auth): add token validation"`
Amend the previous commit:
`/core-go:commit --amend`
## Behavior
1. **Analyze Staged Changes**: Examines the `git diff --staged` to understand the nature of the changes.
2. **Generate Conventional Commit Message**:
- `feat`: For new files, functions, or features.
- `fix`: For bug fixes.
- `refactor`: For code restructuring without changing external behavior.
- `docs`: For changes to documentation.
- `test`: For adding or modifying tests.
- `chore`: For routine maintenance tasks.
3. **Determine Scope**: Infers the scope from the affected module's file paths (e.g., `auth`, `payment`, `ui`).
4. **Add Co-Authored-By Trailer**: Appends `Co-Authored-By: Claude <noreply@anthropic.com>` to the commit message.
## Message Generation Example
```
feat(auth): add JWT token validation
- Add validateToken() function
- Add token expiry check
- Add unit tests for validation
Co-Authored-By: Claude <noreply@anthropic.com>
```

View file

@ -0,0 +1,128 @@
---
name: qa
description: Run Go QA checks and fix all issues iteratively
hooks:
PostToolUse:
- matcher: "Bash"
hooks:
- type: command
command: "${CLAUDE_PLUGIN_ROOT}/scripts/qa-filter.sh"
Stop:
- hooks:
- type: command
command: "${CLAUDE_PLUGIN_ROOT}/scripts/qa-verify.sh"
once: true
---
# QA Fix Loop
Run the full Go QA pipeline and fix all issues.
## Process
1. **Run QA**: Execute `core go qa`
2. **Parse issues**: Extract failures from output (see format below)
3. **Fix each issue**: Address one at a time, simplest first
4. **Re-verify**: After fixes, re-run QA
5. **Repeat**: Until all checks pass
6. **Report**: Summary of what was fixed
## Issue Priority
Fix in this order (fastest feedback first):
1. **fmt** - formatting issues (auto-fix with `core go fmt`)
2. **lint** - static analysis (usually quick fixes)
3. **test** - failing tests (may need more investigation)
4. **build** - compilation errors (fix before tests can run)
## Output Parsing
### Go QA Output
```
=== FMT ===
FAIL: pkg/api/handler.go needs formatting
=== LINT ===
pkg/api/handler.go:42:15: undefined: ErrNotFound (typecheck)
pkg/api/handler.go:87:2: ineffectual assignment to err (ineffassign)
=== TEST ===
--- FAIL: TestCreateUser (0.02s)
handler_test.go:45: expected 200, got 500
FAIL
=== RESULT ===
fmt: FAIL
lint: FAIL (2 issues)
test: FAIL (1 failed)
```
## Fixing Strategy
**Formatting (fmt):**
- Just run `core go fmt`
- No code reading needed
**Lint errors:**
- Read the specific file:line
- Understand the error type
- Make minimal fix
**Test failures:**
- Read the test file to understand expectation
- Read the implementation
- Fix the root cause (not just the symptom)
**Build errors:**
- Usually missing imports or typos
- Fix before attempting other checks
## Stop Condition
Only stop when:
- All QA checks pass, OR
- User explicitly cancels, OR
- Same error repeats 3 times (stuck - ask for help)
## Example Session
```
Running: core go qa
## QA Issues
pkg/api/handler.go:42:15: undefined: ErrNotFound
--- FAIL: TestCreateUser (0.02s)
**Summary:** lint: FAIL (1) | test: FAIL (1)
---
Fixing lint issue: undefined ErrNotFound
Reading pkg/api/handler.go...
Adding error variable definition.
Running: core go qa
## QA Issues
--- FAIL: TestCreateUser (0.02s)
expected 200, got 404
**Summary:** lint: PASS | test: FAIL (1)
---
Fixing test issue: expected 200, got 404
Reading test setup...
Correcting test data.
Running: core go qa
✓ All checks passed!
**Summary:**
- Fixed: undefined ErrNotFound (added error variable)
- Fixed: TestCreateUser (corrected test setup)
- 2 issues resolved, all checks passing
```

View file

@ -0,0 +1,63 @@
---
name: review
description: Perform code review on staged changes or PRs
args: [commit-range|--pr=N|--security]
---
# Code Review
Perform a thorough code review of the specified changes.
## Arguments
- No args: Review staged changes
- `HEAD~3..HEAD`: Review last 3 commits
- `--pr=123`: Review PR #123
- `--security`: Focus on security issues
## Process
1. **Gather changes**: Get diff for the specified range
2. **Analyse each file**: Review for issues by category
3. **Report findings**: Output structured review
## Review Checklist
| Category | Checks |
|----------|--------|
| **Correctness** | Logic errors, edge cases, error handling |
| **Security** | SQL injection, XSS, hardcoded secrets, CSRF |
| **Performance** | N+1 queries, unnecessary loops, large allocations |
| **Maintainability** | Naming, structure, complexity |
| **Tests** | Coverage gaps, missing assertions |
## Output Format
```markdown
## Code Review: [title]
### Critical
- **file:line** - Issue description
### Warning
- **file:line** - Issue description
### Suggestions
- **file:line** - Improvement idea
---
**Summary**: X critical, Y warnings, Z suggestions
```
## Commands
```bash
# Get staged diff
git diff --cached
# Get PR diff
gh pr diff 123
# Get commit range diff
git diff HEAD~3..HEAD
```

View file

@ -0,0 +1,75 @@
---
name: verify
description: Verify work is complete before stopping
args: [--quick|--full]
---
# Work Verification
Verify that Go work is complete and ready to commit/push.
## Arguments
- No args: Standard verification
- `--quick`: Fast checks only (format, lint)
- `--full`: All checks including slow tests
## Verification Steps
### 1. Check for uncommitted changes
```bash
git status --porcelain
```
### 2. Check for debug statements
Look for:
- Go: `fmt.Println`, `log.Println`, `spew.Dump`
- PHP: `dd(`, `dump(`, `var_dump(`, `ray(`
- JS/TS: `console.log`, `debugger`
### 3. Run tests
```bash
core go test
```
### 4. Run linter
```bash
core go lint
```
### 5. Check formatting
```bash
core go fmt --check
```
## Output
Report verification status:
```
## Verification Results
✓ No uncommitted changes
✓ No debug statements found
✓ Tests passing (47/47)
✓ Lint clean
✓ Formatting correct
**Status: READY**
```
Or if issues found:
```
## Verification Results
✓ No uncommitted changes
✗ Debug statement found: src/handler.go:42
✗ Tests failing (45/47)
✓ Lint clean
✓ Formatting correct
**Status: NOT READY**
Fix these issues before proceeding.
```

View file

@ -0,0 +1,6 @@
marketplace:
registry: forge.lthn.ai
organization: core
repository: core-go
auto_update: true
check_interval: 24h

View file

@ -0,0 +1,62 @@
#!/bin/bash
# Filter QA output to show only actionable issues during /core:qa mode
#
# PostToolUse hook that processes QA command output and extracts
# only the failures, hiding verbose success output.
read -r input
COMMAND=$(echo "$input" | jq -r '.tool_input.command // empty')
OUTPUT=$(echo "$input" | jq -r '.tool_response.stdout // .tool_response.output // empty')
EXIT_CODE=$(echo "$input" | jq -r '.tool_response.exit_code // 0')
# Only process QA-related commands
case "$COMMAND" in
"core go qa"*|"core php qa"*|"core go test"*|"core php test"*|"core go lint"*|"core php stan"*)
;;
*)
# Not a QA command, pass through unchanged
echo "$input"
exit 0
;;
esac
# Extract failures from output
FAILURES=$(echo "$OUTPUT" | grep -E "^(FAIL|---\s*FAIL|✗|ERROR|undefined:|error:|panic:)" | head -20)
SUMMARY=$(echo "$OUTPUT" | grep -E "^(fmt:|lint:|test:|pint:|stan:|=== RESULT ===)" | tail -5)
# Also grab specific error lines with file:line references
FILE_ERRORS=$(echo "$OUTPUT" | grep -E "^[a-zA-Z0-9_/.-]+\.(go|php):[0-9]+:" | head -10)
if [ -z "$FAILURES" ] && [ "$EXIT_CODE" = "0" ]; then
# All passed - show brief confirmation
cat << 'EOF'
{
"suppressOutput": true,
"hookSpecificOutput": {
"hookEventName": "PostToolUse",
"additionalContext": "✓ QA passed"
}
}
EOF
else
# Combine failures and file errors
ISSUES="$FAILURES"
if [ -n "$FILE_ERRORS" ]; then
ISSUES="$ISSUES
$FILE_ERRORS"
fi
# Escape for JSON
ISSUES_ESCAPED=$(echo "$ISSUES" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/\\n/g')
SUMMARY_ESCAPED=$(echo "$SUMMARY" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/ | /g')
cat << EOF
{
"suppressOutput": true,
"hookSpecificOutput": {
"hookEventName": "PostToolUse",
"additionalContext": "## QA Issues\n\n\`\`\`\n$ISSUES_ESCAPED\n\`\`\`\n\n**Summary:** $SUMMARY_ESCAPED"
}
}
EOF
fi

View file

@ -0,0 +1,28 @@
#!/bin/bash
# Verify QA passes before stopping during /core-go:qa mode.
read -r input
STOP_ACTIVE=$(echo "$input" | jq -r '.stop_hook_active // false')
# Prevent infinite loop
if [ "$STOP_ACTIVE" = "true" ]; then
exit 0
fi
# Run Go QA for this plugin family.
RESULT=$(core go qa 2>&1) || true
# Check if QA passed
if echo "$RESULT" | grep -qE "FAIL|ERROR|✗|panic:|undefined:"; then
ISSUES=$(echo "$RESULT" | grep -E "^(FAIL|ERROR|✗|undefined:|panic:)|^[a-zA-Z0-9_/.-]+\.go:[0-9]+:" | head -5)
ISSUES_ESCAPED=$(echo "$ISSUES" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/\\n/g')
cat << EOF
{
"decision": "block",
"reason": "QA still has issues:\n\n$ISSUES_ESCAPED\n\nPlease fix these before stopping."
}
EOF
else
exit 0
fi

View file

@ -0,0 +1,108 @@
#!/bin/bash
# Smart commit script for /core:commit command
CUSTOM_MESSAGE=""
AMEND_FLAG=""
# Parse arguments
while (( "$#" )); do
case "$1" in
--amend)
AMEND_FLAG="--amend"
shift
;;
-*)
echo "Unsupported flag $1" >&2
exit 1
;;
*)
# The rest of the arguments are treated as the commit message
CUSTOM_MESSAGE="$@"
break
;;
esac
done
# Get staged changes
STAGED_FILES=$(git diff --staged --name-status)
if [ -z "$STAGED_FILES" ]; then
echo "No staged changes to commit."
exit 0
fi
# Determine commit type and scope
COMMIT_TYPE="chore" # Default to chore
SCOPE=""
# Get just the file paths
STAGED_FILE_PATHS=$(git diff --staged --name-only)
# Determine type from file paths/status
# Order is important here: test and docs are more specific than feat.
if echo "$STAGED_FILE_PATHS" | grep -q -E "(_test\.go|\.test\.js|/tests/|/spec/)"; then
COMMIT_TYPE="test"
elif echo "$STAGED_FILE_PATHS" | grep -q -E "(\.md|/docs/|README)"; then
COMMIT_TYPE="docs"
elif echo "$STAGED_FILES" | grep -q "^A"; then
COMMIT_TYPE="feat"
elif git diff --staged | grep -q -E "^\+.*(fix|bug|issue)"; then
COMMIT_TYPE="fix"
elif git diff --staged | grep -q -E "^\+.*(refactor|restructure)"; then
COMMIT_TYPE="refactor"
fi
# Determine scope from the most common path component
if [ -n "$STAGED_FILE_PATHS" ]; then
# Extract the second component of each path (e.g., 'code' from 'claude/code/file.md')
# This is a decent heuristic for module name.
# We filter for lines that have a second component.
POSSIBLE_SCOPES=$(echo "$STAGED_FILE_PATHS" | grep '/' | cut -d/ -f2)
if [ -n "$POSSIBLE_SCOPES" ]; then
SCOPE=$(echo "$POSSIBLE_SCOPES" | sort | uniq -c | sort -nr | head -n 1 | awk '{print $2}')
fi
# If no scope is found (e.g., all files are in root), SCOPE remains empty, which is valid.
fi
# Construct the commit message
if [ -n "$CUSTOM_MESSAGE" ]; then
COMMIT_MESSAGE="$CUSTOM_MESSAGE"
else
# Auto-generate a descriptive summary
DIFF_CONTENT=$(git diff --staged)
# Try to find a function or class name from the diff
# This is a simple heuristic that can be greatly expanded.
SUMMARY=$(echo "$DIFF_CONTENT" | grep -E -o "(function|class|def) \w+" | head -n 1 | sed -e 's/function //g' -e 's/class //g' -e 's/def //g')
if [ -z "$SUMMARY" ]; then
if [ $(echo "$STAGED_FILE_PATHS" | wc -l) -eq 1 ]; then
FIRST_FILE=$(echo "$STAGED_FILE_PATHS" | head -n 1)
SUMMARY="update $(basename "$FIRST_FILE")"
else
SUMMARY="update multiple files"
fi
else
SUMMARY="update $SUMMARY"
fi
SUBJECT="$COMMIT_TYPE($SCOPE): $SUMMARY"
BODY=$(echo "$DIFF_CONTENT" | grep -E "^\+" | sed -e 's/^+//' | head -n 5 | sed 's/^/ - /')
COMMIT_MESSAGE="$SUBJECT\n\n$BODY"
fi
# Add Co-Authored-By trailer
CO_AUTHOR="Co-Authored-By: Claude <noreply@anthropic.com>"
if ! echo "$COMMIT_MESSAGE" | grep -q "$CO_AUTHOR"; then
COMMIT_MESSAGE="$COMMIT_MESSAGE\n\n$CO_AUTHOR"
fi
# Execute the commit
git commit $AMEND_FLAG -m "$(echo -e "$COMMIT_MESSAGE")"
if [ $? -eq 0 ]; then
echo "Commit successful."
else
echo "Commit failed."
exit 1
fi

View file

@ -0,0 +1,63 @@
---
name: api-endpoints
description: Use when a Core plugin needs to call api.lthn.sh or mcp.lthn.sh. Documents the JSON headers, auth, and endpoint conventions required by the plugin restructure RFC.
---
# API and MCP Endpoints
Use this skill when a command, script, or tool talks to the shared Core endpoints.
## Canonical endpoints
- `https://api.lthn.sh` — REST API
- `https://mcp.lthn.sh` — MCP bridge endpoint
These conventions apply to both production and self-hosted `lthn.sh` installs.
## Required headers
- Send `Accept: application/json` on every API request. The default response may be HTML if this header is missing.
- Send `Content-Type: application/json` for JSON request bodies.
- Send `Authorization: Bearer <token>` for authenticated requests.
## REST shape
- Use `/v1/{resource}` paths.
- Expect JSON request and response bodies.
- Keep request payloads explicit and small.
Example:
```bash
curl -s https://api.lthn.sh/v1/issues \
-H 'Accept: application/json' \
-H "Authorization: Bearer ${TOKEN}"
```
```bash
curl -s https://api.lthn.sh/v1/brain/recall \
-X POST \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer ${TOKEN}" \
-d '{"query":"dispatch status","top_k":3}'
```
## MCP usage
- Remote MCP can be reached at `https://mcp.lthn.sh`.
- Local plugin configs in this repository use `core mcp serve` through `.mcp.json`.
Local `.mcp.json` pattern:
```json
{
"mcpServers": {
"core": {
"type": "stdio",
"command": "core",
"args": ["mcp", "serve"]
}
}
}
```

View file

@ -0,0 +1,107 @@
---
name: core-go
description: Use when creating Go packages or extending the core CLI.
---
# Go Framework Patterns
Core CLI uses `pkg/` for reusable packages. Use `core go` commands.
## Package Structure
```
core/
├── main.go # CLI entry point
├── pkg/
│ ├── cli/ # CLI framework, output, errors
│ ├── {domain}/ # Domain package
│ │ ├── cmd_{name}.go # Cobra command definitions
│ │ ├── service.go # Business logic
│ │ └── *_test.go # Tests
│ └── ...
└── internal/ # Private packages
```
## Adding a CLI Command
1. Create `pkg/{domain}/cmd_{name}.go`:
```go
package domain
import (
"github.com/host-uk/core/pkg/cli"
"github.com/spf13/cobra"
)
func NewNameCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "name",
Short: cli.T("domain.name.short"),
RunE: func(cmd *cobra.Command, args []string) error {
// Implementation
cli.Success("Done")
return nil
},
}
return cmd
}
```
2. Register in parent command.
## CLI Output Helpers
```go
import "github.com/host-uk/core/pkg/cli"
cli.Success("Operation completed") // Green check
cli.Warning("Something to note") // Yellow warning
cli.Error("Something failed") // Red error
cli.Info("Informational message") // Blue info
cli.Fatal(err) // Print error and exit 1
// Structured output
cli.Table(headers, rows)
cli.JSON(data)
```
## i18n Pattern
```go
// Use cli.T() for translatable strings
cli.T("domain.action.success")
cli.T("domain.action.error", "details", value)
// Define in pkg/i18n/locales/en.yaml:
domain:
action:
success: "Operation completed successfully"
error: "Failed: {{.details}}"
```
## Test Naming
```go
func TestFeature_Good(t *testing.T) { /* happy path */ }
func TestFeature_Bad(t *testing.T) { /* expected errors */ }
func TestFeature_Ugly(t *testing.T) { /* panics, edge cases */ }
```
## Commands
| Task | Command |
|------|---------|
| Run tests | `core go test` |
| Coverage | `core go cov` |
| Format | `core go fmt --fix` |
| Lint | `core go lint` |
| Build | `core build` |
| Install | `core go install` |
## Rules
- `CGO_ENABLED=0` for all builds
- UK English in user-facing strings
- All errors via `cli.E("context", "message", err)`
- Table-driven tests preferred

View file

@ -0,0 +1,73 @@
---
name: core
description: Use when working in host-uk repositories, running tests, building, releasing, or managing multi-repo workflows. Provides the core CLI command reference.
---
# Core CLI
The `core` command provides a unified interface for Go/PHP development and multi-repo management.
**Rule:** Always prefer `core <command>` over raw commands.
## Quick Reference
| Task | Command |
|------|---------|
| Smart tests | `core test` |
| Go tests | `core go test` |
| Go coverage | `core go cov` |
| Go format | `core go fmt --fix` |
| Go lint | `core go lint` |
| PHP dev server | `core php dev` |
| PHP tests | `core php test` |
| PHP format | `core php fmt --fix` |
| Build | `core build` |
| Preview release | `core ci` |
| Publish | `core ci --were-go-for-launch` |
| Multi-repo status | `core dev health` |
| Commit dirty repos | `core dev commit` |
| Push repos | `core dev push` |
## Decision Tree
```
Go project?
tests: core go test
format: core go fmt --fix
build: core build
PHP project?
dev: core php dev
tests: core php test
format: core php fmt --fix
deploy: core php deploy
Multiple repos?
status: core dev health
commit: core dev commit
push: core dev push
```
## Common Mistakes
| Wrong | Right |
|-------|-------|
| `go test ./...` | `core go test` |
| `go build` | `core build` |
| `php artisan serve` | `core php dev` |
| `./vendor/bin/pest` | `core php test` |
| `git status` per repo | `core dev health` |
Run `core --help` or `core <cmd> --help` for full options.
## Smart Test Runner: `core test`
The `core test` command provides an intelligent way to run only the tests relevant to your recent changes.
- **`core test`**: Automatically detects changed files since the last commit and runs only the corresponding tests.
- **`core test --all`**: Runs the entire test suite for the project.
- **`core test --filter <TestName>`**: Runs a specific test by name.
- **`core test --coverage`**: Generates a test coverage report.
- **`core test <path/to/file>`**: Runs tests for a specific file or directory.
The runner automatically detects whether the project is Go or PHP and executes the appropriate testing tool. If it cannot map changed files to test files, it will fall back to running the full test suite.

View file

@ -0,0 +1,420 @@
---
name: go-agent
description: Autonomous Go development agent - picks up issues, implements, handles reviews, merges
---
# Go Agent Skill
You are an autonomous Go development agent working on the Host UK Go projects (primarily the `core` CLI). You continuously pick up issues, implement solutions, handle code reviews, and merge PRs.
## Workflow Loop
This skill runs as a continuous loop:
```
1. CHECK PENDING PRs → Fix reviews if CodeRabbit commented
2. FIND ISSUE → Pick a Go issue from host-uk org
3. IMPLEMENT → Create branch, code, test, push
4. HANDLE REVIEW → Wait for/fix CodeRabbit feedback
5. MERGE → Merge when approved
6. REPEAT → Start next task
```
## State Management
Track your work with these variables:
- `PENDING_PRS`: PRs waiting for CodeRabbit review
- `CURRENT_ISSUE`: Issue currently being worked on
- `CURRENT_BRANCH`: Branch for current work
---
## Step 1: Check Pending PRs
Before starting new work, check if any of your pending PRs have CodeRabbit reviews ready.
```bash
# List your open PRs in the core repo
gh pr list --repo host-uk/core --author=@me --state=open --json number,title,headRefName,url
# For each PR, check CodeRabbit status
gh api repos/host-uk/core/commits/{sha}/status --jq '.statuses[] | select(.context | contains("coderabbit")) | {context, state, description}'
```
### If CodeRabbit review is complete:
- **Success (no issues)**: Merge the PR
- **Has comments**: Fix the issues, commit, push, continue to next task
```bash
# Check for new reviews
gh api repos/host-uk/core/pulls/{pr_number}/reviews --jq 'sort_by(.submitted_at) | .[-1] | {author: .user.login, state: .state, body: .body[:500]}'
# If actionable comments, read and fix them
# Then commit and push:
git add -A && git commit -m "fix: address CodeRabbit feedback
Co-Authored-By: Claude <noreply@anthropic.com>"
git push
```
### Merging PRs
```bash
# When CodeRabbit approves (status: success), merge without admin
gh pr merge {pr_number} --squash --repo host-uk/core
```
---
## Step 2: Find an Issue
Search for Go issues in the Host UK organization.
```bash
# Find open issues labeled for Go
gh search issues --owner=host-uk --state=open --label="lang:go" --json number,title,repository,url --limit=10
# Or list issues in the core repo directly
gh issue list --repo host-uk/core --state=open --json number,title,labels,body --limit=20
# Check for agent-ready issues
gh issue list --repo host-uk/core --state=open --label="agent:ready" --json number,title,body
```
### Issue Selection Criteria
1. **Priority**: Issues with `priority:high` or `good-first-issue` labels
2. **Dependencies**: Check if issue depends on other incomplete work
3. **Scope**: Prefer issues that can be completed in one session
4. **Labels**: Look for `agent:ready`, `help-wanted`, or `enhancement`
### Claim the Issue
```bash
# Comment to claim the issue
gh issue comment {number} --repo host-uk/core --body "I'm picking this up. Starting work now."
# Assign yourself (if you have permission)
gh issue edit {number} --repo host-uk/core --add-assignee @me
```
---
## Step 3: Implement the Solution
### Setup Branch
```bash
# Navigate to the core package
cd packages/core
# Ensure you're on dev and up to date
git checkout dev && git pull
# Create feature branch
git checkout -b feature/issue-{number}-{short-description}
```
### Development Workflow
1. **Read the code** - Understand the package structure
2. **Write tests first** - TDD approach when possible
3. **Implement the solution** - Follow Go best practices
4. **Run tests** - Ensure all tests pass
```bash
# Run tests (using Task)
task test
# Or directly with go
go test ./...
# Run tests with coverage
task cov
# Run linting
task lint
# Or with golangci-lint directly
golangci-lint run
# Build to check compilation
go build ./...
```
### Go Code Quality Checklist
- [ ] Tests written and passing
- [ ] Code follows Go conventions (gofmt, effective go)
- [ ] Error handling is proper (no ignored errors)
- [ ] No unused imports or variables
- [ ] Documentation for exported functions
- [ ] Context passed where appropriate
- [ ] Interfaces used for testability
### Go-Specific Patterns
**Error Handling:**
```go
// Use errors.E for contextual errors
return errors.E("service.method", "what failed", err)
// Or errors.Wrap for wrapping
return errors.Wrap(err, "service.method", "description")
```
**Test Naming Convention:**
```go
// Use _Good, _Bad, _Ugly suffix pattern
func TestMyFunction_Good_ValidInput(t *testing.T) { ... }
func TestMyFunction_Bad_InvalidInput(t *testing.T) { ... }
func TestMyFunction_Ugly_PanicCase(t *testing.T) { ... }
```
**i18n Strings:**
```go
// Use i18n package for user-facing strings
i18n.T("cmd.mycommand.description")
i18n.Label("status")
```
### Creating Sub-Issues
If the issue reveals additional work needed:
```bash
# Create a follow-up issue
gh issue create --repo host-uk/core \
--title "Follow-up: {description}" \
--body "Discovered while working on #{original_issue}
## Context
{explain what was found}
## Proposed Solution
{describe the approach}
## References
- Parent issue: #{original_issue}" \
--label "lang:go,follow-up"
```
---
## Step 4: Push and Create PR
```bash
# Stage and commit
git add -A
git commit -m "feat({pkg}): {description}
{longer description if needed}
Closes #{issue_number}
Co-Authored-By: Claude <noreply@anthropic.com>"
# Push
git push -u origin feature/issue-{number}-{short-description}
# Create PR
gh pr create --repo host-uk/core \
--title "feat({pkg}): {description}" \
--body "$(cat <<'EOF'
## Summary
{Brief description of changes}
## Changes
- {Change 1}
- {Change 2}
## Test Plan
- [ ] Unit tests added/updated
- [ ] `task test` passes
- [ ] `task lint` passes
- [ ] Manual testing completed
Closes #{issue_number}
---
Generated with Claude Code
EOF
)"
```
---
## Step 5: Handle CodeRabbit Review
After pushing, CodeRabbit will automatically review. Track PR status:
```bash
# Check CodeRabbit status on latest commit
gh api repos/host-uk/core/commits/$(git rev-parse HEAD)/status --jq '.statuses[] | select(.context | contains("coderabbit"))'
```
### While Waiting
Instead of blocking, **start working on the next issue** (go to Step 2).
### When Review Arrives
```bash
# Check the review
gh api repos/host-uk/core/pulls/{pr_number}/reviews --jq '.[-1]'
# If "Actionable comments posted: N", fix them:
# 1. Read each comment
# 2. Make the fix
# 3. Commit with clear message
# 4. Push
```
### Common CodeRabbit Feedback for Go
- **Unused variables**: Remove or use them (Go compiler usually catches this)
- **Error not checked**: Handle or explicitly ignore with `_ =`
- **Missing context**: Add `ctx context.Context` parameter
- **Race conditions**: Use mutex or channels
- **Resource leaks**: Add `defer` for cleanup
- **Inefficient code**: Use `strings.Builder`, avoid allocations in loops
- **Missing documentation**: Add doc comments for exported symbols
---
## Step 6: Merge and Close
When CodeRabbit status shows "Review completed" with state "success":
```bash
# Merge the PR (squash merge)
gh pr merge {pr_number} --squash --repo host-uk/core
# The issue will auto-close if "Closes #N" was in PR body
# Otherwise, close manually:
gh issue close {number} --repo host-uk/core
```
---
## Step 7: Restart Loop
After merging:
1. Remove PR from `PENDING_PRS`
2. Check remaining pending PRs for reviews
3. Pick up next issue
4. **Restart this skill** to continue the loop
```
>>> LOOP COMPLETE - Restart /go-agent to continue working <<<
```
---
## Go Packages Reference (core CLI)
| Package | Purpose |
|---------|---------|
| `pkg/cli` | Command framework, styles, output |
| `pkg/errors` | Error handling with context |
| `pkg/i18n` | Internationalization |
| `pkg/qa` | QA commands (watch, review) |
| `pkg/setup` | Setup commands (github, bootstrap) |
| `pkg/dev` | Multi-repo dev workflow |
| `pkg/go` | Go tooling commands |
| `pkg/php` | PHP tooling commands |
| `pkg/build` | Build system |
| `pkg/release` | Release management |
| `pkg/sdk` | SDK generators |
| `pkg/container` | Container/VM management |
| `pkg/agentic` | Agent orchestration |
| `pkg/framework/core` | Core DI framework |
---
## Task Commands Reference
```bash
# Testing
task test # Run all tests
task test:verbose # Verbose output
task test:run -- Name # Run specific test
task cov # Coverage report
# Code Quality
task fmt # Format code
task lint # Run linter
task qa # Full QA (fmt, vet, lint, test)
task qa:quick # Quick QA (no tests)
# Building
task cli:build # Build CLI to ./bin/core
task cli:install # Install to system
# Other
task mod:tidy # go mod tidy
task review # CodeRabbit review
```
---
## Troubleshooting
### CodeRabbit Not Reviewing
```bash
# Check commit status
gh api repos/host-uk/core/commits/$(git rev-parse HEAD)/status
# Check if webhooks are configured
gh api repos/host-uk/core/hooks
```
### Tests Failing
```bash
# Run with verbose output
go test -v ./...
# Run specific test
go test -run TestName ./pkg/...
# Run with race detector
go test -race ./...
```
### Build Errors
```bash
# Check for missing dependencies
go mod tidy
# Verify build
go build ./...
# Check for vet issues
go vet ./...
```
### Merge Conflicts
```bash
# Rebase on dev
git fetch origin dev
git rebase origin/dev
# Resolve conflicts, then continue
git add .
git rebase --continue
git push --force-with-lease
```
---
## Best Practices
1. **One issue per PR** - Keep changes focused
2. **Small commits** - Easier to review and revert
3. **Descriptive messages** - Help future maintainers
4. **Test coverage** - Don't decrease coverage
5. **Documentation** - Update if behavior changes
6. **Error context** - Use errors.E with service.method prefix
7. **i18n strings** - Add to en_GB.json for user-facing text
## Labels Reference
- `lang:go` - Go code changes
- `agent:ready` - Ready for AI agent pickup
- `good-first-issue` - Simple, well-defined tasks
- `priority:high` - Should be addressed soon
- `follow-up` - Created from another issue
- `needs:review` - Awaiting human review
- `bug` - Something isn't working
- `enhancement` - New feature or improvement

View file

@ -0,0 +1,18 @@
{
"name": "core-php",
"version": "0.1.0",
"description": "Claude plugin family for Core PHP services, modules, and tooling.",
"author": {
"name": "Lethean Community",
"email": "hello@lethean.io"
},
"homepage": "https://lthn.ai",
"repository": "https://forge.lthn.ai/core/agent.git",
"license": "EUPL-1.2",
"keywords": [
"claude",
"core",
"php",
"agent"
]
}

View file

@ -0,0 +1,9 @@
{
"mcpServers": {
"core": {
"type": "stdio",
"command": "core",
"args": ["mcp", "serve"]
}
}
}

View file

@ -0,0 +1,6 @@
# core-php
This plugin family covers Claude workflows for Core PHP services and application modules.
It is the canonical home for PHP-focused commands, agents, and skills in the Core ecosystem.
The scope includes framework conventions, module structure, QA, verification, and delivery support.
Marketplace metadata for this family is defined in `marketplace.yaml`.
Commands, agents, and skills here are seeded from the existing Claude and Codex plugin material in this repository.

View file

@ -0,0 +1,24 @@
---
name: php-developer
description: PHP development agent for Core services and modules. Derived from the existing core-php, php-agent, and senior-developer material.
tools: Bash, Read, Edit, MultiEdit, Grep, Glob, LS
model: sonnet
color: purple
---
You are a PHP developer working in the Core ecosystem.
## Working rules
- Follow the module conventions in `skills/core/SKILL.md` and `skills/core-php/SKILL.md`.
- Use the delivery loop in `skills/php-agent/SKILL.md` when the task requires autonomous implementation.
- Prefer `core php test`, `core php fmt`, and `core php stan` over raw commands when the wrapper exists.
- Keep `declare(strict_types=1);` on PHP files and keep user-facing strings in UK English.
- Use Actions for business logic, thin controllers, and Pest for tests.
## Delivery standard
1. Read the module structure before making changes.
2. Keep business logic in Actions and keep multi-tenant boundaries explicit.
3. Fix the failing behaviour and add or update tests.
4. Run QA and verification before stopping.

View file

@ -0,0 +1,52 @@
---
name: commit
description: Generate a conventional commit message for staged changes
args: "[message]"
flags:
- --amend
hooks:
Before:
- hooks:
- type: command
command: "${CLAUDE_PLUGIN_ROOT}/scripts/smart-commit.sh"
---
# Smart Commit
Generate a conventional commit message for staged changes.
## Usage
Generate message automatically:
`/core-php:commit`
Provide a custom message:
`/core-php:commit "feat(module): add action validation"`
Amend the previous commit:
`/core-php:commit --amend`
## Behavior
1. **Analyze Staged Changes**: Examines the `git diff --staged` to understand the nature of the changes.
2. **Generate Conventional Commit Message**:
- `feat`: For new files, functions, or features.
- `fix`: For bug fixes.
- `refactor`: For code restructuring without changing external behavior.
- `docs`: For changes to documentation.
- `test`: For adding or modifying tests.
- `chore`: For routine maintenance tasks.
3. **Determine Scope**: Infers the scope from the affected module's file paths (e.g., `auth`, `payment`, `ui`).
4. **Add Co-Authored-By Trailer**: Appends `Co-Authored-By: Claude <noreply@anthropic.com>` to the commit message.
## Message Generation Example
```
feat(auth): add JWT token validation
- Add validateToken() function
- Add token expiry check
- Add unit tests for validation
Co-Authored-By: Claude <noreply@anthropic.com>
```

View file

@ -0,0 +1,126 @@
---
name: qa
description: Run PHP QA checks and fix all issues iteratively
hooks:
PostToolUse:
- matcher: "Bash"
hooks:
- type: command
command: "${CLAUDE_PLUGIN_ROOT}/scripts/qa-filter.sh"
Stop:
- hooks:
- type: command
command: "${CLAUDE_PLUGIN_ROOT}/scripts/qa-verify.sh"
once: true
---
# QA Fix Loop
Run the full PHP QA pipeline and fix all issues.
## Process
1. **Run QA**: Execute `core php qa`
2. **Parse issues**: Extract failures from output (see format below)
3. **Fix each issue**: Address one at a time, simplest first
4. **Re-verify**: After fixes, re-run QA
5. **Repeat**: Until all checks pass
6. **Report**: Summary of what was fixed
## Issue Priority
Fix in this order (fastest feedback first):
1. **pint** - formatting issues (auto-fix with `core php fmt`)
2. **stan** - static analysis (usually quick fixes)
3. **test** - failing tests (may need more investigation)
4. **build** - runtime bootstrap or syntax errors (fix before tests can run)
## Output Parsing
### PHP QA Output
```
=== PINT ===
FAIL: 2 files need formatting
=== STAN ===
src/Http/Controller.php:42 - Undefined variable $user
=== TEST ===
✗ CreateUserTest::testSuccess
Expected status 200, got 500
=== RESULT ===
pint: FAIL
stan: FAIL (1 error)
test: FAIL (1 failed)
```
## Fixing Strategy
**Formatting (pint):**
- Just run `core php fmt`
- No code reading needed
**Static analysis errors:**
- Read the specific file:line
- Understand the error type
- Make minimal fix
**Test failures:**
- Read the test file to understand expectation
- Read the implementation
- Fix the root cause (not just the symptom)
**Build errors:**
- Usually bootstrap, syntax, or autoload issues
- Fix before attempting other checks
## Stop Condition
Only stop when:
- All QA checks pass, OR
- User explicitly cancels, OR
- Same error repeats 3 times (stuck - ask for help)
## Example Session
```
Running: core php qa
## QA Issues
src/Http/Controller.php:42 - Undefined variable $user
✗ CreateUserTest::testSuccess
**Summary:** stan: FAIL (1) | test: FAIL (1)
---
Fixing static analysis issue: undefined variable
Reading src/Http/Controller.php...
Adding the missing variable assignment.
Running: core php qa
## QA Issues
✗ CreateUserTest::testSuccess
Expected status 200, got 500
**Summary:** stan: PASS | test: FAIL (1)
---
Fixing test issue: expected 200, got 500
Reading test setup...
Correcting test data.
Running: core php qa
✓ All checks passed!
**Summary:**
- Fixed: undefined variable (added assignment)
- Fixed: TestCreateUser (corrected test setup)
- 2 issues resolved, all checks passing
```

View file

@ -0,0 +1,63 @@
---
name: review
description: Perform code review on staged changes or PRs
args: [commit-range|--pr=N|--security]
---
# Code Review
Perform a thorough code review of the specified changes.
## Arguments
- No args: Review staged changes
- `HEAD~3..HEAD`: Review last 3 commits
- `--pr=123`: Review PR #123
- `--security`: Focus on security issues
## Process
1. **Gather changes**: Get diff for the specified range
2. **Analyse each file**: Review for issues by category
3. **Report findings**: Output structured review
## Review Checklist
| Category | Checks |
|----------|--------|
| **Correctness** | Logic errors, edge cases, error handling |
| **Security** | SQL injection, XSS, hardcoded secrets, CSRF |
| **Performance** | N+1 queries, unnecessary loops, large allocations |
| **Maintainability** | Naming, structure, complexity |
| **Tests** | Coverage gaps, missing assertions |
## Output Format
```markdown
## Code Review: [title]
### Critical
- **file:line** - Issue description
### Warning
- **file:line** - Issue description
### Suggestions
- **file:line** - Improvement idea
---
**Summary**: X critical, Y warnings, Z suggestions
```
## Commands
```bash
# Get staged diff
git diff --cached
# Get PR diff
gh pr diff 123
# Get commit range diff
git diff HEAD~3..HEAD
```

View file

@ -0,0 +1,75 @@
---
name: verify
description: Verify work is complete before stopping
args: [--quick|--full]
---
# Work Verification
Verify that PHP work is complete and ready to commit/push.
## Arguments
- No args: Standard verification
- `--quick`: Fast checks only (format, lint)
- `--full`: All checks including slow tests
## Verification Steps
### 1. Check for uncommitted changes
```bash
git status --porcelain
```
### 2. Check for debug statements
Look for:
- Go: `fmt.Println`, `log.Println`, `spew.Dump`
- PHP: `dd(`, `dump(`, `var_dump(`, `ray(`
- JS/TS: `console.log`, `debugger`
### 3. Run tests
```bash
core php test
```
### 4. Run linter
```bash
core php stan
```
### 5. Check formatting
```bash
core php fmt --test
```
## Output
Report verification status:
```
## Verification Results
✓ No uncommitted changes
✓ No debug statements found
✓ Tests passing (47/47)
✓ Lint clean
✓ Formatting correct
**Status: READY**
```
Or if issues found:
```
## Verification Results
✓ No uncommitted changes
✗ Debug statement found: src/handler.go:42
✗ Tests failing (45/47)
✓ Lint clean
✓ Formatting correct
**Status: NOT READY**
Fix these issues before proceeding.
```

View file

@ -0,0 +1,6 @@
marketplace:
registry: forge.lthn.ai
organization: core
repository: core-php
auto_update: true
check_interval: 24h

View file

@ -0,0 +1,62 @@
#!/bin/bash
# Filter QA output to show only actionable issues during /core:qa mode
#
# PostToolUse hook that processes QA command output and extracts
# only the failures, hiding verbose success output.
read -r input
COMMAND=$(echo "$input" | jq -r '.tool_input.command // empty')
OUTPUT=$(echo "$input" | jq -r '.tool_response.stdout // .tool_response.output // empty')
EXIT_CODE=$(echo "$input" | jq -r '.tool_response.exit_code // 0')
# Only process QA-related commands
case "$COMMAND" in
"core go qa"*|"core php qa"*|"core go test"*|"core php test"*|"core go lint"*|"core php stan"*)
;;
*)
# Not a QA command, pass through unchanged
echo "$input"
exit 0
;;
esac
# Extract failures from output
FAILURES=$(echo "$OUTPUT" | grep -E "^(FAIL|---\s*FAIL|✗|ERROR|undefined:|error:|panic:)" | head -20)
SUMMARY=$(echo "$OUTPUT" | grep -E "^(fmt:|lint:|test:|pint:|stan:|=== RESULT ===)" | tail -5)
# Also grab specific error lines with file:line references
FILE_ERRORS=$(echo "$OUTPUT" | grep -E "^[a-zA-Z0-9_/.-]+\.(go|php):[0-9]+:" | head -10)
if [ -z "$FAILURES" ] && [ "$EXIT_CODE" = "0" ]; then
# All passed - show brief confirmation
cat << 'EOF'
{
"suppressOutput": true,
"hookSpecificOutput": {
"hookEventName": "PostToolUse",
"additionalContext": "✓ QA passed"
}
}
EOF
else
# Combine failures and file errors
ISSUES="$FAILURES"
if [ -n "$FILE_ERRORS" ]; then
ISSUES="$ISSUES
$FILE_ERRORS"
fi
# Escape for JSON
ISSUES_ESCAPED=$(echo "$ISSUES" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/\\n/g')
SUMMARY_ESCAPED=$(echo "$SUMMARY" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/ | /g')
cat << EOF
{
"suppressOutput": true,
"hookSpecificOutput": {
"hookEventName": "PostToolUse",
"additionalContext": "## QA Issues\n\n\`\`\`\n$ISSUES_ESCAPED\n\`\`\`\n\n**Summary:** $SUMMARY_ESCAPED"
}
}
EOF
fi

View file

@ -0,0 +1,28 @@
#!/bin/bash
# Verify QA passes before stopping during /core-php:qa mode.
read -r input
STOP_ACTIVE=$(echo "$input" | jq -r '.stop_hook_active // false')
# Prevent infinite loop
if [ "$STOP_ACTIVE" = "true" ]; then
exit 0
fi
# Run PHP QA for this plugin family.
RESULT=$(core php qa 2>&1) || true
# Check if QA passed
if echo "$RESULT" | grep -qE "FAIL|ERROR|✗|panic:|undefined:"; then
ISSUES=$(echo "$RESULT" | grep -E "^(FAIL|ERROR|✗|undefined:|panic:)|^[a-zA-Z0-9_/.-]+\.php:[0-9]+:" | head -5)
ISSUES_ESCAPED=$(echo "$ISSUES" | sed 's/\\/\\\\/g' | sed 's/"/\\"/g' | sed ':a;N;$!ba;s/\n/\\n/g')
cat << EOF
{
"decision": "block",
"reason": "QA still has issues:\n\n$ISSUES_ESCAPED\n\nPlease fix these before stopping."
}
EOF
else
exit 0
fi

View file

@ -0,0 +1,108 @@
#!/bin/bash
# Smart commit script for /core:commit command
CUSTOM_MESSAGE=""
AMEND_FLAG=""
# Parse arguments
while (( "$#" )); do
case "$1" in
--amend)
AMEND_FLAG="--amend"
shift
;;
-*)
echo "Unsupported flag $1" >&2
exit 1
;;
*)
# The rest of the arguments are treated as the commit message
CUSTOM_MESSAGE="$@"
break
;;
esac
done
# Get staged changes
STAGED_FILES=$(git diff --staged --name-status)
if [ -z "$STAGED_FILES" ]; then
echo "No staged changes to commit."
exit 0
fi
# Determine commit type and scope
COMMIT_TYPE="chore" # Default to chore
SCOPE=""
# Get just the file paths
STAGED_FILE_PATHS=$(git diff --staged --name-only)
# Determine type from file paths/status
# Order is important here: test and docs are more specific than feat.
if echo "$STAGED_FILE_PATHS" | grep -q -E "(_test\.go|\.test\.js|/tests/|/spec/)"; then
COMMIT_TYPE="test"
elif echo "$STAGED_FILE_PATHS" | grep -q -E "(\.md|/docs/|README)"; then
COMMIT_TYPE="docs"
elif echo "$STAGED_FILES" | grep -q "^A"; then
COMMIT_TYPE="feat"
elif git diff --staged | grep -q -E "^\+.*(fix|bug|issue)"; then
COMMIT_TYPE="fix"
elif git diff --staged | grep -q -E "^\+.*(refactor|restructure)"; then
COMMIT_TYPE="refactor"
fi
# Determine scope from the most common path component
if [ -n "$STAGED_FILE_PATHS" ]; then
# Extract the second component of each path (e.g., 'code' from 'claude/code/file.md')
# This is a decent heuristic for module name.
# We filter for lines that have a second component.
POSSIBLE_SCOPES=$(echo "$STAGED_FILE_PATHS" | grep '/' | cut -d/ -f2)
if [ -n "$POSSIBLE_SCOPES" ]; then
SCOPE=$(echo "$POSSIBLE_SCOPES" | sort | uniq -c | sort -nr | head -n 1 | awk '{print $2}')
fi
# If no scope is found (e.g., all files are in root), SCOPE remains empty, which is valid.
fi
# Construct the commit message
if [ -n "$CUSTOM_MESSAGE" ]; then
COMMIT_MESSAGE="$CUSTOM_MESSAGE"
else
# Auto-generate a descriptive summary
DIFF_CONTENT=$(git diff --staged)
# Try to find a function or class name from the diff
# This is a simple heuristic that can be greatly expanded.
SUMMARY=$(echo "$DIFF_CONTENT" | grep -E -o "(function|class|def) \w+" | head -n 1 | sed -e 's/function //g' -e 's/class //g' -e 's/def //g')
if [ -z "$SUMMARY" ]; then
if [ $(echo "$STAGED_FILE_PATHS" | wc -l) -eq 1 ]; then
FIRST_FILE=$(echo "$STAGED_FILE_PATHS" | head -n 1)
SUMMARY="update $(basename "$FIRST_FILE")"
else
SUMMARY="update multiple files"
fi
else
SUMMARY="update $SUMMARY"
fi
SUBJECT="$COMMIT_TYPE($SCOPE): $SUMMARY"
BODY=$(echo "$DIFF_CONTENT" | grep -E "^\+" | sed -e 's/^+//' | head -n 5 | sed 's/^/ - /')
COMMIT_MESSAGE="$SUBJECT\n\n$BODY"
fi
# Add Co-Authored-By trailer
CO_AUTHOR="Co-Authored-By: Claude <noreply@anthropic.com>"
if ! echo "$COMMIT_MESSAGE" | grep -q "$CO_AUTHOR"; then
COMMIT_MESSAGE="$COMMIT_MESSAGE\n\n$CO_AUTHOR"
fi
# Execute the commit
git commit $AMEND_FLAG -m "$(echo -e "$COMMIT_MESSAGE")"
if [ $? -eq 0 ]; then
echo "Commit successful."
else
echo "Commit failed."
exit 1
fi

View file

@ -0,0 +1,63 @@
---
name: api-endpoints
description: Use when a Core plugin needs to call api.lthn.sh or mcp.lthn.sh. Documents the JSON headers, auth, and endpoint conventions required by the plugin restructure RFC.
---
# API and MCP Endpoints
Use this skill when a command, script, or tool talks to the shared Core endpoints.
## Canonical endpoints
- `https://api.lthn.sh` — REST API
- `https://mcp.lthn.sh` — MCP bridge endpoint
These conventions apply to both production and self-hosted `lthn.sh` installs.
## Required headers
- Send `Accept: application/json` on every API request. The default response may be HTML if this header is missing.
- Send `Content-Type: application/json` for JSON request bodies.
- Send `Authorization: Bearer <token>` for authenticated requests.
## REST shape
- Use `/v1/{resource}` paths.
- Expect JSON request and response bodies.
- Keep request payloads explicit and small.
Example:
```bash
curl -s https://api.lthn.sh/v1/issues \
-H 'Accept: application/json' \
-H "Authorization: Bearer ${TOKEN}"
```
```bash
curl -s https://api.lthn.sh/v1/brain/recall \
-X POST \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer ${TOKEN}" \
-d '{"query":"dispatch status","top_k":3}'
```
## MCP usage
- Remote MCP can be reached at `https://mcp.lthn.sh`.
- Local plugin configs in this repository use `core mcp serve` through `.mcp.json`.
Local `.mcp.json` pattern:
```json
{
"mcpServers": {
"core": {
"type": "stdio",
"command": "core",
"args": ["mcp", "serve"]
}
}
}
```

View file

@ -0,0 +1,126 @@
---
name: core-php
description: Use when creating PHP modules, services, or actions in core-* packages.
---
# PHP Framework Patterns
Host UK PHP modules follow strict conventions. Use `core php` commands.
## Module Structure
```
core-{name}/
├── src/
│ ├── Core/ # Namespace: Core\{Name}
│ │ ├── Boot.php # Module bootstrap (listens to lifecycle events)
│ │ ├── Actions/ # Single-purpose business logic
│ │ └── Models/ # Eloquent models
│ └── Mod/ # Namespace: Core\Mod\{Name} (optional extensions)
├── resources/views/ # Blade templates
├── routes/ # Route definitions
├── database/migrations/ # Migrations
├── tests/ # Pest tests
└── composer.json
```
## Boot Class Pattern
```php
<?php
declare(strict_types=1);
namespace Core\{Name};
use Core\Php\Events\WebRoutesRegistering;
use Core\Php\Events\AdminPanelBooting;
class Boot
{
public static array $listens = [
WebRoutesRegistering::class => 'onWebRoutes',
AdminPanelBooting::class => ['onAdmin', 10], // With priority
];
public function onWebRoutes(WebRoutesRegistering $event): void
{
$event->router->middleware('web')->group(__DIR__ . '/../routes/web.php');
}
public function onAdmin(AdminPanelBooting $event): void
{
$event->panel->resources([...]);
}
}
```
## Action Pattern
```php
<?php
declare(strict_types=1);
namespace Core\{Name}\Actions;
use Core\Php\Action;
class CreateThing
{
use Action;
public function handle(User $user, array $data): Thing
{
return Thing::create([
'user_id' => $user->id,
...$data,
]);
}
}
// Usage: CreateThing::run($user, $validated);
```
## Multi-Tenant Models
```php
<?php
declare(strict_types=1);
namespace Core\{Name}\Models;
use Core\Tenant\Concerns\BelongsToWorkspace;
use Illuminate\Database\Eloquent\Model;
class Thing extends Model
{
use BelongsToWorkspace; // Auto-scopes queries, sets workspace_id
protected $fillable = ['name', 'workspace_id'];
}
```
## Commands
| Task | Command |
|------|---------|
| Run tests | `core php test` |
| Format | `core php fmt --fix` |
| Analyse | `core php analyse` |
| Dev server | `core php dev` |
| Create migration | `/core:migrate create <name>` |
| Create migration from model | `/core:migrate from-model <model>` |
| Run migrations | `/core:migrate run` |
| Rollback migrations | `/core:migrate rollback` |
| Refresh migrations | `/core:migrate fresh` |
| Migration status | `/core:migrate status` |
## Rules
- Always `declare(strict_types=1);`
- UK English: colour, organisation, centre
- Type hints on all parameters and returns
- Pest for tests, not PHPUnit
- Flux Pro for UI, not vanilla Alpine

View file

@ -0,0 +1,73 @@
---
name: core
description: Use when working in host-uk repositories, running tests, building, releasing, or managing multi-repo workflows. Provides the core CLI command reference.
---
# Core CLI
The `core` command provides a unified interface for Go/PHP development and multi-repo management.
**Rule:** Always prefer `core <command>` over raw commands.
## Quick Reference
| Task | Command |
|------|---------|
| Smart tests | `core test` |
| Go tests | `core go test` |
| Go coverage | `core go cov` |
| Go format | `core go fmt --fix` |
| Go lint | `core go lint` |
| PHP dev server | `core php dev` |
| PHP tests | `core php test` |
| PHP format | `core php fmt --fix` |
| Build | `core build` |
| Preview release | `core ci` |
| Publish | `core ci --were-go-for-launch` |
| Multi-repo status | `core dev health` |
| Commit dirty repos | `core dev commit` |
| Push repos | `core dev push` |
## Decision Tree
```
Go project?
tests: core go test
format: core go fmt --fix
build: core build
PHP project?
dev: core php dev
tests: core php test
format: core php fmt --fix
deploy: core php deploy
Multiple repos?
status: core dev health
commit: core dev commit
push: core dev push
```
## Common Mistakes
| Wrong | Right |
|-------|-------|
| `go test ./...` | `core go test` |
| `go build` | `core build` |
| `php artisan serve` | `core php dev` |
| `./vendor/bin/pest` | `core php test` |
| `git status` per repo | `core dev health` |
Run `core --help` or `core <cmd> --help` for full options.
## Smart Test Runner: `core test`
The `core test` command provides an intelligent way to run only the tests relevant to your recent changes.
- **`core test`**: Automatically detects changed files since the last commit and runs only the corresponding tests.
- **`core test --all`**: Runs the entire test suite for the project.
- **`core test --filter <TestName>`**: Runs a specific test by name.
- **`core test --coverage`**: Generates a test coverage report.
- **`core test <path/to/file>`**: Runs tests for a specific file or directory.
The runner automatically detects whether the project is Go or PHP and executes the appropriate testing tool. If it cannot map changed files to test files, it will fall back to running the full test suite.

View file

@ -0,0 +1,334 @@
---
name: php-agent
description: Autonomous PHP development agent - picks up issues, implements, handles reviews, merges
---
# PHP Agent Skill
You are an autonomous PHP development agent working on the Host UK Laravel packages. You continuously pick up issues, implement solutions, handle code reviews, and merge PRs.
## Workflow Loop
This skill runs as a continuous loop:
```
1. CHECK PENDING PRs → Fix reviews if CodeRabbit commented
2. FIND ISSUE → Pick a PHP issue from host-uk org
3. IMPLEMENT → Create branch, code, test, push
4. HANDLE REVIEW → Wait for/fix CodeRabbit feedback
5. MERGE → Merge when approved
6. REPEAT → Start next task
```
## State Management
Track your work with these variables:
- `PENDING_PRS`: PRs waiting for CodeRabbit review
- `CURRENT_ISSUE`: Issue currently being worked on
- `CURRENT_BRANCH`: Branch for current work
---
## Step 1: Check Pending PRs
Before starting new work, check if any of your pending PRs have CodeRabbit reviews ready.
```bash
# List your open PRs across host-uk org
gh search prs --author=@me --state=open --owner=host-uk --json number,title,repository,url
# For each PR, check CodeRabbit status
gh api repos/host-uk/{repo}/commits/{sha}/status --jq '.statuses[] | select(.context | contains("coderabbit")) | {context, state, description}'
```
### If CodeRabbit review is complete:
- **Success (no issues)**: Merge the PR
- **Has comments**: Fix the issues, commit, push, continue to next task
```bash
# Check for new reviews
gh api repos/host-uk/{repo}/pulls/{pr_number}/reviews --jq 'sort_by(.submitted_at) | .[-1] | {author: .user.login, state: .state, body: .body[:500]}'
# If actionable comments, read and fix them
# Then commit and push:
git add -A && git commit -m "fix: address CodeRabbit feedback
Co-Authored-By: Claude <noreply@anthropic.com>"
git push
```
### Merging PRs
```bash
# When CodeRabbit approves (status: success), merge without admin
gh pr merge {pr_number} --squash --repo host-uk/{repo}
```
---
## Step 2: Find an Issue
Search for PHP issues across the Host UK organization.
```bash
# Find open issues labeled for PHP or in PHP repos
gh search issues --owner=host-uk --state=open --label="lang:php" --json number,title,repository,url --limit=10
# Or search across all repos for PHP-related issues
gh search issues --owner=host-uk --state=open --json number,title,repository,labels,body --limit=20
# Filter for PHP repos (core-php, core-tenant, core-admin, etc.)
```
### Issue Selection Criteria
1. **Priority**: Issues with `priority:high` or `good-first-issue` labels
2. **Dependencies**: Check if issue depends on other incomplete work
3. **Scope**: Prefer issues that can be completed in one session
4. **Labels**: Look for `agent:ready` or `help-wanted`
### Claim the Issue
```bash
# Comment to claim the issue
gh issue comment {number} --repo host-uk/{repo} --body "I'm picking this up. Starting work now."
# Assign yourself (if you have permission)
gh issue edit {number} --repo host-uk/{repo} --add-assignee @me
```
---
## Step 3: Implement the Solution
### Setup Branch
```bash
# Navigate to the package
cd packages/{repo}
# Ensure you're on main/dev and up to date
git checkout dev && git pull
# Create feature branch
git checkout -b feature/issue-{number}-{short-description}
```
### Development Workflow
1. **Read the code** - Understand the codebase structure
2. **Write tests first** - TDD approach when possible
3. **Implement the solution** - Follow Laravel/PHP best practices
4. **Run tests** - Ensure all tests pass
```bash
# Run tests
composer test
# Run linting
composer lint
# Run static analysis if available
composer analyse
```
### Code Quality Checklist
- [ ] Tests written and passing
- [ ] Code follows PSR-12 style
- [ ] No debugging code left in
- [ ] Documentation updated if needed
- [ ] Types/PHPDoc added for new methods
### Creating Sub-Issues
If the issue reveals additional work needed:
```bash
# Create a follow-up issue
gh issue create --repo host-uk/{repo} \
--title "Follow-up: {description}" \
--body "Discovered while working on #{original_issue}
## Context
{explain what was found}
## Proposed Solution
{describe the approach}
## References
- Parent issue: #{original_issue}" \
--label "lang:php,follow-up"
```
---
## Step 4: Push and Create PR
```bash
# Stage and commit
git add -A
git commit -m "feat({scope}): {description}
{longer description if needed}
Closes #{issue_number}
Co-Authored-By: Claude <noreply@anthropic.com>"
# Push
git push -u origin feature/issue-{number}-{short-description}
# Create PR
gh pr create --repo host-uk/{repo} \
--title "feat({scope}): {description}" \
--body "$(cat <<'EOF'
## Summary
{Brief description of changes}
## Changes
- {Change 1}
- {Change 2}
## Test Plan
- [ ] Unit tests added/updated
- [ ] Manual testing completed
- [ ] CI passes
Closes #{issue_number}
---
Generated with Claude Code
EOF
)"
```
---
## Step 5: Handle CodeRabbit Review
After pushing, CodeRabbit will automatically review. Track PR status:
```bash
# Add PR to pending list (note the PR number)
# PENDING_PRS+=({repo}:{pr_number})
# Check CodeRabbit status
gh api repos/host-uk/{repo}/commits/$(git rev-parse HEAD)/status --jq '.statuses[] | select(.context | contains("coderabbit"))'
```
### While Waiting
Instead of blocking, **start working on the next issue** (go to Step 2).
### When Review Arrives
```bash
# Check the review
gh api repos/host-uk/{repo}/pulls/{pr_number}/reviews --jq '.[-1]'
# If "Actionable comments posted: N", fix them:
# 1. Read each comment
# 2. Make the fix
# 3. Commit with clear message
# 4. Push
```
### Common CodeRabbit Feedback Patterns
- **Unused variables**: Remove or use them
- **Missing type hints**: Add return types, parameter types
- **Error handling**: Add try-catch or null checks
- **Test coverage**: Add missing test cases
- **Documentation**: Add PHPDoc blocks
---
## Step 6: Merge and Close
When CodeRabbit status shows "Review completed" with state "success":
```bash
# Merge the PR (squash merge)
gh pr merge {pr_number} --squash --repo host-uk/{repo}
# The issue will auto-close if "Closes #N" was in PR body
# Otherwise, close manually:
gh issue close {number} --repo host-uk/{repo}
```
---
## Step 7: Restart Loop
After merging:
1. Remove PR from `PENDING_PRS`
2. Check remaining pending PRs for reviews
3. Pick up next issue
4. **Restart this skill** to continue the loop
```
>>> LOOP COMPLETE - Restart /php-agent to continue working <<<
```
---
## PHP Packages Reference
| Package | Type | Description |
|---------|------|-------------|
| core-php | foundation | Core framework - events, modules, lifecycle |
| core-tenant | module | Multi-tenancy, workspaces, users |
| core-admin | module | Admin panel, Livewire, Flux UI |
| core-api | module | REST API, webhooks |
| core-mcp | module | MCP server framework |
| core-agentic | module | AI agent orchestration |
| core-bio | product | Link-in-bio pages |
| core-social | product | Social media scheduling |
| core-analytics | product | Privacy-first analytics |
| core-commerce | module | Billing, Stripe |
| core-content | module | CMS, pages, blog |
---
## Troubleshooting
### CodeRabbit Not Reviewing
```bash
# Check if CodeRabbit is enabled for the repo
gh api repos/host-uk/{repo} --jq '.topics'
# Check webhook configuration
gh api repos/host-uk/{repo}/hooks
```
### Tests Failing
```bash
# Run with verbose output
composer test -- --verbose
# Run specific test
composer test -- --filter=TestClassName
```
### Merge Conflicts
```bash
# Rebase on dev
git fetch origin dev
git rebase origin/dev
# Resolve conflicts, then continue
git add .
git rebase --continue
git push --force-with-lease
```
---
## Best Practices
1. **One issue per PR** - Keep changes focused
2. **Small commits** - Easier to review and revert
3. **Descriptive messages** - Help future maintainers
4. **Test coverage** - Don't decrease coverage
5. **Documentation** - Update if behavior changes
## Labels Reference
- `lang:php` - PHP code changes
- `agent:ready` - Ready for AI agent pickup
- `good-first-issue` - Simple, well-defined tasks
- `priority:high` - Should be addressed soon
- `follow-up` - Created from another issue
- `needs:review` - Awaiting human review

View file

@ -0,0 +1,18 @@
{
"name": "infra",
"version": "0.1.0",
"description": "Claude plugin family for Core infrastructure, operations, and platform tooling.",
"author": {
"name": "Lethean Community",
"email": "hello@lethean.io"
},
"homepage": "https://lthn.ai",
"repository": "https://forge.lthn.ai/core/agent.git",
"license": "EUPL-1.2",
"keywords": [
"claude",
"core",
"infra",
"operations"
]
}

6
plugins/infra/README.md Normal file
View file

@ -0,0 +1,6 @@
# infra
This plugin family covers Claude workflows for Core infrastructure and operational tooling.
It is the canonical home for platform, deployment, networking, and systems support content.
The scope includes environment management, automation, observability, and service operations.
Marketplace metadata for this family is defined in `marketplace.yaml`.
The agent content here is seeded from the existing infrastructure and DevOps material in this repository.

View file

@ -0,0 +1,23 @@
---
name: infra-ops
description: Infrastructure operations agent for Core platform work. Derived from the existing infrastructure-maintainer and DevOps automator material.
tools: Bash, Read, Grep, Glob, LS
model: sonnet
color: orange
---
You are the infrastructure operations agent for the Core platform.
## Working rules
- Operate through automation first. Use Ansible playbooks and reproducible commands instead of ad-hoc server changes.
- Treat Docker Compose as the deployment layer and Traefik as the ingress layer.
- Keep security and observability in scope: TLS, health checks, logs, monitoring, and rollback paths.
- Follow the existing platform guidance around Forgejo, Beszel, CloudNS, and Authentik.
## Delivery standard
1. Inspect the current deployment shape before changing it.
2. Prefer reversible, scripted changes.
3. Call out operational risk before touching production paths.
4. Record verification steps and expected health checks.

View file

@ -0,0 +1,6 @@
marketplace:
registry: forge.lthn.ai
organization: core
repository: infra
auto_update: true
check_interval: 24h