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
108 changes: 98 additions & 10 deletions .github/workflows/deploy-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,9 @@ jobs:
run: |
# All governed documents: directory/filename (without .md)
DOCS=(
"ai-governance/ai-vetting-criteria"
"ai-governance/fragmented-catholic-ai-governance"
"ai-governance/governance-as-code-catholic-ai"
"ai-governance/trusted-synthetic-data-ministry-ai"
"research/fragmented-catholic-digital-governance"
"research/governance-as-code-catholic-technology"
"research/trusted-data-infrastructure-catholic-ministry"
"project-governance/definitions"
"project-governance/project-types"
"project-governance/lifecycle"
Expand Down Expand Up @@ -73,6 +72,24 @@ jobs:

echo "changed_docs=$CHANGED_DOCS" >> "$GITHUB_OUTPUT"

# Detect deleted governance documents (stale pages to remove)
DELETED_DOCS=""
if [ "$DEPLOY_ALL" != true ] && [ -n "$DIFF_BASE" ]; then
DELETED=$(git diff --name-only --diff-filter=D "$DIFF_BASE" HEAD 2>/dev/null || echo "")
for FILE in $DELETED; do
case "$FILE" in
# Skip non-governance markdown files
README.md|RELEASING.md|CONTRIBUTING.md|CHANGELOG.md|*/README.md) continue ;;
*/*.md)
DOC="${FILE%.md}"
echo " Deleted: $FILE"
DELETED_DOCS="${DELETED_DOCS:+$DELETED_DOCS }${DOC}"
;;
esac
done
fi
echo "deleted_docs=$DELETED_DOCS" >> "$GITHUB_OUTPUT"

- name: Install pandoc
uses: pandoc/actions/setup@v1.1.1

Expand All @@ -86,23 +103,22 @@ jobs:
run: |
# Document titles keyed by directory/basename
declare -A DOC_TITLES=(
["ai-governance/ai-vetting-criteria"]="CDCF Project Vetting Criteria: AI Tools"
["ai-governance/fragmented-catholic-ai-governance"]="Fragmented Catholic AI Governance at Scale"
["ai-governance/governance-as-code-catholic-ai"]="Governance-as-Code for Catholic AI Agent Deployment"
["ai-governance/trusted-synthetic-data-ministry-ai"]="Trusted Synthetic Data for Ministry-Scale AI"
["research/fragmented-catholic-digital-governance"]="Fragmented Catholic Digital Governance at Scale"
["research/governance-as-code-catholic-technology"]="Governance-as-Code for Catholic Technology Deployment"
["research/trusted-data-infrastructure-catholic-ministry"]="Trusted Data Infrastructure for Catholic Ministry"
["project-governance/definitions"]="CDCF Governance Definitions"
["project-governance/project-types"]="CDCF Project Types: Foundation Projects and Community Projects"
["project-governance/lifecycle"]="CDCF Project Lifecycle"
["project-governance/project-vetting-criteria"]="CDCF Project Vetting Criteria: General Framework"
["project-governance/project-vetting-criteria"]="CDCF Project Vetting Criteria"
["project-governance/committees"]="CDCF Governance Bodies"
["standards/overview"]="CDCF Standards: Overview"
["standards/committees"]="CDCF Standards Committees"
)

# Parent page slugs for each section
declare -A SECTION_PARENTS=(
["ai-governance"]="ai-governance"
["project-governance"]="project-governance"
["research"]="research"
["standards"]="standards"
)

Expand Down Expand Up @@ -228,6 +244,78 @@ jobs:
echo ""
echo "All translations complete."

- name: Remove stale WordPress pages
if: steps.changes.outputs.deleted_docs != ''
env:
WP_REST_URL: ${{ vars.WP_REST_URL }}
WP_APP_USERNAME: ${{ secrets.WP_APP_USERNAME }}
WP_APP_PASSWORD: ${{ secrets.WP_APP_PASSWORD }}
run: |
STALE_SECTIONS=()

for DOC in ${{ steps.changes.outputs.deleted_docs }}; do
SECTION=$(dirname "$DOC")
BASENAME=$(basename "$DOC")
if [ "$SECTION" = "standards" ]; then
SLUG="standards-${BASENAME}"
else
SLUG="$BASENAME"
fi

echo "Checking for stale page: ${SLUG}..."
EXISTING=$(curl -s \
-u "$WP_APP_USERNAME:$WP_APP_PASSWORD" \
"$WP_REST_URL/wp/v2/pages?slug=${SLUG}&status=publish,draft")

PAGE_ID=$(echo "$EXISTING" | jq -r 'if type == "array" then .[0].id // empty else empty end')

if [ -n "$PAGE_ID" ] && [ "$PAGE_ID" != "null" ]; then
echo " Trashing page ID $PAGE_ID (slug: ${SLUG})..."
HTTP_CODE=$(curl -s -o /dev/null -w '%{http_code}' -X DELETE \
-u "$WP_APP_USERNAME:$WP_APP_PASSWORD" \
"$WP_REST_URL/wp/v2/pages/$PAGE_ID")
if [[ "$HTTP_CODE" -lt 300 ]]; then
echo " Trashed."
else
echo " Warning: delete returned HTTP $HTTP_CODE"
fi
else
echo " No WordPress page found — skipping."
fi

# Track sections that had deletions
if [[ ! " ${STALE_SECTIONS[*]} " =~ " ${SECTION} " ]]; then
STALE_SECTIONS+=("$SECTION")
fi
done

# If an entire section directory no longer exists, trash the parent page
for SECTION in "${STALE_SECTIONS[@]}"; do
if [ ! -d "$SECTION" ]; then
echo "Section '${SECTION}' no longer exists — checking for stale parent page..."
PARENT=$(curl -s \
-u "$WP_APP_USERNAME:$WP_APP_PASSWORD" \
"$WP_REST_URL/wp/v2/pages?slug=${SECTION}&status=publish,draft")

PARENT_ID=$(echo "$PARENT" | jq -r 'if type == "array" then .[0].id // empty else empty end')

if [ -n "$PARENT_ID" ] && [ "$PARENT_ID" != "null" ]; then
echo " Trashing parent page ID $PARENT_ID (slug: ${SECTION})..."
HTTP_CODE=$(curl -s -o /dev/null -w '%{http_code}' -X DELETE \
-u "$WP_APP_USERNAME:$WP_APP_PASSWORD" \
"$WP_REST_URL/wp/v2/pages/$PARENT_ID")
if [[ "$HTTP_CODE" -lt 300 ]]; then
echo " Trashed."
else
echo " Warning: delete returned HTTP $HTTP_CODE"
fi
fi
fi
done

echo ""
echo "Stale page cleanup complete."

- name: Setup Node.js
uses: actions/setup-node@v6
with:
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
node_modules/
dist/
37 changes: 17 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,39 +24,36 @@ A working repository for governance documentation supporting the **Catholic Digi
This repository holds the policy frameworks, evaluation criteria, and research documentation that inform how the CDCF reviews, incubates, and graduates technology projects. It is
modeled on established foundation governance (such as the Apache Software Foundation) but is uniquely grounded in Catholic Social Teaching and Canon Law.

The documentation is organized into a general project governance framework, applicable to all technology projects, and specialized domain-specific criteria (starting with AI
governance).
The documentation is organized into a unified project governance framework (with domain-specific extensions for AI integrated inline), supplementary research memos, and standards
for canonical data interoperability.

---

## Document Stack

### General Project Governance
### Project Governance

The core frameworks for any project seeking CDCF endorsement.

| Document | Type | Description |
| :------------------------------------------------------------------------------ | :--------- | :------------------------------------------------------------------------------------- |
| [project-vetting-criteria.md](./project-governance/project-vetting-criteria.md) | **Policy** | The foundational 8 criteria for any CDCF project. |
| [lifecycle.md](./project-governance/lifecycle.md) | Procedure | Definition of the stages from proposal through incubation, graduation, and retirement. |
| [committees.md](./project-governance/committees.md) | Structure | Governance bodies: Board of Directors, TCSC, and PMCs. |
| [project-types.md](./project-governance/project-types.md) | Policy | Distinction between Foundation Projects and Community Projects. |
| [definitions.md](./project-governance/definitions.md) | Glossary | Shared vocabulary for CDCF governance and vetting. |
| Document | Type | Description |
| :------------------------------------------------------------------------------ | :--------- | :-------------------------------------------------------------------------------------------------------- |
| [project-vetting-criteria.md](./project-governance/project-vetting-criteria.md) | **Policy** | The foundational 8 criteria for any CDCF project, with AI domain extensions integrated inline. |
| [lifecycle.md](./project-governance/lifecycle.md) | Procedure | Definition of the stages from proposal through incubation, graduation, and retirement. |
| [committees.md](./project-governance/committees.md) | Structure | Governance bodies: Board of Directors, TCSC, and PMCs. |
| [project-types.md](./project-governance/project-types.md) | Policy | Distinction between Foundation Projects and Community Projects. |
| [definitions.md](./project-governance/definitions.md) | Glossary | Shared vocabulary for CDCF governance and vetting. |

---

### Specialized Domain Governance
### Research

Domain-specific extensions to the general framework.
Supplementary research memos informing the design of the vetting criteria.

#### AI Governance

| Document | Type | Description |
| :--------------------------------------------------------------------------------------------- | :------------ | :-------------------------------------------------------------------------- |
| [ai-vetting-criteria.md](./ai-governance/ai-vetting-criteria.md) | **Policy** | Operational vetting criteria for AI tools, extending the general framework. |
| [fragmented-catholic-ai-governance.md](./ai-governance/fragmented-catholic-ai-governance.md) | Research memo | The urgency of shared AI governance standards. |
| [governance-as-code-catholic-ai.md](./ai-governance/governance-as-code-catholic-ai.md) | Research memo | Machine-enforceable deployment governance architecture. |
| [trusted-synthetic-data-ministry-ai.md](./ai-governance/trusted-synthetic-data-ministry-ai.md) | Research memo | Synthetic data infrastructure for ministry-scale AI. |
| Document | Type | Description |
| :------------------------------------------------------------------------------------------ | :------------ | :------------------------------------------------------ |
| [fragmented-catholic-digital-governance.md](./research/fragmented-catholic-digital-governance.md) | Research memo | The urgency of shared digital governance standards. |
| [governance-as-code-catholic-technology.md](./research/governance-as-code-catholic-technology.md) | Research memo | Machine-enforceable deployment governance architecture. |
| [trusted-data-infrastructure-catholic-ministry.md](./research/trusted-data-infrastructure-catholic-ministry.md) | Research memo | Trusted data infrastructure for Catholic ministry. |

---

Expand Down
144 changes: 144 additions & 0 deletions RELEASING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
# Releasing

This document describes how governance documents are built, deployed, and released.

## Overview

The release pipeline is driven by the GitHub Actions workflow
`.github/workflows/deploy-docs.yml`. It triggers on:

- **Tag push** matching `v*` (e.g. `v0.2`) -- deploys only documents changed
since the previous tag.
- **Manual dispatch** (`workflow_dispatch`) -- deploys all documents.

A single workflow run performs four stages in order:

1. Deploy changed documents to WordPress
2. Translate deployed pages
3. Build standalone HTML and combined PDF artifacts
4. Create (or update) a GitHub release with those artifacts

## Prerequisites

The following repository secrets and variables must be configured in GitHub:

| Name | Type | Purpose |
| :------------------ | :------- | :----------------------------------------------- |
| `WP_REST_URL` | Variable | Base URL of the WordPress REST API |
| `WP_APP_USERNAME` | Secret | WordPress application password username |
| `WP_APP_PASSWORD` | Secret | WordPress application password |

The WordPress site must also expose a custom REST endpoint
(`cdcf/v1/translate`) that accepts a `source_id` and `target_lang` for the
translation step.

## How to release

### 1. Prepare the branch

Ensure all changes are merged to `main` and that quality checks pass:

```bash
npm run lint:md # 0 errors expected
npm run build:html # standalone HTML files in dist/
npm run build:pdf # combined PDF in dist/
```

### 2. Tag and push

```bash
git tag v0.X
git push origin v0.X
```

This triggers the deploy workflow automatically.

Alternatively, run the workflow manually from the GitHub Actions tab
(**Run workflow** on the `main` branch). Manual runs deploy all documents and
auto-increment the version tag.

### 3. What the workflow does

#### Stage 1 -- WordPress deployment

- Compares the tagged commit against the previous tag to determine which
`.md` files changed.
- Converts each changed document from Markdown to HTML using `pandoc` with
the Lua filter `scripts/fix-internal-links.lua` (which rewrites internal
`.md` links for the target output format).
- Creates or updates the corresponding WordPress page via the REST API,
organized under parent pages (`project-governance`, `research`, `standards`).

#### Stage 1b -- Stale page cleanup

- Uses `git diff --diff-filter=D` between tags to detect governance `.md`
files that were deleted or renamed since the previous release.
- Derives the WordPress slug for each deleted file (using the same logic as
deployment) and trashes the corresponding page.
- If an entire section directory no longer exists (e.g. `ai-governance/` was
removed), the parent page is also trashed.
- Pages are moved to the WordPress trash (not permanently deleted), so they
can be recovered if needed.
- This step only runs for tag-triggered deploys (not manual dispatch, which
has no previous tag to compare against).

#### Stage 2 -- Translation

- Each newly deployed page is translated into **it**, **es**, **fr**, **pt**,
and **de** via the `cdcf/v1/translate` endpoint.

#### Stage 3 -- Build artifacts

- `npm run build:html` (`scripts/build-standalone-html.sh`) -- produces one
self-contained HTML file per document in `dist/`, each with a navigation
sidebar linking to the other documents.
- `npm run build:pdf` (`scripts/build-combined-pdf.sh`) -- concatenates all
documents into a single Markdown file, converts to standalone HTML, then
renders a paginated PDF using `pagedjs-cli`.

Both scripts use `scripts/docs-print.css` for styling and
`scripts/fix-internal-links.lua` for link rewriting.

#### Stage 4 -- GitHub release

- Creates a GitHub release titled **Governance Docs vX.Y** with all
`dist/*.html` and `dist/*.pdf` files attached.
- If the release already exists (e.g. re-run), assets are uploaded with
`--clobber`.

## Local builds

You can build artifacts locally without deploying:

```bash
npm install # first time only
npm run build:html # dist/*.html
npm run build:pdf # dist/cdcf-governance-docs.pdf (requires pagedjs-cli)
```

The PDF build requires Google Chrome or Chromium installed locally
(`pagedjs-cli` uses it for rendering). Set `PUPPETEER_EXECUTABLE_PATH` if
the binary is not in the default location.

## Document inventory

The following documents are included in builds and deployments:

| Section | File |
| :----------------- | :----------------------------------------------- |
| Project Governance | `project-governance/project-vetting-criteria.md` |
| Project Governance | `project-governance/lifecycle.md` |
| Project Governance | `project-governance/committees.md` |
| Project Governance | `project-governance/project-types.md` |
| Project Governance | `project-governance/definitions.md` |
| Research | `research/fragmented-catholic-digital-governance.md` |
| Research | `research/governance-as-code-catholic-technology.md` |
| Research | `research/trusted-data-infrastructure-catholic-ministry.md` |
| Standards | `standards/overview.md` |
| Standards | `standards/committees.md` |

To add a new document, update the `DOCS` array in all three places:

1. `.github/workflows/deploy-docs.yml` (lines 27-38 and 87-98)
2. `scripts/build-standalone-html.sh` (lines 10-21)
3. `scripts/build-combined-pdf.sh` (lines 12-24)
Loading