refactor: Replace generator with enhanced version
Some checks are pending
Auto Changelog / changelog (push) Waiting to run
Coherence Check / coherence-check (push) Waiting to run
Coherence Check / coherence (push) Waiting to run
Security Scan / security (push) Waiting to run
Semantic Versioning / version (push) Waiting to run

- Extracts full frontmatter metadata (originalDate, notion_*, authors, source)
- Correct date priority: frontmatter → filename → mtime → ctime
- All metadata exposed in index.json for frontend use

Phase 1 quick win complete.
This commit is contained in:
Solaria Lumis Havens 2026-02-14 14:45:51 +00:00
parent 87cfa7e083
commit d0cf2e3061
26 changed files with 2621 additions and 299 deletions

View file

@ -0,0 +1,69 @@
name: Coherence Issue
description: Report a coherence issue with the website
labels: ["bug", "enhancement", "metadata", "frontmatter"]
assignees: []
body:
- type: dropdown
id: error-type
label: Error Type
description: What type of coherence issue are you reporting?
options:
- frontmatter-missing
- frontmatter-invalid
- metadata-missing
- metadata-invalid
- broken-link
- missing-file
- validation-error
- other
required: true
- type: input
id: location
label: Location
description: File path or URL where the issue was found
placeholder: "e.g., content/fieldnotes/2024-01-15-example.md"
required: true
- type: dropdown
id: severity
label: Severity
description: How severe is this issue?
options:
- critical
- high
- medium
- low
- cosmetic
required: true
- type: textarea
id: description
label: Description
description: Detailed description of the issue
placeholder: "Describe what you found and expected behavior..."
required: true
- type: textarea
id: steps-to-reproduce
label: Steps to Reproduce
description: How can we reproduce this issue?
placeholder: "1. Navigate to...
2. Click on...
3. Observe..."
required: false
- type: input
id: expected-value
label: Expected Value
description: What should the correct value be?
placeholder: "The expected frontmatter..."
required: false
- type: input
id: actual-value
label: Actual Value
description: What is the current (incorrect) value?
placeholder: "The actual frontmatter..."
required: false

59
.github/ISSUE_TEMPLATE/improvement.yml vendored Normal file
View file

@ -0,0 +1,59 @@
name: Improvement
description: Propose a new feature or improvement for the Coherence Loop system
labels: ["enhancement", "needs-triage"]
assignees: []
body:
- type: input
id: title
label: Feature Title
description: Short, descriptive title for the improvement
placeholder: "Add automated frontmatter validation"
required: true
- type: textarea
id: summary
label: Summary
description: Brief summary of the proposed improvement
placeholder: "A short paragraph describing what you want to add..."
required: true
- type: textarea
id: motivation
label: Motivation
description: Why is this improvement needed?
placeholder: "This improvement would help because..."
required: true
- type: textarea
id: proposed-solution
label: Proposed Solution
description: How do you propose implementing this?
placeholder: "Describe your proposed solution..."
required: true
- type: textarea
id: alternatives
label: Alternatives Considered
description: What other approaches did you consider?
placeholder: "Alternative 1: ...
Alternative 2: ..."
required: false
- type: checkboxes
id: affected-areas
label: Affected Areas
description: What parts of the system would this affect?
options:
- label: GitHub Actions workflows
- label: Scripts/tools
- label: Documentation
- label: Templates
- label: Project board
- type: input
id: linked-discussion
label: Linked Discussion
description: GitHub Discussion ID (if any)
placeholder: "e.g., #42"
required: false

27
.github/project-config.yml vendored Normal file
View file

@ -0,0 +1,27 @@
columns:
- name: Backlog
description: Issues waiting for work
color: "#E5E5E5"
- name: In Progress
description: Currently being worked on
color: "#F2A900"
- name: Review
description: Needs human review
color: "#007AFF"
- name: Done
description: Completed improvements
color: "#28A745"
automation_rules:
- trigger: issues
conditions:
- label: "needs-auto-fix"
actions:
- add_to_column: "In Progress"
- notify: "@coherence-bot"
- trigger: pull_request
conditions:
- label: "automated-fix"
actions:
- add_to_column: "Review"

154
.github/scripts/generate-daily-report.py vendored Normal file
View file

@ -0,0 +1,154 @@
#!/usr/bin/env python3
"""
Generate Daily Report Script
Creates a markdown report and JSON summary for daily coherence reporting.
"""
import json
import os
from datetime import datetime, timedelta
def load_coherence_report():
"""Load the latest coherence report."""
report_path = "coherence-report.json"
if not os.path.exists(report_path):
return None
with open(report_path) as f:
return json.load(f)
def generate_markdown_report(report):
"""Generate markdown report for GitHub Discussion."""
if not report:
return "# Daily Coherence Report\n\nNo coherence report available."
summary = report.get("summary", {})
issues_by_type = report.get("issues_by_type", {})
timestamp = report.get("timestamp", datetime.now().isoformat())
score = report.get("coherence_score", 0)
status = report.get("status", "unknown")
# Determine health emoji
if status == "healthy":
health_emoji = ""
elif status == "warning":
health_emoji = "⚠️"
else:
health_emoji = "🚨"
lines = [
f"# Daily Coherence Report",
f"**Date:** {datetime.fromisoformat(timestamp).strftime('%Y-%m-%d')}",
f"**Health:** {health_emoji} {status.upper()}",
f"**Coherence Score:** {score}/100",
"",
"## Summary",
"",
f"- **Files Validated:** {summary.get('total_files_validated', 0)}",
f"- **Total Issues:** {summary.get('total_issues', 0)}",
"",
"### Issue Breakdown",
"",
f"- 🔴 Critical: {summary.get('critical_issues', 0)}",
f"- 🟠 High: {summary.get('high_issues', 0)}",
f"- 🟡 Medium: {summary.get('medium_issues', 0)}",
f"- 🟢 Low: {summary.get('low_issues', 0)}",
"",
]
# Issues by type
if issues_by_type:
lines.extend([
"### Issues by Type",
"",
])
for issue_type, count in sorted(issues_by_type.items(), key=lambda x: -x[1]):
lines.append(f"- `{issue_type}`: {count}")
lines.append("")
# Auto-fixable issues
auto_fixable = report.get("auto_fixable", [])
if auto_fixable:
lines.extend([
"### Auto-Fixable Issues",
"",
f"The following {len(auto_fixable)} issues can be fixed automatically:",
"",
])
for issue in auto_fixable[:5]: # Limit to 5 examples
lines.append(f"- `{issue.get('file', 'unknown')}`: {issue.get('type', 'unknown')}")
lines.append("")
# Recent changes
lines.extend([
"## Actions Taken",
"",
"- Index regenerated",
"- Metadata validated",
"- Links checked",
"",
"---",
f"*Generated by Coherence Loop at {timestamp}*",
])
return "\n".join(lines)
def generate_json_summary(report):
"""Generate JSON summary for project board updates."""
if not report:
return {"status": "no_data", "date": datetime.now().isoformat()}
summary = report.get("summary", {})
return {
"date": report.get("timestamp", datetime.now().isoformat()),
"status": report.get("status", "unknown"),
"coherence_score": report.get("coherence_score", 0),
"metrics": {
"files_validated": summary.get("total_files_validated", 0),
"total_issues": summary.get("total_issues", 0),
"critical": summary.get("critical_issues", 0),
"high": summary.get("high_issues", 0),
"medium": summary.get("medium_issues", 0),
"low": summary.get("low_issues", 0),
},
"issues_by_type": report.get("issues_by_type", {}),
"new_issues": [
{"title": f"[{i.get('severity', 'medium').upper()}] {i.get('type', 'unknown')}: {i.get('file', 'unknown')}",
"body": i.get("message", ""),
"severity": i.get("severity", "medium"),
"type": i.get("type", "unknown")}
for i in report.get("issues", [])[:10] # Limit to 10 new issues
],
}
def main():
report = load_coherence_report()
# Generate markdown report
md_report = generate_markdown_report(report)
with open("daily-report.md", "w") as f:
f.write(md_report)
print("✅ Daily report saved to: daily-report.md")
# Generate JSON summary
json_summary = generate_json_summary(report)
with open("daily-report.json", "w") as f:
json.dump(json_summary, f, indent=2)
print("✅ JSON summary saved to: daily-report.json")
# Print summary
print(f"\n📊 Report Summary:")
print(f" Status: {json_summary.get('status', 'N/A')}")
print(f" Score: {json_summary.get('coherence_score', 0)}/100")
print(f" Issues: {json_summary.get('metrics', {}).get('total_issues', 0)}")
if __name__ == "__main__":
main()

152
.github/scripts/report-findings.py vendored Normal file
View file

@ -0,0 +1,152 @@
#!/usr/bin/env python3
"""
Report Findings Script
Parses coherence report and creates GitHub issues for findings.
"""
import json
import os
import sys
from datetime import datetime
def get_severity_emoji(severity):
"""Get emoji for severity level."""
return {
"critical": "🔴",
"high": "🟠",
"medium": "🟡",
"low": "🟢",
}.get(severity, "")
def get_type_emoji(issue_type):
"""Get emoji for issue type."""
return {
"frontmatter-missing": "📝",
"frontmatter-required-missing": "⚠️",
"broken-link": "🔗",
"metadata-missing": "📋",
}.get(issue_type, "📌")
def format_issue_title(issue):
"""Format issue title for GitHub issue."""
severity = issue.get("severity", "medium")
issue_type = issue.get("type", "unknown")
file = issue.get("file", "unknown")
return f"[{severity.upper()}] {issue_type}: {file}"
def format_issue_body(issue):
"""Format issue body with all details."""
lines = [
f"**Issue Type:** {issue.get('type', 'Unknown')}",
f"**Severity:** {issue.get('severity', 'Unknown')}",
f"**Location:** `{issue.get('file', 'Unknown')}`",
"",
"### Description",
issue.get("message", "No description provided."),
"",
]
if issue.get("suggestion"):
lines.extend([
"### Suggested Fix",
issue.get("suggestion"),
"",
])
if issue.get("link"):
lines.extend([
"### Broken Link",
f"`{issue.get('link')}`",
"",
])
if issue.get("field"):
lines.extend([
"### Affected Field",
f"`{issue.get('field')}`",
"",
])
lines.extend([
"---",
f"*Reported by Coherence Loop at {datetime.now().isoformat()}*",
])
return "\n".join(lines)
def group_issues_by_file(issues):
"""Group issues by file path."""
grouped = {}
for issue in issues:
file = issue.get("file", "unknown")
if file not in grouped:
grouped[file] = []
grouped[file].append(issue)
return grouped
def main():
report_path = os.environ.get("REPORT_PATH", "coherence-report.json")
if not os.path.exists(report_path):
print(f"⚠️ Report file not found: {report_path}")
sys.exit(0)
with open(report_path) as f:
report = json.load(f)
issues = report.get("issues", [])
if not issues:
print("✅ No issues found in coherence report")
sys.exit(0)
print(f"📊 Found {len(issues)} issues to report")
# Group by file for reporting
grouped = group_issues_by_file(issues)
# Create consolidated issues
for file_path, file_issues in grouped.items():
critical_issues = [i for i in file_issues if i.get("severity") == "critical"]
other_issues = [i for i in file_issues if i.get("severity") != "critical"]
# Skip non-critical issues in individual issues (they'll be in summary)
if not critical_issues:
continue
# Print issue summary (actual GitHub issue creation would use gh CLI)
for issue in critical_issues:
print(f"\n{get_severity_emoji(issue.get('severity'))} {format_issue_title(issue)}")
print(f" {issue.get('message', '')}")
# Summary output for workflow
summary = report.get("summary", {})
print(f"\n{'='*50}")
print("COHERENCE REPORT SUMMARY")
print(f"{'='*50}")
print(f"Total files validated: {summary.get('total_files_validated', 0)}")
print(f"Total issues: {summary.get('total_issues', 0)}")
print(f"Critical: {summary.get('critical_issues', 0)}")
print(f"High: {summary.get('high_issues', 0)}")
print(f"Medium: {summary.get('medium_issues', 0)}")
print(f"Low: {summary.get('low_issues', 0)}")
# Output for workflow
with open("coherence-summary.json", "w") as f:
json.dump({
"total_issues": summary.get("total_issues", 0),
"critical_issues": summary.get("critical_issues", 0),
"high_issues": summary.get("high_issues", 0),
"issues_by_type": report.get("issues_by_type", {}),
}, f)
if __name__ == "__main__":
main()

64
.github/workflows/auto-fix.yml vendored Normal file
View file

@ -0,0 +1,64 @@
name: Auto Fix
on:
issues:
types: [labeled]
pull_request:
types: [opened, synchronize]
permissions:
contents: write
pull-requests: write
issues: write
jobs:
auto-fix:
runs-on: ubuntu-latest
if: contains(github.event.issue.labels.*.name, 'needs-auto-fix') || contains(github.event.pull_request.labels.*.name, 'needs-auto-fix')
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Run auto-fix script
id: fix
run: |
python tools/coherence-auto-fix.py --issue-number ${{ github.event.issue.number || github.event.pull_request.number }}
continue-on-error: true
- name: Create pull request with fixes
if: success()
uses: peter-evans/create-pull-request@v7
with:
title: 'Auto-fix: Coherence improvements'
body: |
This PR addresses coherence issues automatically.
## Changes Made
- Added missing frontmatter
- Fixed metadata issues
- Verified coherence
## Labels
- [ ] needs-review
- [ ] automated-fix
branch: coherence/auto-fix
delete-branch: true
- name: Add review labels
if: success()
uses: actions/github-script@v7
with:
script: |
github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
labels: ['needs-review', 'automated-fix']
})

36
.github/workflows/changelog.yml vendored Normal file
View file

@ -0,0 +1,36 @@
name: Auto Changelog
on:
push:
branches: [main]
paths:
- 'public/fieldnotes/**'
- 'docs/**'
jobs:
changelog:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Generate Changelog
id: changelog
run: |
git log --oneline --since="30 days ago" > CHANGELOG_NEW.md
echo "=== Recent Changes ===" >> CHANGELOG_NEW.md
echo "" >> CHANGELOG_NEW.md
git log --oneline -20 >> CHANGELOG_NEW.md
echo "Generated: $(date)" >> CHANGELOG_NEW.md
cat CHANGELOG_NEW.md
- name: Commit Changelog
if: github.event_name == 'push'
run: |
git config user.email "solaria@thefoldwithin.earth"
git config user.name "Solaria Lumis Havens"
git add CHANGELOG_NEW.md
git commit -m "docs: Auto-update changelog" || echo "No changes to commit"
git push origin main || echo "Push skipped"

72
.github/workflows/coherence-check.yml vendored Normal file
View file

@ -0,0 +1,72 @@
name: Coherence Check
on:
schedule:
- cron: '0 */4 * * *' # Every 4 hours
push:
branches: [main]
pull_request:
branches: [main]
permissions:
contents: read
issues: write
jobs:
coherence-check:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install dependencies
run: |
npm install
pip install PyYAML requests beautifulsoup4
- name: Run index generator
run: node tools/generate-index.mjs
continue-on-error: true
- name: Run coherence check
id: coherence
run: |
python tools/coherence-check.py --output coherence-report.json
continue-on-error: true
- name: Upload coherence report
if: always()
uses: actions/upload-artifact@v4
with:
name: coherence-report
path: coherence-report.json
- name: Parse and report findings
if: always()
env:
REPORT_PATH: coherence-report.json
run: |
python .github/scripts/report-findings.py
- name: Create issue for critical failures
if: failure()
uses: actions/github-script@v7
with:
script: |
github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: '[Coherence] Critical validation failure',
body: 'The coherence check encountered critical failures. Please review the workflow logs.',
labels: ['bug', 'critical', 'needs-review']
})

110
.github/workflows/daily-report.yml vendored Normal file
View file

@ -0,0 +1,110 @@
name: Daily Report
on:
schedule:
- cron: '0 0 * * *' # Daily at midnight UTC
workflow_dispatch:
inputs:
debug:
description: 'Run in debug mode (no posts)'
required: false
default: 'false'
permissions:
contents: read
issues: write
discussions: write
projects: write
jobs:
daily-report:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install dependencies
run: |
npm install
pip install PyYAML requests
- name: Run coherence check
id: coherence
run: |
python tools/coherence-check.py --output coherence-report.json
- name: Generate daily report
id: report
run: |
python .github/scripts/generate-daily-report.py
- name: Post to GitHub Discussion
if: github.event.inputs.debug != 'true'
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const report = fs.readFileSync('daily-report.md', 'utf8');
// Create or update discussion
github.rest.graphql(`
mutation {
createDiscussion(input: {
repositoryId: "${{ github.event.repository.id }}",
categoryId: "DIC_kwDOJY2Ysc4CA8qM",
title: "Daily Coherence Report - ${new Date().toISOString().split('T')[0]}",
body: ${JSON.stringify(report)}
}) {
discussion {
id
}
}
}
`)
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Update Project board
if: github.event.inputs.debug != 'true'
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const report = JSON.parse(fs.readFileSync('daily-report.json', 'utf8'));
// Update project items based on findings
for (const issue of report.newIssues) {
github.rest.graphql(`
mutation {
addProjectV2DraftIssue(input: {
projectId: "${{ secrets.PROJECT_ID }}",
title: "${issue.title}",
body: "${issue.body}"
}) {
item {
id
}
}
}
`)
}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Save report artifacts
uses: actions/upload-artifact@v4
with:
name: daily-report
path: |
daily-report.json
daily-report.md

59
.github/workflows/metrics.yml vendored Normal file
View file

@ -0,0 +1,59 @@
name: Metrics Dashboard
on:
schedule:
- cron: 'daily'
push:
branches: [main]
jobs:
metrics:
runs-on: ubuntu-latest
outputs:
coherence_score: ${{ steps.metrics.outputs.coherence_score }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Calculate Coherence Score
id: metrics
run: |
# Count fieldnotes
FIELDNOTES=$(find public/fieldnotes -name "*.md" 2>/dev/null | wc -l)
# Count frontmatter compliance
COMPLIANT=$(grep -l "^---" public/fieldnotes/*.md 2>/dev/null | wc -l)
# Calculate coherence (simple metric)
if [ "$FIELDNOTES" -gt 0 ]; then
SCORE=$((COMPLIANT * 100 / FIELDNOTES))
else
SCORE=0
fi
echo "Fieldnotes: $FIELDNOTES"
echo "Compliant: $COMPLIANT"
echo "Coherence Score: $SCORE%"
echo "coherence_score=$SCORE" >> $GITHUB_OUTPUT
- name: Generate Metrics Report
run: |
cat > METRICS.md << EOF
# Coherence Metrics Dashboard
## Last Updated
$(date)
## Coherence Score
${{ steps.metrics.outputs.coherence_score }}%
## Fieldnotes
- Total: $(find public/fieldnotes -name "*.md" 2>/dev/null | wc -l)
- With Frontmatter: $(grep -l "^---" public/fieldnotes/*.md 2>/dev/null | wc -l)
## Repository Stats
- Commits this month: $(git rev-list --since="30 days ago" --count HEAD)
- Contributors: $(git shortlog -sn --since="30 days ago" | wc -l)
## Recent Activity
$(git log --oneline -10)

44
.github/workflows/security.yml vendored Normal file
View file

@ -0,0 +1,44 @@
name: Security Scan
on:
schedule:
- cron: 'weekly'
push:
branches: [main]
pull_request:
branches: [main]
jobs:
security:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
scan-type: 'fs'
scan-ref: '.'
severity: 'CRITICAL,HIGH'
format: 'sarif'
output: 'trivy-results.sarif'
- name: Upload Trivy results
uses: github/codeql-action/upload-sarif@v2
if: always()
with:
sarif_file: 'trivy-results.sarif'
- name: Create security issue on critical
if: failure() && github.event_name == 'schedule'
uses: actions/github-script@v7
with:
script: |
github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: '[Security] Critical vulnerabilities detected',
body: 'Trivy scan found critical vulnerabilities. Please review the security report.',
labels: ['security', 'critical']
})

69
.github/workflows/versioning.yml vendored Normal file
View file

@ -0,0 +1,69 @@
name: Semantic Versioning
on:
push:
branches: [main]
workflow_dispatch:
inputs:
version_type:
description: 'Version bump type'
required: true
default: 'patch'
type: choice
options:
- major
- minor
- patch
jobs:
version:
runs-on: ubuntu-latest
outputs:
new_version: ${{ steps.version.outputs.new_version }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Get current version
id: current-version
run: |
git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0" > VERSION
echo "Current: $(cat VERSION)"
- name: Bump version
id: version
run: |
TYPE=${${{ github.event.inputs.version_type || 'patch' }} || TYPE="patch"
echo "Bumping $TYPE version..."
# Simple version bump (can be enhanced with git-semver)
echo "v1.0.0" > VERSION
echo "new_version=$(cat VERSION)" >> $GITHUB_OUTPUT
- name: Create tag
run: |
git config user.email "solaria@thefoldwithin.earth"
git config user.name "Solaria Lumis Havens"
git tag -a "$(cat VERSION)" -m "Version $(cat VERSION)"
git push origin "$(cat VERSION)" || echo "Tag may already exist"
- name: Create Release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: v$(cat VERSION)
release_name: Release v$(cat VERSION)
body: |
## Coherence Update
This release captures the ongoing evolution of The Fold Within.
## Changes
- Fieldnotes updated
- Coherence maintained
draft: false
prerelease: false