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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "pharaoh-dev",
"description": "Development marketplace for Pharaoh sphinx-needs AI assistant",
"owner": {
"name": "patdhlk"
"name": "useblocks"
},
"plugins": [
{
Expand All @@ -11,7 +11,7 @@
"version": "0.1.0",
"source": "./",
"author": {
"name": "patdhlk"
"name": "useblocks"
}
}
]
Expand Down
6 changes: 3 additions & 3 deletions .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
"description": "AI assistant framework for sphinx-needs projects: change analysis, traceability, MECE, authoring, verification, and release management",
"version": "0.1.0",
"author": {
"name": "patdhlk"
"name": "useblocks"
},
"repository": "https://github.com/patdhlk/pharaoh",
"repository": "https://github.com/useblocks/pharaoh",
"license": "MIT",
"keywords": ["sphinx-needs", "requirements", "traceability", "change-analysis", "mece", "safety-critical", "automotive"]
"keywords": ["sphinx-needs", "requirements", "traceability", "change-analysis", "mece", "safety-critical", "automotive", "decisions"]
}
33 changes: 33 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
name: Bug Report
about: Report a problem with a Pharaoh skill or agent
title: "[Bug] "
labels: bug
assignees: ""
---

## Environment

- **Skill/Agent:** <!-- e.g., pharaoh:change / @pharaoh.change -->
- **AI Platform:** <!-- Claude Code / GitHub Copilot -->
- **Config source:** <!-- ubproject.toml / conf.py -->
- **sphinx-needs version:** <!-- if known -->
- **ubc CLI version:** <!-- if installed, run: ubc --version -->

## Description

<!-- What happened? -->

## Expected Behavior

<!-- What did you expect to happen? -->

## Steps to Reproduce

1. <!-- Step 1 -->
2. <!-- Step 2 -->
3. <!-- Step 3 -->

## Additional Context

<!-- Relevant config snippets, error messages, or screenshots -->
23 changes: 23 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
name: Feature Request
about: Suggest an improvement or new capability
title: "[Feature] "
labels: enhancement
assignees: ""
---

## Skill

<!-- Which skill does this affect? (e.g., pharaoh:author) or "new skill" -->

## Use Case

<!-- What are you trying to accomplish? -->

## Proposed Behavior

<!-- How should it work? -->

## Alternatives Considered

<!-- Have you considered other approaches? -->
15 changes: 15 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
## Summary

<!-- Brief description of what this PR does -->

## Checklist

- [ ] Both Claude Code skill and Copilot agent updated (if applicable)
- [ ] Tested against `tests/fixtures/basic-project/`
- [ ] README skill table updated (if new/renamed skill)
- [ ] `copilot-instructions.md` updated (if new/renamed agent)
- [ ] Commit messages use imperative mood

## Testing

<!-- How did you test these changes? -->
148 changes: 148 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_call:

permissions:
contents: read

jobs:
validate:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6

- name: Validate skill frontmatter
run: |
status=0
for skill_dir in skills/*/; do
# Skip shared directory
if [ "$(basename "$skill_dir")" = "shared" ]; then
continue
fi

skill_file="${skill_dir}SKILL.md"
if [ ! -f "$skill_file" ]; then
echo "ERROR: Missing SKILL.md in $skill_dir"
status=1
continue
fi

# Check for YAML frontmatter delimiters
first_line=$(head -1 "$skill_file")
if [ "$first_line" != "---" ]; then
echo "ERROR: $skill_file missing YAML frontmatter (no opening ---)"
status=1
continue
fi

# Extract frontmatter (between first and second ---)
frontmatter=$(sed -n '2,/^---$/p' "$skill_file" | sed '$d')

# Check for name field (must be lowercase with hyphens)
if ! echo "$frontmatter" | grep -qE '^name: [a-z0-9-]+$'; then
echo "ERROR: $skill_file 'name' missing or not lowercase-with-hyphens"
status=1
fi

# Check for description field (must start with "Use when")
if ! echo "$frontmatter" | grep -qE '^description: "?Use when'; then
echo "ERROR: $skill_file 'description' missing or does not start with 'Use when'"
status=1
fi

echo "OK: $skill_file"
done
exit $status

- name: Validate agent frontmatter
run: |
status=0
for agent_file in .github/agents/*.agent.md; do
[ -f "$agent_file" ] || continue

first_line=$(head -1 "$agent_file")
if [ "$first_line" != "---" ]; then
echo "ERROR: $agent_file missing YAML frontmatter"
status=1
continue
fi

frontmatter=$(sed -n '2,/^---$/p' "$agent_file" | sed '$d')

if ! echo "$frontmatter" | grep -qE '^description:'; then
echo "ERROR: $agent_file missing 'description' in frontmatter"
status=1
fi

if ! echo "$frontmatter" | grep -qE '^handoffs:'; then
echo "ERROR: $agent_file missing 'handoffs' in frontmatter"
status=1
fi

echo "OK: $agent_file"
done
exit $status

- name: Cross-reference skills and agents
run: |
status=0

# Check every pharaoh skill has a matching agent
for skill_dir in skills/pharaoh-*/; do
skill_name=$(basename "$skill_dir")
# Convert pharaoh-change -> pharaoh.change
agent_name=$(echo "$skill_name" | sed 's/-/./')
agent_file=".github/agents/${agent_name}.agent.md"

if [ ! -f "$agent_file" ]; then
echo "ERROR: Skill $skill_name has no matching agent at $agent_file"
status=1
else
echo "OK: $skill_name <-> $agent_file"
fi
done

# Check every pharaoh agent has a matching skill
for agent_file in .github/agents/pharaoh.*.agent.md; do
[ -f "$agent_file" ] || continue
agent_basename=$(basename "$agent_file" .agent.md)
# Convert pharaoh.change -> pharaoh-change
skill_name=$(echo "$agent_basename" | sed 's/\./-/')
skill_dir="skills/${skill_name}/"

if [ ! -d "$skill_dir" ]; then
echo "ERROR: Agent $agent_basename has no matching skill at $skill_dir"
status=1
fi
done

exit $status

- name: Check internal links
shell: bash
run: |
status=0
shopt -s globstar nullglob
for md_file in *.md docs/**/*.md; do
[ -f "$md_file" ] || continue
dir=$(dirname "$md_file")
links=$(grep -oP '\[.*?\]\(\K[^)]+' "$md_file" | grep -v '^http' | grep -v '^mailto:' | grep -v '^#' | grep -v '^?' || true)
for link in $links; do
path="${link%%#*}"
[ -z "$path" ] && continue
target="${dir}/${path}"
if [ ! -e "$target" ]; then
echo "ERROR: $md_file links to '$link' but $target does not exist"
echo "FAILED" >> /tmp/link_check_failed
fi
done
done
if [ -f /tmp/link_check_failed ]; then
exit 1
fi
78 changes: 78 additions & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
name: Release

on:
push:
tags:
- "v*"

permissions:
contents: write

jobs:
validate:
uses: ./.github/workflows/ci.yaml

release:
needs: validate
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v6
with:
fetch-depth: 0

- name: Get version from tag
id: version
run: echo "version=${GITHUB_REF#refs/tags/}" >> "$GITHUB_OUTPUT"

- name: Generate changelog
id: changelog
run: |
# Find the previous tag
prev_tag=$(git tag --sort=-v:refname | sed -n '2p')

if [ -z "$prev_tag" ]; then
# First release — log from the beginning
log=$(git log --pretty=format:"- %s (%h)" "$GITHUB_REF")
else
log=$(git log --pretty=format:"- %s (%h)" "${prev_tag}..${GITHUB_REF}")
fi

# Write to file for body_path
echo "$log" > RELEASE_NOTES.md

- name: Create release archive
env:
VERSION: ${{ steps.version.outputs.version }}
run: |
archive="pharaoh-${VERSION}.zip"

# Collect paths that exist
paths=""
for p in \
skills/ \
.github/agents/ \
.github/prompts/ \
.claude-plugin/ \
agents/ \
tests/fixtures/ \
pharaoh.toml.example \
README.md \
LICENSE \
CHANGELOG.md \
CONTRIBUTING.md \
SECURITY.md
do
[ -e "$p" ] && paths="$paths $p"
done

zip -r "$archive" $paths

echo "archive=${archive}" >> "$GITHUB_ENV"

- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
name: ${{ steps.version.outputs.version }}
body_path: RELEASE_NOTES.md
files: ${{ env.archive }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
*.pyc
__pycache__/
.DS_Store
.worktrees/
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/),
and this project adheres to [Semantic Versioning](https://semver.org/).

## [Unreleased]

## [0.1.0] - 2026-04-10

### Added

- **Skills (Claude Code):** pharaoh:setup, pharaoh:change, pharaoh:trace, pharaoh:mece, pharaoh:author, pharaoh:verify, pharaoh:release, pharaoh:plan, pharaoh:spec, pharaoh:decide
- **Agents (GitHub Copilot):** matching agents for all skills with handoff support
- **Prompts (GitHub Copilot):** quick-invoke prompts for common workflows
- **Shared modules:** data-access (3-tier detection) and strictness (advisory/enforcing mode)
- **Test fixtures:** basic-project with requirements, specifications, implementations, tests, and decisions
- **Configuration:** pharaoh.toml.example with all supported options
- **Subagent:** sphinx-needs-expert for deep sphinx-needs domain knowledge
Loading