fork-sync-all
Sync · Mirror · Automate
fork-sync-all is the control plane for the Interested-Deving-1896 GitHub org.
It mirrors repositories into OpenOS-Project-OSP (GitHub) and then to
openos-project (GitLab), manages READMEs across ~49 OSP-bound repos,
syncs upstream forks, and runs org-wide maintenance workflows.
Quick navigation
Architecture
Three-org mirror chain, data flow, GitLab subgroup map, token model, quota layers.
Workflow Triggers
All 180 workflows — schedules, triggers, cross-workflow dependencies, index + glossary.
Operations
GitHub Actions limits, quota management, concurrency groups, schedule summary.
Quota Costs
Per-workflow REST call cost table, daily budget, REST→GraphQL savings.
Runbooks
Quota exhaustion, queue pile-up, token expiry, mirror chain broken, incident response.
Contributing
Adding workflows, scripts, config files; testing; white-labeling guide.
Source Tree
Full directory/file index of the entire fork-sync-all source hierarchy.
Glossary
Definitions for every term, acronym, and concept used across the project.
fork-sync-all
When Git Platforms Give You Anxiety Attacks, Who Are You Going To Call? Fork-Sync-All!
Control plane for the Interested-Deving-1896 GitHub org. Runs 147 GitHub Actions workflows that keep three GitHub orgs and two GitLab groups in sync, manage READMEs and badges across OSP-bound repos, resolve CI failures, and maintain registered upstream imports.
| Workflows | 180 |
| Registered imports | 157 |
| Template consumers | 82 |
| GitLab subgroups | 14 |
| GitLab repos mirrored | 225 |
How it works
┌─────────────────────────────────────────────────────────────────────────────┐
│ Mirror chain (outward, every 6h) │
│ │
│ Interested-Deving-1896 ──► OpenOS-Project-OSP │
│ ▲ │ │
│ │ ▼ │
│ │ OpenOS-Project-Ecosystem-OOC │
│ │ │ │
│ │ ▼ │
│ │ GitLab openos-project │
│ │ (14 subgroups, 225 repos mirrored) │
│ │ │
│ └──── upstream-commits / upstream-prs (OSP + OOC → I-D-1896) ─────┘
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ Full pipeline (manual / monthly) │
│ │
│ flush-lifecycle ──► pre-flush-prep ──► full-chain-flush (25 stages) ──► post-flush-prep │
│ │ │ │ │
│ QUOTA_SNAPSHOT QUOTA_SNAPSHOT QUOTA_SNAPSHOT │
│ (chain entry) (chain start) (chain exit) │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ Quota & queue management (automatic, every 30 min) │
│ │
│ quota-reserve ──► queue-manager ──► rate-limit-rerun │
│ │ │
│ cancel-stale-runs │
│ quota-monitor │
└─────────────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────────────┐
│ OTA system (versioned updates for independent forks) │
│ │
│ ota-release ──► ota-deliver ──► opted-in forks (PR per fork) │
│ ▲ │
│ semver tag push │
│ │
│ ota-reconcile (weekly) ──► path A: stamp · B: drift PR · C: quota PR │
└─────────────────────────────────────────────────────────────────────────────┘
This project provides automated management for git repositories and organizations across multiple git-based platforms. It addresses challenges such as keeping forks synchronized, generating READMEs, injecting badges, tracking upstream changes, mirroring repositories, and managing releases. It is used by developers and organizations to streamline repository maintenance and ensure consistency across distributed version control systems.
Documentation
| Resource | Description |
|---|---|
| Full documentation | Architecture, quota management, workflow reference, runbooks |
| Workflow Triggers | All 185 workflows — schedules, triggers, synopses (plain text · published) |
| OTA Reconcile | Hybrid A/B/C fallback layer for mirror-chain consumers |
| OTA System | OTA delivery architecture and opt-in guide |
| AI Agent Costs | OCU pricing, tokenizer reference, per-task estimates |
| Quota Costs | Per-workflow REST call estimates (p50/p95) |
| Workflow Scheduling | Optimal dispatch windows, quota floors, EST/UTC timing |
| Runbooks | Incident response and operational procedures |
Workflow groups
158 workflows across 20 functional groups. Full detail in DOCS/workflow-triggers.md.
| Group | Workflows | Description |
|---|---|---|
| Accessibility | 1 | CODEOWNERS coverage, screen-reader scan, WCAG audit, audio overview, Braille output |
| AI & Cost Tracking | 4 | Session cost log, weekly price sync |
| BDFS / Filesystem Workspace | 5 | DwarFS/BTRFS workspace dev and packaging |
| Bugzilla Integration | 1 | Sync commits/PRs to Bugzilla, milestone shipping |
| Build & Release | 10 | Build, checks, release, kernel content, arch config |
| CI & Failure Resolution | 7 | Rate-limit rerun, failure resolver, runner status |
| Documentation & Publishing | 9 | mdBook, GitBook, NotebookLM, translate docs, triggers doc |
| Fork & Import Sync | 20 | Upstream fork sync, registered imports, platform import |
| Full Pipeline | 8 | pre-flush → full-chain-flush → post-flush + critical-deploy |
| Git Platform Sync | 5 | Bidirectional push/pull sync with GitLab |
| Infrastructure & Environment | 4 | Dev container SDK, Incus, FSA API |
| Maintenance & Housekeeping | 16 | Config validation, cleanup, token rotation, dep updates |
| Mirror Chain | 14 | Outward mirror: I-D-1896 → OSP → OOC → GitLab |
| OSP-Bound Repo Management | 7 | Add mirror repo, CI status, setup OSP mirrors |
| OTA System | 5 | Release delivery, reconcile, self-update, discover, opt-in |
| PR Governance & Trust | 10 | Vouch, PR gate, labeler, auto-merge, rebase |
| Quota & Queue Management | 5 | Reserve, dedup, monitor, cost registry |
| README Management | 10 | Create, update, badge, translate, validate READMEs |
| Security & Compliance | 6 | SBOM, CodeQL, vendor audit, arch audit, pin workflows |
| Utility / On-Demand | 11 | Manual and specialised workflows |
Key config files
| File | Purpose |
|---|---|
config/agent-cost-profiles.yml | Machine-readable AI agent cost profiles (8 variants, 10 complexity tiers) |
config/gitlab-subgroups.yml | Single source of truth for GitLab subgroup placement |
config/ota-blocklist.yml | Orgs/profiles excluded from OTA delivery by default |
config/ota-registry.yml | Opted-in forks receiving OTA updates |
config/template-consumers.yml | 80 repos that receive template updates via sync-template.yml |
config/template-manifest.yml | Profile definitions for template sync (full / mirror / infra-core / standalone) |
config/workflow-priority-tiers.yml | Cancellation priority (Tier 1 = never cancel, Tier 4 = cancel first) |
config/workflow-quota-costs.yml | Per-workflow REST call cost estimates — drives quota pre-flight and quota-reserve.yml |
config/workflow-sync.yml | Which workflows have GitLab CI counterparts |
registered-imports.json | 156 upstream repos kept in ongoing sync |
Secrets
| Secret | Used by | Notes |
|---|---|---|
ACTIVITYSMITH_API_KEY | full-chain-flush.yml | Optional — live activity tracking; skipped if unset |
ADD_MIRROR_REPO_SYNC | add-mirror-repo.yml | Scoped PAT for repo creation |
BITBUCKET_TOKEN | import-repo.yml, sync-registered-imports.yml | Bitbucket app password (private repos only) |
GH_SYNC_TOKEN | GitLab CI sync-from-gitlab job | Same PAT stored as a GitLab CI variable |
GITEA_TOKEN | import-repo.yml, sync-registered-imports.yml | Gitea/Codeberg PAT (private repos only) |
GITLAB_SYNC_TOKEN | mirror-osp-to-gitlab.yml, post-flush verification | GitLab PAT for mirror operations |
GITLAB_TOKEN | GitLab workflows | GitLab PAT — api + write_repository on openos-project |
NOTEBOOKLM_AUTH_JSON | generate-notebooklm.yml | Short-lived auth state, rotated weekly by refresh-notebooklm-auth.yml |
OSP_ADMIN_TOKEN | OSP org admin operations | PAT with admin:org on OpenOS-Project-OSP |
SOURCEHUT_TOKEN | import-repo.yml | Sourcehut PAT (private repos only) |
SYNC_IN_SERVER_URL | sync-in.yml | URL of the local sync-in server instance |
SYNC_TOKEN | All workflows | GitHub PAT — repo + workflow + admin:org scopes |
gh secret set <SECRET_NAME> --repo Interested-Deving-1896/fork-sync-all
Rate limits
Both SYNC_TOKEN and GH_SYNC_TOKEN belong to the same user and share the same 5,000 req/hr REST bucket. Treat them as one pool. raw.githubusercontent.com fetches do not count against the quota.
| API | Limit | Reset |
|---|---|---|
| GitHub REST | 5,000 req/hr per token | Top of the hour |
| GitHub GraphQL | 5,000 pts/hr (counts as 1 REST call) | Top of the hour |
| GitHub Models | Varies by model | Per-minute window |
| GitLab REST | 2,000 req/min per token | Per-minute window |
quota-reserve.yml cancels low-priority queued runs when remaining quota drops below 1,000. Check current quota:
curl -sf -H "Authorization: token $SYNC_TOKEN" \
"https://api.github.com/rate_limit" | \
python3 -c "
import sys, json, datetime
d = json.load(sys.stdin)['resources']['core']
reset = datetime.datetime.utcfromtimestamp(d['reset']).strftime('%H:%M UTC')
print(f'remaining={d[\"remaining\"]} resets={reset}')
"
GitLab subgroups
14 subgroups under gitlab.com/openos-project, 225 repos mirrored. Assignments are in config/gitlab-subgroups.yml.
| Subgroup | Repos | Focus |
|---|---|---|
accessibility_deving | 9 | Screen readers, Braille, WCAG auditing, audio overviews |
agnostic-api_deving | 29 | Unified Agnostic API — virtual filesystems, AI/LLM adapters, OS-compat layers |
ai-agents_deving | 10 | AI agent frameworks and tools |
cachyos_deving | 12 | CachyOS distro packages |
git-management_deving | 9 | Git tooling and org management |
immutable-filesystem_deving | 1 | Immutable filesystem projects |
incus_deving | 49 | Incus container/VM tooling |
linux-kernel_filesystem_deving | 14 | Kernel and filesystem repos |
neon-deving | 8 | KDE Neon repos |
ops | 30 | Infrastructure and org management tooling |
penguins-eggs_deving | 17 | penguins-eggs distro tools |
rust-systems_deving | 2 | Rust systems programming |
taubyte_deving | 1 | Taubyte protocol |
yaml-tooling_deving | 34 | YAML tools, linters, schema validators, GH Actions tooling |
All automation is implemented as Bash scripts in scripts/ and GitHub Actions workflows in .github/workflows/. There are no compiled artifacts, no Node.js runtime dependencies, and no build step — every workflow runs directly against the shell scripts.
.
├── .github/workflows/ # 147 GitHub Actions workflows
├── scripts/ # Bash automation scripts
│ └── includes/ # Shared helpers (gh-api.sh, budget.sh, quota-instrument.sh, …)
├── config/ # YAML config: subgroup maps, quota costs, priority tiers, …
├── DOCS/ # mdBook source (architecture, runbooks, quota reference, …)
│ └── generated/ # Auto-generated pages (workflow reference, source tree, …)
├── services/ # Long-running service helpers (sync-in server)
├── vendor/ # Third-party components hosted by fork-sync-all
├── .devcontainer/ # Dev container definition and local features
├── .ona/ # Ona automations (services + tasks)
├── registered-imports.json # Upstream repos kept in sync
├── book.toml # mdBook configuration
└── Dockerfile # Container image for CI runners
Scripts communicate via environment variables and exit codes. Shared helpers in scripts/includes/ provide GitHub API access (gh-api.sh), quota budgeting (budget.sh), and run instrumentation (quota-instrument.sh). See Architecture for the full data-flow diagram.
The repository uses GitHub Actions for continuous integration and automation. Below are the workflows and their purposes:
- build.yml: Builds the project for all supported platforms. No secrets required.
- test.yml: Runs unit and integration tests. No secrets required.
- lint.yml: Checks code formatting and style using ESLint. No secrets required.
- sync-forks.yml: Synchronizes forks with upstream repositories. Requires
UPSTREAM_TOKENsecret. - mirror-orgs-full.yml: Mirrors repositories across organizations. Requires
MIRROR_TOKENsecret. - inject-badges.yml: Injects badges into README files. No secrets required.
- release.yml: Manages release creation and tagging. Requires
RELEASE_TOKENsecret. - check-ci.yml: Validates CI configuration files. No secrets required.
- cleanup-branches.yml: Deletes stale branches. Requires
GITHUB_TOKENsecret. - codeql-analysis.yml: Performs CodeQL security analysis. Requires
GH_CODEQL_TOKENsecret.
Secrets must be configured in the repository settings under "Settings > Secrets and variables > Actions."
Origins
Auto-generated by
generate-dep-graph.sh. Do not edit manually. Last generated: 2026-06-12 (stub — full graph generated on next scheduled run)
This graph maps every OSP-bound repo in Interested-Deving-1896 to its upstream
origin(s), as declared in each repo's ## Origins README section.
| Repo | Origin | Host | Fork in I-D-1896 |
|---|---|---|---|
github-codeowners | kohofinancial/github-codeowners | GitHub | ✅ |
github-codeowners | jjmschofield/github-codeowners | GitHub | ❌ |
gitlab-enhanced | openos-project/git-management_deving/gitlab-enhanced | GitLab | ✅ |
Summary
- OSP-bound repos scanned: stub (full scan runs weekly via
generate-dep-graph.yml) - Tooling dependencies tracked:
github-codeowners(CODEOWNERS auditing across all OSP repos)
Tooling Dependencies
| Tool | Purpose | Upstream |
|---|---|---|
| github-codeowners | Audits CODEOWNERS coverage — surfaces ownership stats per repo | kohofinancial/github-codeowners |
Resources
| File | Description |
|---|---|
| registered-imports.json | Registered ongoing-sync imports |
| dep-graph/origins.md | Dependency graph (Markdown table) |
| .gitlab/merge_request_templates/Default.md | GitLab MR template |
| config/gitlab-subgroups.yml | GitLab subgroup map |
Accessibility
This repo uses automated accessibility auditing via check-accessibility.yml.
Checks include: CODEOWNERS ownership coverage, README screen-reader compatibility, WCAG 2.1 AA HTML compliance, audio overview (espeak-ng), and Braille output (liblouis).
Run the Check Accessibility workflow to generate the first report and accessibility artifacts. See DOCS/accessibility.md for the full reference.
This repo is maintained in Interested-Deving-1896/fork-sync-all and mirrored through:
Interested-Deving-1896/fork-sync-all ──► OpenOS-Project-OSP/fork-sync-all ──► OpenOS-Project-Ecosystem-OOC/fork-sync-all
Changes flow downstream automatically via the hourly mirror chain in
fork-sync-all.
Direct commits to OSP or OOC are detected and opened as PRs back to Interested-Deving-1896.
Contributors
@Interested-Deving-1896: 480 commits
@github-actions[bot]: 78 commits
@actions-user: 7 commits
@dependabot[bot]: 6 commits
@web-flow: 5 commits
Note: This repository may be a mirror. Please refer to the upstream source for additional context.
License
AGENTS.md
Conventions, patterns, and known pitfalls for AI agents working in this repo.
Repository overview
fork-sync-all is the control plane for the Interested-Deving-1896 GitHub org.
It mirrors repos into OpenOS-Project-OSP (GitHub) and then to openos-project (GitLab),
manages READMEs across ~49 OSP-bound repos, syncs upstream forks, and runs org-wide
maintenance workflows.
Key config files:
config/gitlab-subgroups.yml— single source of truth for GitLab subgroup placementregistered-imports.json— upstream repos to keep in syncscripts/— all automation scripts.github/workflows/— GitHub Actions workflows
Key directories:
vendor/— third-party components hosted/deployed by fork-sync-all (e.g.infra-dashboard). Everything inscripts/is first-party automation. Do not move scripts intovendor/.
GitHub API quota
Both GH_TOKEN and SYNC_TOKEN belong to the same user (ID 202036334) and share
the same 5000 req/hr REST bucket. Treat them as one pool.
raw.githubusercontent.comfetches do not count against the quota- GraphQL counts as 1 call regardless of how many repos are queried
- The quota pre-flight in workflows uses
MIN_QUOTA(typically 1000–1500) to skip runs when the bucket is too low;quota-monitor.shretries after reset
When quota is at 0, avoid any gh api, curl .../api.github.com/..., or gh_get
calls. Check reset time with:
curl -sf -H "Authorization: token $SYNC_TOKEN" \
"https://api.github.com/rate_limit" | jq '{remaining, reset: (.resources.core.reset | todate)}'
AI agent cost budgeting
This repo uses multiple AI agents. Each has a different billing model — understand which resource you're spending before starting a task.
| Agent | Billing | Approx. cost per session |
|---|---|---|
| Ona Agent (Claude 4 Sonnet) | OCUs ($0.25/OCU) | 1–31 OCUs ($0.25–$7.75) depending on task size |
| Codex (Ona-managed) | OCUs (env + model) | Same as Ona Agent |
| Codex (ChatGPT plan connected) | OCUs (env only) + OpenAI | ~1 OCU/hr env; model via ChatGPT plan |
GitHub Models (llm.sh) | GitHub Models quota | ~0.25–1 OCU env runtime; model is free |
| Anthropic API direct | Anthropic pay-per-token | ~$0.30–$0.60/session; no OCUs |
OCU top-up packages (one-time, $0.25/OCU flat): 40 OCUs/$10 · 100/$25 · 200/$50 · 400/$100 · 1,000/$250 · 2,000/$500 · 4,000/$1,000 · 8,000/$2,000
Rough task sizing (Ona Agent on Standard environment):
- Small fix / single file: 1–4 OCUs
- Multi-file feature + tests: 8–12 OCUs
- Large session (3–4 hr, many files): 15–24 OCUs
- Full end-to-end update: 19–31 OCUs
GitHub API quota and OCUs are independent. GitHub quota exhaustion pauses the agent but does not consume OCUs. OCU exhaustion stops the session regardless of GitHub quota state.
Full reference: DOCS/ai-agent-costs.md
Machine-readable profiles: config/agent-cost-profiles.yml
Log a session: gh workflow run track-agent-costs.yml --field agent=ona --field ...
Script conventions
All logging helpers must write to stderr
Every script defines some combination of info(), warn(), dry(), and log().
All must use >&2:
info() { echo "[script-name] $*" >&2; }
warn() { echo "[warn] $*" >&2; }
dry() { echo "[dry-run] $*" >&2; }
log() { echo "[$(date -u '+%H:%M:%S')] $*" >&2; }
Why this matters: Several functions are called inside $(...) subshell captures
where their stdout becomes the captured value (e.g. README content, repo lists,
API responses). Any logging call without >&2 inside such a function will corrupt
the captured data.
This applies to includes/gh-api.sh too — merge_upstream() status messages
must go to stderr since callers may capture its output via result=$(merge_upstream ...).
Known functions called inside $(...) captures — never emit to stdout inside these:
rewrite_readme()inupdate-readmes.shfill_missing_sections()inupdate-readmes.shbuild_readme()increate-readmes.shgenerate_*()functions inupdate-readmes.shmerge_upstream()inscripts/includes/gh-api.sh
YAML parsing
Always use yaml.safe_load — never hand-rolled regex/indent parsers:
import yaml
with open(config_path) as f:
config = yaml.safe_load(f)
subgroups = config.get("subgroups", {}) or {}
This applies to gitlab-subgroups.yml parsing in all scripts.
includes/ scripts
scripts/includes/budget.sh, scripts/includes/gh-api.sh, and
scripts/includes/quota-instrument.sh are sourced by many scripts and workflows.
Changes there have broad impact.
budget.sh— providesbudget_init,budget_check,budget_report,osp_priority_repos, andworkflow_min_quota. The latter reads per-workflowmin_quotafromconfig/workflow-quota-costs.yml.gh-api.sh— providesgh_api,gh_get,gh_api_graphql,merge_upstream,get_default_sha. All status messages use>&2. Guard against double-sourcing is in place (_GH_API_LOADED).gh_get URLis a convenience GET wrapper aroundgh_apiwith full retry and reset-aware backoff — the canonical implementation that individual scripts should migrate to (see consolidation note below).platform-adapter.sh— uniform interface for GitHub, GitLab, Gitea, Forgejo, and Codeberg. See Platform adapter below.fsa-node-identity.sh— extendsfsa-mode.shwith a chain position layer. See Node identity below.auto-merge-prs.sh— standalone script (not an include); see Auto-merge PRs below.
gh_get / gh_api consolidation (complete)
All scripts now source includes/gh-api.sh for gh_get. The three tiers
that existed during migration have been fully consolidated:
| Tier | Scripts | Status |
|---|---|---|
| Full retry (canonical) | check-osp-ci.sh, cleanup-branches.sh | ✅ migrated |
| No retry, fail-fast | create-readmes.sh, inject-badges.sh, pre-flush-prep.sh, readme-wizard.sh, rebase-prs.sh, sync-template.sh, update-readmes.sh | ✅ migrated |
| No retry, silent fail | rerun-after-rate-limit.sh, scan-rate-limit-failures.sh | ✅ migrated (added || echo '{}' fallbacks on capture sites) |
All new scripts should source includes/gh-api.sh and use gh_get directly.
Do not define a local gh_get() in any new script.
-
quota-instrument.sh— providesqi_begin/qi_endfor measuring REST quota consumption per workflow run. Wire into the main job step of any workflow you want to instrument. Writes a structured HTML comment toGITHUB_STEP_SUMMARYthatupdate-quota-costs.ymlparses weekly to compute observed p50/p95 values.qi_begin/qi_endmust be in the samerun:step —_QI_BEFOREis a shell variable that does not survive across step boundaries. When the work spans multiple steps (e.g.delete-stale-repos.yml), persist the value via a temp file:# Step A — sample before source scripts/includes/quota-instrument.sh qi_begin echo "$_QI_BEFORE" > /tmp/qi_before # Step B (always()) — emit delta source scripts/includes/quota-instrument.sh if [[ -f /tmp/qi_before ]]; then _QI_BEFORE=$(cat /tmp/qi_before) qi_end fiIf Step A is skipped (e.g. quota pre-flight exits early),
/tmp/qi_beforewill not exist and theqi_endblock silently no-ops — no spurious delta is recorded.
REST → GraphQL conversion
Prefer GraphQL over paginated REST for any loop that fetches the same data for multiple repos. GraphQL counts as 1 REST call regardless of how many repos are queried.
Standard pattern for org repo lists:
result=$(curl -sf \
-H "Authorization: token ${GH_TOKEN}" \
-H "Content-Type: application/json" \
"${GH_API}/graphql" \
-d "{\"query\":\"{ organization(login: \\\"${ORG}\\\") { repositories(first: 100) { nodes { name } pageInfo { hasNextPage endCursor } } } }\"}" \
2>/dev/null || echo "{}")
echo "$result" | python3 -c "
import json,sys
d=json.load(sys.stdin)
for n in d.get('data',{}).get('organization',{}).get('repositories',{}).get('nodes',[]):
print(n['name'])
" 2>/dev/null
Prefetch pattern for per-repo metadata (existence, pushedAt, README): Batch all repos into a single GraphQL call using aliases, populate an associative array, then read from the cache in the loop — zero REST calls per repo:
declare -A _REPO_EXISTS=()
# ... build aliases, fire one GraphQL call, populate _REPO_EXISTS ...
# In the loop:
[[ -z "${_REPO_EXISTS[$repo]:-}" ]] && continue # skip non-existent repos
See sync-registered-imports.sh (prefetch_repo_metadata),
mirror-releases.sh (prefetch_upstream_existence), and
inject-badges.sh (list_gh_repos + _README_CACHE) for reference implementations.
What cannot be converted to GraphQL:
check-runsandstatusesendpoints — not exposed in GraphQLactions/workflowsandactions/secrets— not in GraphQL- Write operations (create repo, push file, cancel run) — REST only
Tree fetches
Use ?recursive=1 on the git trees endpoint to get all file paths in one call,
then check membership with grep -qxF before fetching individual files:
tree_json=$(gh_get "${GH_API}/repos/${owner}/${repo}/git/trees/HEAD?recursive=1")
tree_paths=$(echo "$tree_json" | jq -r '.tree[] | select(.type=="blob") | .path')
echo "$tree_paths" | grep -qxF "package.json" && # file exists, fetch it
Never probe file existence with per-file /contents/ calls in a loop.
YAML-safe shell in run: blocks
GitHub Actions run: blocks are YAML block scalars. The YAML parser processes
the file before the shell runner sees it, so certain shell constructs break
parsing even though they would be valid bash.
Patterns that break YAML — never use these inside run: blocks:
| Pattern | Why it breaks | Fix |
|---|---|---|
VAR=" with newline before closing " | Opens an unclosed YAML flow scalar | Use printf or write to a temp file |
python3 -c " with newline before closing " | Same — unclosed flow scalar | Collapse to a single-line -c invocation |
--- on its own line | YAML document separator | Use ---- or printf '\xe2\x80\x94' for em dash |
Heredoc end-marker that is a bare YAML keyword (YAML, EOF, END) at column 0 | Parsed as a bare mapping key | Rename to OTA_CONFIG_EOF, PYEOF, etc. — anything not a YAML keyword |
Multi-line git commit -m "..." | Unclosed flow scalar | Use $'subject\n\nbody' ANSI-C quoting or chained -m flags |
Safe alternatives:
# Multi-line python: collapse to one line
repos=$(python3 -c "import yaml; d=yaml.safe_load(open('config/x.yml')); print(' '.join(d.get('repos',[])))")
# Multi-line variable: use printf into a temp file
printf 'line1\nline2\n' > /tmp/body.txt
# Multi-line commit message: ANSI-C quoting
git commit -m $'subject\n\nbody line 1\nbody line 2'
# Or chained -m flags (each becomes a paragraph)
git commit -m "subject" -m "body paragraph"
# Heredoc end-marker: use a non-YAML-keyword name
cat > file.yml << 'CONFIG_EOF'
...
CONFIG_EOF
The validator catches these: python3 scripts/validate-workflow-guards.py runs
a YAML parse check across all 75 workflow files. Run it after editing any workflow.
The full-suite parse check is also embedded in validate-config.yml.
Workflow patterns
Queue and quota management
Four workflows protect the system from quota exhaustion cascades and runner starvation:
| Workflow | Schedule | Purpose |
|---|---|---|
queue-manager.yml | Every 30 min + after rate-limit-rerun | Deduplicates queued runs (keeps newest per workflow) and evicts runs queued > 25 min |
quota-reserve.yml | Every 30 min + after rate-limit-rerun | Cancels low-priority queued runs when quota drops below 1000. Uses per-workflow min_quota from config/workflow-quota-costs.yml for cost-aware cancellation. |
critical-deploy.yml | Manual only | Fast-lane: commit + push → aggressive queue clear → priority dispatch |
flush-active-watchdog.yml | workflow_run: completed | Clears FLUSH_ACTIVE=false whenever Flush Lifecycle Manager or any critical-deploy workflow completes — prevents stuck mutex after force-cancel |
Priority tiers — single source of truth in config/workflow-priority-tiers.yml:
- Tier 1 CRITICAL — never cancelled (token rotation, queue/reserve management, config validation)
- Tier 2 HIGH — mirror chain, sync operations
- Tier 3 MEDIUM — READMEs, CI checks (default for unknown workflows)
- Tier 4 LOW — translation, dep graph, maintenance (cancelled first)
When adding a new workflow, add it to both:
config/workflow-priority-tiers.yml— by workflowname:field (not filename). Bothqueue-manager.shandquota-reserve.shload tiers from this file at runtime — no script edits needed.config/workflow-sync.yml— undergithub_only(most workflows) orpaired(if it has a GitLab CI counterpart).validate-workflow-guards.pywarns on any workflow file not listed in either section.
Run python3 scripts/validate-workflow-guards.py after adding any workflow to confirm zero warnings.
dispatch-and-wait.sh exit codes:
0— workflow completed successfully1— workflow failed or timed out2— workflow was cancelled (by queue-manager or manually) — retriable, not a real failure
full-chain-flush.yml and critical-deploy.sh both handle exit 2 with a warning rather than aborting.
Concurrency groups
All workflows triggered by schedule or workflow_run must have a concurrency group
to prevent queue pile-ups:
concurrency:
group: workflow-name
cancel-in-progress: true
workflow_run triggers
Each workflow should have at most one workflow_run upstream trigger.
Multiple triggers cause fan-out: N completions × M downstream workflows = queue explosion.
Every name in workflow_run.workflows: must exactly match the name: field of a
workflow file that actually exists in .github/workflows/. A phantom name causes the
trigger to fire on every push but the job fails immediately — GitHub cannot resolve
the upstream workflow. validate-workflow-guards.py (Check 5) catches this automatically.
Quota pre-flight
All hourly/daily/frequent workflows include a quota pre-flight step before doing
any API work. The step sets skip=true when remaining < MIN_QUOTA and subsequent
steps check if: steps.quota.outputs.skip == 'false'.
Quota cost registry
config/workflow-quota-costs.yml is the single source of truth for per-workflow
REST call cost estimates. It drives:
quota-reserve.sh— cost-aware cancellation (min_quotaper workflow)budget.shworkflow_min_quota()— pre-flight helper for self-skippingDOCS/quota-costs.md— rendered documentation in mdBook
Phase 1 values are code-audit estimates (basis: code-audit).
Phase 2 (update-quota-costs.yml, weekly) replaces them with observed p50/p95
values (basis: observed) once ≥5 run samples exist per workflow.
When adding a new workflow that makes significant REST calls, add it to
config/workflow-quota-costs.yml with estimated min_quota, cost_low,
cost_mid, cost_high, and basis: code-audit. Wire qi_begin/qi_end
from scripts/includes/quota-instrument.sh into its main job step so Phase 2
can measure it automatically.
Instrumented workflows (Phase 2 active):
- Sync All Forks
- Inject Built-with-Ona Badges
- Reconcile Org References
- Cleanup Stale Branches
- Check OSP-Bound CI Status
- Check Shell Tools CI
- Sync Registered Imports
- Sync Shell Tools
- Sync UAA Vendor
- Mirror Interested-Deving-1896 → OSP
- Pre-Mirror CI Gate
- Verify Mirror Integrity
- Post-Flush Verification
- Pipeline Telemetry
- Translate Docs
- Integrate Shell Tools
- Onboard Repo
- Critical Deploy
- Critical Deploy — OSP
- Critical Deploy — OOC
- GitLab Critical Deploy
- Critical Deploy — All (all four deploy jobs)
- Flush Active Watchdog
- Branch Hygiene Report
- btrfs-devel sync
- Delete Stale Repos
FLUSH_ACTIVE mutex
FLUSH_ACTIVE is a GitHub Actions repo variable (true/false) used as a mutex
to prevent queue-manager and quota-reserve from cancelling runs during a flush
pipeline. It is set by flush-lifecycle.yml and cleared by flush-active-watchdog.yml.
The force-cancel problem: If a flush run is cancelled via the GitHub UI, its
always() cleanup step never executes, leaving FLUSH_ACTIVE=true permanently.
Three layers defend against this:
-
Primary —
flush-active-watchdog.yml: Fires onworkflow_run: completedfor Flush Lifecycle Manager + all 5 critical-deploy variants. Unconditionally clearsFLUSH_ACTIVE=falseregardless of conclusion (success/failure/cancelled). -
Belt-and-suspenders — TTL check in
queue-manager.sh+quota-reserve.sh: Both scripts read the variable'supdated_attimestamp and treat it as unset if >8h old. A stuck mutex auto-expires even if the watchdog misses an event. -
Pipeline guard —
scripts/includes/pipeline-guard.sh: Reusable include sourced by all critical-deploy workflows. Providespipeline_guard_start,pipeline_guard_checkpoint, andpipeline_guard_endhelpers that manageFLUSH_ACTIVEstate and emit step-summary annotations.
When adding a new workflow that participates in the flush pipeline:
- Source
scripts/includes/pipeline-guard.shand callpipeline_guard_start/pipeline_guard_endaround the protected work. - Add the workflow's
name:toflush-active-watchdog.yml'sworkflow_run.workflows:list.
queue-manager.sh and quota-reserve.sh FLUSH_ACTIVE check:
# Both scripts skip cancellation when FLUSH_ACTIVE=true AND updated within 8h.
# If updated_at is >8h ago the variable is treated as stale and ignored.
flush_active=$(gh api "/repos/${REPO}/actions/variables/FLUSH_ACTIVE" \
--jq '.value' 2>/dev/null || echo "false")
flush_updated=$(gh api "/repos/${REPO}/actions/variables/FLUSH_ACTIVE" \
--jq '.updated_at' 2>/dev/null || echo "")
# TTL check: ignore if >8h old
Pipeline guard pattern
All critical-deploy workflows use scripts/includes/pipeline-guard.sh to
standardise how they interact with FLUSH_ACTIVE:
source scripts/includes/pipeline-guard.sh
# At job start — sets FLUSH_ACTIVE=true, emits step-summary header
pipeline_guard_start
# Mid-run quota check — logs remaining quota to step summary
pipeline_guard_checkpoint
# At job end (in always() step) — clears FLUSH_ACTIVE=false
pipeline_guard_end
Each critical-deploy workflow also has a sentinel job that runs in parallel
with the deploy job (needs: [], if: always()). The sentinel holds a runner
slot for the duration of the deploy, preventing the runner pool from being
exhausted by lower-priority queued work during a critical operation.
Path filters + required status checks (gate job pattern)
When a workflow uses path filters to skip jobs on irrelevant changes, required status checks will block PRs indefinitely if the filtered jobs never run. Fix this with a gate job that always runs and reflects the filtered outcomes:
jobs:
changes:
name: Detect changes
runs-on: ubuntu-latest
outputs:
shell: ${{ steps.filter.outputs.shell }}
steps:
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v3
id: filter
with:
filters: |
shell:
- '**/*.sh'
lint:
name: ShellCheck
needs: changes
if: needs.changes.outputs.shell == 'true'
runs-on: ubuntu-latest
steps: [...]
# Set THIS as the required status check — not the individual jobs above.
ci-required:
name: CI Required
runs-on: ubuntu-latest
needs: [lint]
if: always()
steps:
- name: Check results
run: |
if echo "${{ join(needs.*.result, ' ') }}" | grep -qw "failure"; then
exit 1
fi
Branch protection must require CI Required (the gate job name), not the
individual filtered job names. If the individual names are listed as required
checks, PRs that skip those jobs will be permanently blocked.
Applied in: btrfs-dwarfs-framework/.github/workflows/ci.yaml
Autonomous-fallback mode
Consumer repos that receive the infra-core or upstream-sync profile get a
bundle of operational workflows (rate-limit rerun, CI resolver, queue manager,
quota reserve, notify-poller, branch cleanup) as autonomous fallbacks.
Managed mode (default): fork-sync-all is present and handles all of these centrally. The bundled workflows detect this and skip themselves.
Autonomous mode: if a consumer repo is forked independently without fork-sync-all alongside it, the bundled workflows activate and self-manage, scoped to the repo's own owner.
Mode detection (scripts/includes/fsa-mode.sh)
Three-tier hybrid check, evaluated in order:
| Check | Mechanism | Cost |
|---|---|---|
| B | FSA_MANAGED repo variable (vars.FSA_MANAGED == 'true') | 0 API calls |
| A | GET /repos/{owner}/fork-sync-all — 200 = managed | 1 API call |
| C | Token owner's fork-sync-all existence (tiebreaker) | 2 API calls |
sync-template.sh sets FSA_MANAGED=true as a repo Actions variable on every
successful consumer sync via PUT /repos/{owner}/{repo}/actions/variables/FSA_MANAGED.
Adding the guard to a workflow
- name: Check FSA mode
id: fsa
env:
GH_TOKEN: ${{ secrets.SYNC_TOKEN }}
FSA_MANAGED: ${{ vars.FSA_MANAGED }}
REPO_OWNER: ${{ github.repository_owner }}
run: |
source scripts/includes/fsa-mode.sh
if fsa_is_managed; then
echo "managed=true" >> "$GITHUB_OUTPUT"
echo "Managed by fork-sync-all — skipping."
else
echo "managed=false" >> "$GITHUB_OUTPUT"
fi
# Then on work steps:
- name: Do work
if: steps.fsa.outputs.managed == 'false'
For workflows without a checkout (e.g. notify-poller.yml), inline the
three-tier check directly in the step's run: block rather than sourcing
fsa-mode.sh. See notify-poller.yml for the canonical inline implementation.
The inline version replicates checks B → A → C using curl and python3.
Node identity (fsa-node-identity.sh)
scripts/includes/fsa-node-identity.sh extends fsa-mode.sh (managed/autonomous
binary) with a position layer — each instance knows where it sits in the
mirror chain and adjusts which operations it runs accordingly.
Three positions:
| Position | Detected when | Write operations |
|---|---|---|
source | GITHUB_REPOSITORY == Interested-Deving-1896/fork-sync-all | All |
mirror | FSA_MANAGED=true + non-canonical owner, or FSA_UPSTREAM_OWNER set | Mirror-to-github, mirror-to-gitlab only |
downstream-fork | No upstream FSA detected | All (scoped to own org) |
Mirror nodes skip source-only operations (readmes, badges, fork-sync, templates, translate) to prevent duplicate work across the chain.
Detection order (first match wins):
- Explicit
FSA_CHAIN_POSITIONenv var override GITHUB_REPOSITORYmatches canonical slug (Interested-Deving-1896/fork-sync-all)FSA_UPSTREAM_OWNERenv var set → mirrorfsa_is_managed()returns true + non-canonical owner → mirror- Default →
downstream-fork
Exported variables (also written to GITHUB_OUTPUT):
FSA_NODE_POSITION—source|mirror|downstream-forkFSA_NODE_OWNER— the org this instance managesFSA_UPSTREAM_OWNER— the org being mirrored from (empty for source/fork)FSA_CHAIN_DEPTH— 0=source, 1=first mirror, 2=downstream-fork
Capability predicates — return 0 (true) or 1 (false):
fsa_can_mirror_to_github # push repos to a downstream GitHub org
fsa_can_mirror_to_gitlab # push repos to a GitLab group
fsa_can_update_readmes # write README files (source + fork only)
fsa_can_inject_badges # inject badges (source + fork only)
fsa_can_sync_forks # sync upstream forks (source + fork only)
fsa_can_translate # run translation (source + fork only)
fsa_can_manage_templates # push templates to consumers (source + fork only)
Usage:
source scripts/includes/fsa-node-identity.sh
fsa_node_detect
fsa_node_summary # prints position + active capabilities to stderr
fsa_can_update_readmes && bash scripts/update-readmes.sh
Override env vars (set in workflow env: block):
FSA_CHAIN_POSITION— force a specific position (skips all detection)FSA_UPSTREAM_OWNER— declare the upstream org (triggers mirror detection)FSA_CANONICAL_OWNER— override the canonical source org (default:Interested-Deving-1896)
Scope narrowing in autonomous mode
Workflows that are org-wide in managed mode narrow their scope in autonomous mode:
| Workflow | Managed scope | Autonomous scope |
|---|---|---|
resolve-failures.yml | I-D-1896 (OSP-bound) + OSP + OOC | github.repository_owner only |
cleanup-branches.yml | I-D-1896 + OSP + OOC | github.repository_owner only |
queue-manager.yml | github.repository (already scoped) | same |
quota-reserve.yml | github.repository (already scoped) | same |
rate-limit-rerun.yml | github.repository_owner/name | same |
Template manifest — source:dest remap syntax
Include entries in config/template-manifest.yml support a source:dest remap:
include:
- assets/docs-scaffold/SUMMARY.md:DOCS/SUMMARY.md # read from assets/, write to DOCS/
- scripts/write-summary.sh # plain entry: source == dest
sync-template.sh splits on the first : — the left side is the path relative
to the template root (read), the right side is the path written into the target
repo. Plain entries (no :) write to the same path.
Scaffold-only behaviour: entries whose source starts with assets/docs-scaffold/
are skipped if the destination file already exists in the target repo. This
prevents overwriting a consumer's existing DOCS/ content on subsequent syncs.
Devcontainer template propagation
devcontainer.template.json and automations.template.yaml are propagated to
consumer repos via source:dest remaps in config/template-manifest.yml. Both
are scaffold-only — skipped if the destination already exists in the consumer.
include:
- .devcontainer/devcontainer.template.json:.devcontainer/devcontainer.json
- .devcontainer/automations.template.yaml:.ona/automations.yaml
These entries are present in the infra-core, upstream-sync, standalone,
and shell-tools profiles. The .devcontainer/ directory is otherwise excluded
from template sync (it contains fork-sync-all-specific config that consumers
should not receive).
Template divergence rule: devcontainer.template.json and the live
.devcontainer/devcontainer.json must stay in sync. When updating either:
- Pin
headroom-aito a specific version in both files - Keep
--no-ccr-inject-toolin the headroom proxy start command in bothautomations.template.yamland.ona/automations.yaml - Run
python3 scripts/devcontainer-validate.pyto catch divergences
Devcontainer feature — git-platform-clis
.devcontainer/features/git-platform-clis/ is a devcontainer feature that
installs CLIs for all major git hosting platforms.
Installed by default: gh (GitHub CLI), glab (GitLab CLI), tea (Gitea CLI)
Optional via feature options: hub (legacy GitHub CLI), bb (Bitbucket CLI),
forgejo-cli (Forgejo/Gitea v1.21+ API client) — all false by default.
Referenced in devcontainer.json and devcontainer.template.json by local path.
When published to GHCR via devcontainer-sdk.yml publish mode, consumers can
reference it by URI: ghcr.io/Interested-Deving-1896/fork-sync-all/git-platform-clis:1
The feature has not yet been published to GHCR. Until a publish run
completes, only local path references work. Run devcontainer-sdk.yml with
mode: publish to push it.
Devcontainer feature — sync-in-server
.devcontainer/features/sync-in-server/ installs the Sync-in server binary
at container build time from github.com/Sync-in/server releases.
Binary resolution order in services/sync-in/start.sh (hybrid A→B→C→D):
| Step | Path | When |
|---|---|---|
| A | /usr/local/bin/sync-in-server | Feature ran at build time |
| B | ~/.local/bin/sync-in-server | postCreateCommand ran services/sync-in/install.sh |
| C | PATH search | Binary installed by other means |
| D | Self-install | Downloads latest release from GitHub at service start time |
If all four fail, the service exits with a clear message and suggests running
the Install Sync-in Server automation task.
services/sync-in/install.sh is the shared install helper used by both
postCreateCommand (B) and the automations task (C). It skips silently if
the binary is already present; set FORCE=true to reinstall.
Both services/sync-in/start.sh and services/sync-in/install.sh are
scaffold-only includes in all four template manifest profiles — consumers
receive them on first sync, subsequent syncs skip them if already present.
Sync-in workflow (sync-in.yml)
Manages the Sync-in server/client lifecycle. Every devcontainer starts a local
Sync-in server automatically via the sync-in-server automation service
(port 3284, admin token at ~/.local/share/sync-in/.admin_token).
Enable/disable toggle — vars.SYNC_IN_ENABLED:
Set as a repo Actions variable (not a secret — it's plain text):
# Enable
gh api --method POST /repos/{owner}/{repo}/actions/variables \
-f name="SYNC_IN_ENABLED" -f value="true"
# Disable (maintenance mode)
gh api --method PATCH /repos/{owner}/{repo}/actions/variables/SYNC_IN_ENABLED \
-f value="false"
Decision matrix in secrets-check job:
| Condition | Result |
|---|---|
force_run=true (dispatch input) | Run — bypasses everything |
SYNC_IN_ENABLED == 'false' | Skip — explicit opt-out |
SYNC_IN_ENABLED == 'true' | Run — explicit opt-in |
SYNC_IN_ENABLED unset | Run if both secrets present, skip otherwise |
Required secrets (only needed when SYNC_IN_ENABLED=true):
SYNC_IN_SERVER_URL— public URL of the Sync-in instance (must be reachable by GitHub Actions runners —localhost:3284only works from inside the container)SYNC_IN_ADMIN_TOKEN— admin token from~/.local/share/sync-in/.admin_token
Federated mesh — config/sync-in-peers.yml is the peer registry. Each
entry declares a node's node_id, secret names for its URL and token, role
(server/client/both), and managed orgs. The register-with-peers action
in sync-in-client.sh announces this node to each peer's /api/v1/peers
endpoint. Dispatch with role=register-peers or role=all.
Devcontainer SDK workflow (devcontainer-sdk.yml)
Three modes, selectable via workflow_dispatch:
| Mode | Trigger | What it does |
|---|---|---|
validate | Auto on push to .devcontainer/ | Runs devcontainer-validate.py — checks JSON validity, template divergence, feature schema |
build | Manual | Builds the devcontainer image and pushes to GHCR as an OCI artifact |
publish | Manual | Publishes features from .devcontainer/features/ to GHCR so consumers can reference by URI |
Supporting scripts: scripts/devcontainer-validate.py, scripts/devcontainer-build.sh,
scripts/devcontainer-publish-features.sh, scripts/devcontainer-base-image.py.
Verify Fork Integrity
verify-fork-integrity.yml / scripts/verify-fork-integrity.sh — single-repo
equivalent of verify-mirror-integrity.yml. Compares this repo's default-branch
HEAD against its upstream (fork parent or upstream_override).
Upstream resolution order:
inputs.upstream_override(workflow dispatch input).ota/config.ymlupstream_overridefield- GitHub fork parent API field (auto-detected)
Returns status: identical | ahead | behind | diverged. Set
BLOCK_ON_DRIFT=true to exit 1 on behind or diverged.
OTA system — autonomous upstream resolution
Both ota-self-update.yml and ota-opt-in.yml now resolve their upstream
dynamically rather than hardcoding Interested-Deving-1896/fork-sync-all:
| Priority | Source |
|---|---|
| 1 | upstream_override in .ota/config.yml |
| 2 | GitHub fork parent API (/repos/{owner}/{repo} → parent.full_name) |
| 3 | Fallback: Interested-Deving-1896/fork-sync-all |
ota-opt-in.yml writes the resolved upstream into .ota/config.yml as
upstream_override so subsequent ota-self-update.yml runs use Check 1
(zero API calls for resolution).
ota-opt-in.yml opens the registration issue against the resolved upstream
repo (not hardcoded fork-sync-all). The upstream repo must have an
ota-registration label and a config/ota-registry.yml for the issue to
be actionable.
resolve-failures.sh — EXCLUDED_REPOS convention
EXCLUDED_REPOS in scripts/resolve-failures.sh is intentionally empty. The
resolver appends [skip ci] to every fix commit, which prevents CI re-triggers
in all standard repos. Only add a repo to EXCLUDED_REPOS when [skip ci] is
genuinely insufficient — for example, a repo with a push hook that ignores
[skip ci] and would cause an infinite fix→trigger→fail→fix loop.
README & repo description management — autonomous single-repo mode
In autonomous mode (fork-sync-all not present), README workflows scope to the current repo only:
update-readmes.sh: setSINGLE_REPO=<repo-name>to bypass the org fetch and process exactly one repo.update-readmes.ymlsets this automatically via the FSA mode check.translate-readmes.sh:SCOPE=singlesetsREPOSto the current repo name (extracted fromGITHUB_REPOSITORY).translate-readmes.ymlsets this automatically in autonomous mode.
resolve-failures.sh — rate-limit rerun
Before sending a failed run to the AI fixer, resolve-failures.sh calls
rerun_if_rate_limited(), which checks job logs for rate-limit signal patterns
and re-triggers via POST /repos/{owner}/{repo}/actions/runs/{id}/rerun-failed-jobs.
This covers all three orgs (I-D-1896 OSP-bound, OSP, OOC). The loop guard
checks for "rate_limit_rerun": "true" in the step summary — a second
rate-limit failure is logged but not re-triggered again.
Template sync profiles
config/template-consumers.yml controls which repos receive automatic file
updates from sync-template.yml. Each consumer has a profile that determines
what gets injected.
Profile assignments
| Profile | What it injects | Who should use it |
|---|---|---|
full | Everything — all workflows, scripts, config | fork-sync-all only |
mirror | Mirror/sync workflows + infra tooling | Nobody — deprecated, do not assign |
infra-core | PR automation, token rotation, token health, README render validation + full autonomous-fallback suite (rate-limit rerun, CI resolver, queue/quota management, branch cleanup, PR rebase, dep updates, OTA self-management, README & repo description management, mdBook deploy/translate, fork integrity check) — dormant when fork-sync-all is present | Consumer repos that are targets of the mirror chain |
standalone | PR automation + token rotation only | External project forks (KDE Invent, etc.) |
upstream-sync | infra-core contents + upstream sync workflow and script | Repos that track upstream projects via a registry file |
Critical rule
Never assign mirror profile to consumer repos. The mirror profile injects
the full fork-sync-all mirror/sync suite (60+ workflow files, 100+ scripts) into
repos that are targets of the mirror chain, not operators of it. This causes
template pollution — files that have no purpose in the target repo and clutter
its .github/workflows/ and scripts/ directories.
Template pollution cleanup
If a repo has been polluted by the mirror profile:
- Check which files don't belong:
for f in .github/workflows/*.yml; do
grep -q "SYNC_TOKEN\|openos-project\|mirror-to-osp\|registered-imports" "$f" \
&& echo "POLLUTION: $(basename $f)" \
|| echo "native: $(basename $f)"
done
- Remove them with
git rm --cachedand commit:
git rm --cached .github/workflows/add-mirror-repo.yml # etc.
git commit -m "chore: remove fork-sync-all template pollution"
- Delete the untracked files from disk:
git status --short | grep "^??" | awk '{print $2}' | xargs rm -f
- Trigger
cleanup-pollution.yml(workflow_dispatch) to clean remaining consumer repos automatically.
Repos cleaned of mirror pollution (2026-06-06)
KPort— 74 files removedbtrfs-dwarfs-framework— 133 files removed- All other
infra-coreconsumers — cleaned viacleanup-pollution.yml
Queue pile-up pattern
Workflows that trigger on .github/workflows/** (e.g. validate-config,
update-workflow-triggers-doc) must have concurrency: cancel-in-progress: true
to prevent stacking. Without it, rapid pushes create a queue of identical runs
that consume quota on every reset, causing a deadlock where the queue can't
drain because quota is always 0.
concurrency:
group: workflow-name-${{ github.ref }}
cancel-in-progress: true
Brandable backend
config/brand.yml allows fork-sync-all to be adopted as a white-label subsystem.
When brand.enabled=true, sync-template.sh substitutes {{FSA_*}} tokens in
propagated file content with the consumer's own identity values.
Default state: brand.enabled=false — no behaviour change until a consumer
explicitly opts in by setting enabled: true in their own config/brand.yml.
Substitution tokens
| Token | Field | Example |
|---|---|---|
{{FSA_NAME}} | brand.name | fork-sync-all |
{{FSA_SLUG}} | brand.slug | fsa |
{{FSA_ORG}} | brand.org | Interested-Deving-1896 |
{{FSA_REPO}} | brand.repo | fork-sync-all |
{{FSA_DESCRIPTION}} | brand.description | one-line description |
{{FSA_SUPPORT_URL}} | brand.support_url | support/docs URL |
Applying brand substitution
scripts/apply-brand.py reads config/brand.yml and rewrites tokens in a
target file. Called by sync-template.sh after writing each propagated file
when brand.enabled=true.
python3 scripts/apply-brand.py path/to/file.yml
skin.files overrides
The skin.files list in config/brand.yml maps source files to destination
paths in consumer repos, applied after the profile include list. Entries are
scaffold-only by default (scaffold_only: true). Set scaffold_only: false
to always overwrite.
Git subtree / submodule / umbrella scaffold
config/subtree-manifest.yml declares three relationship types between this
repo and external repos. scripts/manage-subtrees.sh implements all operations.
manage-subtrees.yml runs weekly (Sunday 01:00 UTC) and on manual dispatch.
Relationship types
| Type | Mechanism | Best for |
|---|---|---|
subtree | git subtree add/pull — remote history merged under a prefix dir, no .gitmodules | Vendored upstream code you modify locally |
submodule | Standard git submodule — pinned SHA, .gitmodules entry, pointer not copy | External deps you consume but don't modify |
umbrella | This repo as super-repo — aggregates child repos as submodules under umbrella.prefix/ | Monorepo-style development across org repos |
manage-subtrees.sh commands
bash scripts/manage-subtrees.sh sync # pull all subtrees + update all submodules
bash scripts/manage-subtrees.sh add <name> # add a new subtree/submodule from manifest
bash scripts/manage-subtrees.sh status # show drift vs upstream for all entries
bash scripts/manage-subtrees.sh umbrella-init # initialise umbrella children as submodules
Adding a new entry
Add to the appropriate list in config/subtree-manifest.yml, then run
manage-subtrees.sh add <name>. Do not run git subtree add or
git submodule add manually — the script handles squash flags, shallow
clones, and .gitmodules consistency.
Nested submodule policy
nested.recurse=false by default. Enable only when a submodule itself has
submodules you need. nested.max_depth=2 prevents runaway recursion.
OSP-bound repo list
The canonical list of ~49 repos that are mirrored to GitLab lives in
config/gitlab-subgroups.yml. Parse it with yaml.safe_load — do not hardcode
repo names anywhere else.
To get the list in bash:
python3 -c "
import yaml
data = yaml.safe_load(open('config/gitlab-subgroups.yml'))
for sg in data.get('subgroups', {}).values():
for repo in (sg.get('repos') or []):
print(repo)
"
GitLab subgroup IDs
OSP leg — openos-project (gitlab.com/openos-project)
| Subgroup slug | GitLab ID |
|---|---|
git-management_deving | 130516820 |
penguins-eggs_deving | 130516402 |
immutable-filesystem_deving | 130516465 |
linux-kernel_filesystem_deving | 130516188 |
incus_deving | 130516536 |
taubyte_deving | 133909500 |
neon-deving | 130739746 |
ops | 130734009 |
yaml-tooling_deving | 133909501 |
cachyos_deving | 133909503 |
ai-agents_deving | 133909504 |
rust-systems_deving | 133954601 |
accessibility_deving | 134613311 |
agnostic-api_deving | 134613312 |
All IDs are authoritative — sourced from config/gitlab-subgroups.yml. Do not hardcode them elsewhere.
OOC leg — openos-project-ooc-ecosystem (gitlab.com/openos-project-ooc-ecosystem)
Root group ID: 134901804
OOC subgroup names mirror OSP exactly — same slugs, different GitLab group.
Config: config/gitlab-subgroups-ooc.yml.
| Subgroup slug | GitLab ID |
|---|---|
git-management_deving | 134918116 |
penguins-eggs_deving | 134918117 |
immutable-filesystem_deving | 134918118 |
linux-kernel_filesystem_deving | 134918121 |
incus_deving | 134918123 |
taubyte_deving | 134918126 |
neon-deving | 134918128 |
ops | 134918131 |
yaml-tooling_deving | 134918134 |
cachyos_deving | 134918136 |
ai-agents_deving | 134918137 |
rust-systems_deving | 134918138 |
accessibility_deving | 134918140 |
agnostic-api_deving | 134918142 |
projects (fallback) | 134901804 |
All IDs are authoritative — sourced from config/gitlab-subgroups-ooc.yml.
Subgroup mirroring convention: when adding a new subgroup to the OSP config,
add the same slug to the OOC config with id: null and repos: []. The two
repos: lists are populated independently — OSP repos and OOC repos are distinct
even when they share a subgroup name.
README & Repo Description Management
AI marker format
<!-- AI:start:section-name -->
content
<!-- AI:end:section-name -->
Eight AI-owned sections: what-it-does, architecture, ci, mirror-chain,
contributors, origins, resources, license.
Human-owned sections (Install, Usage, Configuration, License) never get
AI markers — they get placeholder HTML comments on first creation.
Three modes in update-readmes.sh
rewrite— no AI markers present → build full template from scratchfill— some markers present but missing sections → inject missing onesupdate— all markers present → regenerate AI section content
check-readme-render.sh
Run this against any README before committing. It catches: leaked log lines,
unclosed fences, unclosed AI markers, empty sections, missing H1, broken tables,
bare [text] links, raw angle brackets.
bash scripts/check-readme-render.sh path/to/README.md
Per-file repo descriptions (generate-repo-descriptions.sh)
Generates a one-line AI description for every file in a repo and commits the
results to DESCRIPTIONS.md. Uses GitHub Models (gpt-4o-mini by default —
high volume, short outputs, no frontier reasoning needed).
Inspired by ioncakephper/repo-description — reimplemented using llm.sh
(GitHub Models) instead of Groq + Node.js.
Output format (DESCRIPTIONS.md):
# File Descriptions
<!-- AI:generated -->
| File | Description |
|---|---|
| `scripts/sync-forks.sh` | Syncs all upstream forks via the GitHub merge-upstream API |
| `config/gitlab-subgroups.yml` | Maps OSP-bound repos to their GitLab subgroup placement |
Workflow: generate-repo-descriptions.yml — runs weekly (Sunday 03:30 UTC),
dispatches manually with target_repo, model, max_files, file_filter inputs.
SKIP_EXISTING=true by default so incremental runs only describe new files.
Key env vars:
TARGET_REPO— repo to describe (defaults tofork-sync-allitself on schedule)MAX_FILES— cap per run (default: 200) to control quota consumptionMODEL— override model (default:openai/gpt-4o-mini)
Repo settings management (manage-repo-settings.sh)
Declarative repo settings drift detection and enforcement across all OSP-bound
repos. Reads config/repo-settings.yml and either reports drift (check mode)
or enforces declared state (apply mode) via the GitHub REST API.
Inspired by andrewthetechie/gha-repo-manager — reimplemented as a shell script
using gh-api.sh + budget.sh infrastructure.
Settings file: config/repo-settings.yml — defaults block applies to all
repos, overrides block provides per-repo overrides, skip list excludes repos.
Supported fields: description, homepage, has_issues, has_projects,
has_wiki, has_discussions, allow_squash_merge, allow_merge_commit,
allow_rebase_merge, allow_auto_merge, delete_branch_on_merge,
squash_merge_commit_title, squash_merge_commit_message, topics,
vulnerability_alerts.
Workflow: manage-repo-settings.yml — runs weekly in check mode (Monday
04:30 UTC). Apply mode is manual-only (workflow_dispatch with mode: apply)
to prevent accidental bulk changes.
API cost: 1 REST call per repo in check mode. 1–3 REST calls per drifted repo in apply mode (PATCH settings + PUT topics + PUT/DELETE vulnerability alerts).
GitLab CI variables
These must be set as masked CI/CD variables in the openos-project/fork-sync-all GitLab project settings (not GitHub secrets):
| Variable | Maps to | Used by | Notes |
|---|---|---|---|
GITLAB_TOKEN | GITLAB_TOKEN GitHub secret | Most GitLab CI jobs | api + read_repository + write_repository scope |
WORKFLOW_SECRET | SYNC_TOKEN GitHub secret | sync-forks, notify-poller, resolve-failures, rate-limit-rerun, token-health, cleanup-branches | GitHub PAT with repo + workflow + admin:org scopes |
GH_SYNC_TOKEN | GH_SYNC_TOKEN GitHub secret | sync-from-gitlab | GitHub PAT with repo + workflow scopes |
GITLAB_MAINTENANCE_TOKEN | — | maintain:storage | Inherited from openos-project group variable; api scope on GitLab |
Headroom proxy
A context compression proxy runs on port 8787 (started automatically via
.ona/automations.yaml). To use it with Claude:
ANTHROPIC_BASE_URL=http://localhost:8787 claude
# or
headroom wrap claude
Check savings: headroom stats
Token rotation
Tracked tokens
The "PAT name" column is the display name shown at github.com/settings/tokens (classic).
| Secret | PAT name | Scope | Platform / Org | Expiry | Used by | Rotate via |
|---|---|---|---|---|---|---|
SYNC_TOKEN | fork-sync-all SYNC_TOKEN | admin:org, admin:org_hook, admin:repo_hook, audit_log, delete:packages, delete_repo, gist, notifications, project, repo, workflow, write:packages | GitHub / I-D-1896 | 2026-09-02 | Most workflows | rotate-token.yml |
GH_SYNC_TOKEN | sync-mirror-watchdog | admin:org, admin:org_hook, admin:public_key, admin:repo_hook, audit_log, gist, notifications, project, repo, workflow, write:discussion, write:packages | GitHub / I-D-1896 | 2026-09-03 | mirror workflows | rotate-token.yml |
OSP_ADMIN_TOKEN | OSP_ADMIN_TOKEN | admin:org | GitHub / OpenOS-Project-OSP | 2026-09-03 | rotate-token.yml (OSP org secret rotation) | rotate-token.yml |
MIRROR_TOKEN | OSP-ORG Mirror Token | admin:enterprise, admin:gpg_key, admin:org, admin:org_hook, admin:public_key, admin:repo_hook, admin:ssh_signing_key, project, repo, workflow | GitHub / OpenOS-Project-OSP | 2026-09-01 | mirror workflows | rotate-token.yml |
ORG_MIRROR_OSP_TO_OOC | OSP-ORG Mirror Token | (same PAT as MIRROR_TOKEN) | GitHub / OpenOS-Project-OSP | 2026-09-01 | mirror-osp-to-ooc.yaml | rotate-token.yml |
ADD_MIRROR_REPO_SYNC | fork-sync-all-ona | admin:repo_hook, read:org, repo, workflow | GitHub / I-D-1896 | 2026-08-13 ⚠️ | add-mirror-repo.yml | rotate-token.yml |
GITLAB_SYNC_TOKEN | fork-sync-all-sync | api, read_repository, write_repository | GitLab / openos-project | 2027-05-13 | sync-to-gitlab.yml, mirror-osp-to-gitlab.yml, sync-from-gitlab.yml | rotate-token.yml |
GITLAB_TOKEN | Ona-Env-Secret | api | GitLab / openos-project | 2027-05-17 | Ona dev environment (injected as GITLAB_TOKEN env var); also used by gl-storage-scan, sync-to-gitlab-variant, cleanup-pollution, reconcile-org-refs | rotate-token.yml |
BITBUCKET_TOKEN | n/a (opt-in) | Bitbucket API | Bitbucket | unknown | sync-registered-imports.yml, clone-org.yml, import-repo.yml — skipped if unset | rotate-token.yml |
GITEA_TOKEN | n/a (opt-in) | Gitea API | Gitea instance | unknown | sync-registered-imports.yml, clone-org.yml, import-repo.yml — skipped if unset | rotate-token.yml |
| ACTIVITYSMITH_API_KEY | n/a (external service) | ActivitySmith API | ActivitySmith | unknown | full-chain-flush.yml (live activity tracking) — optional, skipped if unset | manual |
| ACTIVITYSMITH_CHANNELS | n/a (external service) | ActivitySmith channel IDs | ActivitySmith | n/a | full-chain-flush.yml — optional, skipped if unset | manual |
| ANTHROPIC_API_KEY | n/a (external service) | Anthropic API | Anthropic | n/a | validate-config.yml (AgentShield scan) — optional, skipped if unset | manual |
How to rotate a repo secret (SYNC_TOKEN, GH_SYNC_TOKEN, etc.)
- Generate a new PAT at https://github.com/settings/tokens
- Go to rotate-token.yml → Run workflow
- Select the secret name from the dropdown
- Paste the new token value into the
token_valuefield - Leave
validatechecked — it confirms the token works before finishing - After the run completes, update the expiry date in this table
How to rotate an OSP org secret (ORG_MIRROR_OSP_TO_OOC, MIRROR_TOKEN)
OSP org secrets live in OpenOS-Project-OSP and require a token with
admin:org on that org. SYNC_TOKEN only covers Interested-Deving-1896.
The rotate-token.yml workflow resolves the OSP token automatically in
this priority order:
Option 1 — GitHub App (preferred, permanent)
A GitHub App installation token never expires and has fine-grained permissions.
One-time setup:
- Create a GitHub App at https://github.com/settings/apps/new
- Name:
fork-sync-all-osp-rotator(or similar) - Permissions: Organization secrets → Read and write
- Uncheck everything else
- Name:
- Install the App on
OpenOS-Project-OSPorg - Note the App ID (shown on the app settings page)
- Generate a private key (PEM format) from the app settings page
- Add two repo secrets to
Interested-Deving-1896/fork-sync-all:OSP_APP_ID— the numeric App IDOSP_APP_PRIVATE_KEY— the full PEM contents (including header/footer)
- Run rotate-token.yml — it will use the App automatically
Option 2 — Dedicated PAT (bridge until App is set up)
- Generate a new PAT at https://github.com/settings/tokens with:
admin:orgscope- Authorized for
OpenOS-Project-OSPorg (SSO authorize if required)
- Add it as repo secret
OSP_ADMIN_TOKENinInterested-Deving-1896/fork-sync-all - Run rotate-token.yml — it will use
OSP_ADMIN_TOKENautomatically
Option 3 — Manual fallback
If neither OSP_APP_* nor OSP_ADMIN_TOKEN is set, the workflow prints
the exact error and the two options above. You can also update manually:
- Generate a new PAT with
admin:orgonOpenOS-Project-OSP - Go to OSP org secrets and update the secret value directly
- Update the expiry date in
scripts/token-monitor.sh(OSP_ORG_SECRETSarray) and in the table above
⚠️ Upcoming rotations (as of 2026-06-08):
ADD_MIRROR_REPO_SYNC— expires 2026-08-13 (66 days).token-health.ymlwill open an issue around 2026-06-29.MIRROR_TOKEN/ORG_MIRROR_OSP_TO_OOC— expire 2026-09-01 (85 days). Alert ~2026-07-17.SYNC_TOKEN— expires 2026-09-02 (86 days). Alert ~2026-07-18.GH_SYNC_TOKEN/OSP_ADMIN_TOKEN— expire 2026-09-03 (87 days). Alert ~2026-07-19.
Automated monitoring
token-health.yml runs weekly (Monday 09:00 UTC) and warns at 45 days before expiry.
When a token needs attention it opens a GitHub issue labelled token-monitor.
Run it manually at any time to get a current status report.
vendor/ conventions
Agnostic-by-default rule
Everything imported into vendor/ must be deployment-agnostic. No distro names,
org-specific URLs, org/repo slugs, or arch/repo paths may appear as hardcoded
fallback values in shell ${VAR:-...}, YAML || '...', or TypeScript ?? '...'
expressions. All deployment-identity values belong in CI variables or repo vars
set per deployment.
Enforcement
scripts/check-vendor-agnostic.sh scans a vendor directory and exits 1 on violations:
bash scripts/check-vendor-agnostic.sh vendor/infra-dashboard # specific component
bash scripts/check-vendor-agnostic.sh vendor # all of vendor/
enforce-agnostic-vendor.yml runs this automatically on every push/PR touching vendor/.
To suppress a specific line that is intentionally non-agnostic:
SOME_VAR="${SOME_VAR:-specific-value}" # check-vendor-agnostic: ignore
What the checker flags vs. allows
Flagged (deployment-identity):
- Public URLs as fallbacks:
${VITE_ENDPOINT_URL:-https://api.myorg.com} - Org/repo slugs:
${MIRRORLIST_REPO:-MyOrg/my-repo} - Arch/repo paths:
${MIRROR_REPO_PATHS:-x86_64/core,x86_64/extra} - Bare distro names:
${DISTRO:-cachyos},${DISTRO:-ubuntu}
Allowed (generic defaults):
- Localhost dev URLs:
${API_URL:-http://localhost:5862} - Generic relative paths:
${MIRRORLIST_PATH:-mirrorlist/mirrorlist} - Single-word tokens:
${LOG_LEVEL:-info},${ENV:-production} - UI strings:
${APP_NAME:-Infra Dashboard}
Workflow integrations
import-repo → immediate sync
When ongoing_sync=true, import-repo.sh writes to registered-imports.json
and then immediately dispatches sync-registered-imports.yml with
repo_filter=<name> and force_sync=true. This avoids the up-to-6h wait for
the scheduled run to pick up the new entry.
If the dispatch fails (quota, permissions), it falls back gracefully — the entry is still registered and will sync on the next scheduled run.
merge-to-monorepo → OSP mirror chain
merge-to-monorepo.yml has a mirror_monorepo boolean input (default: false).
When set, it dispatches add-mirror-repo.yml for the newly created monorepo after
a successful merge, entering it into the standard OSP mirror chain automatically.
Action version pinning
Canonical versions (verified 2026-06-24). Use these exactly — do not downgrade, do not guess from memory.
| Action | Version |
|---|---|
actions/checkout | @v7 |
actions/setup-python | @v6 |
actions/setup-node | @v6 |
actions/cache | @v6 |
actions/cache/save | @v6 |
actions/upload-artifact | @v7 |
actions/download-artifact | @v8 |
actions/upload-pages-artifact | @v5 |
actions/deploy-pages | @v5 |
actions/labeler | @v6 |
actions/github-script | @v9 |
Before adding a new action or bumping a version, verify with:
curl -sf "https://api.github.com/repos/actions/checkout/releases/latest" \
-H "Authorization: token $GH_TOKEN" \
| python3 -c "import json,sys; print(json.load(sys.stdin)['tag_name'])"
History: This repo has had repeated bulk regressions from agents writing
versions from memory. checkout moved v4→v5→v6→v7 across sessions; each
transition caused a mass failure. The table above is the single source of
truth — update it here when versions change, then do a bulk find-replace
across .github/workflows/.
GitHub Actions expression and permissions constraints
These are constraints GitHub's own validator enforces that pyyaml does not
catch locally. All three produce the same symptom: the run shows "This run
likely failed because of a workflow file issue" with 0s duration — the
runner never starts.
Diagnose with:
gh workflow run <workflow-file>.yml --repo <owner>/<repo> [--field key=val]
# HTTP 422 response body contains the exact line/col and error message
Secrets not allowed in if: conditions
# ❌ GitHub rejects this — secrets context unavailable in if: expressions
- name: Deploy via SSH
if: ${{ secrets.SSH_KEY != '' }}
# ✅ Use an env var and branch in the run: block instead
- name: Deploy
env:
SSH_KEY: ${{ secrets.SSH_KEY }}
run: |
if [[ -n "$SSH_KEY" ]]; then
# SSH path
else
# fallback path
fi
Invalid permissions: scopes
GitHub Actions only accepts a specific set of permission scopes. secrets and
variables are not valid — they will cause a parse failure.
# ❌ Both of these are rejected
permissions:
secrets: write
variables: write
# ✅ Valid scopes only
permissions:
contents: read
actions: read
# Full list: actions, checks, contents, deployments, id-token, issues,
# discussions, packages, pages, pull-requests, repository-projects,
# security-events, statuses, workflows
Note: writing repo variables requires the actions: write scope (via the
Actions API), not a dedicated variables scope.
Dynamic step outcome access (steps[var].outcome)
GitHub Actions expressions do not support dynamic property access via variables.
steps[check].outcome where check is a shell variable is rejected.
# ❌ Rejected — dynamic bracket access not supported
- name: Summarise
run: |
for check in check_yaml check_guards; do
result="${{ steps[check].outcome }}"
done
# ✅ Pass all step outcomes via toJSON(steps) and read with python3
- name: Summarise
env:
STEPS_JSON: ${{ toJSON(steps) }}
run: |
for check in check_yaml check_guards; do
result=$(echo "$STEPS_JSON" | python3 -c \
"import json,sys; d=json.load(sys.stdin); print(d.get('${check}',{}).get('outcome','skipped'))")
done
workflow_run trigger + reusable workflow call (uses:)
GitHub prohibits calling a reusable workflow from a workflow_run-triggered
workflow. The combination produces startup_failure (0s duration, "workflow
file issue") even though the YAML is syntactically valid and pyyaml accepts it.
# ❌ startup_failure — workflow_run + reusable call is forbidden
on:
workflow_run:
workflows: ["Validate Config"]
types: [completed]
jobs:
guard:
uses: ./.github/workflows/pr-lifecycle-guard.yml # NOT allowed
Fix: inline the reusable workflow's logic as steps in the calling job.
schedule and workflow_dispatch triggers are unaffected — only workflow_run
has this restriction.
Detection: scan for the combination with:
python3 -c "
import re, pathlib
for wf in pathlib.Path('.github/workflows').glob('*.yml'):
c = wf.read_text()
if re.search(r'^\s+workflow_run:', c, re.MULTILINE) and \
re.search(r'^\s{4}uses:\s+\./', c, re.MULTILINE):
print(wf.name)
"
actions/checkout must precede quota-snapshot.sh
scripts/includes/quota-snapshot.sh sources time_format.py via a path
relative to BASH_SOURCE[0]. Without actions/checkout the script file
does not exist on the runner and the source call fails with
No such file or directory.
Rule: in every job that sources quota-snapshot.sh, actions/checkout
must be the first step.
# ✅ correct
steps:
- uses: actions/checkout@v7
- name: Quota pre-flight
run: |
source scripts/includes/quota-snapshot.sh
quota_snapshot
# ❌ wrong — source fails before checkout runs
steps:
- name: Quota pre-flight
run: |
source scripts/includes/quota-snapshot.sh # file not found
quota_snapshot
- uses: actions/checkout@v7
validate-workflow-guards.py Check 7 detects this automatically. Run it
after adding any new workflow that uses quota-snapshot.sh.
SUBGROUPS_CONFIG relative path and cd into work dirs
scripts/mirror-osp-to-gitlab.sh does cd "$work_dir" into a git mirror
clone. Any relative path passed via env var before that cd will break.
The workflow passes SUBGROUPS_CONFIG: config/gitlab-subgroups-ooc.yml
(relative). The script now resolves it to absolute at startup:
_raw="${SUBGROUPS_CONFIG:-config/gitlab-subgroups.yml}"
if [[ "${_raw}" != /* ]]; then
GL_SUBGROUP_CONFIG="${REPO_ROOT}/${_raw}"
else
GL_SUBGROUP_CONFIG="${_raw}"
fi
General rule: resolve any env-var path to absolute before any cd that
could change the working directory.
Incus daemon and runner capabilities
The incusd service and sync-in-server service require Linux capabilities
that are not available on standard Ona Cloud runners. This section documents
what is needed and how to enable it.
Capability requirements
| Capability | Required for | Standard Ona Cloud | Self-hosted (privileged) |
|---|---|---|---|
CAP_SYS_ADMIN | namespace creation, mount | ✗ missing | ✓ available |
CAP_NET_ADMIN | bridge/veth, nftables | ✗ missing | ✓ available |
/dev/kvm | hardware-accelerated VMs | ✗ not present | ✓ if nested virt enabled |
/dev/fuse | fuse-overlayfs rootfs | ✗ not present | ✓ available |
| user namespaces | unprivileged containers | ✗ blocked | ✓ available |
On standard Ona Cloud runners the incusd service will fail to start with
CAP_SYS_ADMIN not available. The Incus client (incus CLI) is still
installed and can manage remote Incus servers.
Enabling on a self-hosted runner
To run incusd locally in the devcontainer, the runner VM must:
- Expose capabilities — run the devcontainer with
--privilegedor grantCAP_SYS_ADMIN+CAP_NET_ADMIN+seccomp=unconfined. - Enable nested virtualization — for KVM-accelerated VMs, the host
must have
vmx/svmCPU flags and expose/dev/kvmto the container. Without KVM, Incus falls back to QEMU TCG (software emulation — slower but functional for testing and image building). - Expose
/dev/fuse— for fuse-overlayfs rootfs driver.
On AWS, use a metal instance type (e.g. c5.metal) or an instance with
nested virtualization enabled. On GCP, enable "Enable nested virtualization"
in the VM configuration.
Service startup order
When the runner supports it, start services in this order:
gitpod automations service start incusd # starts incusd, runs incus admin init --auto
gitpod automations service start sync-in-server # launches syncin/server via incus launch docker:...
sync-in-server calls incus info at startup and exits immediately if
incusd is not running.
OCI image source
Sync-in/server is published to Docker Hub as syncin/server (tags: latest,
2, 2.4.1, etc.). Incus pulls it via docker:syncin/server:latest using
its built-in OCI image support — no Docker daemon required.
The ./features/incus/install.sh feature detects capabilities at build time:
- If
CAP_SYS_ADMIN+CAP_NET_ADMINare present → installs full daemon from zabbly daily channel + QEMU - Otherwise → installs client only from zabbly stable channel
Known pitfalls
-
fill_missing_sectionscase statement — must handle all 8 AI sections. If you add a new section toALL_AI_SECTIONS, add it to thecaseinfill_missing_sections,rewrite_readme, and theupdatemode loop. -
sync-registered-imports.shdoes not create repos —ensure_gh_repo()handles creation now, but the target repo must be reachable via the GitHub API. New entries inregistered-imports.jsonwill auto-create the repo on first run. -
GitLab mirror chain — two independent legs:
- OSP leg:
I-D-1896 → OpenOS-Project-OSP (GitHub) → openos-project (GitLab) - OOC leg:
OpenOS-Project-Ecosystem-OOC (GitHub) → openos-project-ooc-ecosystem (GitLab)
Adding a repo to
gitlab-subgroups.yml(OSP) orgitlab-subgroups-ooc.yml(OOC) is required for GitLab mirroring on the respective leg. Adding toregistered-imports.jsonis required for upstream sync. All three are independent — a repo can be in any combination. - OSP leg:
-
_inter_repo_sleepinupdate-readmes.sh— quota-aware pacing. No delay when quota > 2000; scales to 30s when < 500. The cached_quota_remainingvariable is decremented by 10 per repo to trigger re-checks before actually hitting the threshold.
FSA-API
fsa-api/ is a two-layer HTTP API over the fork-sync-all control plane.
Full reference: fsa-api/README.md. Key conventions for agents:
Layer structure
fsa-api/uaa/ — Unified Agnostic API (generic, platform-agnostic)
fsa-api/core/ — FSA-specific adapters (GitHub-org-specific)
fsa-api/config/ — fsa-routes.yml + fsa-toggles.yml + fsa-deployments.yml
fsa-api/server/ — fsa-start.sh (merges both route files)
Never put FSA-specific logic in fsa-api/uaa/. UAA is propagated to
consumer repos via sync-template.sh. FSA-specific adapters belong in
fsa-api/core/adapters/<domain>/.
Adding an adapter
Every new adapter must:
- Source
fsa-adapter.sh(notadapter.shdirectly) - Call
fsa_quota_check Nbefore any API calls - Check its toggle with
toggle_enabled <name>if the domain has one - Have a route entry in
fsa-api/config/fsa-routes.yml - Pass
python3 scripts/validate-workflow-guards.pywith zero warnings
#!/usr/bin/env bash
# GET /api/fsa/<domain>/<resource>
source "$(dirname "${BASH_SOURCE[0]}")/../../lib/fsa-adapter.sh"
fsa_quota_check 50 || exit 0
toggle_enabled my_toggle || { fsa_error "disabled" 503; exit 0; }
# ... logic ...
fsa_ok '{"result":"..."}'
shared.sh — UAA ↔ FSA sync point
fsa-api/uaa/lib/shared.sh is sourced by both uaa/lib/adapter.sh and
fsa-api/core/lib/fsa-adapter.sh. It contains platform-agnostic logic
shared between the two layers:
- Toggle system:
toggle_get / toggle_enabled / toggle_set / toggle_listreadsUAA_TOGGLES_FILE(set tofsa-api/config/fsa-toggles.ymlby FSA) - Quota guard:
quota_check N/quota_fetch— FSA overridesquota_fetch()with the GitHub-specific implementation; UAA defaults to 9999 (unlimited) - JSON helpers:
json_ok / json_error / json_list—fsa_ok / fsa_error / fsa_listare aliases kept for backward compatibility - Route merge:
merge_routes_files FILE...— merges multiple route manifests - Capability registry:
register_capability / list_capabilities
When adding logic that is genuinely platform-agnostic (no GitHub/GitLab coupling),
add it to shared.sh so both UAA consumers and FSA adapters benefit. When adding
logic that is GitHub-specific, add it to fsa-adapter.sh only.
Platform-agnostic adapters (fsa_platform_init)
fsa-adapter.sh sources scripts/includes/platform-adapter.sh. Every FSA
adapter can switch platforms by calling fsa_platform_init:
fsa_platform_init gitlab # switches to GitLab, selects GITLAB_TOKEN
pa_list_repos "openos-project" # uses GitLab API
fsa_platform_init github # switch back
Token selection is automatic: github→GH_TOKEN, gitlab→GITLAB_TOKEN,
gitea→GITEA_TOKEN, forgejo→FORGEJO_TOKEN, codeberg→CODEBERG_TOKEN.
workflows/list.sh and workflows/run.sh have platform branches for all 5
platforms. New workflow-management adapters should follow the same pattern:
check PA_PLATFORM and branch accordingly.
Deployment registry (config/fsa-deployments.yml)
Single source of truth for all known FSA instances. The deployments adapter
domain reads this file — do not hardcode deployment coordinates in adapters.
deployments:
- id: source
platform: github
org: Interested-Deving-1896
...
- id: osp-gitlab
platform: gitlab
group_path: openos-project/ops
...
When a new FSA instance is created (new org, new platform), add it here.
The /api/fsa/deployments/* routes and codebase/drift will pick it up
automatically.
codebase/sync dispatch rule
POST /api/fsa/codebase/sync always dispatches on the source repo
(Interested-Deving-1896/fork-sync-all), never on FSA_REPO. The source
workflow (sync-fsa-forks.yml) then pushes updates to all mirrors.
force=true dispatches critical-deploy-gitlab.yml instead (direct git push,
bypasses mirror sync chain — use for emergency GitLab mirror recovery).
Route manifest conventions
fsa-api/config/fsa-routes.yml extends the UAA route format. Fields:
- path: /api/fsa/<domain>/<resource>
script: core/adapters/<domain>/<verb>.sh
method: GET|POST|PUT|DELETE
auth: true # require FSA_API_TOKEN header (write operations)
toggle: <name> # gate on fsa-toggles.yml entry
# comment describing query params or body shape
fsa-start.sh merges fsa-api/uaa/config/routes.yml + fsa-api/config/fsa-routes.yml
using shared.sh's merge_routes_files(). Last writer wins on path+method conflicts.
Platform adapter (platform-adapter.sh)
scripts/includes/platform-adapter.sh provides a uniform interface for
interacting with any supported git hosting platform so that sync scripts can
be written once and work against any backend.
Supported platforms: github | gitlab | gitea | forgejo | codeberg
Initialisation — must be called before any other pa_* function:
PLATFORM=gitlab PLATFORM_TOKEN="$GITLAB_TOKEN" pa_init gitlab
# With self-hosted host override:
PLATFORM=gitea PLATFORM_TOKEN="$TEA_TOKEN" pa_init gitea https://gitea.myco.com
Sets PA_HOST, PA_API, PA_AUTH_HEADER, PA_CLONE_PREFIX as internal state.
Guard against double-sourcing is in place (_PLATFORM_ADAPTER_LOADED).
Public functions:
| Function | Purpose |
|---|---|
pa_init PLATFORM [HOST] | Initialise adapter for the given platform |
pa_list_repos ORG | Print one repo name per line; handles pagination |
pa_repo_exists ORG REPO | Returns 0 if repo exists, 1 otherwise |
pa_clone_url ORG REPO | Authenticated HTTPS clone URL |
pa_push_url ORG REPO | Authenticated HTTPS push URL (same as clone for most platforms) |
pa_create_repo ORG REPO [DESC] | Create repo if absent; no-op if already exists |
pa_api_get URL | Authenticated GET with rate-limit retry |
pa_rate_limit_remaining | Remaining API quota (best-effort) |
Rate-limit retry — pa_api_get retries HTTP 429/403 up to 3 times with
reset-aware backoff. Reads X-RateLimit-Reset (GitHub/Gitea/Forgejo) or
RateLimit-Reset (GitLab) from response headers; falls back to 60s if absent.
Auth header format per platform:
- GitHub:
Authorization: token TOKEN - GitLab:
PRIVATE-TOKEN: TOKEN - Gitea/Forgejo/Codeberg:
Authorization: token TOKEN
Clone URL prefix per platform:
- GitHub:
https://x-access-token:TOKEN@github.com - GitLab:
https://oauth2:TOKEN@gitlab.com - Gitea/Forgejo/Codeberg:
https://x-access-token:TOKEN@HOST
git-platform-sync.sh is the primary consumer. It uses pa_init twice per
sync leg (once for source, once for dest) and calls pa_list_repos, pa_repo_exists,
pa_clone_url, pa_push_url, and pa_create_repo. The git-platform-sync.yml
workflow replaces the deprecated sync-to-gitlab.yml (direction=push) and
sync-from-gitlab.yml (direction=pull) — both are now no-op stubs kept only for
workflow_run name resolution.
Template consumer tiers
config/template-consumers.yml has a tier field that controls whether
sync-template.sh may write to a repo:
tier: protected— skipped in all three modes (create, inject, propagate). Used for fork-sync-all itself and all its mirrors (OSP GitHub, OOC GitHub, both GitLab groups). These repos receive updates via the mirror chain, not direct template injection. Adding a new fork-sync-all mirror: list it here withtier: protected— no script changes needed.tier: managed— normal sync target (default when omitted).
The guard is enforced at three layers:
scripts/sync-template.sh— readstierfrom the YAML parser (line 10 of the record format); skips protected entries in all three run_ functions..github/workflows/sync-template.yml—validatejob callscheck_protected()and rejects protected targets before any runner runs.config/template-consumers.yml— prominent comment at the top of the file.
Known pitfall: sync-template.sh CREATE mode cannot read tier from the
consumers file for a repo that doesn't exist yet. It does a runtime lookup
against the consumers file by name — so a new fork-sync-all mirror must be
added to template-consumers.yml with tier: protected before anyone
attempts to CREATE it via sync-template.
sync-template contamination — what happened and how it's prevented
In June 2026, sync-template.sh was run with fork-sync-all as a target
(either CREATE or INJECT mode). Because the script runs from a fork-sync-all
checkout and copies the working tree into the target, this committed ~224
eggs-ai application source files (src/, bin/, myclaw/, install.sh,
package.json, etc.) directly into fork-sync-all over several weeks.
Root causes fixed:
fork-sync-allwas listed intemplate-consumers.ymlas a managed consumer withprofile: full— removed and replaced withtier: protected.- No guard existed in the script or workflow against self-targeting — added (see Template consumer tiers above).
mirror.yaml(a raw git-push mirror introduced via the contamination) was pointing atInterested-Deving-1896/eggs-aiinstead of the OSP mirror — removed entirely (superseded bymirror-to-osp.yml).actions/checkout@v6(non-existent) was in 113 workflow files — replaced with@v4across all workflows.
If you see chore: add template file <eggs-ai-path> [skip ci] commits in the
log, the contamination has recurred. The fix is to revert those commits and
verify the tier guard is in place.
GitLab token scopes
Two different tokens are used for GitLab operations:
| Token | Env var | Scopes | Used for |
|---|---|---|---|
| GitLab read token | GITLAB_TOKEN (Ona project secret) | read_api, read_repository | API reads (project metadata, branch info, commit lookup) |
| GitLab sync token | GITLAB_SYNC_TOKEN (GitHub Actions secret only) | api, write_repository | git push to GitLab mirrors, project creation, branch protection |
GITLAB_SYNC_TOKEN is not injected into Ona environments — it only exists
as a GitHub Actions secret. Any operation that needs to push to GitLab must be
done via a dispatched workflow, not directly from an agent environment.
GITLAB_TOKEN in the Ona environment has zero length if the project secret
wasn't set at environment creation time. Check with echo ${#GITLAB_TOKEN}.
Auto-merge PRs
scripts/auto-merge-prs.sh merges open PRs once their required checks pass.
Three hybrid detections run per PR at runtime — no static configuration needed.
Scope detection (which PRs to merge)
Priority order — first match wins:
- Label
auto-mergepresent → merge (explicit opt-in) - PR author login ends in
[bot], or matches the SYNC_TOKEN owner → merge (automation output) AUTO_MERGE_ALL=trueenv var → merge all open PRs- Default → skip (human PRs require explicit opt-in)
Bot detection uses the token owner resolved via GET /user at startup (1 API call,
cached for the run). Any login matching *[bot] is also treated as a bot regardless
of token ownership.
Strategy detection (how to merge)
Per-PR, based on commit history (GET /repos/{repo}/pulls/{n}/commits):
- Single commit →
rebase(linear history, no merge commit) - Multiple commits, single author →
squash(clean history) - Multiple commits, multiple authors →
merge(preserves attribution)
Override with MERGE_STRATEGY=squash|rebase|merge.
Mechanism detection (when to fire)
Detected once per run via GET /repos/{repo}/branches/{base}/protection:
- Required status checks configured → native auto-merge (
gh pr merge --auto). GitHub queues the merge and fires it exactly when checks pass. Zero polling, no runner time consumed waiting. - No branch protection / no required checks → poll
mergeable_stateuntilclean, then merge directly. Polls everyPOLL_INTERVAL_SEC(default 30s) up toPOLL_TIMEOUT_MIN(default 30min).
Override with MERGE_MECHANISM=native|poll.
Workflow trigger
auto-merge-prs.yml fires on:
workflow_runcompletion ofValidate Configwithconclusion == success(primary — fires immediately after CI passes on any PR)- Schedule every 2h at :55 (fallback for PRs already green before the workflow existed)
workflow_dispatchwith optionalpr_filter(comma-separated PR numbers)
Registered: tier 3 MEDIUM, min_quota: 300.
Architecture
The three-org chain
fork-sync-all is the control plane for a three-organisation mirror chain on GitHub, with a fourth leg into GitLab:
Interested-Deving-1896 ──► OpenOS-Project-OSP
▲ │
│ ▼
│ OpenOS-Project-Ecosystem-OOC
│ │
│ ▼
│ GitLab openos-project
│ (14 subgroups, 225 repos mirrored)
│
└──── upstream-commits / upstream-prs (OSP + OOC → I-D-1896)
| Org | Role |
|---|---|
Interested-Deving-1896 | Primary — forks live here, all automation runs here |
OpenOS-Project-OSP | Secondary mirror — receives pushes from I-D-1896 |
OpenOS-Project-Ecosystem-OOC | Tertiary mirror — receives pushes from OSP |
gitlab.com/openos-project | GitLab mirror — receives pushes from OSP via GitLab CI |
All automation runs in Interested-Deving-1896/fork-sync-all. The other orgs are
passive recipients — they do not run their own automation except for the GitLab CI
mirror job that pushes back to GitLab.
Data flow
Inbound (upstream → I-D-1896)
Three paths bring upstream changes into Interested-Deving-1896:
sync-forks.yml(daily) — syncs all GitHub forks with their upstream parentssync-registered-imports.yml(daily at 04:55 UTC) — re-syncs repos registered inregistered-imports.json, including non-GitHub sources (GitLab, Bitbucket, Codeberg, etc.)upstream-commits.yml/upstream-prs.yml(daily) — detects direct commits and open PRs in OSP/OOC that haven't been reflected upstream, and opens PRs in I-D-1896
Outbound (I-D-1896 → OSP → OOC → GitLab)
The mirror chain runs in sequence, each leg triggered by the previous:
mirror-to-osp.yml ──► mirror-osp-to-ooc.yml ──► GitLab CI (sync-to-gitlab.yml)
(every 6h at :13) (every 6h at :45) (on OSP push)
flush-lifecycle.yml is the top-level entry point for a full pipeline run. It
sets FLUSH_ACTIVE=true, holds a sentinel runner slot, and coordinates the
three-stage sequence with quota reservation and pause/resume at reset windows:
flush-lifecycle.yml
└─ pre-flush-prep.yml ← cancels stale runs, merges PRs, validates config
└─ full-chain-flush.yml ← all mirror + README + CI stages in order
└─ post-flush-prep.yml ← integrity checks and queue health verification
full-chain-flush.yml orchestrates the pipeline stages themselves — mirror
chain, README updates, sync, and validation — but should be triggered via
flush-lifecycle.yml rather than directly, so the FLUSH_ACTIVE mutex and
quota reservation are active for the full run.
GitLab subgroup placement
config/gitlab-subgroups.yml is the single source of truth for which repos go
into which GitLab subgroup. The 14 subgroups map to topic areas:
| Subgroup | Repos | Topic |
|---|---|---|
incus_deving | 49 | Incus / container infrastructure |
yaml-tooling_deving | 34 | YAML, CI, and tooling |
ops | 30 | Operations and control plane |
agnostic-api_deving | 29 | Unified Agnostic API — virtual filesystems, AI/LLM adapters, OS-compat layers |
penguins-eggs_deving | 17 | penguins-eggs ecosystem |
linux-kernel_filesystem_deving | 14 | Kernel and filesystem |
cachyos_deving | 12 | CachyOS packages |
ai-agents_deving | 10 | AI agent tooling |
accessibility_deving | 9 | Screen readers, Braille, WCAG auditing, audio overviews |
git-management_deving | 9 | Git tooling |
neon-deving | 8 | KDE Neon ecosystem |
rust-systems_deving | 2 | Rust system tools |
taubyte_deving | 1 | Taubyte platform |
immutable-filesystem_deving | 1 | Immutable Linux |
Repos not listed in any subgroup fall into the ops default subgroup.
Quota management
Both GH_TOKEN and SYNC_TOKEN belong to the same GitHub user and share a
single 5000 req/hr REST bucket. The system has three layers of protection:
quota-reserve.yml ──► queue-manager.yml
(every 30 min) (every 30 min)
quota-monitor.yml is a separate manual-dispatch-only tool for waiting out quota
exhaustion. It is not part of the automatic quota management loop — see
Operations for when and how to use it.
| Layer | Threshold | Action |
|---|---|---|
quota-reserve | < 1000 remaining | Cancels tier-4 (LOW) queued runs |
quota-reserve | < 500 remaining | Cancels tier-3 (MEDIUM) queued runs |
queue-manager | Run queued > 25 min | Evicts stale queued runs |
queue-manager | Duplicate workflow | Keeps newest, cancels older |
Workflow priority tiers are defined in config/workflow-priority-tiers.yml.
Tier 1 (CRITICAL) runs are never cancelled. See Operations for
the full quota reference.
Config files
| File | Purpose |
|---|---|
config/gitlab-subgroups.yml | GitLab subgroup placement for 225 repos (14 subgroups) |
config/ona-projects.yml | Ona project registry — maps repos to project IDs, environment classes, and tags |
config/workflow-priority-tiers.yml | Priority tier for each workflow (used by queue-manager and quota-reserve) |
config/workflow-quota-costs.yml | min_quota + cost tiers per workflow — source of truth for quota-reserve and pre-flight checks |
config/workflow-cost-profiles.yml | Detailed REST/GraphQL/GitLab/AI call estimates per workflow (used by rate-limit-profile.sh) |
config/workflow-sync.yml | GitHub ↔ GitLab CI job mapping (used by validate-workflow-guards) |
config/ota-registry.yml | Repos opted in to the OTA update system |
config/ota-blocklist.yml | Orgs/namespaces excluded from OTA by default |
config/template-manifest.yml | Template sync profiles and file ownership |
config/template-consumers.yml | Repos consuming each template profile |
registered-imports.json | Upstream repos registered for ongoing sync |
vendor/
vendor/ contains third-party components that fork-sync-all hosts or deploys.
It is distinct from scripts/ (first-party automation) and config/ (config data).
Current components:
| Component | Description |
|---|---|
vendor/infra-dashboard | Mirror-health and package-search SPA + Rust API backend |
All vendored components must be deployment-agnostic — no distro names, org-specific URLs, or hardcoded deployment values. See Contributing for the enforcement workflow.
Token architecture
Two GitHub PATs are in active use, both owned by the same user (ID 202036334) and sharing the same 5000 req/hr quota:
| Secret | Used by | Scope |
|---|---|---|
SYNC_TOKEN | Most workflows | repo, workflow, admin:org |
GH_TOKEN | Validation, README, config workflows | repo, workflow |
GitLab operations use GITLAB_SYNC_TOKEN (api, read/write_repository scope).
Token expiry is monitored weekly by token-health.yml. See Token Rotation
for rotation procedures.
Workflow Triggers
All workflows in .github/workflows/. Grouped by function, with every trigger listed.
Plain-text version:
DOCS/workflow-triggers.txt
Published: interested-deving-1896.github.io/fork-sync-all/workflow-triggers.html
Auto-generated on 2026-07-03 from.github/workflows/andconfig/workflow-quota-costs.yml
Index
Jump to any section:
Quick links: Glossary · Schedule Summary · Source
Accessibility
| Workflow | Synopsis | File | Schedule | Also triggers on |
|---|---|---|---|---|
| Check Accessibility ↗ ▶ Run | Multi-layer accessibility audit — CODEOWNERS coverage, README screen-reader scan, WCAG 2.1 AA HTML check, audio overview (espeak-ng), and Braille output (liblouis). Commits README.audio.mp3 and README.brl artifacts. | check-accessibility.yml | Weekly Mon 04:17 | push to README.md, .github/CODEOWNERS, CODEOWNERS (+1 more) · dispatch |
AI & Cost Tracking
| Workflow | Synopsis | File | Schedule | Also triggers on |
|---|---|---|---|---|
| Eco Audit ↗ ▶ Run | Audits fork-sync-all against KDE Eco / Blue Angel DE-UZ 215 criteria. Checks green hosting, CI efficiency, telemetry, dependency footprint. Stubs KEcoLab energy measurement for GitLab activation. Weekly on Sundays. | eco-audit.yml | Weekly Sun 05:00 | push to scripts/eco/**, .github/workflows/eco-audit.yml, config/workflow-quota-costs.yml · dispatch |
| opencode ↗ ▶ Run | OpenCode AI assistant integration. Triggered on issue/PR comments. | opencode.yml | — | — |
| Sync Agent Prices ↗ ▶ Run | Weekly hybrid A+B+C price refresh for config/agent-cost-profiles.yml. Fetches LiteLLM model_prices_and_context_window.json at a pinned SHA, diffs against current prices, and opens a PR for human review if anything changed. Flags stale manual entries as warnings. Never auto-merges. | sync-agent-prices.yml | Weekly Mon 09:00 | dispatch |
| Track Agent Costs ↗ ▶ Run | Records AI agent session cost estimates (OCUs, USD, tokens) to a structured JSON log. Supports Ona Agent, Codex, GitHub Models, and direct API agents. Builds an observed cost dataset to replace code-audit estimates in DOCS/ai-agent-costs.md over time. | track-agent-costs.yml | — | dispatch |
BDFS / Filesystem Workspace
| Workflow | Synopsis | File | Schedule | Also triggers on |
|---|---|---|---|---|
| BDFS Dev Workspace ↗ ▶ Run | Creates and manages mutable dev workspaces on top of immutable filesystem roots using the bdfs framework (btrfs, overlay, or dwarfs backends). Actions: create, drop, list, commit, status. | bdfs-dev.yml | — | dispatch |
| BDFS Dev — BTRFS Backend ↗ ▶ Run | Creates a writable BTRFS snapshot of a source subvolume as a bdfs dev workspace. Source must be on a BTRFS filesystem. | bdfs-dev-btrfs.yml | — | dispatch |
| BDFS Dev — DwarFS Backend ↗ ▶ Run | Mounts a DwarFS image read-only as the lower layer of an overlayfs workspace, with a writable upper layer (BTRFS subvolume or tmpfs). | bdfs-dev-dwarfs.yml | — | dispatch |
| BDFS Dev — Overlay Backend ↗ ▶ Run | Creates an overlayfs workspace with a source path as the read-only lower layer and tmpfs or a directory as the writable upper layer. Works on any filesystem. | bdfs-dev-overlay.yml | — | dispatch |
| bdfs Package ↗ ▶ Run | Packages fork-sync-all as a bdfs workspace (DwarFS + BTRFS). | bdfs-package.yml | — | push to (any) · dispatch |
Bugzilla Integration
| Workflow | Synopsis | File | Schedule | Also triggers on |
|---|---|---|---|---|
| Sync to Bugzilla ↗ ▶ Run | Parses commits and PRs for Bug NNN references and updates Bugzilla status and comments. | sync-to-bugzilla.yml | — | pull_request · dispatch |
Build & Release
| Workflow | Synopsis | File | Schedule | Also triggers on |
|---|---|---|---|---|
| Build ↗ ▶ Run | Builds the project. Triggered on push/PR. | build.yml | — | push to (any) · pull_request · dispatch |
| Build (self-hosted) ↗ ▶ Run | Builds the project on a self-hosted runner. | build-selfhosted.yml | — | push to (any) · dispatch |
| Build ARM64 ↗ ▶ Run | Builds the project for ARM64 architecture. | build-arm64.yml | — | push to (any) · pull_request · dispatch |
| Build x86-64 ↗ ▶ Run | Builds the project for x86-64 architecture. | build-x86.yml | — | push to (any) · pull_request · dispatch |
| Update kde-builder vendor ↗ ▶ Run | Pulls latest kde-builder upstream into vendor/kde-builder/ via git subtree. Manual dispatch only. | update-kde-builder-vendor.yml | — | dispatch |
| Checks ↗ ▶ Run | General checks workflow. Triggered on push/PR. | checks.yml | — | push to (any) · pull_request |
| Mirror Releases ↗ ▶ Run | Mirrors GitHub Releases (tags + release notes + assets) from Interested-Deving-1896 repos to their OSP and OOC counterparts. | mirror-releases.yml | Every 12h at :03 | dispatch |
| OTA Release ↗ ▶ Run | Triggered on semver tag push. Assembles and delivers OTA updates to all opted-in repos in config/ota-registry.yml, then updates CHANGELOG.md with release notes. | ota-release.yml | — | push to (any) · dispatch |
| Release ↗ ▶ Run | Creates a GitHub release and uploads build artifacts on tag push. | release.yaml | — | push to (any) · dispatch |
| DwarFS Pack Release ↗ ▶ Run | Packages a DwarFS release artifact when an upstream release completes. | dwarfs-pack-caller.yml | — | Release completes · dispatch |
| Push Kernel Content ↗ ▶ Run | Pushes kernel version metadata (READY, VERSION, config/, patches/, README.md) to the debian-{arch}-kernel-base repos (one per arch, up to 10). | push-kernel-content.yml | — | dispatch |
| Seed Patchset Branches ↗ ▶ Run | Seeds 9 patchset branches per debian-{arch}-kernel-base repo for Debian (trixie/forky/sid), Devuan (excalibur/forky/ceres), and Ubuntu (resolute/stonking/devel). | seed-patchset-branches.yml | — | dispatch |
| Generate architecture config ↗ ▶ Run | Generates architecture config from org repo metadata. | gen-arch-config.yml | — | dispatch |
CI & Failure Resolution
| Workflow | Synopsis | File | Schedule | Also triggers on |
|---|---|---|---|---|
| Rate-Limit Re-trigger ↗ ▶ Run | Scans recently-failed workflow runs, identifies those that failed due to rate limiting, and re-triggers them after their quota reset epoch. | rate-limit-rerun.yml | Every 4h at :05 | dispatch |
| Notification Poller ↗ ▶ Run | Polls GitHub notifications for unread CI failure notifications and triggers resolve-failures immediately when any are found. | notify-poller.yml | Every 4h at :32 | dispatch |
| Resolve CI Failures ↗ ▶ Run | Analyses CI failure patterns across OSP-bound repos and applies automated fixes (dependency updates, config corrections, workflow patches) where possible. | resolve-failures.yml | Daily 07:43 | dispatch |
| Rebuild LTS Branch (penguins-eggs) ↗ ▶ Run | Rebases the all-features branch onto the upstream master after each pieroproietti sync, then force-pushes the result to the lts branch. | rebase-lts.yml | — | Sync pieroproietti Forks completes · dispatch |
| Rate Limit Status ↗ ▶ Run | Queries current rate limit status for all external APIs used by fork-sync-all. On-demand health check. | rate-limit-status.yml | — | Rate-Limit Re-trigger completes · dispatch |
| Notification Manager ↗ ▶ Run | Hourly notification triage. Auto-marks known-safe patterns (mirror failures, quota artifacts, Dependabot) as read. Supports manual dispatch with list/mark-all-read actions. | notify-manager.yml | 17 * * * * | Resolve CI Failures completes · dispatch |
| Runner Status ↗ ▶ Run | Reports runner utilisation and queue depth across the org. Flags workflows with queue depth above configurable warn/critical thresholds. | runner-status.yml | Every 1h at :10 | Queue Manager completes · Rate-Limit Re-trigger completes · dispatch |
Documentation & Publishing
| Workflow | Synopsis | File | Schedule | Also triggers on |
|---|---|---|---|---|
| Deploy Book ↗ ▶ Run | Builds the mdBook documentation site from DOCS/ and deploys it to GitHub Pages at interested-deving-1896.github.io/fork-sync-all/. | deploy-book.yml | — | push to DOCS/**, book.toml, README.md (+4 more) · dispatch |
| Generate Book Pages ↗ ▶ Run | Regenerates DOCS/generated/ pages from config sources (workflow-quota-costs.yml, priority-tiers.yml, gitlab-subgroups.yml, registered-imports.json) and commits the result. | generate-book-pages.yml | — | push to config/workflow-quota-costs.yml, config/workflow-priority-tiers.yml, config/gitlab-subgroups.yml (+3 more) · dispatch |
| Update Book Index ↗ ▶ Run | Regenerates DOCS/generated/ pages (source tree, glossary, workflow index) on push to main. Commits with [skip ci]. | update-book-index.yml | — | push to .github/workflows/**, config/workflow-quota-costs.yml, config/workflow-priority-tiers.yml (+8 more) · dispatch |
| Sync penguins-eggs docs to penguins-eggs-book ↗ ▶ Run | Triggered by repository_dispatch from penguins-eggs when docs/chromiumos/ changes on all-features. Syncs the updated docs into the penguins-eggs-book repo. | sync-eggs-docs-to-book.yml | — | dispatch |
| Export Book (Multi-Engine) ↗ ▶ Run | Exports the book to one or all supported engines (mdBook, MkDocs, Docusaurus, Pandoc). Manual dispatch only. | book-export.yml | — | dispatch |
| GitBook OSS ↗ ▶ Run | Manages the GitBook OSS (Next.js) renderer. Actions: build, export, update, dev-info. Weekly update check on Mondays. | gitbook-oss.yml | Weekly Mon 04:17 | dispatch |
| Translate Docs ↗ ▶ Run | Translates DOCS/ mdBook pages into a target language using GitHub Models API. Writes translated files to DOCS/ | translate-docs.yml | 15 11 */2 * * | Deploy Book completes · dispatch |
| Generate NotebookLM Content ↗ ▶ Run | Generates NotebookLM content artifacts (audio, video, slides, infographic, quiz, flashcards, report) for a given notebook and uploads them to a GitHub Release. | generate-notebooklm.yml | — | dispatch |
| Refresh NotebookLM Auth ↗ ▶ Run | Rotates the short-lived __Secure-1PSIDTS cookie in NOTEBOOKLM_AUTH_JSON weekly and writes the updated state back to the repo secret. | refresh-notebooklm-auth.yml | Weekly Tue 06:17 | dispatch |
| Update Workflow Triggers Doc ↗ ▶ Run | Regenerates docs/workflow-triggers.md and docs/workflow-triggers.txt whenever a workflow file changes on main. Commits the result directly to main. | update-workflow-triggers-doc.yml | — | push to .github/workflows/**, config/workflow-quota-costs.yml · dispatch |
| Upload NotebookLM Assets ↗ ▶ Run | Uploads NotebookLM generated output files (audio, PDF) to a GitHub Release. Creates the release if it does not exist yet. | upload-notebooklm.yml | — | dispatch |
Fork & Import Sync
| Workflow | Synopsis | File | Schedule | Also triggers on |
|---|---|---|---|---|
| Sync All Forks ↗ ▶ Run | Syncs all branches of every fork owned by Interested-Deving-1896 with their upstream via the GitHub merge-upstream API, falling back to force-reset on divergence. | sync-forks.yml | Daily 06:07 | dispatch |
| Sync Registered Imports ↗ ▶ Run | Re-syncs all repos listed in registered-imports.json — bare-clones each source URL and pushes all branches and tags to Interested-Deving-1896. | sync-registered-imports.yml | Daily 04:55 | dispatch |
| Sync FSA Forks ↗ ▶ Run | Keeps downstream fork-sync-all forks in sync with upstream. Opens PRs on drift. | sync-fsa-forks.yml | Daily 04:00 | push to (any) · dispatch |
| Sync UAA Vendor ↗ ▶ Run | Syncs vendor/unified-agnostic-api from Interested-Deving-1896/unified-agnostic-api via sparse checkout. Runs on push to vendor/unified-agnostic-api/** or weekly schedule. | sync-uaa-vendor.yml | Weekly Tue 05:00 | push to vendor/unified-agnostic-api/**, fsa-api/uaa/**, .github/workflows/sync-uaa-vendor.yml · dispatch |
| Sync Shell Tools Vendor ↗ ▶ Run | Sparse-clones each of the 24 shell-tools forks and copies entrypoint scripts into vendor/shell-tools/. One clone per tool (~2 REST calls each via git protocol). Weekly Sunday 02:00 UTC. | sync-shell-tools.yml | Weekly Sun 02:00 | dispatch |
| Integrate Shell Tools ↗ ▶ Run | Runs smoke tests and integration demos for vendored shell-tools. No GitHub API calls — pure runner execution. Weekly Sunday 03:00 UTC (after sync-shell-tools). | integrate-shell-tools.yml | Weekly Sun 03:00 | Sync Shell Tools Vendor completes · dispatch |
| Upstream Direct Commits from OSP + OOC ↗ ▶ Run | Detects commits pushed directly to OSP/OOC default branches (without a PR) and opens PRs against Interested-Deving-1896 to reconcile them. | upstream-commits.yml | Daily 03:47 | Mirror Interested-Deving-1896 → OSP completes · dispatch |
| Upstream PRs from OSP + OOC ↗ ▶ Run | Detects commits on OSP and OOC default branches that are not present in Interested-Deving-1896 and opens PRs to bring them upstream. | upstream-prs.yml | Daily 03:33 | Mirror Interested-Deving-1896 → OSP completes · dispatch |
| Import Repository ↗ ▶ Run | Platform-agnostic repo importer — clones any public or authenticated git URL into Interested-Deving-1896, optionally mirrors through the OSP→OOC chain and registers for ongoing sync. | import-repo.yml | — | dispatch |
| Sync KDE Groups Mirrors ↗ ▶ Run | Syncs all KDE group mirror repos under openos-project/kde-ecosystem-deving/kde-groups from invent.kde.org. Daily schedule. | sync-kde-groups-mirrors.yml | Daily 01:00 | dispatch |
| Sync KDE Neon Mirrors ↗ ▶ Run | Syncs all KDE Neon mirror repos in openos-project/kde-ecosystem-deving/neon-deving from invent.kde.org/neon/. Daily schedule, offset 30 min from Sync KDE Groups Mirrors. | sync-kde-neon-mirrors.yml | Daily 01:30 | dispatch |
| Sync Ona Projects ↗ ▶ Run | Reconciles config/ona-projects.yml with the Ona API. Creates or updates Ona projects for all repos in the org chain. Runs in dry-run mode when ONA_TOKEN is absent. | sync-ona-projects.yml | Daily 06:00 | push to config/ona-projects.yml · dispatch |
| Sync Pieroproietti GitLab Forks ↗ ▶ Run | Syncs the three pieroproietti GitLab forks (penguins-eggs, penguins-eggs-book, oa-tools) from their GitHub upstreams. Mirrors branches, tags, and creates GitLab Releases for new tags. | sync-pieroproietti-gl-forks.yml | Daily 02:15 | dispatch |
| Sync Registry Backend ↗ ▶ Run | Agnostic registry sync backend propagated to upstream-sync consumers. Dispatch-only, no schedule, no hardcoded defaults. Reads vars.AF_REGISTRY_REPO / AF_REGISTRY_BRANCH / AF_REGISTRY_PATH for self-configuration. | sync-registry-backend.yml | — | dispatch |
| Sync Registry Sources ↗ ▶ Run | Registry-driven upstream sync (central orchestrator) — reads a JSON registry of upstream sources and syncs each repo via merge-upstream or force-reset. Runs daily from fork-sync-all with penguins-eggs defaults. | sync-registry-sources.yml | Daily 03:05 | Sync Registered Imports completes · dispatch |
| Sync Upstream Mirrors (GitLab) ↗ ▶ Run | Syncs all upstream mirror repos in openos-project/upstream-mirrors from their original GitHub sources. Daily schedule. | sync-upstream-mirrors.yml | Daily 00:00 | dispatch |
| Sync Upstream Sources ↗ ▶ Run | Reads the Origins section of every OSP-bound repo and syncs each referenced external fork to its upstream HEAD via merge-upstream or force-reset. | sync-upstream-sources.yml | Daily 01:37 | dispatch |
| Sync btrfs-devel Branches ↗ ▶ Run | Syncs tracked btrfs-devel branches from the upstream kernel tree into the btrfs-dwarfs-framework fork. | sync-btrfs-devel-branches.yml | Daily 05:02 | dispatch |
| Sync pieroproietti Forks ↗ ▶ Run | Syncs all penguins-eggs forks owned by Interested-Deving-1896 with their upstream pieroproietti sources via merge-upstream. | sync-pieroproietti-forks.yml | Daily 01:07 | dispatch |
| Sync-in ↗ ▶ Run | Manages Sync-in server/client lifecycle. Server role: health-check, deploy, token rotation. Client role: register OSP-bound repos as workspaces, trigger syncs. Scheduled health every 6h, workspace sync daily. | sync-in.yml | Every 6h at :37 · Daily 10:15 | dispatch |
| Upstream Contribute (caller) ↗ ▶ Run | Consumer-repo caller for upstream-contribute.yml. Analyses push diff and opens upstream PRs. | upstream-contribute-caller.yml | — | push to (any) · dispatch |
| Upstream Workflow Proposal ↗ ▶ Run | Scans OSP-bound repos for new workflow patterns not present in fork-sync-all and opens a PR proposing them as template skeletons. | upstream-workflow-proposal.yml | Weekly Mon 06:06 | dispatch |
| btrfs-devel sync ↗ ▶ Run | Weekly sync of fs/btrfs/ subtree from kdave/btrfs-devel into this repo via git read-tree. Opens a PR when changes are found. | btrfs-devel-sync.yml | Weekly Mon 03:00 | dispatch |
Full Pipeline
| Workflow | Synopsis | File | Schedule | Also triggers on |
|---|---|---|---|---|
| Flush Lifecycle Manager ↗ ▶ Run | Coordinates the three-stage flush pipeline with quota reservation, runner slot holding via a parallel sentinel job, and pause/resume at quota reset windows. Sets FLUSH_ACTIVE=true so queue-manager and quota-reserve protect flush stages. | flush-lifecycle.yml | Weekly Sun 06:00 | Pre-Flush Prep completes · dispatch |
| Pre-Flush Prep ↗ ▶ Run | Prepares the system for a clean full-chain-flush — cancels stale runs, merges ready PRs, validates config, cleans merged branches, removes template pollution, then dispatches full-chain-flush when quota is sufficient. | pre-flush-prep.yml | — | dispatch |
| Full Chain Flush ↗ ▶ Run | Orchestrates the complete mirror chain in sequence — mirror-to-osp → mirror-osp-to-ooc → mirror-osp-to-gitlab — with quota checks between each stage. | full-chain-flush.yml | Monthly 1st 05:17 | dispatch |
| Post-Flush Verification ↗ ▶ Run | End-to-end health check after full-chain-flush — mirror integrity across all three pairs, CI status on I-D-1896 OSP-bound repos, quota health, and workflow queue health. | post-flush-prep.yml | — | Full Chain Flush completes · dispatch |
| Critical Deploy ↗ ▶ Run | Fast-lane workflow for deploying critical fixes when the system is degraded — commits and pushes changes, clears the queue aggressively, then dispatches priority workflows. | critical-deploy.yml | — | dispatch |
| Critical Deploy — All ↗ ▶ Run | Fast-lane critical deploy across all four platforms (Interested-Deving-1896, OSP, OOC, GitLab) in sequence. Cost is approximately 4× the single-org variant. | critical-deploy-all.yml | — | dispatch |
| Critical Deploy — OOC ↗ ▶ Run | Fast-lane critical deploy scoped to OpenOS-Project-Ecosystem-OOC — same three-phase pattern as Critical Deploy but targets the OOC mirror org only. | critical-deploy-github-ooc.yml | — | dispatch |
| Critical Deploy — OSP ↗ ▶ Run | Fast-lane critical deploy scoped to OpenOS-Project-OSP — same three-phase pattern as Critical Deploy but targets the OSP mirror org only. | critical-deploy-github-osp.yml | — | dispatch |
| Critical Deploy — Stub (template — not functional) ↗ ▶ Run | Template for new platform critical deploy targets. Non-functional until copied, renamed, and filled in. Update costs when the platform is activated. | critical-deploy-stub.yml | — | dispatch |
| GitLab Critical Deploy ↗ ▶ Run | Fast-lane GitLab mirror recovery. Pushes current HEAD directly to GitLab via HTTPS, cancels pending pipelines, pauses/resumes schedules, and optionally triggers a fresh pipeline. Works even when GitHub quota is near 0. | critical-deploy-gitlab.yml | — | dispatch |
| Flush Active Watchdog ↗ ▶ Run | Clears FLUSH_ACTIVE=false whenever Flush Lifecycle Manager or any critical-deploy workflow completes. Prevents stuck-mutex after force-cancel. | flush-active-watchdog.yml | — | Flush Lifecycle Manager completes · Full Chain Flush completes · Critical Deploy completes · Critical Deploy — All completes · Critical Deploy — OSP completes · Critical Deploy — OOC completes · GitLab Critical Deploy completes · dispatch |
| Pipeline Telemetry ↗ ▶ Run | Post-run observability workflow. Fetches completed run data, builds a span tree (workflow→jobs→steps), computes Thoth-equivalent metrics, parses log severity, writes a step summary and trace artifact, and upserts a rolling metrics issue. | pipeline-telemetry.yml | — | Full Chain Flush completes · Pre-Flush Prep completes · Mirror Interested-Deving-1896 → OSP completes · Mirror OSP → GitLab completes · Mirror to OpenOS-Project-Ecosystem-OOC completes · Reconcile Org References completes · Check CI Status completes · Sync All Forks completes · Sync Registered Imports completes · Pre-Mirror CI Gate completes · Verify Mirror Integrity completes · Post-Flush Verification completes · dispatch |
| Bootstrap Triggers ↗ ▶ Run | One-shot self-destruct workflow that fires pending workflow_dispatch triggers on push. | bootstrap-triggers.yml | — | push to .github/workflows/bootstrap-triggers.yml · dispatch |
Git Platform Sync
| Workflow | Synopsis | File | Schedule | Also triggers on |
|---|---|---|---|---|
| Check GitLab CI Sync ↗ ▶ Run | Compares paired jobs in .gitlab-ci.yml against config/workflow-sync.yml and reports drift — scripts with changed entry points, mismatched cadence rules, or jobs missing from either side. | check-gitlab-sync.yml | — | Validate Config completes · dispatch |
| Git Platform Sync ↗ ▶ Run | Agnostic git platform sync. Replaces sync-to-gitlab.yml (direction=push) and sync-from-gitlab.yml (direction=pull). Supports GitHub, GitLab, Gitea, Forgejo, Codeberg as source or destination. | git-platform-sync.yml | Daily 09:23 · Daily 04:27 | Add Mirror Repo completes · dispatch |
| Sync from GitLab ↗ ▶ Run | DEPRECATED. Superseded by Git Platform Sync (direction=pull). Stub kept for backwards compatibility. | sync-from-gitlab.yml | — | dispatch |
| Sync to GitLab Variant ↗ ▶ Run | Variant of Sync to GitLab that uses a different token and push strategy — used when the primary sync is blocked or for testing. | sync-to-gitlab-variant.yml | Daily 01:50 | push to config/ota-registry.yml, config/ota-blocklist.yml, .ota/schema.yml (+2 more) · dispatch |
| Sync to GitLab ↗ ▶ Run | DEPRECATED. Superseded by Git Platform Sync (direction=push). Stub kept for backwards compatibility. | sync-to-gitlab.yml | — | dispatch |
Infrastructure & Environment
| Workflow | Synopsis | File | Schedule | Also triggers on |
|---|---|---|---|---|
| Devcontainer SDK ↗ ▶ Run | Validates devcontainer.json, features, and automations templates. Optionally builds and pushes the devcontainer image or publishes features to GHCR. | devcontainer-sdk.yml | — | push to .devcontainer/**, .github/workflows/devcontainer-sdk.yml · dispatch |
| Docker → Incus Migration ↗ ▶ Run | Scans repos for Docker artifacts (Dockerfile, docker-compose.yml) and replaces them with Incus equivalents. Runs after Add Mirror Repo and weekly. | docker-to-incus.yml | Weekly Sun 03:08 | Add Mirror Repo completes · dispatch |
| FSA API ↗ ▶ Run | FSA API server lifecycle and adapter dispatch. Validates config, smoke-tests server startup, or calls individual adapters directly via workflow_dispatch. | fsa-api.yml | — | dispatch |
| Test Time Format ↗ ▶ Run | Validates time_format.py portability across glibc, musl, and BSD libc. Runs on push/PR to time_format.py. | test-time-format.yml | — | push to scripts/includes/time_format.py, .github/workflows/test-time-format.yml · pull_request · dispatch |
Maintenance & Housekeeping
| Workflow | Synopsis | File | Schedule | Also triggers on |
|---|---|---|---|---|
| Reconcile Identity Assets ↗ ▶ Run | Detects the current FSA instance, selects the matching brand variant, writes active assets to assets/brand/.active/, and injects identity content into DOCS/cover.md. | reconcile-identity-assets.yml | — | push to assets/brand/**, config/identity-assets.yml, DOCS/cover.md · Mirror Interested-Deving-1896 → OSP completes · Mirror OSP → GitLab completes · dispatch |
| Cleanup Stale Branches ↗ ▶ Run | Deletes branches that have been merged into the default branch across all repos in Interested-Deving-1896, OSP, and OOC. | cleanup-branches.yml | Monthly 1st 04:29 | Sync All Forks completes · dispatch |
| Validate Config ↗ ▶ Run | Validates all config files (gitlab-subgroups.yml, workflow-sync.yml, priority-tiers.yml, registered-imports.json) on every push that touches them. Blocks merges on invalid config. | validate-config.yml | — | push to config/gitlab-subgroups.yml, config/workflow-sync.yml, config/workflow-cost-profiles.yml (+16 more) · pull_request · dispatch |
| Reconcile Org References ↗ ▶ Run | Rewrites org/repo references in OSP and OOC mirrors to point at the correct org, fixing stale Interested-Deving-1896 references left by the mirror process. | reconcile-org-refs.yml | 50 5 */2 * * | dispatch |
| Cleanup Template Pollution ↗ ▶ Run | Removes files incorrectly propagated from fork-sync-all to consumer repos via the template sync pipeline, across all three GitHub orgs and GitLab. | cleanup-pollution.yml | — | Sync Template completes · dispatch |
| Sync Template ↗ ▶ Run | Syncs fork-sync-all's file tree into target repos. Three modes — create (new repo + mirror chain), inject (copy into existing repo), propagate (push-triggered sync to all consumers in template-consumers.yml). | sync-template.yml | — | push to .devcontainer/**, .ona/**, config/template-manifest.yml · dispatch |
| Update Infrastructure Dependencies ↗ ▶ Run | Scans workflow files across the three-org chain for outdated Actions versions, EOL runners, and EOL Node/Python versions, then opens PRs. | update-infra-deps.yml | Weekly Mon 06:11 | dispatch |
| Generate OSP Dependency Graph ↗ ▶ Run | Scans all OSP-bound repos for package.json and requirements.txt files and generates a dependency graph showing inter-repo relationships. | generate-dep-graph.yml | Weekly Sun 03:10 | Sync Registered Imports completes · dispatch |
| Token Health Monitor ↗ ▶ Run | Checks expiry dates for all tracked PATs and GitLab tokens. Opens a GitHub issue labelled token-monitor when any token expires within 45 days. | token-health.yml | Weekly Mon 09:24 | dispatch |
| Rotate Secret Token ↗ ▶ Run | Rotates GitHub PATs and GitLab tokens stored as org/repo secrets. Validates the new token before committing, then triggers Cancel Runs After Token Rotation to clear stale runs. | rotate-token.yml | — | dispatch |
| Cancel Runs After Token Rotation ↗ ▶ Run | Cancels any queued or in-progress workflow runs immediately after token rotation to prevent runs using the old token. | cancel-post-rotation.yml | — | Rotate Secret Token completes · dispatch |
| Branch Hygiene Report ↗ ▶ Run | Reports stale and unmerged branches. Manual dispatch only. | branch-hygiene-report.yml | Weekly Mon 14:00 | dispatch |
| Manage Subtrees ↗ ▶ Run | Keeps git subtrees, submodules, and umbrella repo relationships current per config/subtree-manifest.yml. | manage-subtrees.yml | Weekly Sun 01:00 | dispatch |
| Org Storage Maintenance ↗ ▶ Run | Weekly GitLab storage housekeeping across openos-project: triggers artifact expiry and deletes old generic package versions older than 90 days (keeps 5 per package). | org-storage-maintenance.yml | Weekly Sun 02:00 | dispatch |
| Pin Manager ↗ ▶ Run | Manages version pinning, GitHub profile pins, and repo issue pins. | pin-manager.yml | Weekly Mon 06:00 · Daily 07:00 | dispatch |
Mirror Chain
| Workflow | Synopsis | File | Schedule | Also triggers on |
|---|---|---|---|---|
| Mirror Interested-Deving-1896 → OSP ↗ ▶ Run | Bare-clones every repo in Interested-Deving-1896 and git push --mirror into OpenOS-Project-OSP, syncing all branches, tags, and refs exactly. | mirror-to-osp.yml | Every 6h at :13 | dispatch |
| Mirror to OpenOS-Project-Ecosystem-OOC ↗ ▶ Run | Bare-clones every repo in OpenOS-Project-OSP and git push --mirror into OpenOS-Project-Ecosystem-OOC, completing the second hop of the three-org mirror chain. | mirror-osp-to-ooc.yaml | 15 * * * * | push to (any) · dispatch |
| Mirror to OpenOS-Project-Ecosystem-OOC ↗ ▶ Run | Bare-clones every repo in OpenOS-Project-OSP and git push --mirror into OpenOS-Project-Ecosystem-OOC, completing the second hop of the three-org mirror chain. | mirror-osp-to-ooc.yml | Every 6h at :45 | dispatch |
| Mirror OSP → GitLab ↗ ▶ Run | Mirrors every repo in OpenOS-Project-OSP to its GitLab counterpart under openos-project, creating the GitLab project in the correct subgroup if it does not exist yet. | mirror-osp-to-gitlab.yml | Daily 01:23 | Add Mirror Repo completes · dispatch |
| Mirror Orgs ↗ ▶ Run | Mirrors all repos from Interested-Deving-1896 to OpenOS-Project-OSP and OpenOS-Project-Ecosystem-OOC using bare clone + push --mirror. | mirror-orgs-full.yml | Daily 02:17 | dispatch |
| Mirror Watchdog ↗ ▶ Run | Triggers when any mirror workflow fails — waits 5 minutes then retries once. Surfaces persistent failures in the Actions tab without consuming quota on repeated retries. | mirror-orgs-watchdog.yml | — | Mirror Interested-Deving-1896 → OSP completes · Mirror Orgs completes · Mirror OSP → GitLab completes · Mirror Releases completes · Mirror Artifacts completes · dispatch |
| Mirror Artifacts ↗ ▶ Run | Mirrors GitHub Releases, Flatpak packages, and RPM packages from Interested-Deving-1896 repos to their OSP and OOC counterparts. | mirror-artifacts.yml | Daily 02:10 | dispatch |
| Mirror Chain Dispatch ↗ ▶ Run | Agnostic mirror-chain backend. Dispatch-only on canonical instance — dedicated mirror workflows own schedules. Downstream forks without dedicated workflows may add a schedule. | mirror-chain-dispatch.yml | — | dispatch |
| Verify Fork Integrity ↗ ▶ Run | Compares this repo's default-branch HEAD against its upstream parent (or upstream_override from .ota/config.yml). Reports sync status; configurable hard-fail on drift. | verify-fork-integrity.yml | Weekly Mon 06:25 | Sync All Forks completes · dispatch |
| Verify Mirror Integrity ↗ ▶ Run | Compares default-branch HEAD SHAs between source and destination for all OSP-bound repos after a mirror stage. Reports mismatches as warnings; configurable hard-fail mode. | verify-mirror-integrity.yml | — | Mirror Interested-Deving-1896 → OSP completes · Mirror to OpenOS-Project-Ecosystem-OOC completes · Mirror OSP → GitLab completes · dispatch |
| Mirror Flatpak Repo ↗ ▶ Run | Builds and publishes a self-hosted Flatpak repo on GitHub Pages. Downloads Flatpak bundles from OSP/OOC releases and imports them into the org flatpak-repo. | mirror-flatpak.yml | Daily 05:00 | dispatch |
| Mirror GHCR Images ↗ ▶ Run | Re-tags and pushes GHCR container images from an upstream owner into OSP and OOC orgs. Daily schedule. | mirror-ghcr.yml | Daily 03:00 | dispatch |
| Mirror PyPI Packages ↗ ▶ Run | Re-publishes PyPI packages from upstream repos to OSP/OOC with org-prefixed package names (e.g. osp-linux-kernel-manager). | mirror-pypi.yml | — | dispatch |
| Mirror RPM Repo ↗ ▶ Run | Mirrors RPM packages from OSP/OOC releases to a self-hosted RPM repo on GitHub Pages. Daily schedule. | mirror-rpm.yml | Daily 04:30 | dispatch |
| Mirror to OpenOS-Project-OSP ↗ ▶ Run | Mirrors Interested-Deving-1896 repos to OpenOS-Project-OSP on schedule and push. | mirror.yaml | 0 * * * * | push to (any) · dispatch |
OSP-Bound Repo Management
| Workflow | Synopsis | File | Schedule | Also triggers on |
|---|---|---|---|---|
| Manage Repo Settings ↗ ▶ Run | Declarative repo settings drift detection and enforcement. Check mode reads current state (1 REST call per repo) and reports drift. Apply mode patches drifted fields (1-3 REST calls per drifted repo). | manage-repo-settings.yml | Weekly Mon 04:30 | dispatch |
| Add Mirror Repo ↗ ▶ Run | Adds a new repo to the three-org mirror chain (Interested-Deving-1896 → OSP → OOC) by creating the repo in each org, setting up webhooks, and registering it in gitlab-subgroups.yml. | add-mirror-repo.yml | — | dispatch |
| Create OOC GitLab Subgroups ↗ ▶ Run | Creates the GitLab subgroup structure for OpenOS-Project-Ecosystem-OOC and records the resulting subgroup IDs. | create-ooc-subgroups.yml | — | dispatch |
| Delete Stale Repos ↗ ▶ Run | One-shot cleanup of superseded repos across GitHub orgs and GitLab. Manual dispatch only. | delete-stale-repos.yml | — | dispatch |
| Onboard Repository ↗ ▶ Run | Onboards new repos into the ecosystem — applies labels, branch protection, topics, description, welcome issue, and dispatches sync-template/setup-osp-mirrors/sync-registered-imports. | onboard-repo.yml | — | push to registered-imports.json, config/template-consumers.yml · dispatch |
| Provision GitLab Maintenance Schedules ↗ ▶ Run | Pushes .gitlab/scheduled-maintenance.yml and creates a weekly maintenance schedule on every actively developed project under openos-project. Safe to re-run. | provision-maintenance.yml | — | dispatch |
| Setup OSP Mirror Workflows ↗ ▶ Run | Ensures all repos in OpenOS-Project-OSP have the correct mirror workflow files and secrets configured for the OSP→OOC mirror chain. | setup-osp-mirrors.yml | Daily 02:45 | Mirror Interested-Deving-1896 → OSP completes · dispatch |
OTA System
| Workflow | Synopsis | File | Schedule | Also triggers on |
|---|---|---|---|---|
| OTA Reconcile ↗ ▶ Run | Weekly drift detection and quota-fallback reconcile for mirror-chain consumer repos. Autonomously selects path A (stamp), B (drift PR), or C (quota-recovery PR) per repo based on .ota/version SHA, open PR state, and OTA_SYNC_INCOMPLETE variable. | ota-reconcile.yml | Weekly Wed 03:17 | dispatch |
| OTA Self-Update ↗ ▶ Run | Propagated to opted-in forks. Pulls the latest OTA release from fork-sync-all and applies it to the fork's workflow files. | ota-self-update.yml | Weekly Mon 05:15 | dispatch |
| OTA Discover ↗ ▶ Run | Scans forks of fork-sync-all for .ota/config.yml with enabled: true and adds newly discovered repos to config/ota-registry.yml. | ota-discover.yml | Daily 06:38 | dispatch |
| OTA Opt-In ↗ ▶ Run | Propagated to opted-in forks. Fork owners run this once to create .ota/config.yml and open a registration PR against fork-sync-all's OTA registry. | ota-opt-in.yml | — | dispatch |
PR Governance & Trust
| Workflow | Synopsis | File | Schedule | Also triggers on |
|---|---|---|---|---|
| Vouch Check PR ↗ ▶ Run | Hybrid A/B/C PR trust gate. Reads VOUCHED.td and changed file paths to select response — denounced authors auto-closed, unknown authors touching sensitive paths blocked, unknown authors on safe paths warned only. | vouch-check-pr.yml | — | — |
| Vouch Manage ↗ ▶ Run | Manages contributor vouch status via issue/PR comments. Maintainers use vouch/unvouch/denounce commands; changes are applied via auto-opened PRs against VOUCHED.td. | vouch-manage.yml | — | dispatch |
| Vouch Sync Codeowners ↗ ▶ Run | Weekly sync of CODEOWNERS entries and org members into VOUCHED.td via vouch-seed.sh. Opens a PR if VOUCHED.td changed. | vouch-sync-codeowners.yml | Weekly Mon 04:23 | dispatch |
| Accessibility PR Gate ↗ ▶ Run | Accessibility gate on pull requests. Blocks merge if accessibility violations are found. | a11y-pr-gate.yml | — | pull_request |
| PR Gate ↗ ▶ Run | Required status check for incoming PRs. Checks quota remaining and posts a comment if the system is degraded. Two rate_limit calls per run. | pr-gate.yml | — | pull_request |
| PR Lifecycle Guard ↗ ▶ Run | Reusable quota + queue pre-flight called by PR-creating workflows (OTA Release, Upstream PRs, Rebase PRs). One rate_limit call plus optional queue-manager pass. | pr-lifecycle-guard.yml | — | — |
| PR Automation ↗ ▶ Run | Applies size labels, path-based labels, reviewer auto-assignment, risky pattern detection, and auto-merge for low-risk PRs on every PR open or update. | pr-automation.yml | — | pull_request |
| Auto-merge PRs ↗ ▶ Run | Merges open PRs once required checks pass. Hybrid auto-detection per PR: scope (label/bot/all), strategy (rebase/squash/merge), mechanism (native auto-merge vs poll). | auto-merge-prs.yml | Every 6h at :55 | Validate Config completes · dispatch |
| Merge Ready PRs ↗ ▶ Run | Waits for CI then merges all open PRs with passing checks across fork-sync-all and btrfs-dwarfs-framework. | merge-ready-prs.yml | — | dispatch |
| Rebase PRs ↗ ▶ Run | Rebases open PRs in Interested-Deving-1896 onto their base branch when they fall behind, keeping PRs mergeable without manual intervention. | rebase-prs.yml | 10 5 */2 * * | Validate Config completes · dispatch |
Quota & Queue Management
| Workflow | Synopsis | File | Schedule | Also triggers on |
|---|---|---|---|---|
| Quota Reserve ↗ ▶ Run | Cancels low-priority queued runs when remaining quota drops below RESERVE_FLOOR (default 1000). Uses per-workflow min_quota from workflow-quota-costs.yml for cost-aware cancellation. | quota-reserve.yml | Every 30 min | dispatch |
| Queue Manager ↗ ▶ Run | Deduplicates queued workflow runs (keeps newest per workflow) and evicts runs queued longer than STALE_QUEUE_MIN (default 25 min) to prevent quota exhaustion cascades. | queue-manager.yml | Every 30 min | Rate-Limit Re-trigger completes · dispatch |
| Quota Monitor ↗ ▶ Run | Polls GitHub quota and optionally dispatches a target workflow once quota recovers above a configurable threshold. Dispatch-only — never scheduled. | quota-monitor.yml | — | Rate-Limit Re-trigger completes · dispatch |
| Update Quota Cost Registry ↗ ▶ Run | Reads quota-instrument records from job logs, computes observed p50/p95 REST costs per workflow, and commits updated values to workflow-quota-costs.yml weekly. | update-quota-costs.yml | Weekly Mon 08:00 | Pipeline Telemetry completes · dispatch |
| List Active Runs ↗ ▶ Run | Lists all active workflow runs with clickable web and API URLs. | list-active-runs.yml | Every 30 min | dispatch |
README Management
| Workflow | Synopsis | File | Schedule | Also triggers on |
|---|---|---|---|---|
| Create Missing READMEs ↗ ▶ Run | Creates README.md from the standard template for OSP-bound repos that have no README, with placeholder sections for human-owned content. | create-readmes.yml | Daily 07:08 | Add Mirror Repo completes · Import Repository completes · Clone Org completes · Merge Repos into Monorepo completes · dispatch |
| Update READMEs ↗ ▶ Run | Regenerates AI-owned sections (what-it-does, architecture, ci, mirror-chain, etc.) in README.md for all OSP-bound repos, preserving human-owned sections. | update-readmes.yml | Daily 03:15 | push to config/gitlab-subgroups.yml, config/template-manifest.yml · Sync Registered Imports completes · dispatch |
| Validate README Render ↗ ▶ Run | Checks README.md for rendering issues — leaked log lines, unclosed fences, bare brackets, raw angle brackets, unclosed AI markers, missing H1, and empty sections. | validate-readme-render.yml | — | push to README.md · Update READMEs completes · dispatch |
| Inject Built-with-Ona Badges ↗ ▶ Run | Adds a Built-with-Ona badge to README.md for all repos in Interested-Deving-1896 that are missing it. Skips repos that already have the badge. | inject-badges.yml | 15 8 */2 * * | Mirror OSP → GitLab completes · dispatch |
| LTS README Standardisation ↗ ▶ Run | Standardises README.md structure for LTS-tagged repos, ensuring they follow the LTS template with correct version badges and support tables. | lts-readmes.yml | Monthly 1st 03:19 | Rebuild LTS Branch (penguins-eggs) completes · dispatch |
| Inject Repo Motto ↗ ▶ Run | Injects repo motto/slogan into README.md files across all orgs. | inject-motto.yml | 30 8 */2 * * | dispatch |
| Generate Repo Descriptions ↗ ▶ Run | AI-powered per-file description generator. Fetches file tree (1 REST call) then reads each file for context (1 REST call per file) before calling GitHub Models. Cost scales with MAX_FILES setting. | generate-repo-descriptions.yml | Weekly Sun 03:30 | dispatch |
| Translate READMEs ↗ ▶ Run | Translates README.md files for OSP-bound repos into additional languages using GitHub Models API. Writes translated files alongside the English original. | translate-readmes.yml | 43 10 */2 * * | Update READMEs completes · Add Mirror Repo completes · Import Repository completes · dispatch |
| README Wizard ↗ ▶ Run | AI-guided README authoring — writes or rewrites a README for a specific repo according to custom instructions (audience, tone, sections), respecting existing human-owned markers. | readme-wizard.yml | — | dispatch |
| Trigger README Update (All Repos) ↗ ▶ Run | Dispatches update-readmes.yml for all OSP-bound repos in batch. Use after a rate-limit reset to propagate README updates org-wide. | trigger-readme-update.yml | — | dispatch |
Security & Compliance
| Workflow | Synopsis | File | Schedule | Also triggers on |
|---|---|---|---|---|
| Audit Arch Repos ↗ ▶ Run | Weekly audit of expected vs actual repos across Interested-Deving-1896. Reports missing, unexpected, and mismatched repos to the step summary. | audit-arch-repos.yml | Weekly Mon 04:00 | dispatch |
| CodeQL ↗ ▶ Run | CodeQL security analysis. Triggered on push/PR/schedule. | codeql-analysis.yml | Weekly Mon 10:34 | push to (any) · pull_request · dispatch |
| Enforce Agnostic Vendor ↗ ▶ Run | Scans vendor/ for distro-specific hardcoded fallback values in shell, YAML, and TypeScript. All vendored components must be deployment-agnostic. | enforce-agnostic-vendor.yml | — | push to vendor/**, scripts/check-vendor-agnostic.sh, .github/workflows/enforce-agnostic-vendor.yml · pull_request · dispatch |
| Full Audit ↗ ▶ Run | Weekly structural audit of workflows, scripts, config registries, assets, and vendor dirs. No REST calls. | full-audit.yml | Weekly Mon 04:00 | dispatch |
| Generate SBOM ↗ ▶ Run | Four-stage SBOM pipeline — Trivy generates CycloneDX+SPDX, sbomasm augments metadata, parlay enriches components, sbomqs scores quality. Runs weekly and on push to main. Release assets attached by OTA Release. | generate-sbom.yml | Weekly Tue 02:41 | push to **.sh, **.py, **.yml (+4 more) · dispatch |
| Pin Workflow Actions ↗ ▶ Run | Pins GitHub Actions uses references to exact SHA commits via ratchet. | pin-workflows.yml | Weekly Tue 05:00 | dispatch |
Utility / On-Demand
| Workflow | Synopsis | File | Trigger |
|---|---|---|---|
| Bootstrap Org ↗ ▶ Run | One-shot org bootstrap: fork fork-sync-all into a new org, substitute config, set secrets, dispatch post-bootstrap workflows. | bootstrap-org.yml | dispatch |
| Cancel Stale Runs ↗ ▶ Run | Cancels queued and in-progress workflow runs older than MAX_AGE_MINUTES (default 90) or created before a fix commit, preventing stale runs from burning quota. | cancel-stale-runs.yml | Rate-Limit Re-trigger completes · dispatch |
| Check CI Status ↗ ▶ Run | Agnostic CI status checker. Runs check-ci.sh for each enabled target in config/ci-check-targets.yml (GitHub orgs and GitLab groups). | check-ci.yml | Add Mirror Repo completes · dispatch |
| Check OOC CI Status ↗ ▶ Run | Daily check of CI status on the default branch HEAD for every OOC-bound repo. Reports failing repos to the step summary. | check-ooc-ci.yml | dispatch |
| Check Shell Tools CI ↗ ▶ Run | Batch-fetches CI run status for all 24 shell-tools repos via a single GraphQL query. Minimal quota cost. Weekly Monday 06:30 UTC. | check-shell-tools-ci.yml | Sync Shell Tools Vendor completes · dispatch |
| CI ↗ ▶ Run | Runs CI checks on push and pull request events. | ci.yaml | push to tests/run-tests.sh, profiles/**, .github/workflows/ci.yaml · pull_request |
| Clear All Notifications ↗ ▶ Run | Marks all GitHub notifications as read for the authenticated user. | clear-notifications.yml | dispatch |
| Clone Org ↗ ▶ Run | Clones all repositories from an org or user on any supported platform (GitHub, GitLab, Bitbucket, Gitea) into Interested-Deving-1896. | clone-org.yml | dispatch |
| Fork KDE Neon Repos ↗ ▶ Run | One-shot workflow that clones the 6 KDE Invent neon repos into Interested-Deving-1896 and pushes them through the OSP mirror chain. Ongoing re-sync handled by sync-registered-imports. | fork-neon-repos.yml | dispatch |
| GitLab Storage Scan ↗ ▶ Run | Scans all projects under openos-project on GitLab and reports storage usage. Useful for diagnosing when the namespace approaches its 10 GiB limit. | gl-storage-scan.yml | Mirror OSP → GitLab completes · dispatch |
| HW Detect CI ↗ ▶ Run | Runs CI for hardware detection tooling on schedule and push. | hw-detect-ci.yml | push to scripts/hw-detect.sh, scripts/hw-build-env.sh, scripts/kport/kport-detect*.sh (+3 more) · pull_request · dispatch |
| List Chromium GitLab Repos ↗ ▶ Run | Lists all projects under the Chromium_Browser_OS_Deving GitLab group. Informational only — used to audit what has been mirrored. | list-chromium-repos.yml | dispatch |
| Merge Repos into Monorepo ↗ ▶ Run | Merges multiple git repositories into a single monorepo, preserving full commit history, tags, and Git LFS objects. Manual dispatch only. | merge-to-monorepo.yml | dispatch |
| Pre-Mirror CI Gate ↗ ▶ Run | Checks CI status on all OSP-bound repos in Interested-Deving-1896 before mirroring. Dispatches resolve-failures for red repos, waits, then re-checks. Blocks the mirror if repos are still failing. | pre-mirror-ci-gate.yml | Reconcile Org References completes · dispatch |
| Repo Manifest ↗ ▶ Run | Exports a manifest of all repos in an org, or imports repos from a manifest into a target GitHub org. Supports multi-platform bulk import. | repo-manifest.yml | dispatch |
| Resolve CI Failures (Agnostic) ↗ ▶ Run | Agnostic CI failure resolver. Runs resolve-ci.sh for each enabled target in config/ci-check-targets.yml. GitHub targets use LLM analysis and auto-fix; GitLab targets retry failed/canceled pipelines. | resolve-ci.yml | Check CI Status completes · dispatch |
| Setup Dashboard Variables ↗ ▶ Run | Sets all VITE_* repository variables required by the infra-dashboard public-dashboard build. Safe to re-run — blank inputs leave existing variables unchanged. | setup-dashboard-vars.yml | dispatch |
| Setup GitLab CI Schedules ↗ ▶ Run | Replaces all existing GitLab pipeline schedules in openos-project/ops/fork-sync-all with the 3 consolidated CADENCE-based schedules. Safe to re-run. | setup-gitlab-schedules.yml | dispatch |
| Shallow Reclone Large GitLab Mirrors ↗ ▶ Run | Reduces GitLab storage usage by replacing full git history on large mirror projects with a shallow clone. Run when openos-project approaches its 10 GiB storage limit. | shallow-reclone-chromium.yml | dispatch |
| Trigger Artifact Mirror ↗ ▶ Run | Dispatches mirror-artifacts immediately when a release is published in this repo, so OSP and OOC receive the release without waiting for the next scheduled run. | trigger-artifact-mirror.yml | dispatch |
| Upload Asset ↗ ▶ Run | Uploads files from URLs, artifacts, or repo paths to a release, repo directory, or issue comment. | upload-asset.yml | dispatch |
Glossary
Key terms used in this document. Full glossary: DOCS/generated/glossary.md
dispatch
: Manual workflow_dispatch trigger — run from the Actions UI or via gh workflow run.
workflow_run : Trigger that fires when another named workflow completes. Used to chain workflows.
quota pre-flight
: Step that checks remaining REST quota before doing API work. Sets skip=true when below MIN_QUOTA.
MIN_QUOTA
: Minimum remaining REST quota required before a workflow proceeds. Per-workflow value from workflow-quota-costs.yml.
OSP : OpenOS-Project-OSP — second org in the mirror chain (GitHub).
OOC : OpenOS-Project-Ecosystem-OOC — third org in the mirror chain (GitHub).
mirror chain : Three-org pipeline: Interested-Deving-1896 → OSP → GitLab.
DRY_RUN
: When true, scripts print what they would do without making changes.
SYNC_TOKEN
: Cross-org GitHub token. Shares the 5000 req/hr bucket with GH_TOKEN.
OTA : Over-the-air update system delivering workflow/config updates to consumer repos.
pre-flush-prep : Pre-flight workflow run before full-chain-flush.
full-chain-flush : End-to-end pipeline: pre-flush-prep → mirror chain → post-flush-prep.
priority tiers : Tier 1 CRITICAL → Tier 4 LOW. Controls queue-manager and quota-reserve cancellation order.
consumer repo : Repo receiving template files from fork-sync-all via sync-template.sh.
OSP-bound repo : Repo mirrored into OSP and managed by fork-sync-all.
Schedule Summary (UTC)
| Time | Frequency | Workflow |
|---|---|---|
| 00:00 | Daily | Sync Upstream Mirrors (GitLab) ↗ ▶ Run |
| Sun 01:00 | Weekly | Manage Subtrees ↗ ▶ Run |
| 01:00 | Daily | Sync KDE Groups Mirrors ↗ ▶ Run |
| 01:07 | Daily | Sync pieroproietti Forks ↗ ▶ Run |
| at :10 | Every 1h | Runner Status ↗ ▶ Run |
| 01:23 | Daily | Mirror OSP → GitLab ↗ ▶ Run |
| 01:30 | Daily | Sync KDE Neon Mirrors ↗ ▶ Run |
| 01:37 | Daily | Sync Upstream Sources ↗ ▶ Run |
| 01:50 | Daily | Sync to GitLab Variant ↗ ▶ Run |
| Sun 02:00 | Weekly | Org Storage Maintenance ↗ ▶ Run |
| Sun 02:00 | Weekly | Sync Shell Tools Vendor ↗ ▶ Run |
| 02:10 | Daily | Mirror Artifacts ↗ ▶ Run |
| 02:15 | Daily | Sync Pieroproietti GitLab Forks ↗ ▶ Run |
| 02:17 | Daily | Mirror Orgs ↗ ▶ Run |
| Tue 02:41 | Weekly | Generate SBOM ↗ ▶ Run |
| 02:45 | Daily | Setup OSP Mirror Workflows ↗ ▶ Run |
| Sun 03:00 | Weekly | Integrate Shell Tools ↗ ▶ Run |
| 03:00 | Daily | Mirror GHCR Images ↗ ▶ Run |
| Mon 03:00 | Weekly | btrfs-devel sync ↗ ▶ Run |
| 03:05 | Daily | Sync Registry Sources ↗ ▶ Run |
| Sun 03:08 | Weekly | Docker → Incus Migration ↗ ▶ Run |
| Sun 03:10 | Weekly | Generate OSP Dependency Graph ↗ ▶ Run |
| 03:15 | Daily | Update READMEs ↗ ▶ Run |
| Wed 03:17 | Weekly | OTA Reconcile ↗ ▶ Run |
| 1st 03:19 | Monthly | LTS README Standardisation ↗ ▶ Run |
| Sun 03:30 | Weekly | Generate Repo Descriptions ↗ ▶ Run |
| 03:33 | Daily | Upstream PRs from OSP + OOC ↗ ▶ Run |
| 03:47 | Daily | Upstream Direct Commits from OSP + OOC ↗ ▶ Run |
| Mon 04:00 | Weekly | Audit Arch Repos ↗ ▶ Run |
| Mon 04:00 | Weekly | Full Audit ↗ ▶ Run |
| 04:00 | Daily | Sync FSA Forks ↗ ▶ Run |
| at :05 | Every 4h | Rate-Limit Re-trigger ↗ ▶ Run |
| Mon 04:17 | Weekly | Check Accessibility ↗ ▶ Run |
| Mon 04:17 | Weekly | GitBook OSS ↗ ▶ Run |
| Mon 04:23 | Weekly | Vouch Sync Codeowners ↗ ▶ Run |
| 04:27 | Daily | Git Platform Sync ↗ ▶ Run |
| 1st 04:29 | Monthly | Cleanup Stale Branches ↗ ▶ Run |
| Mon 04:30 | Weekly | Manage Repo Settings ↗ ▶ Run |
| 04:30 | Daily | Mirror RPM Repo ↗ ▶ Run |
| at :32 | Every 4h | Notification Poller ↗ ▶ Run |
| 04:55 | Daily | Sync Registered Imports ↗ ▶ Run |
| Sun 05:00 | Weekly | Eco Audit ↗ ▶ Run |
| 05:00 | Daily | Mirror Flatpak Repo ↗ ▶ Run |
| Tue 05:00 | Weekly | Pin Workflow Actions ↗ ▶ Run |
| Tue 05:00 | Weekly | Sync UAA Vendor ↗ ▶ Run |
| 05:02 | Daily | Sync btrfs-devel Branches ↗ ▶ Run |
| 10 5 */2 * * | Rebase PRs ↗ ▶ Run | |
| Mon 05:15 | Weekly | OTA Self-Update ↗ ▶ Run |
| 1st 05:17 | Monthly | Full Chain Flush ↗ ▶ Run |
| 50 5 */2 * * | Reconcile Org References ↗ ▶ Run | |
| Sun 06:00 | Weekly | Flush Lifecycle Manager ↗ ▶ Run |
| Mon 06:00 | Weekly | HW Detect CI ↗ ▶ Run |
| Mon 06:00 | Weekly | Pin Manager ↗ ▶ Run |
| 06:00 | Daily | Sync Ona Projects ↗ ▶ Run |
| Mon 06:06 | Weekly | Upstream Workflow Proposal ↗ ▶ Run |
| 06:07 | Daily | Sync All Forks ↗ ▶ Run |
| Mon 06:11 | Weekly | Update Infrastructure Dependencies ↗ ▶ Run |
| at :13 | Every 6h | Mirror Interested-Deving-1896 → OSP ↗ ▶ Run |
| Tue 06:17 | Weekly | Refresh NotebookLM Auth ↗ ▶ Run |
| Mon 06:25 | Weekly | Verify Fork Integrity ↗ ▶ Run |
| 06:30 | Daily | Check OOC CI Status ↗ ▶ Run |
| Mon 06:30 | Weekly | Check Shell Tools CI ↗ ▶ Run |
| at :37 | Every 6h | Sync-in ↗ ▶ Run |
| 06:38 | Daily | OTA Discover ↗ ▶ Run |
| at :45 | Every 6h | Mirror to OpenOS-Project-Ecosystem-OOC ↗ ▶ Run |
| at :55 | Every 6h | Auto-merge PRs ↗ ▶ Run |
| 07:00 | Daily | Pin Manager ↗ ▶ Run |
| 07:08 | Daily | Create Missing READMEs ↗ ▶ Run |
| 07:43 | Daily | Resolve CI Failures ↗ ▶ Run |
| 07:43 | Daily | Resolve CI Failures (Agnostic) ↗ ▶ Run |
| Mon 08:00 | Weekly | Update Quota Cost Registry ↗ ▶ Run |
| 15 8 */2 * * | Inject Built-with-Ona Badges ↗ ▶ Run | |
| 30 8 */2 * * | Inject Repo Motto ↗ ▶ Run | |
| Mon 09:00 | Weekly | Sync Agent Prices ↗ ▶ Run |
| 09:05 | Daily | Check CI Status ↗ ▶ Run |
| 09:23 | Daily | Git Platform Sync ↗ ▶ Run |
| Mon 09:24 | Weekly | Token Health Monitor ↗ ▶ Run |
| 10:15 | Daily | Sync-in ↗ ▶ Run |
| Mon 10:34 | Weekly | CodeQL ↗ ▶ Run |
| 43 10 */2 * * | Translate READMEs ↗ ▶ Run | |
| 15 11 */2 * * | Translate Docs ↗ ▶ Run | |
| at :03 | Every 12h | Mirror Releases ↗ ▶ Run |
| Mon 14:00 | Weekly | Branch Hygiene Report ↗ ▶ Run |
| 0 * * * * | Mirror to OpenOS-Project-OSP ↗ ▶ Run | |
| 15 * * * * | Mirror to OpenOS-Project-Ecosystem-OOC ↗ ▶ Run | |
| 17 * * * * | Notification Manager ↗ ▶ Run | |
| Every 30 min | List Active Runs ↗ ▶ Run | |
| Every 30 min | Queue Manager ↗ ▶ Run | |
| Every 30 min | Quota Reserve ↗ ▶ Run |
Workflow Scheduling Guide
Optimal trigger windows, quota requirements, and timing constraints for every scheduled workflow. Use this when deciding when to manually dispatch a workflow or when to adjust a cron schedule.
How to read this guide
Quota cost — REST API calls consumed per run (mid = typical, high = worst case).
Source: config/workflow-quota-costs.yml. GraphQL calls count as 1 REST call
regardless of how many repos are queried.
Best window — the UTC hour range where quota headroom is highest and concurrency with other workflows is lowest.
Avoid — hours where the scheduled burst is already high or where a dependency workflow hasn't finished yet.
Quota floor — the minimum remaining quota required before the workflow
will run (from min_quota in config/workflow-quota-costs.yml). If quota
is below this, the workflow skips itself and waits for the next reset.
Time format note
Per-workflow tables show two schedule columns:
- Schedule (UTC) — 24h UTC, the authoritative cron time
- Schedule (EST) — EST (UTC−5, Nov–Mar). Add 1h for EDT (UTC−4, Mar–Nov).
Example: 09:05 UTC = 4:05 AM EST = 5:05 AM EDT.
The timing map and "Best manual dispatch windows" tables use the full
24h UTC / 12h UTC / 12h ET (EST/EDT) format for completeness.
Daily quota budget
| Metric | Value |
|---|---|
| Quota per hour | 5,000 REST calls |
| Scheduled drain (daily avg) | ~3,200 calls/day (~133/hr average) |
| Worst scheduled burst (03:xx UTC / 3:xx AM UTC / 10:xx PM ET) | ~612 calls in one hour |
| Headroom at worst hour | ~4,388 calls remaining |
| Safe manual dispatch window | Any hour with < 2,000 calls already consumed |
Check current quota before dispatching:
curl -sf -H "Authorization: token $SYNC_TOKEN" \
"https://api.github.com/rate_limit" | \
python3 -c "
import sys,json,datetime
d=json.load(sys.stdin)['resources']['core']
print(f\"remaining={d['remaining']} resets={datetime.datetime.utcfromtimestamp(d['reset']).strftime('%H:%M UTC')}\")
"
Scheduled workflow timing map
All times UTC (24h) with 12h UTC and approximate ET equivalents.
[*/2] = every other day (even days of month). (*/30) = every 30 min.
Hour (UTC) 12h UTC ET (EDT/EST) Workflows
─────────────────────────────────────────────────────────────────────────────
00:xx 12:xx AM 8:xx PM / 7:xx PM mirror-to-osp (:13) sync-in (:37)
mirror-osp-to-ooc (:45) auto-merge-prs (:55)
01:xx 1:xx AM 9:xx PM / 8:xx PM sync-pieroproietti-forks (:07)
mirror-osp-to-gitlab (:23)
sync-to-gitlab-variant (:50)
02:xx 2:xx AM 10:xx PM / 9:xx PM mirror-artifacts (:10) mirror-orgs-full (:17)
setup-osp-mirrors (:45)
03:xx 3:xx AM 11:xx PM / 10:xx PM upstream-prs (:33) upstream-commits (:47)
04:xx 4:xx AM 12:xx AM / 11:xx PM git-platform-sync/pull (:27)
sync-registered-imports (:55)
05:xx 5:xx AM 1:xx AM / 12:xx AM sync-btrfs-devel-branches (:02)
rebase-prs [*/2] (:10)
reconcile-org-refs [*/2] (:50)
06:xx 6:xx AM 2:xx AM / 1:xx AM queue-manager (*/30) quota-reserve (*/30)
[Mon only: update-infra-deps (:11)]
07:xx 7:xx AM 3:xx AM / 2:xx AM resolve-ci (:43)
08:xx 8:xx AM 4:xx AM / 3:xx AM check-ci (:05) inject-badges [*/2] (:15)
09:xx 9:xx AM 5:xx AM / 4:xx AM git-platform-sync/push (:23)
check-shell-tools-ci (:30)
10:xx 10:xx AM 6:xx AM / 5:xx AM sync-in/daily (:15)
translate-readmes [*/2] (:43)
11:xx 11:xx AM 7:xx AM / 6:xx AM translate-docs [*/2] (:15)
12:xx–23:xx 12:xx PM– 8:xx AM– mirror-releases (:03 at 12:xx)
11:xx PM 7:xx PM queue-manager + quota-reserve (*/30, all hours)
Per-workflow scheduling reference
Core mirror chain
| Workflow | Schedule (UTC) | Schedule (EST) | Quota mid | Quota high | Floor | Best window (UTC) | Avoid |
|---|---|---|---|---|---|---|---|
| Mirror I-D-1896 → OSP | Every 6h at :13 | Every 6h at :13 | 80 | 200 | 300 | After 14:00 reset | 00:00–06:00 (busy) |
| Mirror OSP → OOC | Every 6h at :45 | Every 6h at :45 | 80 | 200 | 300 | 32 min after mirror-to-osp | Before :13 slot |
| Mirror Orgs | Daily 02:17 | Daily 9:17 PM | 60 | 150 | 200 | 02:00–04:00 | 06:xx (weekly burst) |
| Mirror OSP → GitLab | Daily 01:23 | Daily 8:23 PM | 80 | 200 | 200 | 01:00–03:00 | During mirror chain |
| Mirror Releases | Every 12h at :03 (00:03 + 12:03) | 7:03 PM + 7:03 AM | 100 | 300 | 200 | 00:03 or 12:03 | During flush |
| Mirror Artifacts | Daily 02:10 | Daily 9:10 PM | 80 | 200 | 200 | 02:00–04:00 | During flush |
Mirror chain dependency order: Mirror I-D-1896 → OSP must complete before Mirror OSP → OOC. The :13/:45 stagger (32 min gap) is intentional — do not reduce this gap when manually dispatching both.
CI check + resolver
| Workflow | Schedule (UTC) | Schedule (EST) | Quota mid | Quota high | Floor | Best window (UTC) | Avoid |
|---|---|---|---|---|---|---|---|
| Check CI Status | Daily 09:05 | 4:05 AM | 300 | 900 | 1500 | 09:00–11:00 | During flush |
| Resolve CI Failures (Agnostic) | Daily 07:43 | 2:43 AM | 120 | 400 | 100 | 07:00–09:00 | During flush |
| Check Shell Tools CI | Daily 09:30 | 4:30 AM | 50 | 100 | 200 | 09:00–11:00 | — |
Note: Check CI Status requires a 1,500 quota floor — the highest of any workflow. If quota is below 1,500 at 09:05 UTC (4:05 AM EST / 5:05 AM EDT), it skips and waits for the next day. Manually dispatch after the 14:00 UTC reset if you need it to run same-day.
Sync operations
| Workflow | Schedule (UTC) | Schedule (EST) | Quota mid | Quota high | Floor | Best window (UTC) | Avoid |
|---|---|---|---|---|---|---|---|
| Sync All Forks | Via full-chain-flush | — | 200 | 500 | 500 | 04:00–08:00 | During mirror chain |
| Sync Registered Imports | Daily 04:55 | 11:55 PM | 45 | 100 | 200 | 04:00–06:00 | — |
| Sync btrfs-devel Branches | Daily 05:02 | 12:02 AM | 30 | 80 | 100 | 05:00–07:00 | — |
| Sync pieroproietti Forks | Daily 01:07 | 8:07 PM | 60 | 150 | 200 | 01:00–03:00 | — |
| Sync to GitLab Variant | Daily 01:50 | 8:50 PM | 40 | 100 | 100 | 01:00–03:00 | — |
| Setup OSP Mirror Workflows | Daily 02:45 | 9:45 PM | 80 | 200 | 200 | 02:00–04:00 | — |
| Git Platform Sync | Daily 04:27 + 09:23 | 11:27 PM + 4:23 AM | 60 | 150 | 200 | 04:00 or 09:00 | — |
| Upstream PRs from OSP+OOC | Daily 03:33 | 10:33 PM | 80 | 200 | 300 | 03:00–05:00 | — |
| Upstream Direct Commits | Daily 03:47 | 10:47 PM | 80 | 200 | 300 | After upstream-prs (:33) | Before :33 slot |
README + badge operations
| Workflow | Schedule (UTC) | Schedule (EST) | Quota mid | Quota high | Floor | Best window (UTC) | Avoid |
|---|---|---|---|---|---|---|---|
| Update READMEs | Via flush | — | 150 | 400 | 500 | 10:00–12:00 | During mirror chain |
| Create Missing READMEs | Via flush | — | 100 | 300 | 300 | 10:00–12:00 | — |
| Inject Built-with-Ona Badges | Every 2 days 08:15 | 3:15 AM | 120 | 300 | 300 | 08:00–10:00 | — |
| Translate READMEs | Every 2 days 10:43 | 5:43 AM | 150 | 400 | 300 | 10:00–12:00 | — |
| Translate Docs | Every 2 days 11:15 | 6:15 AM | 100 | 250 | 200 | 11:00–13:00 | — |
| Reconcile Org References | Every 2 days 05:50 | 12:50 AM | 80 | 200 | 200 | 05:00–07:00 | — |
Infrastructure / quota management
| Workflow | Schedule (UTC) | Schedule (EST) | Quota mid | Quota high | Floor | Notes |
|---|---|---|---|---|---|---|
| Queue Manager | Every 30 min | Every 30 min | 15 | 30 | 50 | Never manually dispatch — runs automatically |
| Quota Reserve | Every 30 min | Every 30 min | 15 | 30 | 50 | Never manually dispatch |
| Rate-Limit Re-trigger | Every 6h | Every 6h | 30 | 80 | 100 | Fires automatically after quota recovery |
| Auto-merge PRs | Every 6h at :55 (00:55, 06:55, 12:55, 18:55) | 7:55 PM, 1:55 AM, 7:55 AM, 1:55 PM | 30 | 80 | 100 | Safe to dispatch any time |
| Rebase PRs | Every 2 days 05:10 | 12:10 AM | 40 | 100 | 100 | Safe to dispatch any time |
Heavy / manual-only workflows
| Workflow | Trigger | Schedule (EST) | Quota mid | Quota high | Floor | Best window (UTC) |
|---|---|---|---|---|---|---|
| Full Chain Flush | Manual / daily 05:17 | 12:17 AM | 400 | 1000 | 1000 | 04:00–08:00 |
| Pre-Flush Prep | Manual only | — | 50 | 150 | 3000 | 14:05 (5 min after reset) |
| Critical Deploy | Manual only | — | 100 | 300 | 500 | Any time — bypasses queue |
| Onboard Repo | Manual only | — | 80 | 200 | 300 | Any time |
| Add Mirror Repo | Manual only | — | 60 | 150 | 200 | Any time |
| Sync Ona Projects | Daily 06:00 / manual | 1:00 AM | 1 | 20 | 50 | Any time — dry-run by default on schedule |
Pre-Flush Prep has the highest floor (3,000) because it validates config, merges PRs, and then dispatches the full flush chain. Trigger it immediately after the 14:00 UTC (9:00 AM EST / 10:00 AM EDT) reset for maximum headroom.
Best manual dispatch windows
Highest quota headroom
| Window | 24h UTC | 12h UTC | ET (EDT) | ET (EST) | Why |
|---|---|---|---|---|---|
| Best | 14:00–15:00 | 2:00–3:00 PM | 10:00–11:00 AM | 9:00–10:00 AM | Immediately after hourly reset; ~4,867 calls available |
| Good | 05:00–07:00 | 5:00–7:00 AM | 1:00–3:00 AM | 12:00–2:00 AM | Low scheduled activity; ~4,400 calls typically available |
| Good | 20:00–23:00 | 8:00–11:00 PM | 4:00–7:00 PM | 3:00–6:00 PM | No scheduled workflows; quota recovering |
Lowest concurrency (fewest parallel jobs)
| Window | 24h UTC | 12h UTC | ET (EDT) | ET (EST) | Why |
|---|---|---|---|---|---|
| Best | 15:00–17:00 | 3:00–5:00 PM | 11:00 AM–1:00 PM | 10:00 AM–12:00 PM | No scheduled workflows at all |
| Good | 11:00–13:00 | 11:00 AM–1:00 PM | 7:00–9:00 AM | 6:00–8:00 AM | Only translate workflows (every 2 days); runners mostly idle |
Avoid
| Window | 24h UTC | 12h UTC | ET (EDT) | ET (EST) | Why |
|---|---|---|---|---|---|
| Worst | 03:00–04:00 | 3:00–4:00 AM | 11:00 PM–12:00 AM | 10:00–11:00 PM | Highest burst (~612 calls); upstream PRs + commits + sync all fire |
| Caution | 06:00–07:00 | 6:00–7:00 AM | 2:00–3:00 AM | 1:00–2:00 AM | Monday only: 13-workflow concurrent spike (update-infra-deps) |
| Caution | 09:00–10:00 | 9:00–10:00 AM | 5:00–6:00 AM | 4:00–5:00 AM | Check CI Status fires (1,500 floor); marginal quota risks skipping it |
Pre-flush-prep checklist
Before triggering pre-flush-prep.yml:
# 1. Check quota
curl -sf -H "Authorization: token $SYNC_TOKEN" \
"https://api.github.com/rate_limit" | \
python3 -c "
import sys,json,datetime
d=json.load(sys.stdin)['resources']['core']
reset=datetime.datetime.utcfromtimestamp(d['reset']).strftime('%H:%M UTC')
ok = '✅' if d['remaining'] >= 3000 else '❌'
print(f\"{ok} remaining={d['remaining']} (need 3000) resets={reset}\")
"
# 2. Run validators locally
python3 scripts/validate-workflow-guards.py
python3 scripts/validate-gitlab-subgroups.py config/gitlab-subgroups.yml
python3 scripts/validate-registered-imports.py registered-imports.json
python3 scripts/validate-priority-tiers.py config/workflow-priority-tiers.yml
python3 scripts/validate-cost-profiles.py config/workflow-cost-profiles.yml
# 3. Check for open PRs that would block the flush
gh pr list --state open --json number,title,mergeable
Ideal trigger time:
| 24h UTC | 12h UTC | ET (EDT) | ET (EST) |
|---|---|---|---|
| 14:05 | 2:05 PM | 10:05 AM | 9:05 AM |
5 minutes after the hourly reset — maximum quota headroom before any scheduled workflows consume from the fresh bucket.
Quota drain reduction history
| Date | Change | Saving |
|---|---|---|
| 2026-06 | Removed schedule from check-osp-ci + check-ooc-ci stubs | −600/day |
| 2026-06 | auto-merge-prs: 2h → 6h | −240/day |
| 2026-06 | upstream-prs + upstream-commits: 6h → daily | −480/day |
| 2026-06 | setup-osp-mirrors: 6h → daily | −240/day |
| 2026-06 | sync-to-gitlab + sync-from-gitlab stubs: removed schedule | −0 cost, freed runner slots |
| 2026-06 | sync-btrfs-devel + sync-registered-imports: 6h → daily | −105/day |
| 2026-06 | mirror-releases: 6h → 12h | −100/day |
| 2026-06 | sync-to-gitlab-variant + sync-pieroproietti + mirror-osp-to-gitlab + mirror-artifacts: 8h → daily | −480/day |
| 2026-06 | reconcile-org-refs + rebase-prs + inject-badges + translate-readmes + translate-docs: daily → every 2 days | −300/day |
| Total | −2,545/day (−46% from 5,495 baseline) |
Current baseline: ~3,200 calls/day (~133/hr average).
Remaining quota reduction opportunities
These are known but not yet applied — each has a trade-off noted.
| Opportunity | Potential saving | Trade-off |
|---|---|---|
Convert sync-forks.sh REST repo loop → GraphQL prefetch | ~200/run | Code change required in script |
Convert reconcile-org-refs.sh REST loop → GraphQL | ~100/run | Code change required |
mirror-releases.yml: 12h → daily | ~50/day | Releases delayed up to 24h |
resolve-ci.yml: remove daily schedule, trigger-only | ~60/day | Failures only resolved when check-ci fires |
check-shell-tools-ci.yml: daily → every 2 days | ~25/day | Shell tools CI lag |
Add actions/cache@v5 to full-audit.yml (pyyaml) | runner time only | Trivial |
Add actions/cache@v5 to check-accessibility.yml (pa11y) | runner time only | Trivial |
sync-pieroproietti-gl-forks.sh: migrate to gh_get | reliability | Raw curl has no retry |
Speed improvement opportunities
Scripts
| Script | Issue | Fix |
|---|---|---|
sync-forks.sh | Sequential REST calls per repo | GraphQL prefetch for repo list + existence |
reconcile-org-refs.sh | Paginated REST for org repos | GraphQL batch query |
update-readmes.sh | Per-repo /contents/README.md calls | Tree fetch with ?recursive=1 then filter |
resolve-failures.sh | Sequential per-repo run scan | Parallel with xargs -P 4 for log fetches |
sync-pieroproietti-gl-forks.sh | Raw curl without retry | Source includes/gh-api.sh, use gh_get |
Workflows
| Workflow | Issue | Fix |
|---|---|---|
full-audit.yml | pip install pyyaml on every run | Add actions/cache@v5 |
check-accessibility.yml | npm install -g pa11y on every run | Add actions/cache@v5 |
validate-config.yml | ✅ Already cached (pytest, yamllint, gavi) | — |
critical-deploy*.yml | fetch-depth: 0 (full history) | Only needed for git log — use fetch-depth: 1 + git fetch --unshallow only when needed |
sync-shell-tools.yml | fetch-depth: 0 | Same as above |
manage-subtrees.yml | fetch-depth: 0 | Required for subtree — keep |
sync-uaa-vendor.yml | fetch-depth: 0 | Required for vendor merge — keep |
Runner minutes
Public repos on GitHub get unlimited free runner minutes. If this repo is public, runner minutes are not a constraint. If private:
- Current worst-case estimate: ~8,000 min/month (well over 2,000 free tier)
- Self-hosted runner eliminates the cap entirely
- Alternatively: reduce
timeout-minuteson workflows that consistently finish in < 5 min but have 30 min timeouts — this doesn't save minutes (billing is actual runtime, not timeout) but prevents runaway jobs
Workflows with oversized timeouts relative to typical runtime:
| Workflow | timeout-minutes | Typical runtime | Suggested |
|---|---|---|---|
| Queue Manager | 10 | < 1 min | 5 |
| Quota Reserve | 10 | < 1 min | 5 |
| Auto-merge PRs | 15 | 1–3 min | 8 |
| Rebase PRs | 20 | 2–5 min | 10 |
| Reconcile Org Refs | 30 | 5–10 min | 15 |
Quota Cost Registry
GitHub's REST API allows 5,000 requests per hour per user (shared across all tokens belonging to the same user). This page documents how many REST calls each workflow consumes per run, the minimum quota required before a workflow should start, and how the quota management system uses this data.
GraphQL counts as 1 call regardless of how many repos are queried. raw.githubusercontent.com fetches are exempt entirely.
How quota is managed
Three mechanisms work together:
| Mechanism | Where | What it does |
|---|---|---|
quota-reserve.sh | Runs every 30 min | Cancels queued low-priority runs when remaining < RESERVE_FLOOR (default: 1000). Uses min_quota per workflow to also cancel runs that couldn't succeed with current quota even if they started. |
budget_check() | Inside each script loop | Stops processing mid-run when time budget is exhausted. Prevents a single run from consuming all quota in one shot. |
workflow_min_quota() | Pre-flight steps | Returns the min_quota for a workflow from config/workflow-quota-costs.yml. Workflows can use this to skip themselves when quota is too low. |
The single source of truth for costs is config/workflow-quota-costs.yml.
Cost table
Costs are estimated from code audit (Phase 1). Phase 2 will replace these with observed p50/p95 values from actual run measurements.
min_quota = minimum REST calls required before this workflow should be allowed to start.
Tier 1 — Critical (never cancelled)
| Workflow | min_quota | Low | Mid | High | Notes |
|---|---|---|---|---|---|
| Rotate Secret Token | 50 | 5 | 10 | 20 | Token validation + secret update |
| Queue Manager | 50 | 5 | 15 | 30 | Queued run list + cancel calls |
| Quota Reserve | 10 | 1 | 5 | 15 | rate_limit check (exempt) + cancels |
| Rate-Limit Re-trigger | 50 | 5 | 20 | 50 | Failed run scan + dispatch calls |
| Token Health Monitor | 50 | 5 | 10 | 20 | Token validation only |
| CI | 50 | 2 | 5 | 10 | ShellCheck + lint, minimal API |
| Pre-Flush Prep | 100 | 10 | 30 | 60 | PR list + check-run queries |
Tier 2 — High
| Workflow | min_quota | Low | Mid | High | Notes |
|---|---|---|---|---|---|
| Mirror Interested-Deving-1896 → OSP | 500 | 20 | 80 | 200 | 2 GraphQL + 1 REST/repo (check-runs, gated) |
| Mirror OSP → GitLab | 300 | 5 | 20 | 50 | 1 GraphQL for repo list; GitLab calls exempt |
| Sync Registered Imports | 200 | 5 | 15 | 30 | 1 GraphQL prefetch; REST only for new repos |
| Sync All Forks | 500 | 50 | 200 | 500 | 1 GraphQL + 1 REST merge-upstream per fork |
| Full Chain Flush | 1000 | 100 | 400 | 1000 | Orchestrates chain — cost is additive |
| Add Mirror Repo | 200 | 10 | 30 | 60 | Repo creation + webhook + dispatch |
Tier 3 — Medium
| Workflow | min_quota | Low | Mid | High | Notes |
|---|---|---|---|---|---|
| Update READMEs | 300 | 50 | 150 | 300 | Tree fetch + file reads/writes per repo |
| Create Missing READMEs | 200 | 20 | 80 | 200 | Same as Update READMEs, subset of repos |
| Inject Built-with-Ona Badges | 200 | 5 | 30 | 80 | 1 GraphQL (repo list + README); REST only on write |
| Reconcile Org References | 300 | 10 | 60 | 150 | 1 GraphQL repo list; pushedAt from cache |
| Check OSP-Bound CI Status | 300 | 50 | 150 | 300 | 4 REST/repo (check-runs not in GraphQL) |
| Rebase PRs | 100 | 5 | 20 | 50 | PR list + rebase trigger |
| Sync btrfs-devel Branches | 100 | 5 | 20 | 50 | Branch sync per tracked branch |
| Sync pieroproietti Forks | 100 | 10 | 40 | 100 | merge-upstream per fork branch |
| Setup OSP Mirror Workflows | 200 | 20 | 80 | 200 | 1 GraphQL + workflow/secrets per repo (not in GraphQL) |
| Upstream PRs from OSP + OOC | 200 | 20 | 80 | 200 | PR creation/update per diverged repo |
| Upstream Direct Commits from OSP + OOC | 200 | 20 | 80 | 200 | Commit compare + PR creation |
| Sync to GitLab | 100 | 5 | 20 | 50 | GitHub reads; GitLab writes exempt |
| Sync to GitLab Variant | 100 | 5 | 20 | 50 | Same as Sync to GitLab |
| Sync from GitLab | 100 | 5 | 20 | 50 | GitLab reads + GitHub writes |
| Notification Poller | 50 | 1 | 5 | 15 | Single notifications call + optional dispatch |
Tier 4 — Low (cancelled first)
| Workflow | min_quota | Low | Mid | High | Notes |
|---|---|---|---|---|---|
| Translate READMEs | 100 | 10 | 40 | 100 | File read + write per README |
| LTS README Standardisation | 100 | 10 | 40 | 100 | File read + write per LTS repo |
| Generate OSP Dependency Graph | 100 | 20 | 60 | 150 | README + package.json reads per repo |
| Upstream Workflow Proposal | 50 | 5 | 20 | 50 | Workflow file reads + PR creation |
| Update Infrastructure Dependencies | 50 | 5 | 15 | 30 | Dependabot config + PR creation |
| Mirror Artifacts | 200 | 10 | 50 | 150 | 2 GraphQL; release asset downloads exempt |
| Mirror Releases | 200 | 10 | 50 | 150 | 2 GraphQL + 1 REST releases list per repo |
| Cleanup Stale Branches | 200 | 10 | 60 | 200 | 1 GraphQL + 1 REST compare per branch |
| OTA Discover | 100 | 10 | 40 | 100 | Fork list + config reads per fork |
| OTA Self-Update | 50 | 5 | 15 | 30 | Config read + PR creation |
| Mirror Orgs | 100 | 20 | 60 | 150 | Repo list + description reads per org |
| Resolve CI Failures | 100 | 10 | 40 | 100 | Failed run list + job details + file writes |
Daily quota budget
At 5,000 calls/hour reset, the effective daily budget depends on how many resets are consumed cleanly vs. drained by backlog. With the schedule reductions applied (June 2026), the expected daily workflow run count dropped by ~172 runs/day.
| Category | Before | After |
|---|---|---|
quota-reserve runs/day | 144 | 48 |
queue-manager runs/day | 96 | 48 |
notify-poller runs/day | 12 | 6 |
rate-limit-rerun runs/day | 12 | 6 |
mirror-artifacts runs/day | 6 | 3 |
mirror-osp-to-gitlab runs/day | 6 | 3 |
sync-pieroproietti-forks runs/day | 6 | 3 |
sync-to-gitlab-variant runs/day | 6 | 3 |
REST → GraphQL conversion log
Scripts converted from per-repo REST loops to batched GraphQL calls:
| Script | Savings/run | Runs/day | Saved/day |
|---|---|---|---|
sync-registered-imports.sh | ~100 | 4 | ~400 |
mirror-osp-to-gitlab.sh | ~2 | 3 | ~6 |
reconcile-org-refs.sh | ~100 | 6 | ~600 |
inject-badges.sh | ~50 | 3 | ~150 |
cleanup-branches.sh | ~200 | 1 | ~200 |
mirror-releases.sh | ~50 | 4 | ~200 |
mirror-artifacts.sh | ~50 | 3 | ~150 |
ota-discover.sh | ~50 | 1 | ~50 |
mirror-orgs.sh | ~60 | 1 | ~60 |
setup-osp-mirrors.sh | ~100 | 4 | ~400 |
| Total | ~2,216/day |
Phase 2: observed cost tracking (planned)
Phase 2 will add lightweight instrumentation to measure actual REST consumption per run:
scripts/includes/quota-instrument.sh— recordsremaining_beforeandremaining_afteras workflow step summary annotationsupdate-quota-costs.yml— weekly workflow that reads the last 30 run summaries via GraphQL, computes p50/p95 per workflow, and commits updated values back toconfig/workflow-quota-costs.ymlwithbasis: observed
Once Phase 2 is active, the tables above will show observed values alongside the code-audit estimates, and quota-reserve.sh will automatically use the more accurate figures.
Operational Reference: GitHub Actions Limits & Quotas
This document covers the GitHub Actions limits that affect fork-sync-all, what consumes them, how to detect exhaustion, and how to recover.
GitHub API Rate Limit
Quota: 5,000 requests/hour per authenticated user token.
Resets: Top of every hour (rolling window).
What consumes it:
| Operation | Cost |
|---|---|
gh api / REST API call | 1 req |
| Listing workflow runs | 1 req per page |
| Cancelling a run | 1 req |
| Triggering a workflow dispatch | 1 req |
| Checking job status | 1 req per job |
| GraphQL query | Separate quota (5,000 points/hr) — unaffected by REST exhaustion |
How fork-sync-all burns it:
- Every
workflow_runtrigger fires a new run, which itself may call the API rate-limit-rerun.yml(formerly hourly) scans all recent failed runsstuck-run-detector.yml(formerly hourly) lists all queued/in-progress runstranslate-readmes.ymlwas triggering after 10 workflows — each trigger consumed dozens of API calls for the org scan- Bulk-cancelling queued runs during cleanup consumes ~1 req per cancel — if the queue is large and quota is already low, the cancel loop itself can exhaust the remaining quota
Detecting exhaustion:
gh api rate_limit --jq '.resources.core | "remaining: \(.remaining)/\(.limit) resets: \(.reset | todate)"'
Recovery: Wait until the top of the next hour. GraphQL remains available during REST exhaustion and can be used for read-only queries.
GitHub Actions Runner Minutes
Free tier: 2,000 minutes/month. Resets on your billing cycle date (the day of the month your GitHub account was created — check Settings → Billing → Actions for the exact date).
Paid: Billed per minute beyond the free tier; Linux runners cost 1×,
Windows 2×, macOS 10×. All workflows in this repo use ubuntu-latest (Linux, 1×).
What counts against the monthly quota:
- Every job that runs on
ubuntu-latest(GitHub-hosted runner) - Time is measured from job start to job end, rounded up to the nearest minute
- Jobs that are queued but never start do not consume minutes
- Jobs that exit immediately (e.g.
if:condition is false at the job level) still consume ~1 minute for runner provisioning
What does NOT count:
workflow_dispatchtriggers that are never clicked- Runs that are cancelled before a job starts
- Skipped jobs (
if:evaluated to false before the runner is assigned) - Self-hosted runners (zero cost regardless of usage)
How fork-sync-all was burning minutes (before May 2026 fixes):
mirror-orgs-watchdogfired after every mirror completion (5 workflows × hourly cadence = ~120 runs/day), each consuming ~1 min even on successupdate-readmestriggered after 7 workflows including high-frequency syncsinject-badgestriggered after mirror workflows that run hourlystuck-run-detectorandrate-limit-rerunran hourly as meta-workflows, each consuming minutes to manage other workflowsworkflow_runlisteners fired on everycompletedevent (success, failure, cancelled) — not just on the outcomes they actually needed
Detecting exhaustion:
Symptoms (in order of appearance):
ubuntu-latestjobs queue but never start- No in-progress runs despite many queued
- Runs queued for hours with 0 runners active
- Billing API returns 404 (needs
userOAuth scope — check web UI instead)
Check via GitHub web UI: Settings → Billing → Actions.
Recovery: Wait until the billing cycle reset date. In the meantime:
- Cancel all queued runs (they will never start)
- Do not push commits that trigger new workflow runs
- Use
workflow_dispatchmanually only for critical operations
Concurrency Groups & Stuck Runs
How they work: A concurrency group allows only one run at a time for a
given key. If cancel-in-progress: false, a second run queues behind the
first. If the first run never finishes (e.g. runner minutes exhausted mid-job),
the queued run is permanently stuck.
The cascade pattern:
- Runner minutes exhaust mid-job → job hangs in
in_progress - Next scheduled run queues behind it (
cancel-in-progress: false) - The in-progress run never finishes → queue grows indefinitely
- API calls to cancel are themselves rate-limited → nothing can be cleared
Orphaned runs: A run can become permanently orphaned if it was triggered
from an older version of a workflow file that contained a job (e.g.
Update cost profile) that no longer exists in the current file. The run
accepts cancel API calls but GitHub immediately re-queues it because the
concurrency group from the old code is still technically active. These runs
time out automatically after GitHub's maximum queue wait (~6 hours). New
runs from the same workflow are not blocked — they use the current file.
Policy in this repo (May 2026): All workflows use cancel-in-progress: true
except those that perform multi-repo writes where mid-run cancellation would
leave state partially applied:
| Workflow | cancel-in-progress | Reason |
|---|---|---|
sync-template | false | Propagates files to 35 repos — partial sync leaves repos inconsistent |
mirror-releases | false | Partial mirror leaves releases incomplete |
lts-readmes | false | Mid-run cancel leaves some repos un-standardised |
mirror-osp-to-gitlab | false | Partial GitLab mirror |
create-readmes | false | Mid-run cancel leaves some repos without READMEs |
mirror-artifacts | false | Partial artifact mirror |
| All others | true | Newer run supersedes safely |
Detecting stuck runs:
gh api "repos/Interested-Deving-1896/fork-sync-all/actions/runs?per_page=100" \
--jq '[.workflow_runs[] | select(.status == "queued")] | length'
Bulk cancel (check quota first — cancel loop consumes ~1 req per run):
gh api rate_limit --jq '.resources.core.remaining'
gh api "repos/Interested-Deving-1896/fork-sync-all/actions/runs?per_page=100" \
--jq '[.workflow_runs[] | select(.status=="queued") | .id] | .[]' | \
xargs -I{} gh api -X POST \
"repos/Interested-Deving-1896/fork-sync-all/actions/runs/{}/cancel"
workflow_run Trigger Cost Model
workflow_run fires on every completed event regardless of conclusion
(success, failure, cancelled, skipped). A listener that only needs to act
on failures still consumes a runner minute for every successful upstream run
unless gated at the job level.
Pattern used in this repo:
# For workflows that act on upstream SUCCESS (content processors):
jobs:
my-job:
if: |
github.event_name != 'workflow_run' ||
github.event.workflow_run.conclusion == 'success'
# For workflows that act on upstream FAILURE (watchdogs/retriers):
jobs:
retry:
if: |
github.event_name == 'workflow_dispatch' ||
github.event.workflow_run.conclusion == 'failure'
This exits immediately (no runner cost) when the conclusion doesn't match, while keeping the trigger automatic.
All workflow_run listeners and their gates (May 2026):
| Workflow | Gate |
|---|---|
mirror-orgs-watchdog | conclusion == 'failure' |
create-readmes | conclusion == 'success' |
inject-badges | conclusion == 'success' |
lts-readmes | conclusion == 'success' |
mirror-osp-to-gitlab | conclusion == 'success' |
translate-readmes | conclusion == 'success' (on gate job) |
update-readmes | conclusion == 'success' |
dwarfs-pack-caller | conclusion == 'success' |
rebase-lts | conclusion == 'success' |
Current Workflow Schedule Summary
Schedules as of June 2026. All times UTC (24h) / UTC (12h) / ET (EDT, UTC−4).
See DOCS/workflow-scheduling.md for full per-workflow quota and window details.
| Workflow | 24h UTC | 12h UTC | ET (EDT) | Cadence | Notes |
|---|---|---|---|---|---|
mirror-to-osp | :13 | :13 AM/PM | −4h | Every 6h | Core mirror chain start |
mirror-osp-to-ooc | :45 | :45 AM/PM | −4h | Every 6h | 32 min after mirror-to-osp |
sync-in | :37 | :37 AM/PM | −4h | Every 6h + daily 10:15 | Health check + workspace sync |
auto-merge-prs | :55 | :55 AM/PM | −4h | Every 6h | |
queue-manager | :00/:30 | :00/:30 AM/PM | −4h | Every 30 min | Infrastructure |
quota-reserve | :00/:30 | :00/:30 AM/PM | −4h | Every 30 min | Infrastructure |
mirror-releases | 00:03 + 12:03 | 12:03 AM + 12:03 PM | 8:03 PM + 8:03 AM | Every 12h | |
sync-pieroproietti-forks | 01:07 | 1:07 AM | 9:07 PM | Daily | Reduced from 8h |
mirror-osp-to-gitlab | 01:23 | 1:23 AM | 9:23 PM | Daily | Reduced from 8h |
sync-to-gitlab-variant | 01:50 | 1:50 AM | 9:50 PM | Daily | Reduced from 8h |
mirror-artifacts | 02:10 | 2:10 AM | 10:10 PM | Daily | Reduced from 8h |
mirror-orgs-full | 02:17 | 2:17 AM | 10:17 PM | Daily | |
setup-osp-mirrors | 02:45 | 2:45 AM | 10:45 PM | Daily | Reduced from 6h |
upstream-prs | 03:33 | 3:33 AM | 11:33 PM | Daily | Reduced from 6h |
upstream-commits | 03:47 | 3:47 AM | 11:47 PM | Daily | Reduced from 6h |
git-platform-sync | 04:27 + 09:23 | 4:27 AM + 9:23 AM | 12:27 AM + 5:23 AM | Daily ×2 | Pull + push |
sync-registered-imports | 04:55 | 4:55 AM | 12:55 AM | Daily | Reduced from 6h |
sync-btrfs-devel-branches | 05:02 | 5:02 AM | 1:02 AM | Daily | Reduced from 6h |
rebase-prs | 05:10 | 5:10 AM | 1:10 AM | Every 2 days | Reduced from daily |
flush-lifecycle | Sun 06:00 | 6:00 AM Sun | 2:00 AM Sun | Weekly + manual | Top-level pipeline entry point |
full-chain-flush | 05:17 | 5:17 AM | 1:17 AM | Monthly (1st) + via flush-lifecycle | Triggered by flush-lifecycle or pre-flush-prep |
reconcile-org-refs | 05:50 | 5:50 AM | 1:50 AM | Every 2 days | Reduced from daily |
resolve-ci | 07:43 | 7:43 AM | 3:43 AM | Daily | |
check-ci | 09:05 | 9:05 AM | 5:05 AM | Daily | 1,500 quota floor |
check-shell-tools-ci | 09:30 | 9:30 AM | 5:30 AM | Daily | |
inject-badges | 08:15 | 8:15 AM | 4:15 AM | Every 2 days | Reduced from daily |
translate-readmes | 10:43 | 10:43 AM | 6:43 AM | Every 2 days | Reduced from daily |
translate-docs | 11:15 | 11:15 AM | 7:15 AM | Every 2 days | Reduced from daily |
refresh-notebooklm-auth | 06:17 Tue | 6:17 AM Tue | 2:17 AM Tue | Weekly | |
update-infra-deps | 06:11 Mon | 6:11 AM Mon | 2:11 AM Mon | Weekly |
Estimated daily drain: ~3,200 REST calls/day (~133/hr average). Worst hourly burst: ~612 calls at 03:xx UTC / 3 AM UTC / 11 PM ET. Headroom at worst hour: ~4,388 calls (well within 5,000/hr limit).
For optimal manual dispatch windows, see DOCS/workflow-scheduling.md.
Self-Hosted Runner Setup (Recommended)
To eliminate the monthly minute cap entirely, add a self-hosted runner:
- Go to Settings → Actions → Runners → New self-hosted runner
- Follow the setup instructions for your host OS
- Change workflow
runs-onfromubuntu-latesttoself-hosted(or add a label and use that label)
Self-hosted runners have no minute cost and no concurrent job cap beyond what the host machine can handle.
Quick Reference: Limit Reset Times
| Limit | Resets |
|---|---|
| GitHub API rate limit (REST) | Top of every hour |
| GitHub API rate limit (GraphQL) | Top of every hour (separate quota) |
| GitHub Actions minutes | Billing cycle date (check Settings → Billing) |
| GitHub Actions concurrent jobs (free) | N/A — blocked by minute exhaustion |
AI Agent Cost Reference
Budgeting guide for AI agent usage on fork-sync-all. Covers all agents used in this repo: Ona Agent (Claude), Codex, GitHub Models (GPT-4o/mini), and direct Anthropic API. Includes token economics, per-task cost estimates, and package selection guidance.
Ona Compute Units (OCUs)
An OCU is Ona's billing unit. It covers both environment runtime and AI model inference. OCUs are not raw tokens — Ona bundles compute + model calls into a single unit.
Top-up packages (one-time, valid 1 year with active subscription)
| Package | OCUs | USD | USD/OCU |
|---|---|---|---|
| Starter | 40 | $10 | $0.25 |
| Small | 100 | $25 | $0.25 |
| Medium | 200 | $50 | $0.25 |
| Large | 400 | $100 | $0.25 |
| XL | 1,000 | $250 | $0.25 |
| 2XL | 2,000 | $500 | $0.25 |
| 3XL | 4,000 | $1,000 | $0.25 |
| 4XL | 8,000 | $2,000 | $0.25 |
All tiers are a flat $0.25/OCU — no bulk discount on top-ups.
Core subscription (monthly, resets each period, does not roll over)
| Monthly OCUs | Notes |
|---|---|
| 80–2,200 | See ona.com/pricing for current tier options |
Consumption order: subscription credits → top-up credits → bonus/gift credits.
Environment runtime
| Class | vCPUs / RAM | OCU rate |
|---|---|---|
| Standard | 4 vCPUs / 16 GB | 1 OCU/hour |
| GPU-accelerated | 16 vCPUs / 64 GB | 7 OCUs/hour |
fork-sync-all agent sessions run on Standard environments. A 2-hour session costs 2 OCUs in runtime before any model inference.
Agents used in this repo
| Agent | Where used | Billing model | Context window |
|---|---|---|---|
| Ona Agent (Claude 4 Sonnet) | Interactive sessions, PRs, automations | OCUs (env + model) | 200K tokens |
| Codex (via Ona, Core plan) | Ona Cloud environments | OCUs (env only if ChatGPT plan connected) | 128K tokens |
| GitHub Models — GPT-4o | llm.sh, update-readmes.sh, translate-docs.sh | GitHub Models quota (not OCUs) | 128K tokens |
| GitHub Models — GPT-4o-mini | resolve-failures.sh, generate-descriptions.sh | GitHub Models quota (not OCUs) | 128K tokens |
| Anthropic API (direct) | Optional via ANTHROPIC_API_KEY | Pay-per-token (Anthropic billing, not OCUs) | 200K tokens |
Billing independence
Ona Agent and Codex (Ona-managed) are billed in OCUs.
Codex with a connected ChatGPT plan: environment runtime is billed in OCUs; model inference is billed by OpenAI against your ChatGPT plan. Ona does not charge OCUs for those model calls.
GitHub Models (llm.sh): uses a separate GitHub Models quota tied to your
GH_TOKEN. Does not consume OCUs. Rate limits apply per model tier.
Anthropic API (direct): billed per-token by Anthropic. Does not consume OCUs.
Tokenizer reference
Token counts determine context window usage and, for pay-per-token models, direct API costs.
Claude (Ona Agent / Anthropic API direct)
Anthropic uses a custom BPE tokenizer:
| Content type | Approx. tokens |
|---|---|
| English prose | 1 token / 4 chars (~750 words per 1K tokens) |
| Code (Python / JS / bash) | 1 token / 3–4 chars |
| YAML / JSON | 1 token / 3 chars |
| Shell scripts | 1 token / 3 chars |
| Markdown with headers | 1 token / 4 chars |
Context window: 200K input / 8K output (Claude 4 Sonnet).
A full fork-sync-all session reading 10 workflow files (~500 lines each) uses roughly 50K–80K input tokens in context before any tool calls.
GPT-4o / GPT-4o-mini (GitHub Models / Codex)
OpenAI uses the cl100k_base tiktoken tokenizer. Rates are nearly identical to
Claude for English and code. Context window: 128K tokens.
Count tokens locally:
pip install tiktoken
python3 -c "
import tiktoken, sys
enc = tiktoken.get_encoding('cl100k_base')
print(len(enc.encode(open(sys.argv[1]).read())), 'tokens')
" path/to/file.yml
Gemini (direct API, if used)
Google SentencePiece tokenizer. Similar rates to GPT-4o for English; slightly fewer tokens for CJK. Context window: 1M tokens (Gemini 1.5 Pro).
Token → OCU conversion (approximate)
Ona does not publish an exact token-to-OCU ratio. Based on Ona's published benchmarks and typical Claude 4 Sonnet pricing:
| Ona benchmark | OCUs | Approx. tokens consumed |
|---|---|---|
| Explain a small codebase | 1 | ~20K–50K |
| Explain a large codebase | 3 | ~80K–150K |
| Create a new web app | 4 | ~100K–200K |
| Add a feature to medium codebase | 8 | ~200K–400K |
Rough conversion: 1 OCU ≈ 25K–50K tokens (input + output combined). Actual OCU consumption depends on environment runtime, tool call overhead, and Ona's internal pricing model.
Anthropic API direct pricing (as of 2026)
If using the Anthropic API directly (not via Ona):
| Model | Input (per 1M tokens) | Output (per 1M tokens) |
|---|---|---|
| Claude 4 Sonnet | $3.00 | $15.00 |
| Claude 3.5 Haiku | $0.80 | $4.00 |
| Claude 3 Opus | $15.00 | $75.00 |
A typical fork-sync-all session (100K input + 10K output tokens) costs roughly $0.45–$0.60 via direct API — cheaper than OCUs for pure model cost, but without the environment, tooling, and orchestration Ona provides.
fork-sync-all task cost estimates
All figures assume Standard environment (1 OCU/hour) + Ona Agent (Claude).
For GitHub Models tasks (llm.sh), OCU cost is environment runtime only.
By task complexity
| Task | Env time | OCUs (env) | OCUs (model) | Total OCUs | USD equiv. |
|---|---|---|---|---|---|
| Quick question / explain one workflow | 15 min | 0.25 | 0.5–1 | 1–1.5 | $0.25–$0.38 |
| Fix a single bug or validator error | 20 min | 0.33 | 1–2 | 1.5–2.5 | $0.38–$0.63 |
| Add a new script or include | 30 min | 0.5 | 2–4 | 2.5–4.5 | $0.63–$1.13 |
| Add a new workflow (single file) | 45 min | 0.75 | 3–5 | 4–6 | $1.00–$1.50 |
| Multi-file feature (e.g. flush watchdog) | 90 min | 1.5 | 6–10 | 8–12 | $2.00–$3.00 |
| Large feature + tests + docs + PR | 2–3 hr | 2–3 | 8–15 | 10–18 | $2.50–$4.50 |
| Full session (e.g. platform hardening) | 3–4 hr | 3–4 | 12–20 | 15–24 | $3.75–$6.00 |
| End-to-end repo update (all outstanding) | 4–6 hr | 4–6 | 15–25 | 19–31 | $4.75–$7.75 |
By specific fork-sync-all operation
| Operation | Agent | Typical OCUs | Notes |
|---|---|---|---|
| Merge open PRs + check CI | Ona | 1–2 | Mostly read + gh CLI |
| Add a registered import entry | Ona | 0.5–1 | Edit JSON + validate |
| Update AGENTS.md | Ona | 1–2 | Read context + write |
| Fix a failing CI check | Ona | 2–5 | Depends on root cause |
| Add a new workflow to mirror chain | Ona | 4–8 | New file + config + tests |
| Full flush lifecycle implementation | Ona | 10–15 | Multi-file, tests, docs, PR |
| Platform hardening (7 tasks) | Ona | 15–20 | Research + 16 files + 271 tests |
| Onboard a new downstream org | Ona | 6–12 | Config + workflows + validation |
| Translate READMEs (all languages) | GitHub Models GPT-4o | 0.5–1 | OCU = env runtime only; model via GH quota |
| Generate repo descriptions | GitHub Models GPT-4o-mini | 0.25–0.5 | OCU = env runtime only |
| Resolve CI failures (LLM-assisted) | GitHub Models GPT-4o-mini | 0.25–0.5 | OCU = env runtime only |
GitHub Models quota (separate from OCUs)
llm.sh and the scripts that use it consume GitHub Models quota, not OCUs.
| Model | Tier | Daily limit (approx.) |
|---|---|---|
openai/gpt-4o | Standard | ~150K tokens/day |
openai/gpt-4o-mini | High | ~1M tokens/day |
Limits are subject to change — check github.com/marketplace/models.
llm.sh handles 429 responses with exponential backoff automatically.
Budgeting by role
Occasional contributor (1–2 sessions/month)
40 OCU ($10) top-up covers:
- ~5–8 small bug fixes or single-workflow additions
- ~2–3 medium features
- ~1 large feature session
Regular contributor (weekly sessions)
100 OCU ($25) top-up or Core subscription with 200+ OCUs/month:
- ~10–15 medium tasks/month
- ~4–6 large feature sessions/month
- Comfortable headroom for exploratory sessions
Maintainer (daily work, full repo updates)
400 OCU ($100) top-up or Core subscription with 400+ OCUs/month:
- Weekly full sessions (~20 OCUs each → ~80 OCUs/month)
- Buffer for unexpected complexity
- Recommended for anyone running
critical-deploy-allor full flush pipelines alongside agent sessions
Auto top-up
Enable auto top-up at Settings → Billing with a 40 OCU trigger threshold. A session interrupted mid-task and restarted from scratch costs more than the top-up itself — context has to be rebuilt from zero.
Cost tracking
This repo includes a workflow and structured log for tracking actual agent costs over time. As observed data accumulates, it replaces the code-audit estimates above.
Log a session
After any significant agent session, run:
# Ona Agent session
gh workflow run track-agent-costs.yml \
--field task_description="Add flush-active-watchdog + pipeline-guard" \
--field agent="ona" \
--field session_hours="3.5" \
--field ocu_estimate="18" \
--field pr_number="166"
# GitHub Models session (no OCU model cost)
gh workflow run track-agent-costs.yml \
--field task_description="Translate READMEs to 5 languages" \
--field agent="github-models-gpt4o" \
--field session_hours="0.5" \
--field ocu_estimate="0.5" \
--field gh_models_tokens="45000"
# Codex with ChatGPT plan (env OCUs only)
gh workflow run track-agent-costs.yml \
--field task_description="Refactor sync-all-forks.sh" \
--field agent="codex-chatgpt" \
--field session_hours="1.0" \
--field ocu_estimate="1.0"
# Direct Anthropic API (no OCUs)
gh workflow run track-agent-costs.yml \
--field task_description="Code review via direct API" \
--field agent="anthropic-direct" \
--field session_hours="0.25" \
--field ocu_estimate="0" \
--field anthropic_input_tokens="32000" \
--field anthropic_output_tokens="2000"
View the log
cat data/agent-cost-log.json | python3 -m json.tool
# Summary by agent
python3 -c "
import json
from collections import defaultdict
log = json.load(open('data/agent-cost-log.json'))
totals = defaultdict(lambda: {'sessions': 0, 'ocu': 0.0, 'hours': 0.0})
for e in log['sessions']:
a = e['agent']
totals[a]['sessions'] += 1
totals[a]['ocu'] += e.get('ocu_estimate', 0)
totals[a]['hours'] += e.get('session_hours', 0)
for agent, t in sorted(totals.items()):
print(f'{agent}: {t[\"sessions\"]} sessions, {t[\"ocu\"]:.1f} OCUs, {t[\"hours\"]:.1f} hrs')
"
Machine-readable profiles
config/agent-cost-profiles.yml contains the cost profiles used by the tracking
workflow for validation and per-agent reporting. Update it as observed data
replaces estimates.
GitHub API quota vs OCU budget
These are independent resources:
| Resource | Unit | Limit | Managed by |
|---|---|---|---|
| GitHub REST API | requests | 5,000/hr per user | quota-reserve.sh, queue-manager.sh |
| GitHub Models | tokens | varies by model | llm.sh (backoff on 429) |
| Ona OCUs | compute units | subscription + top-ups | Ona billing |
| Anthropic API | tokens | pay-per-token | Anthropic billing |
GitHub API exhaustion pauses the agent session but does not consume OCUs. OCU exhaustion stops the session regardless of GitHub quota state.
See DOCS/OPERATIONS.md and DOCS/quota-costs.md for GitHub API quota management.
Keeping this document current
- OCU pricing: verify at
app.gitpod.io/settings/billing. The $0.25/OCU top-up rate has been stable since launch but may change. - Model: Ona Agent currently uses Claude 4 Sonnet. If the underlying model changes, update the tokenizer section.
- Anthropic pricing: verify at
anthropic.com/pricing. Prices change with new model releases. - Task estimates: once ≥10 sessions are logged in
data/agent-cost-log.json, replace the code-audit estimates in the tables above with observed p50/p95 values. - GitHub Models limits: check
github.com/marketplace/models— daily quotas change as the service matures.
OTA Update System
The OTA (over-the-air) system delivers workflow and script updates from
fork-sync-all to forks that have opted in. It is the mechanism by which
downstream forks stay current without manual merges.
Concepts
Upstream — Interested-Deving-1896/fork-sync-all. The source of truth for
all OTA payloads.
Fork — any GitHub repo that has forked fork-sync-all and opted in to OTA.
Payload — a diff of files that changed between the fork's pinned_sha and
the latest upstream release tag. Only files the fork hasn't locally modified are
included.
Registry — config/ota-registry.yml. The list of all opted-in repos.
Blocklist — config/ota-blocklist.yml. Orgs and namespaces excluded from
OTA by default (the three mirror-chain orgs and the GitLab namespace).
Lifecycle
Fork owner runs ota-opt-in
│
▼
.ota/config.yml created in fork
Registration PR opened against fork-sync-all
│
▼
PR merged → repo added to config/ota-registry.yml
│
▼
ota-discover.yml (daily) also finds new opt-ins automatically
│
▼
Semver tag pushed to fork-sync-all (v*.*.*)
│
▼
ota-release.yml assembles payload per opted-in repo
Opens PR in each fork with the diff
│
▼
Fork owner merges PR
ota-self-update.yml (runs in fork on schedule) updates pinned_sha
Workflows
ota-opt-in.yml — fork owner runs this once
Propagated to forks via the standalone template profile. The fork owner
triggers it via workflow_dispatch. It:
- Creates
.ota/config.ymlin the fork with sensible defaults - Opens a registration PR against
fork-sync-all/config/ota-registry.yml
Inputs:
| Input | Description | Default |
|---|---|---|
upstream_override | Override the upstream source (for fork-of-fork cases) | (auto-detected) |
mirror_chain_opt_in | Set true if the fork is in the mirror chain | false |
ota-discover.yml — runs daily in fork-sync-all
Scans GitHub for forks of fork-sync-all that contain .ota/config.yml with
enabled: true. For any not already in config/ota-registry.yml, opens a PR
to add them.
This is the passive discovery path — fork owners don't need to run ota-opt-in
if they create .ota/config.yml manually.
Inputs:
| Input | Description | Default |
|---|---|---|
dry_run | Report new opt-ins without updating registry or opening PR | false |
ota-release.yml — triggered on semver tag push
Triggered when a tag matching v*.*.* is pushed to fork-sync-all. It:
- Iterates all repos in
config/ota-registry.yml(skippingdisabled: true) - For each repo, calls
ota-payload-build.shto assemble the diff - Opens a PR in the fork with the payload
- Updates
CHANGELOG.mdinfork-sync-all
Repos in the blocklist orgs are skipped unless mirror_chain_opt_in: true is
set in their .ota/config.yml.
ota-self-update.yml — runs in the fork on a schedule
Propagated to forks via the standalone template profile. Runs on a schedule
in the fork. It:
- Checks the latest OTA release tag from
fork-sync-all - Compares against the fork's
pinned_shain.ota/config.yml - If behind, applies the payload and updates
pinned_shaandpinned_at
This is the self-healing path — if a fork owner doesn't merge the OTA PR,
ota-self-update will eventually apply the update automatically.
Payload assembly
scripts/ota-payload-build.sh assembles the payload for a single fork:
- Detects the fork's upstream parent via GitHub API (or uses
upstream_override) - Diffs the fork's current state at
pinned_shaagainst the latest upstream tag - Filters out:
- Files listed in the fork's
exclude_paths - Files the fork has locally modified (detected by comparing against upstream)
- Files owned by template profiles (from
config/template-manifest.yml) unless explicitly claimed viaworkflow_overrides.claim
- Files listed in the fork's
- Applies
workflow_overrides.disclaimto remove any files the fork wants to manage independently
The result is a minimal set of files that are safe to overwrite in the fork.
.ota/config.yml reference
Created in the fork by ota-opt-in.yml. All fields except enabled and repo
are optional.
enabled: true # master switch
repo: "owner/repo-name" # must match actual GitHub repo
host: "github" # "github" only currently
upstream_override: "" # override upstream detection (fork-of-fork)
pinned_sha: "" # managed by ota-self-update — do not edit
pinned_at: "" # managed by ota-self-update — do not edit
ota_version: "" # managed by ota-self-update — do not edit
mirror_chain_opt_in: false # set true only for mirror-chain repos
workflow_overrides:
claim: [] # workflows OTA should manage even if in manifest
disclaim: [] # workflows OTA should NOT touch
exclude_paths: [] # glob patterns OTA never writes
include_paths: [] # re-include after exclude_paths
Full field documentation: .ota/schema.yml in this repo.
Blocklist
config/ota-blocklist.yml defines two guards applied before any delivery:
Guard 1 — org/namespace blocklist:
The three mirror-chain GitHub orgs (Interested-Deving-1896,
OpenOS-Project-OSP, OpenOS-Project-Ecosystem-OOC) and the GitLab namespace
(openos-project) are excluded by default. A repo in these orgs can still
receive OTA by setting mirror_chain_opt_in: true.
Guard 2 — profile filter:
Only repos using the standalone template profile are eligible for OTA.
Repos on core, extended, or other profiles are managed by sync-template.yml
instead.
Adding a fork to the registry manually
If ota-opt-in is unavailable or the fork owner prefers manual registration:
- Create
.ota/config.ymlin the fork (copy from.ota/schema.yml, setenabled: trueandrepo) - Add an entry to
config/ota-registry.yml:
opted_in:
- repo: owner/fork-name
host: github
registered_at: "2026-06-07"
pinned_sha: ""
discovery: false
mirror_chain_opt_in: false
disabled: false
- Open a PR against
fork-sync-all—validate-config.ymlwill check the entry.
Disabling OTA for a repo
Set disabled: true in the registry entry. The repo stays registered but
receives no further deliveries until re-enabled. Alternatively, set
enabled: false in the fork's .ota/config.yml — ota-discover will
stop treating it as opted-in.
To remove permanently: delete the entry from config/ota-registry.yml.
Workflow Reference
All workflows in .github/workflows/, grouped by priority tier.
For trigger details and schedules see Workflow Triggers.
Auto-generated on 2026-07-03 from
config/workflow-quota-costs.ymlandconfig/workflow-priority-tiers.yml.
Quota cost columns: Low = fast/cached run · Mid = typical (p50) · High = large/uncached (p95)
Tier 1 — Critical
| Workflow | Synopsis | Schedule | min_quota | Low | Mid | High |
|---|---|---|---|---|---|---|
| Cancel Runs After Token Rotation | Cancels any queued or in-progress workflow runs immediately after token rotation to prevent runs using the old token. | Manual | 50 | 5 | 15 | 30 |
| Cancel Stale Runs | Cancels queued and in-progress workflow runs older than MAX_AGE_MINUTES (default 90) or created before a fix commit, preventing stale runs from burning quota. | Manual | 100 | 10 | 30 | 80 |
| Critical Deploy | Fast-lane workflow for deploying critical fixes when the system is degraded — commits and pushes changes, clears the queue aggressively, then dispatches priority workflows. | Manual | 50 | 5 | 30 | 100 |
| Critical Deploy — All | Fast-lane critical deploy across all four platforms (Interested-Deving-1896, OSP, OOC, GitLab) in sequence. Cost is approximately 4× the single-org variant. | 200 | 20 | 120 | 400 | |
| Critical Deploy — OOC | Fast-lane critical deploy scoped to OpenOS-Project-Ecosystem-OOC — same three-phase pattern as Critical Deploy but targets the OOC mirror org only. | Manual | 50 | 5 | 30 | 100 |
| Critical Deploy — OSP | Fast-lane critical deploy scoped to OpenOS-Project-OSP — same three-phase pattern as Critical Deploy but targets the OSP mirror org only. | Manual | 50 | 5 | 30 | 100 |
| Flush Active Watchdog | Clears FLUSH_ACTIVE=false whenever Flush Lifecycle Manager or any critical-deploy workflow completes. Prevents stuck-mutex after force-cancel. | Manual | 10 | 1 | 2 | 3 |
| Flush Lifecycle Manager | Coordinates the three-stage flush pipeline with quota reservation, runner slot holding via a parallel sentinel job, and pause/resume at quota reset windows. Sets FLUSH_ACTIVE=true so queue-manager and quota-reserve protect flush stages. | Weekly Sun 06:00 UTC | 1500 | 15 | 40 | 80 |
| GitLab Critical Deploy | Fast-lane GitLab mirror recovery. Pushes current HEAD directly to GitLab via HTTPS, cancels pending pipelines, pauses/resumes schedules, and optionally triggers a fresh pipeline. Works even when GitHub quota is near 0. | 50 | 3 | 8 | 15 | |
| Mirror Watchdog | Triggers when any mirror workflow fails — waits 5 minutes then retries once. Surfaces persistent failures in the Actions tab without consuming quota on repeated retries. | Manual | 50 | 5 | 15 | 30 |
| PR Gate | Required status check for incoming PRs. Checks quota remaining and posts a comment if the system is degraded. Two rate_limit calls per run. | On push | 10 | 2 | 2 | 4 |
| Pre-Flush Prep | Prepares the system for a clean full-chain-flush — cancels stale runs, merges ready PRs, validates config, cleans merged branches, removes template pollution, then dispatches full-chain-flush when quota is sufficient. | Manual | 1500 | 10 | 30 | 60 |
| Queue Manager | Deduplicates queued workflow runs (keeps newest per workflow) and evicts runs queued longer than STALE_QUEUE_MIN (default 25 min) to prevent quota exhaustion cascades. | Every 30 min | 50 | 5 | 15 | 30 |
| Quota Monitor | Polls GitHub quota and optionally dispatches a target workflow once quota recovers above a configurable threshold. Dispatch-only — never scheduled. | 10 | 1 | 5 | 10 | |
| Quota Reserve | Cancels low-priority queued runs when remaining quota drops below RESERVE_FLOOR (default 1000). Uses per-workflow min_quota from workflow-quota-costs.yml for cost-aware cancellation. | Every 30 min | 10 | 1 | 5 | 15 |
| Rate-Limit Re-trigger | Scans recently-failed workflow runs, identifies those that failed due to rate limiting, and re-triggers them after their quota reset epoch. | Every 4h at :05 | 50 | 5 | 20 | 50 |
| Rotate Secret Token | Rotates GitHub PATs and GitLab tokens stored as org/repo secrets. Validates the new token before committing, then triggers Cancel Runs After Token Rotation to clear stale runs. | Manual | 50 | 5 | 10 | 20 |
| Token Health Monitor | Checks expiry dates for all tracked PATs and GitLab tokens. Opens a GitHub issue labelled token-monitor when any token expires within 45 days. | Weekly Mon 09:24 UTC | 50 | 5 | 10 | 20 |
| Validate Config | Validates all config files (gitlab-subgroups.yml, workflow-sync.yml, priority-tiers.yml, registered-imports.json) on every push that touches them. Blocks merges on invalid config. | Manual | 50 | 2 | 5 | 10 |
Tier 2 — High
| Workflow | Synopsis | Schedule | min_quota | Low | Mid | High |
|---|---|---|---|---|---|---|
| Add Mirror Repo | Adds a new repo to the three-org mirror chain (Interested-Deving-1896 → OSP → OOC) by creating the repo in each org, setting up webhooks, and registering it in gitlab-subgroups.yml. | Manual | 200 | 10 | 30 | 60 |
| DwarFS Pack Release | Packages a DwarFS release artifact when an upstream release completes. | Manual | 100 | 5 | 15 | 30 |
| Full Chain Flush | Orchestrates the complete mirror chain in sequence — mirror-to-osp → mirror-osp-to-ooc → mirror-osp-to-gitlab — with quota checks between each stage. | 17 5 1 * * | 1000 | 100 | 400 | 1000 |
| Git Platform Sync | Agnostic git platform sync. Replaces sync-to-gitlab.yml (direction=push) and sync-from-gitlab.yml (direction=pull). Supports GitHub, GitLab, Gitea, Forgejo, Codeberg as source or destination. | Daily 09:23 UTC | 100 | 5 | 25 | 60 |
| Import Repository | Platform-agnostic repo importer — clones any public or authenticated git URL into Interested-Deving-1896, optionally mirrors through the OSP→OOC chain and registers for ongoing sync. | 100 | 10 | 30 | 60 | |
| Merge Repos into Monorepo | Merges multiple git repositories into a single monorepo, preserving full commit history, tags, and Git LFS objects. Manual dispatch only. | Manual | 100 | 10 | 30 | 60 |
| Mirror Chain Dispatch | Agnostic mirror-chain backend. Dispatch-only on canonical instance — dedicated mirror workflows own schedules. Downstream forks without dedicated workflows may add a schedule. | 1200 | 5 | 50 | 800 | |
| Mirror Interested-Deving-1896 → OSP | Bare-clones every repo in Interested-Deving-1896 and git push --mirror into OpenOS-Project-OSP, syncing all branches, tags, and refs exactly. | Every 6h at :13 | 500 | 20 | 80 | 200 |
| Mirror OSP → GitLab | Mirrors every repo in OpenOS-Project-OSP to its GitLab counterpart under openos-project, creating the GitLab project in the correct subgroup if it does not exist yet. | Daily 01:23 UTC | 300 | 5 | 20 | 50 |
| Mirror to OpenOS-Project-Ecosystem-OOC | Bare-clones every repo in OpenOS-Project-OSP and git push --mirror into OpenOS-Project-Ecosystem-OOC, completing the second hop of the three-org mirror chain. | Every 6h at :45 | 300 | 20 | 80 | 200 |
| Mirror to OpenOS-Project-OSP | Mirrors Interested-Deving-1896 repos to OpenOS-Project-OSP on schedule and push. | 0 * * * * | 500 | 50 | 200 | 500 |
| PR Lifecycle Guard | Reusable quota + queue pre-flight called by PR-creating workflows (OTA Release, Upstream PRs, Rebase PRs). One rate_limit call plus optional queue-manager pass. | 50 | 3 | 8 | 20 | |
| Pin Workflow Actions | Pins GitHub Actions uses references to exact SHA commits via ratchet. | Weekly Tue 05:00 UTC | 100 | 10 | 50 | 150 |
| Pre-Mirror CI Gate | Checks CI status on all OSP-bound repos in Interested-Deving-1896 before mirroring. Dispatches resolve-failures for red repos, waits, then re-checks. Blocks the mirror if repos are still failing. | Manual | 800 | 50 | 150 | 300 |
| Rebase PRs | Rebases open PRs in Interested-Deving-1896 onto their base branch when they fall behind, keeping PRs mergeable without manual intervention. | 10 5 */2 * * | 100 | 5 | 20 | 50 |
| Sync All Forks | Syncs all branches of every fork owned by Interested-Deving-1896 with their upstream via the GitHub merge-upstream API, falling back to force-reset on divergence. | Daily 06:07 UTC | 500 | 50 | 200 | 500 |
| Sync Registered Imports | Re-syncs all repos listed in registered-imports.json — bare-clones each source URL and pushes all branches and tags to Interested-Deving-1896. | Daily 04:55 UTC | 200 | 5 | 15 | 30 |
| Sync from GitLab | DEPRECATED. Superseded by Git Platform Sync (direction=pull). Stub kept for backwards compatibility. | Manual | 100 | 0 | 0 | 0 |
| Sync to GitLab Variant | Variant of Sync to GitLab that uses a different token and push strategy — used when the primary sync is blocked or for testing. | Daily 01:50 UTC | 100 | 5 | 20 | 50 |
Tier 3 — Medium
| Workflow | Synopsis | Schedule | min_quota | Low | Mid | High |
|---|---|---|---|---|---|---|
| Audit Arch Repos | Weekly audit of expected vs actual repos across Interested-Deving-1896. Reports missing, unexpected, and mismatched repos to the step summary. | Weekly Mon 04:00 UTC | 100 | 5 | 20 | 50 |
| Auto-merge PRs | Merges open PRs once required checks pass. Hybrid auto-detection per PR: scope (label/bot/all), strategy (rebase/squash/merge), mechanism (native auto-merge vs poll). | Every 6h at :55 | 300 | 5 | 30 | 80 |
| BDFS Dev Workspace | Creates and manages mutable dev workspaces on top of immutable filesystem roots using the bdfs framework (btrfs, overlay, or dwarfs backends). Actions: create, drop, list, commit, status. | Manual | 0 | 0 | 0 | 0 |
| BDFS Dev — BTRFS Backend | Creates a writable BTRFS snapshot of a source subvolume as a bdfs dev workspace. Source must be on a BTRFS filesystem. | Manual | 0 | 0 | 0 | 0 |
| BDFS Dev — DwarFS Backend | Mounts a DwarFS image read-only as the lower layer of an overlayfs workspace, with a writable upper layer (BTRFS subvolume or tmpfs). | Manual | 0 | 0 | 0 | 0 |
| BDFS Dev — Overlay Backend | Creates an overlayfs workspace with a source path as the read-only lower layer and tmpfs or a directory as the writable upper layer. Works on any filesystem. | Manual | 0 | 0 | 0 | 0 |
| Bootstrap Triggers | One-shot self-destruct workflow that fires pending workflow_dispatch triggers on push. | Manual | 50 | 2 | 5 | 10 |
| Build (self-hosted) | Builds the project on a self-hosted runner. | Manual | 20 | 1 | 2 | 5 |
| Build ARM64 | Builds the project for ARM64 architecture. | Manual | 20 | 1 | 2 | 5 |
| Build x86-64 | Builds the project for x86-64 architecture. | Manual | 20 | 1 | 2 | 5 |
| CI | Runs CI checks on push and pull request events. | On push | 20 | 1 | 2 | 5 |
| Check Accessibility | Multi-layer accessibility audit — CODEOWNERS coverage, README screen-reader scan, WCAG 2.1 AA HTML check, audio overview (espeak-ng), and Braille output (liblouis). Commits README.audio.mp3 and README.brl artifacts. | Weekly Mon 04:17 UTC | 500 | 5 | 15 | 40 |
| Check CI Status | Agnostic CI status checker. Runs check-ci.sh for each enabled target in config/ci-check-targets.yml (GitHub orgs and GitLab groups). | Daily 09:05 UTC | 300 | 50 | 300 | 900 |
| Check OOC CI Status | Daily check of CI status on the default branch HEAD for every OOC-bound repo. Reports failing repos to the step summary. | Daily 06:30 UTC | 500 | 50 | 150 | 300 |
| Check Shell Tools CI | Batch-fetches CI run status for all 24 shell-tools repos via a single GraphQL query. Minimal quota cost. Weekly Monday 06:30 UTC. | Weekly Mon 06:30 UTC | 50 | 1 | 2 | 3 |
| Cleanup Stale Branches | Deletes branches that have been merged into the default branch across all repos in Interested-Deving-1896, OSP, and OOC. | 29 4 1 * * | 200 | 10 | 60 | 200 |
| Cleanup Template Pollution | Removes files incorrectly propagated from fork-sync-all to consumer repos via the template sync pipeline, across all three GitHub orgs and GitLab. | Manual | 200 | 20 | 80 | 200 |
| Clone Org | Clones all repositories from an org or user on any supported platform (GitHub, GitLab, Bitbucket, Gitea) into Interested-Deving-1896. | Manual | 200 | 20 | 80 | 200 |
| Create Missing READMEs | Creates README.md from the standard template for OSP-bound repos that have no README, with placeholder sections for human-owned content. | Daily 07:08 UTC | 200 | 20 | 80 | 200 |
| Delete Stale Repos | One-shot cleanup of superseded repos across GitHub orgs and GitLab. Manual dispatch only. | Manual | 50 | 2 | 6 | 20 |
| Deploy Book | Builds the mdBook documentation site from DOCS/ and deploys it to GitHub Pages at interested-deving-1896.github.io/fork-sync-all/. | Manual | 50 | 5 | 10 | 20 |
| Devcontainer SDK | Validates devcontainer.json, features, and automations templates. Optionally builds and pushes the devcontainer image or publishes features to GHCR. | Manual | 50 | 0 | 5 | 20 |
| Docker → Incus Migration | Scans repos for Docker artifacts (Dockerfile, docker-compose.yml) and replaces them with Incus equivalents. Runs after Add Mirror Repo and weekly. | Weekly Sun 03:08 UTC | 100 | 10 | 40 | 100 |
| Enforce Agnostic Vendor | Scans vendor/ for distro-specific hardcoded fallback values in shell, YAML, and TypeScript. All vendored components must be deployment-agnostic. | Manual | 50 | 2 | 5 | 10 |
| FSA API | FSA API server lifecycle and adapter dispatch. Validates config, smoke-tests server startup, or calls individual adapters directly via workflow_dispatch. | Manual | 200 | 2 | 10 | 30 |
| Fork KDE Neon Repos | One-shot workflow that clones the 6 KDE Invent neon repos into Interested-Deving-1896 and pushes them through the OSP mirror chain. Ongoing re-sync handled by sync-registered-imports. | Manual | 100 | 10 | 30 | 60 |
| Full Audit | Weekly structural audit of workflows, scripts, config registries, assets, and vendor dirs. No REST calls. | Weekly Mon 04:00 UTC | 50 | 0 | 0 | 0 |
| Generate Book Pages | Regenerates DOCS/generated/ pages from config sources (workflow-quota-costs.yml, priority-tiers.yml, gitlab-subgroups.yml, registered-imports.json) and commits the result. | Manual | 50 | 1 | 2 | 5 |
| Generate Repo Descriptions | AI-powered per-file description generator. Fetches file tree (1 REST call) then reads each file for context (1 REST call per file) before calling GitHub Models. Cost scales with MAX_FILES setting. | Weekly Sun 03:30 UTC | 300 | 20 | 100 | 300 |
| HW Detect CI | Runs CI for hardware detection tooling on schedule and push. | Weekly Mon 06:00 UTC | 50 | 2 | 5 | 15 |
| Inject Built-with-Ona Badges | Adds a Built-with-Ona badge to README.md for all repos in Interested-Deving-1896 that are missing it. Skips repos that already have the badge. | 15 8 */2 * * | 200 | 5 | 30 | 80 |
| List Active Runs | Lists all active workflow runs with clickable web and API URLs. | Every 30 min | 50 | 2 | 3 | 5 |
| Manage Repo Settings | Declarative repo settings drift detection and enforcement. Check mode reads current state (1 REST call per repo) and reports drift. Apply mode patches drifted fields (1-3 REST calls per drifted repo). | Weekly Mon 04:30 UTC | 200 | 10 | 60 | 150 |
| Merge Ready PRs | Waits for CI then merges all open PRs with passing checks across fork-sync-all and btrfs-dwarfs-framework. | Manual | 200 | 10 | 40 | 100 |
| Mirror Flatpak Repo | Builds and publishes a self-hosted Flatpak repo on GitHub Pages. Downloads Flatpak bundles from OSP/OOC releases and imports them into the org flatpak-repo. | Daily 05:00 UTC | 300 | 20 | 60 | 150 |
| Mirror GHCR Images | Re-tags and pushes GHCR container images from an upstream owner into OSP and OOC orgs. Daily schedule. | Daily 03:00 UTC | 200 | 10 | 40 | 100 |
| Mirror PyPI Packages | Re-publishes PyPI packages from upstream repos to OSP/OOC with org-prefixed package names (e.g. osp-linux-kernel-manager). | Manual | 100 | 5 | 20 | 60 |
| Mirror RPM Repo | Mirrors RPM packages from OSP/OOC releases to a self-hosted RPM repo on GitHub Pages. Daily schedule. | Daily 04:30 UTC | 200 | 10 | 40 | 100 |
| OTA Discover | Scans forks of fork-sync-all for .ota/config.yml with enabled: true and adds newly discovered repos to config/ota-registry.yml. | Daily 06:38 UTC | 100 | 10 | 40 | 100 |
| OTA Opt-In | Propagated to opted-in forks. Fork owners run this once to create .ota/config.yml and open a registration PR against fork-sync-all's OTA registry. | 50 | 5 | 15 | 30 | |
| OTA Release | Triggered on semver tag push. Assembles and delivers OTA updates to all opted-in repos in config/ota-registry.yml, then updates CHANGELOG.md with release notes. | Manual | 100 | 10 | 40 | 100 |
| OTA Self-Update | Propagated to opted-in forks. Pulls the latest OTA release from fork-sync-all and applies it to the fork's workflow files. | Weekly Mon 05:15 UTC | 50 | 5 | 15 | 30 |
| Onboard Bugzilla | Guided one-time setup: validates Bugzilla connectivity, creates product/components, writes config/bugzilla.yml. | Manual | 100 | 5 | 15 | 30 |
| Onboard Repository | Onboards new repos into the ecosystem — applies labels, branch protection, topics, description, welcome issue, and dispatches sync-template/setup-osp-mirrors/sync-registered-imports. | Manual | 200 | 20 | 60 | 150 |
| Org Storage Maintenance | Weekly GitLab storage housekeeping across openos-project: triggers artifact expiry and deletes old generic package versions older than 90 days (keeps 5 per package). | Weekly Sun 02:00 UTC | 0 | 0 | 0 | 0 |
| PR Automation | Applies size labels, path-based labels, reviewer auto-assignment, risky pattern detection, and auto-merge for low-risk PRs on every PR open or update. | On push | 50 | 5 | 15 | 30 |
| Pin Manager | Manages version pinning, GitHub profile pins, and repo issue pins. | Weekly Mon 06:00 UTC | 150 | 3 | 10 | 25 |
| Pipeline Telemetry | Post-run observability workflow. Fetches completed run data, builds a span tree (workflow→jobs→steps), computes Thoth-equivalent metrics, parses log severity, writes a step summary and trace artifact, and upserts a rolling metrics issue. | Manual | 200 | 5 | 15 | 30 |
| Post-Flush Verification | End-to-end health check after full-chain-flush — mirror integrity across all three pairs, CI status on I-D-1896 OSP-bound repos, quota health, and workflow queue health. | Manual | 300 | 150 | 350 | 600 |
| Provision GitLab Maintenance Schedules | Pushes .gitlab/scheduled-maintenance.yml and creates a weekly maintenance schedule on every actively developed project under openos-project. Safe to re-run. | 0 | 0 | 0 | 0 | |
| Push Kernel Content | Pushes kernel version metadata (READY, VERSION, config/, patches/, README.md) to the debian-{arch}-kernel-base repos (one per arch, up to 10). | Manual | 100 | 10 | 30 | 80 |
| Rebuild LTS Branch (penguins-eggs) | Rebases the all-features branch onto the upstream master after each pieroproietti sync, then force-pushes the result to the lts branch. | Manual | 50 | 5 | 15 | 30 |
| Reconcile Identity Assets | Detects the current FSA instance, selects the matching brand variant, writes active assets to assets/brand/.active/, and injects identity content into DOCS/cover.md. | Manual | 10 | 1 | 3 | 5 |
| Reconcile Org References | Rewrites org/repo references in OSP and OOC mirrors to point at the correct org, fixing stale Interested-Deving-1896 references left by the mirror process. | 50 5 */2 * * | 300 | 10 | 60 | 150 |
| Release | Creates a GitHub release and uploads build artifacts on tag push. | Manual | 100 | 5 | 15 | 30 |
| Resolve CI Failures | Analyses CI failure patterns across OSP-bound repos and applies automated fixes (dependency updates, config corrections, workflow patches) where possible. | Daily 07:43 UTC | 100 | 10 | 40 | 100 |
| Resolve CI Failures (Agnostic) | Agnostic CI failure resolver. Runs resolve-ci.sh for each enabled target in config/ci-check-targets.yml. GitHub targets use LLM analysis and auto-fix; GitLab targets retry failed/canceled pipelines. | Daily 07:43 UTC | 100 | 10 | 120 | 400 |
| Runner Status | Reports runner utilisation and queue depth across the org. Flags workflows with queue depth above configurable warn/critical thresholds. | Every 1h at :10 | 50 | 2 | 4 | 8 |
| Seed Patchset Branches | Seeds 9 patchset branches per debian-{arch}-kernel-base repo for Debian (trixie/forky/sid), Devuan (excalibur/forky/ceres), and Ubuntu (resolute/stonking/devel). | Manual | 200 | 20 | 60 | 150 |
| Setup Dashboard Variables | Sets all VITE_* repository variables required by the infra-dashboard public-dashboard build. Safe to re-run — blank inputs leave existing variables unchanged. | Manual | 50 | 5 | 15 | 30 |
| Setup OSP Mirror Workflows | Ensures all repos in OpenOS-Project-OSP have the correct mirror workflow files and secrets configured for the OSP→OOC mirror chain. | Daily 02:45 UTC | 200 | 20 | 80 | 200 |
| Sync FSA Forks | Keeps downstream fork-sync-all forks in sync with upstream. Opens PRs on drift. | Daily 04:00 UTC | 200 | 5 | 20 | 60 |
| Sync KDE Groups Mirrors | Syncs all KDE group mirror repos under openos-project/kde-ecosystem-deving/kde-groups from invent.kde.org. Daily schedule. | Daily 01:00 UTC | 300 | 20 | 80 | 200 |
| Sync KDE Neon Mirrors | Syncs all KDE Neon mirror repos in openos-project/kde-ecosystem-deving/neon-deving from invent.kde.org/neon/. Daily schedule, offset 30 min from Sync KDE Groups Mirrors. | Daily 01:30 UTC | 300 | 20 | 80 | 200 |
| Sync Pieroproietti GitLab Forks | Syncs the three pieroproietti GitLab forks (penguins-eggs, penguins-eggs-book, oa-tools) from their GitHub upstreams. Mirrors branches, tags, and creates GitLab Releases for new tags. | Daily 02:15 UTC | 100 | 5 | 15 | 40 |
| Sync Registry Backend | Agnostic registry sync backend propagated to upstream-sync consumers. Dispatch-only, no schedule, no hardcoded defaults. Reads vars.AF_REGISTRY_REPO / AF_REGISTRY_BRANCH / AF_REGISTRY_PATH for self-configuration. | 100 | 10 | 40 | 100 | |
| Sync Registry Sources | Registry-driven upstream sync (central orchestrator) — reads a JSON registry of upstream sources and syncs each repo via merge-upstream or force-reset. Runs daily from fork-sync-all with penguins-eggs defaults. | Daily 03:05 UTC | 100 | 10 | 40 | 100 |
| Sync Shell Tools Vendor | Sparse-clones each of the 24 shell-tools forks and copies entrypoint scripts into vendor/shell-tools/. One clone per tool (~2 REST calls each via git protocol). Weekly Sunday 02:00 UTC. | Weekly Sun 02:00 UTC | 300 | 24 | 48 | 72 |
| Sync Template | Syncs fork-sync-all's file tree into target repos. Three modes — create (new repo + mirror chain), inject (copy into existing repo), propagate (push-triggered sync to all consumers in template-consumers.yml). | Manual | 200 | 20 | 80 | 200 |
| Sync UAA Vendor | Syncs vendor/unified-agnostic-api from Interested-Deving-1896/unified-agnostic-api via sparse checkout. Runs on push to vendor/unified-agnostic-api/** or weekly schedule. | Weekly Tue 05:00 UTC | 100 | 5 | 15 | 30 |
| Sync Upstream Mirrors (GitLab) | Syncs all upstream mirror repos in openos-project/upstream-mirrors from their original GitHub sources. Daily schedule. | Daily 00:00 UTC | 200 | 10 | 40 | 100 |
| Sync Upstream Sources | Reads the Origins section of every OSP-bound repo and syncs each referenced external fork to its upstream HEAD via merge-upstream or force-reset. | Daily 01:37 UTC | 200 | 20 | 80 | 200 |
| Sync btrfs-devel Branches | Syncs tracked btrfs-devel branches from the upstream kernel tree into the btrfs-dwarfs-framework fork. | Daily 05:02 UTC | 100 | 5 | 20 | 50 |
| Sync pieroproietti Forks | Syncs all penguins-eggs forks owned by Interested-Deving-1896 with their upstream pieroproietti sources via merge-upstream. | Daily 01:07 UTC | 100 | 10 | 40 | 100 |
| Sync to GitLab | DEPRECATED. Superseded by Git Platform Sync (direction=push). Stub kept for backwards compatibility. | Manual | 100 | 0 | 0 | 0 |
| Sync-in | Manages Sync-in server/client lifecycle. Server role: health-check, deploy, token rotation. Client role: register OSP-bound repos as workspaces, trigger syncs. Scheduled health every 6h, workspace sync daily. | Every 6h at :37 | 50 | 2 | 20 | 80 |
| Trigger README Update (All Repos) | Dispatches update-readmes.yml for all OSP-bound repos in batch. Use after a rate-limit reset to propagate README updates org-wide. | Manual | 200 | 10 | 30 | 80 |
| Update READMEs | Regenerates AI-owned sections (what-it-does, architecture, ci, mirror-chain, etc.) in README.md for all OSP-bound repos, preserving human-owned sections. | Daily 03:15 UTC | 300 | 50 | 150 | 300 |
| Upload Asset | Uploads files from URLs, artifacts, or repo paths to a release, repo directory, or issue comment. | Manual | 50 | 2 | 5 | 15 |
| Upload NotebookLM Assets | Uploads NotebookLM generated output files (audio, PDF) to a GitHub Release. Creates the release if it does not exist yet. | Manual | 50 | 2 | 5 | 10 |
| Upstream Contribute (caller) | Consumer-repo caller for upstream-contribute.yml. Analyses push diff and opens upstream PRs. | Manual | 50 | 2 | 10 | 20 |
| Validate README Render | Checks README.md for rendering issues — leaked log lines, unclosed fences, bare brackets, raw angle brackets, unclosed AI markers, missing H1, and empty sections. | Manual | 50 | 5 | 15 | 30 |
| Verify Fork Integrity | Compares this repo's default-branch HEAD against its upstream parent (or upstream_override from .ota/config.yml). Reports sync status; configurable hard-fail on drift. | Weekly Mon 06:25 UTC | 100 | 3 | 5 | 8 |
| Verify Mirror Integrity | Compares default-branch HEAD SHAs between source and destination for all OSP-bound repos after a mirror stage. Reports mismatches as warnings; configurable hard-fail mode. | Manual | 400 | 50 | 100 | 150 |
| Vouch Check PR | Hybrid A/B/C PR trust gate. Reads VOUCHED.td and changed file paths to select response — denounced authors auto-closed, unknown authors touching sensitive paths blocked, unknown authors on safe paths warned only. | 30 | 3 | 8 | 20 | |
| Vouch Manage | Manages contributor vouch status via issue/PR comments. Maintainers use vouch/unvouch/denounce commands; changes are applied via auto-opened PRs against VOUCHED.td. | Manual | 20 | 2 | 5 | 10 |
| bdfs Package | Packages fork-sync-all as a bdfs workspace (DwarFS + BTRFS). | Manual | 50 | 1 | 2 | 5 |
Tier 4 — Low
| Workflow | Synopsis | Schedule | min_quota | Low | Mid | High |
|---|---|---|---|---|---|---|
| Accessibility PR Gate | Accessibility gate on pull requests. Blocks merge if accessibility violations are found. | 0 | 0 | 0 | 0 | |
| Bootstrap Org | One-shot org bootstrap: fork fork-sync-all into a new org, substitute config, set secrets, dispatch post-bootstrap workflows. | Manual | 100 | 30 | 60 | 80 |
| Branch Hygiene Report | Reports stale and unmerged branches. Manual dispatch only. | Weekly Mon 14:00 UTC | 0 | 0 | 0 | 0 |
| Bugzilla Failure Reporter | Files or updates a Bugzilla bug when a monitored workflow fails; comments on recovery. | Manual | 30 | 2 | 5 | 10 |
| Bugzilla Milestone Ship | Marks Bugzilla target milestone as shipped and notifies resolved bugs when a version tag is pushed. | Manual | 30 | 2 | 8 | 20 |
| Build | Builds the project. Triggered on push/PR. | Manual | 0 | 0 | 0 | 0 |
| Check GitLab CI Sync | Compares paired jobs in .gitlab-ci.yml against config/workflow-sync.yml and reports drift — scripts with changed entry points, mismatched cadence rules, or jobs missing from either side. | Manual | 50 | 2 | 5 | 10 |
| Checks | General checks workflow. Triggered on push/PR. | On push | 0 | 0 | 0 | 0 |
| Clear All Notifications | Marks all GitHub notifications as read for the authenticated user. | Manual | 50 | 1 | 2 | 5 |
| CodeQL | CodeQL security analysis. Triggered on push/PR/schedule. | 0 | 0 | 0 | 0 | |
| Create OOC GitLab Subgroups | Creates the GitLab subgroup structure for OpenOS-Project-Ecosystem-OOC and records the resulting subgroup IDs. | Manual | 50 | 5 | 20 | 50 |
| Critical Deploy — Stub (template — not functional) | Template for new platform critical deploy targets. Non-functional until copied, renamed, and filled in. Update costs when the platform is activated. | Manual | 50 | 5 | 30 | 100 |
| Eco Audit | Audits fork-sync-all against KDE Eco / Blue Angel DE-UZ 215 criteria. Checks green hosting, CI efficiency, telemetry, dependency footprint. Stubs KEcoLab energy measurement for GitLab activation. Weekly on Sundays. | Weekly Sun 05:00 UTC | 50 | 1 | 3 | 5 |
| Export Book (Multi-Engine) | Exports the book to one or all supported engines (mdBook, MkDocs, Docusaurus, Pandoc). Manual dispatch only. | Manual | 0 | 0 | 0 | 0 |
| Generate NotebookLM Content | Generates NotebookLM content artifacts (audio, video, slides, infographic, quiz, flashcards, report) for a given notebook and uploads them to a GitHub Release. | Manual | 50 | 5 | 15 | 30 |
| Generate OSP Dependency Graph | Scans all OSP-bound repos for package.json and requirements.txt files and generates a dependency graph showing inter-repo relationships. | Weekly Sun 03:10 UTC | 100 | 20 | 60 | 150 |
| Generate SBOM | Four-stage SBOM pipeline — Trivy generates CycloneDX+SPDX, sbomasm augments metadata, parlay enriches components, sbomqs scores quality. Runs weekly and on push to main. Release assets attached by OTA Release. | Weekly Tue 02:41 UTC | 10 | 2 | 5 | 10 |
| Generate architecture config | Generates architecture config from org repo metadata. | Manual | 50 | 2 | 5 | 15 |
| GitBook OSS | Manages the GitBook OSS (Next.js) renderer. Actions: build, export, update, dev-info. Weekly update check on Mondays. | Weekly Mon 04:17 UTC | 0 | 0 | 0 | 0 |
| GitLab Storage Scan | Scans all projects under openos-project on GitLab and reports storage usage. Useful for diagnosing when the namespace approaches its 10 GiB limit. | Manual | 50 | 2 | 5 | 10 |
| Inject Repo Motto | Injects repo motto/slogan into README.md files across all orgs. | 30 8 */2 * * | 200 | 5 | 30 | 100 |
| Integrate Shell Tools | Runs smoke tests and integration demos for vendored shell-tools. No GitHub API calls — pure runner execution. Weekly Sunday 03:00 UTC (after sync-shell-tools). | Weekly Sun 03:00 UTC | 50 | 1 | 2 | 5 |
| LTS README Standardisation | Standardises README.md structure for LTS-tagged repos, ensuring they follow the LTS template with correct version badges and support tables. | 19 3 1 * * | 100 | 10 | 40 | 100 |
| List Chromium GitLab Repos | Lists all projects under the Chromium_Browser_OS_Deving GitLab group. Informational only — used to audit what has been mirrored. | Manual | 50 | 2 | 5 | 10 |
| Manage Subtrees | Keeps git subtrees, submodules, and umbrella repo relationships current per config/subtree-manifest.yml. | Weekly Sun 01:00 UTC | 50 | 0 | 0 | 5 |
| Mirror Artifacts | Mirrors GitHub Releases, Flatpak packages, and RPM packages from Interested-Deving-1896 repos to their OSP and OOC counterparts. | Daily 02:10 UTC | 200 | 10 | 50 | 150 |
| Mirror Orgs | Mirrors all repos from Interested-Deving-1896 to OpenOS-Project-OSP and OpenOS-Project-Ecosystem-OOC using bare clone + push --mirror. | Daily 02:17 UTC | 100 | 20 | 60 | 150 |
| Mirror Releases | Mirrors GitHub Releases (tags + release notes + assets) from Interested-Deving-1896 repos to their OSP and OOC counterparts. | Every 12h at :03 | 200 | 10 | 50 | 150 |
| Notification Manager | Hourly notification triage. Auto-marks known-safe patterns (mirror failures, quota artifacts, Dependabot) as read. Supports manual dispatch with list/mark-all-read actions. | 17 * * * * | 200 | 1 | 5 | 15 |
| Notification Poller | Polls GitHub notifications for unread CI failure notifications and triggers resolve-failures immediately when any are found. | Every 4h at :32 | 50 | 1 | 5 | 15 |
| OTA Reconcile | Weekly drift detection and quota-fallback reconcile for mirror-chain consumer repos. Autonomously selects path A (stamp), B (drift PR), or C (quota-recovery PR) per repo based on .ota/version SHA, open PR state, and OTA_SYNC_INCOMPLETE variable. | Weekly Wed 03:17 UTC | 200 | 20 | 80 | 200 |
| PR Labeler | Automatically labels pull requests based on changed paths. Triggered on pull_request. | 50 | 1 | 2 | 5 | |
| README Wizard | AI-guided README authoring — writes or rewrites a README for a specific repo according to custom instructions (audience, tone, sections), respecting existing human-owned markers. | Manual | 100 | 10 | 30 | 60 |
| Rate Limit Status | Queries current rate limit status for all external APIs used by fork-sync-all. On-demand health check. | Manual | 10 | 2 | 3 | 5 |
| Refresh NotebookLM Auth | Rotates the short-lived __Secure-1PSIDTS cookie in NOTEBOOKLM_AUTH_JSON weekly and writes the updated state back to the repo secret. | Weekly Tue 06:17 UTC | 10 | 1 | 2 | 5 |
| Repo Manifest | Exports a manifest of all repos in an org, or imports repos from a manifest into a target GitHub org. Supports multi-platform bulk import. | Manual | 100 | 10 | 40 | 100 |
| Setup GitLab CI Schedules | Replaces all existing GitLab pipeline schedules in openos-project/ops/fork-sync-all with the 3 consolidated CADENCE-based schedules. Safe to re-run. | 50 | 2 | 5 | 10 | |
| Shallow Reclone Large GitLab Mirrors | Reduces GitLab storage usage by replacing full git history on large mirror projects with a shallow clone. Run when openos-project approaches its 10 GiB storage limit. | Manual | 50 | 2 | 5 | 10 |
| Sync Agent Prices | Weekly hybrid A+B+C price refresh for config/agent-cost-profiles.yml. Fetches LiteLLM model_prices_and_context_window.json at a pinned SHA, diffs against current prices, and opens a PR for human review if anything changed. Flags stale manual entries as warnings. Never auto-merges. | Weekly Mon 09:00 UTC | 50 | 3 | 8 | 15 |
| Sync Ona Projects | Reconciles config/ona-projects.yml with the Ona API. Creates or updates Ona projects for all repos in the org chain. Runs in dry-run mode when ONA_TOKEN is absent. | Daily 06:00 UTC | 50 | 1 | 5 | 20 |
| Sync penguins-eggs docs to penguins-eggs-book | Triggered by repository_dispatch from penguins-eggs when docs/chromiumos/ changes on all-features. Syncs the updated docs into the penguins-eggs-book repo. | Manual | 50 | 5 | 15 | 30 |
| Sync to Bugzilla | Parses commits and PRs for Bug NNN references and updates Bugzilla status and comments. | Manual | 50 | 2 | 8 | 20 |
| Test Time Format | Validates time_format.py portability across glibc, musl, and BSD libc. Runs on push/PR to time_format.py. | Manual | 0 | 0 | 0 | 0 |
| Track Agent Costs | Records AI agent session cost estimates (OCUs, USD, tokens) to a structured JSON log. Supports Ona Agent, Codex, GitHub Models, and direct API agents. Builds an observed cost dataset to replace code-audit estimates in DOCS/ai-agent-costs.md over time. | Manual | 10 | 1 | 2 | 3 |
| Translate Docs | Translates DOCS/ mdBook pages into a target language using GitHub Models API. Writes translated files to DOCS/ | 15 11 */2 * * | 100 | 5 | 15 | 30 |
| Translate READMEs | Translates README.md files for OSP-bound repos into additional languages using GitHub Models API. Writes translated files alongside the English original. | 43 10 */2 * * | 100 | 10 | 40 | 100 |
| Trigger Artifact Mirror | Dispatches mirror-artifacts immediately when a release is published in this repo, so OSP and OOC receive the release without waiting for the next scheduled run. | Manual | 50 | 2 | 5 | 10 |
| Update Book Index | Regenerates DOCS/generated/ pages (source tree, glossary, workflow index) on push to main. Commits with [skip ci]. | Manual | 0 | 0 | 0 | 0 |
| Update Infrastructure Dependencies | Scans workflow files across the three-org chain for outdated Actions versions, EOL runners, and EOL Node/Python versions, then opens PRs. | Weekly Mon 06:11 UTC | 200 | 50 | 150 | 250 |
| Update Quota Cost Registry | Reads quota-instrument records from job logs, computes observed p50/p95 REST costs per workflow, and commits updated values to workflow-quota-costs.yml weekly. | Weekly Mon 08:00 UTC | 200 | 30 | 80 | 150 |
| Update Workflow Triggers Doc | Regenerates docs/workflow-triggers.md and docs/workflow-triggers.txt whenever a workflow file changes on main. Commits the result directly to main. | Manual | 50 | 5 | 10 | 20 |
| Update kde-builder vendor | Pulls latest kde-builder upstream into vendor/kde-builder/ via git subtree. Manual dispatch only. | Manual | 0 | 0 | 0 | 0 |
| Upstream Direct Commits from OSP + OOC | Detects commits pushed directly to OSP/OOC default branches (without a PR) and opens PRs against Interested-Deving-1896 to reconcile them. | Daily 03:47 UTC | 200 | 20 | 80 | 200 |
| Upstream PRs from OSP + OOC | Detects commits on OSP and OOC default branches that are not present in Interested-Deving-1896 and opens PRs to bring them upstream. | Daily 03:33 UTC | 200 | 20 | 80 | 200 |
| Upstream Workflow Proposal | Scans OSP-bound repos for new workflow patterns not present in fork-sync-all and opens a PR proposing them as template skeletons. | Weekly Mon 06:06 UTC | 50 | 5 | 20 | 50 |
| Vouch Onboard | Onboards contributors into the vouch registry (admin/self/auto/seed modes). Runs platform verification checks and commits registry + VOUCHED.td changes. Also triggered by vouch-labelled issues. | Daily 03:00 UTC | 30 | 3 | 10 | 25 |
| Vouch Sync Codeowners | Weekly sync of CODEOWNERS entries and org members into VOUCHED.td via vouch-seed.sh. Opens a PR if VOUCHED.td changed. | Weekly Mon 04:23 UTC | 50 | 5 | 15 | 40 |
| btrfs-devel sync | Weekly sync of fs/btrfs/ subtree from kdave/btrfs-devel into this repo via git read-tree. Opens a PR when changes are found. | Weekly Mon 03:00 UTC | 50 | 0 | 1 | 2 |
| opencode | OpenCode AI assistant integration. Triggered on issue/PR comments. | 0 | 0 | 0 | 0 |
✦ Mid value is an observed p50 measurement. All other values are code-audit estimates.
Registered Imports
All 157 upstream repositories tracked in registered-imports.json. These are synced to Interested-Deving-1896 by sync-registered-imports.yml daily at 04:55 UTC.
Auto-generated on 2026-07-03 from
registered-imports.json.
GitHub (156)
GitLab (1)
| Target repo | Source URL | Added |
|---|---|---|
| kde-eco-website | https://invent.kde.org/websites/eco-kde-org | 2026-06-17 |
GitLab Subgroup Map
All 225 OSP-bound repositories mapped to their GitLab subgroup under openos-project. This is the single source of truth used by mirror-osp-to-gitlab.sh.
Auto-generated on 2026-07-03 from
config/gitlab-subgroups.yml.
accessibility_deving
| Repo | GitHub | GitLab |
|---|---|---|
README | GitHub | GitLab |
axe-core | GitHub | GitLab |
espeak-ng | GitHub | GitLab |
liblouis | GitHub | GitLab |
nvda | GitHub | GitLab |
osara | GitHub | GitLab |
pa11y | GitHub | GitLab |
target-size-highlighter | GitHub | GitLab |
z-index-focus-override | GitHub | GitLab |
agnostic-api_deving
| Repo | GitHub | GitLab |
|---|---|---|
User-Filesystem | GitHub | GitLab |
ai-bom | GitHub | GitLab |
api-base | GitHub | GitLab |
apibrew | GitHub | GitLab |
apifs | GitHub | GitLab |
apifusefs | GitHub | GitLab |
bibhelper | GitHub | GitLab |
browser-fs-access | GitHub | GitLab |
chromium-automation | GitHub | GitLab |
cross-platform-system-interaction | GitHub | GitLab |
darwinkit | GitHub | GitLab |
fswatch-Filesystem-Events-Watchfolder-Shell-Script | GitHub | GitLab |
ipfs-api-mount | GitHub | GitLab |
jail-sh | GitHub | GitLab |
lifo | GitHub | GitLab |
mist.sh | GitHub | GitLab |
mkinitcpio-dir | GitHub | GitLab |
portal | GitHub | GitLab |
puppeteer | GitHub | GitLab |
rm-safely | GitHub | GitLab |
sizes | GitHub | GitLab |
swap.sh | GitHub | GitLab |
tomb | GitHub | GitLab |
unified-ai-api | GitHub | GitLab |
uutils-coreutils | GitHub | GitLab |
zenfs-archives | GitHub | GitLab |
zenfs-bundle | GitHub | GitLab |
zenfs-core | GitHub | GitLab |
zenfs-linux | GitHub | GitLab |
ai-agents_deving
| Repo | GitHub | GitLab |
|---|---|---|
OmoiOS | GitHub | GitLab |
PhoneixAI | GitHub | GitLab |
accessibility-agents | GitHub | GitLab |
clahub | GitHub | GitLab |
clawmetry | GitHub | GitLab |
netclaw | GitHub | GitLab |
nexa-gauge | GitHub | GitLab |
niko-claude-skills | GitHub | GitLab |
notificare | GitHub | GitLab |
pylibsmeta | GitHub | GitLab |
cachyos_deving
| Repo | GitHub | GitLab |
|---|---|---|
CachyOS-PKGBUILDS | GitHub | GitLab |
CachyOS-Settings | GitHub | GitLab |
New-Cli-Installer | GitHub | GitLab |
ananicy-rules | GitHub | GitLab |
cachy-chroot | GitHub | GitLab |
cachy-update | GitHub | GitLab |
cachyos-repo-add-script | GitHub | GitLab |
chwd | GitHub | GitLab |
copr-linux-cachyos | GitHub | GitLab |
kernel-manager | GitHub | GitLab |
repo-manage-util | GitHub | GitLab |
scx-manager | GitHub | GitLab |
git-management_deving
| Repo | GitHub | GitLab |
|---|---|---|
gha-repo-manager | GitHub | GitLab |
git-release-shell | GitHub | GitLab |
git-repo-manager | GitHub | GitLab |
git-repo-worktrees-manager | GitHub | GitLab |
github-api-scripts | GitHub | GitLab |
github-api-scripts1 | GitHub | GitLab |
github-codeowners | GitHub | GitLab |
gitlab-enhanced | GitHub | GitLab |
repo-description | GitHub | GitLab |
immutable-filesystem_deving
incus_deving
| Repo | GitHub | GitLab |
|---|---|---|
Image-Server | GitHub | GitLab |
Incus-MacOS-Toolkit | GitHub | GitLab |
K8s-in-incus | GitHub | GitLab |
LXD-Manager | GitHub | GitLab |
blincus | GitHub | GitLab |
cluster-api-provider-incus | GitHub | GitLab |
ctde | GitHub | GitLab |
distrobuilder | GitHub | GitLab |
dotdrop | GitHub | GitLab |
ezpodman-sandbox | GitHub | GitLab |
gh-actions-manager | GitHub | GitLab |
incus | GitHub | GitLab |
incus-agent-sysvinit | GitHub | GitLab |
incus-app-container | GitHub | GitLab |
incus-cloud-init | GitHub | GitLab |
incus-compose | GitHub | GitLab |
incus-demo-server | GitHub | GitLab |
incus-deploy | GitHub | GitLab |
incus-docker | GitHub | GitLab |
incus-gha | GitHub | GitLab |
incus-goad | GitHub | GitLab |
incus-image-server | GitHub | GitLab |
incus-images | GitHub | GitLab |
incus-init-scripts | GitHub | GitLab |
incus-launch-vm-action | GitHub | GitLab |
incus-linux-toolkit | GitHub | GitLab |
incus-os | GitHub | GitLab |
incus-package-repo | GitHub | GitLab |
incus-sdk | GitHub | GitLab |
incus-ui-canonical | GitHub | GitLab |
incus-waydroid-toolkit | GitHub | GitLab |
incus-windows | GitHub | GitLab |
incus-windows-toolkit | GitHub | GitLab |
incus_container_gui_setup | GitHub | GitLab |
incus_container_manager | GitHub | GitLab |
incuslab | GitHub | GitLab |
infra-dashboard | GitHub | GitLab |
kapsule | GitHub | GitLab |
kapsule-incus-manager | GitHub | GitLab |
lxd_incus_gui_apps | GitHub | GitLab |
packer-plugin-incus | GitHub | GitLab |
packer-plugin-incuschroot | GitHub | GitLab |
podclaw | GitHub | GitLab |
polar | GitHub | GitLab |
setup-incus | GitHub | GitLab |
talos | GitHub | GitLab |
talos-incus | GitHub | GitLab |
terraform-incus-oci-image-updating | GitHub | GitLab |
waydroid-toolkit | GitHub | GitLab |
linux-kernel_filesystem_deving
| Repo | GitHub | GitLab |
|---|---|---|
btrfs-dwarfs-framework | GitHub | GitLab |
kernel-patches | GitHub | GitLab |
linux-cachyos | GitHub | GitLab |
linux-distro-prefix | GitHub | GitLab |
linux-distro-stage3 | GitHub | GitLab |
linux-over-the-air | GitHub | GitLab |
linux-pivot | GitHub | GitLab |
linux-powerwash | GitHub | GitLab |
liquorix-unified-kernel | GitHub | GitLab |
liqxanmod | GitHub | GitLab |
lkf | GitHub | GitLab |
lkm | GitHub | GitLab |
ukm | GitHub | GitLab |
xanmod-unified-kernel | GitHub | GitLab |
neon-deving
| Repo | GitHub | GitLab |
|---|---|---|
KPort | GitHub | GitLab |
docker-images | GitHub | GitLab |
kde-builder | GitHub | GitLab |
pkg-kde-dev-scripts | GitHub | GitLab |
pkg-kde-jenkins | GitHub | GitLab |
pkg-kde-tools | GitHub | GitLab |
qt-kde-team.pages.debian.net | GitHub | GitLab |
ubuntu-core | GitHub | GitLab |
ops
| Repo | GitHub | GitLab |
|---|---|---|
Smart-File-Organizer | GitHub | GitLab |
achievements | GitHub | GitLab |
agentic-shell | GitHub | GitLab |
bash-api-server | GitHub | GitLab |
bash-it | GitHub | GitLab |
bashly | GitHub | GitLab |
build-server | GitHub | GitLab |
flatpak-repo | GitHub | GitLab |
fork-sync-all | GitHub | GitLab |
git-sizer | GitHub | GitLab |
github-exporter | GitHub | GitLab |
headroom | GitHub | GitLab |
hrsync | GitHub | GitLab |
ipinfo | GitHub | GitLab |
linux-shell-script-archive | GitHub | GitLab |
lowlighter-metrics | GitHub | GitLab |
mass_clone | GitHub | GitLab |
namefix | GitHub | GitLab |
operation-phantom-shell | GitHub | GitLab |
org-mirror | GitHub | GitLab |
remote-sync | GitHub | GitLab |
rtk | GitHub | GitLab |
shell2http | GitHub | GitLab |
shellqueue | GitHub | GitLab |
simple-deploy | GitHub | GitLab |
smartcd | GitHub | GitLab |
unified-agnostic-api | GitHub | GitLab |
utility_shell | GitHub | GitLab |
victoriametrics-metrics | GitHub | GitLab |
webhook | GitHub | GitLab |
penguins-eggs_deving
| Repo | GitHub | GitLab |
|---|---|---|
eggs-ai | GitHub | GitLab |
eggs-gui | GitHub | GitLab |
oa-tools | GitHub | GitLab |
penguins-distrobuilder | GitHub | GitLab |
penguins-eggs | GitHub | GitLab |
penguins-eggs-audit | GitHub | GitLab |
penguins-eggs-book | GitHub | GitLab |
penguins-eggs-integrations | GitHub | GitLab |
penguins-eggs-prefix | GitHub | GitLab |
penguins-eggs-stage3 | GitHub | GitLab |
penguins-immutable-framework | GitHub | GitLab |
penguins-incus-platform | GitHub | GitLab |
penguins-kernel-manager | GitHub | GitLab |
penguins-over-the-air | GitHub | GitLab |
penguins-pivot | GitHub | GitLab |
penguins-powerwash | GitHub | GitLab |
penguins-recovery | GitHub | GitLab |
rust-systems_deving
taubyte_deving
yaml-tooling_deving
| Repo | GitHub | GitLab |
|---|---|---|
CI-Debugger | GitHub | GitLab |
actions-orchestrator | GitHub | GitLab |
activitysmith-github-action | GitHub | GitLab |
agentshield | GitHub | GitLab |
blueprint | GitHub | GitLab |
confmgr | GitHub | GitLab |
deardir | GitHub | GitLab |
denoflow | GitHub | GitLab |
directory-model | GitHub | GitLab |
dirstructx | GitHub | GitLab |
fluent-github-actions | GitHub | GitLab |
gavi | GitHub | GitLab |
git-queue | GitHub | GitLab |
github-actions-virtualization-support | GitHub | GitLab |
github-actions-workflow-ts | GitHub | GitLab |
graphize | GitHub | GitLab |
katachi | GitHub | GitLab |
llm-docs-generator | GitHub | GitLab |
matrix-lock | GitHub | GitLab |
mnemonic | GitHub | GitLab |
models-generator | GitHub | GitLab |
pkgbuild-action | GitHub | GitLab |
project-memory-mcp | GitHub | GitLab |
pyvert | GitHub | GitLab |
scriptfs | GitHub | GitLab |
super-yaml | GitHub | GitLab |
system-cleanup-manager | GitHub | GitLab |
velite | GitHub | GitLab |
xml-yaml-json-converter | GitHub | GitLab |
y2j | GitHub | GitLab |
yaml-fuse | GitHub | GitLab |
yaml-sort | GitHub | GitLab |
yamler | GitHub | GitLab |
yamllint-ts | GitHub | GitLab |
Auto-generated by
generate-dep-graph.sh. Do not edit manually. Last generated: 2026-06-12 (stub — full graph generated on next scheduled run)
This graph maps every OSP-bound repo in Interested-Deving-1896 to its upstream
origin(s), as declared in each repo's ## Origins README section.
| Repo | Origin | Host | Fork in I-D-1896 |
|---|---|---|---|
github-codeowners | kohofinancial/github-codeowners | GitHub | ✅ |
github-codeowners | jjmschofield/github-codeowners | GitHub | ❌ |
gitlab-enhanced | openos-project/git-management_deving/gitlab-enhanced | GitLab | ✅ |
Summary
- OSP-bound repos scanned: stub (full scan runs weekly via
generate-dep-graph.yml) - Tooling dependencies tracked:
github-codeowners(CODEOWNERS auditing across all OSP repos)
Tooling Dependencies
| Tool | Purpose | Upstream |
|---|---|---|
| github-codeowners | Audits CODEOWNERS coverage — surfaces ownership stats per repo | kohofinancial/github-codeowners |
Source Tree
Auto-generated 2026-07-03 by
scripts/generate-book-pages.py
Complete directory and file index of the fork-sync-all source hierarchy. Click any path to view it on GitHub.
/ (root)/
| File | Description |
|---|---|
.clang-format | |
.dockerignore | |
.editorconfig | |
.gitignore | |
.gitlab-ci.yml | |
.gitmodules | |
.npmignore | |
.npmrc | |
.yamllint.yml | |
AGENTS.md | AI agent conventions, patterns, and known pitfalls |
CHANGELOG.md | |
CONTRIBUTING.md | |
LICENSE | |
README.md | Project overview, mirror chain diagram, workflow count |
book.toml | mdBook configuration — theme, search, output settings |
registered-imports.json | Upstream repos to keep in sync (registry) |
--help/
DOCS/
generated/
| File | Description |
|---|---|
glossary.md | |
source-tree.md |
.devcontainer/
Dev container configuration (devcontainer.json, features)
| File | Description |
|---|---|
Dockerfile | |
automations.template.yaml | |
devcontainer.json | |
devcontainer.template.json | |
install-security-tools.sh |
features/
dotdrop/
| File | Description |
|---|---|
devcontainer-feature.json | |
install.sh |
git-filter-repo/
| File | Description |
|---|---|
devcontainer-feature.json | |
install.sh |
git-platform-clis/
| File | Description |
|---|---|
devcontainer-feature.json | |
install.sh |
gitr/
| File | Description |
|---|---|
devcontainer-feature.json | |
install.sh |
glab/
| File | Description |
|---|---|
devcontainer-feature.json | |
install.sh |
incus/
| File | Description |
|---|---|
devcontainer-feature.json | |
install.sh |
sync-in-server/
| File | Description |
|---|---|
devcontainer-feature.json | |
install.sh |
.dotdrop/
dotfiles/
templates/
generic/
| File | Description |
|---|---|
blincus.yaml | |
incus-image.yaml |
go-service/
| File | Description |
|---|---|
blincus.yaml | |
incus-image.yaml |
nextjs-app/
| File | Description |
|---|---|
blincus.yaml | |
incus-image.yaml |
rust-service/
| File | Description |
|---|---|
blincus.yaml | |
incus-image.yaml |
vite-app/
| File | Description |
|---|---|
blincus.yaml | |
incus-image.yaml |
.github/
GitHub Actions workflows, issue templates, dependabot config
| File | Description |
|---|---|
FUNDING.yml | |
PULL_REQUEST_TEMPLATE.md | |
VOUCHED-upstreams.td | |
VOUCHED.td | |
dependabot.yml | |
labeler.yml | |
pull_request_template.md |
ISSUE_TEMPLATE/
| File | Description |
|---|---|
bug_report.md | |
config.yml | |
feature_request.md | |
new-repo-support.yml | |
patch-port-request.yml | |
vouch-onboard.yml |
workflows/
All 112 CI/CD workflow YAML files
.gitlab/
| File | Description |
|---|---|
scheduled-maintenance.yml |
merge_request_templates/
| File | Description |
|---|---|
Default.md |
.ona/
Ona automation config (automations.yaml)
| File | Description |
|---|---|
automations.yaml |
skills/
| File | Description |
|---|---|
fork-sync-all-audit.md | |
kport-audit.md | |
notifications-manager.md |
.ota/
| File | Description |
|---|---|
schema.yml |
.reuse/
| File | Description |
|---|---|
dep5 |
DOCS/
mdBook source — all documentation pages
| File | Description |
|---|---|
AGENTS.md | AI agent conventions, patterns, and known pitfalls |
OPERATIONS.md | |
README.md | Project overview, mirror chain diagram, workflow count |
SUMMARY.md | |
accessibility.md | |
ai-agent-costs.md | |
architecture.md | |
contributing.md | |
cover.md | |
fsa-api-deployment.md | |
ota-reconcile.md | |
ota-system.md | |
pre-flush-checklist.md | |
quota-costs.md | |
runbooks.md | |
workflow-scheduling.md | |
workflow-triggers.md | |
workflow-triggers.txt |
generated/
Auto-generated pages (rebuilt by generate-book-pages.py)
| File | Description |
|---|---|
eco-audit.md | |
glossary.md | |
origins.md | |
registered-imports.md | |
source-tree.md | |
subgroup-map.md | |
workflow-reference.md |
LICENSES/
| File | Description |
|---|---|
GPL-3.0-only.txt |
assets/
Static assets: brand logos, docs scaffolds, OTA stubs
| File | Description |
|---|---|
shell-tools-ci.yml | |
shell-tools-sync.yml |
brand/
Logo variants from discussion #125 (7 PNG options)
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
ooc/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
cover-title.md |
osp/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
cover-title.md |
source/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
cover-title.md | |
logo-option-1.png |
docs-scaffold/
Markdown scaffold files propagated to consumer repos
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
SUMMARY.md | |
contributing.md | |
getting-started.md |
ota-stub/
| File | Description |
|---|---|
config.yml |
config/
Single source of truth config files for all automation
data/
| File | Description |
|---|---|
agent-cost-log.json |
dep-graph/
Dependency graph outputs (origins.md, generated data)
| File | Description |
|---|---|
origins.md | |
provenance.yml |
docs/
Supplementary docs: workflow-triggers, NotebookLM outputs
| File | Description |
|---|---|
workflow-triggers.md | |
workflow-triggers.txt |
notebooklm/
NotebookLM export placeholders (audio, video, slides, etc.)
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
audio-overview/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
long/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
2026-06-17/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
medium/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
2026-06-17/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
short/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
2026-06-17/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
flashcards/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
fewer/
easy/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
2026-06-17/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
hard/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
2026-06-17/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
medium/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
2026-06-17/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
more/
easy/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
2026-06-17/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
hard/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
2026-06-17/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
medium/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
2026-06-17/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
standard/
easy/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
2026-06-17/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
hard/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
2026-06-17/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
medium/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
2026-06-17/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
infographic/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
landscape/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
2026-06-17/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
portrait/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
2026-06-17/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
square/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
2026-06-17/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
quiz/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
fewer/
easy/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
2026-06-17/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
hard/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
2026-06-17/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
medium/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
2026-06-17/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
more/
easy/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
2026-06-17/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
hard/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
2026-06-17/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
medium/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
2026-06-17/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
standard/
easy/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
2026-06-17/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
hard/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
2026-06-17/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
medium/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
2026-06-17/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
reports/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
blog-post/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
2026-06-17/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
briefing-doc/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
2026-06-17/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
study-guide/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
2026-06-17/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
slide-deck/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
detailed/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
2026-06-17/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
presenter/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
2026-06-17/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
video-overview/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
brief/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
2026-06-17/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
explainer/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
2026-06-17/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
open-notebook/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
audio-overview/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
reports/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
open-notebooklm/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
audio-overview/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
openbooklm/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
audio-overview/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
reports/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
fsa-api/
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
cli/
| File | Description |
|---|---|
fsa.sh |
config/
| File | Description |
|---|---|
fsa-consumer.yml | |
fsa-routes.yml | |
fsa-toggles.yml |
core/
adapters/
bdfs/
chain/
codebase/
deployments/
| File | Description |
|---|---|
dispatch.sh | |
list.sh | |
status.sh | |
workflows.sh |
docs/
| File | Description |
|---|---|
content.sh | |
dispatch.sh | |
list.sh | |
status.sh |
notifications/
quota/
| File | Description |
|---|---|
status.sh |
repos/
| File | Description |
|---|---|
list.sh | |
onboard.sh |
security/
| File | Description |
|---|---|
scan.sh |
toggles/
workflows/
lib/
| File | Description |
|---|---|
fsa-adapter.sh |
scripts/
| File | Description |
|---|---|
scaffold-consumer.sh |
server/
| File | Description |
|---|---|
fsa-start.sh |
uaa/
| File | Description |
|---|---|
.gitignore | |
README.md | Project overview, mirror chain diagram, workflow count |
.github/
workflows/
| File | Description |
|---|---|
ci.yml | |
server-test.yml |
scripts/
All first-party automation scripts
eco/
| File | Description |
|---|---|
eco-audit.sh | |
eco-ci-shell.sh | |
gitlab-ci-eco.yml.tpl |
includes/
Shared shell + Python includes sourced by multiple scripts
| File | Description |
|---|---|
budget.sh | Quota budget helpers: budget_init, budget_check |
bugzilla-api.sh | |
fsa-mode.sh | Managed/autonomous mode detection (3-tier check) |
fsa-node-identity.sh | Chain position layer: source/mirror/downstream-fork |
gh-api.sh | GitHub API helpers: gh_get, gh_api, merge_upstream |
llm.sh | |
pipeline-guard.sh | |
platform-adapter.sh | |
pr-lifecycle.sh | |
quota-instrument.sh | |
quota-snapshot.sh | |
shell-tools.sh | |
time_format.py | Dual-format world-timezone display (484 IANA zones) |
kport/
| File | Description |
|---|---|
kport-build-flags.sh | |
kport-detect-cpu.sh | |
kport-detect-gpu.sh | |
kport-detect-npu.sh | |
kport-detect.sh | |
kport-toolchain.sh |
tests/
| File | Description |
|---|---|
test-check-readme-render-mobile.sh |
services/
sync-in/
| File | Description |
|---|---|
install.sh | |
start.sh |
tests/
eco/
ocs/
| File | Description |
|---|---|
test-eco-certified.sh | |
test-providers.sh |
integration/
unit/
| File | Description |
|---|---|
CMakeLists.txt | |
test_compression.c | |
test_copyup_job.c | |
test_exec_wrappers.c | |
test_job_alloc.c | |
test_policy_engine.c | |
test_socket_dispatch.c | |
test_uuid.c |
vendor/
Third-party components hosted/deployed by fork-sync-all
book-engine/
Agnostic book export backend (mdBook, MkDocs, Docusaurus, Pandoc)
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
adapters/
Per-engine build adapters
| File | Description |
|---|---|
gitbook-oss.sh | |
gitbook.sh | |
kapidox.sh | |
mdbook.sh | |
mkdocs.sh | |
pandoc.sh |
config/
| File | Description |
|---|---|
engines.yml |
scripts/
| File | Description |
|---|---|
export.sh | |
summary_to_nav.py |
themes/
Brand themes (FSA theme: CSS, JS, cover)
fsa/
| File | Description |
|---|---|
book.js | |
custom.css | |
mkdocs-extra.css |
infra-dashboard/
Unified infrastructure platform (statuspage, dashboards)
| File | Description |
|---|---|
.gitlab-ci.yml | |
README.md | Project overview, mirror chain diagram, workflow count |
config.example.env | |
docker-compose.yml |
.github/
workflows/
| File | Description |
|---|---|
deploy-pages.yml |
bin-pastebin/
| File | Description |
|---|---|
.dockerignore | |
.gitignore | |
Cargo.lock | |
Cargo.toml | |
Dockerfile | |
build.rs | |
copying | |
docker-compose.yml | |
fly.toml | |
readme.md | |
rustfmt.toml |
.cargo/
| File | Description |
|---|---|
config.toml |
.github/
| File | Description |
|---|---|
buildci.sh | |
pull_request_template.md |
files/
| File | Description |
|---|---|
drag_n_drop.gif | |
image_clipboard.gif |
workflows/
| File | Description |
|---|---|
buildci.yml | |
docker.yml | |
flyci.yml |
contrib/
cli/
| File | Description |
|---|---|
client |
resources/
syntaxes/
| File | Description |
|---|---|
syntaxes.bin |
themes/
| File | Description |
|---|---|
ayu_dark.tmTheme |
src/
| File | Description |
|---|---|
main.rs |
models/
| File | Description |
|---|---|
mod.rs | |
paste_id.rs | |
pretty.rs | |
pretty_syntax.rs | |
response_wrapper.rs |
routes/
| File | Description |
|---|---|
index.rs | |
mod.rs | |
pretty_retrieve.rs | |
retrieve.rs | |
static_files.rs | |
submit.rs | |
upload.rs | |
version.rs |
static/
| File | Description |
|---|---|
site.webmanifest |
css/
| File | Description |
|---|---|
index.css | |
pretty.css |
fonts/
| File | Description |
|---|---|
iosevka.css |
ttf/
| File | Description |
|---|---|
iosevka-bold.ttf | |
iosevka-italic.ttf | |
iosevka-regular.ttf |
woff2/
| File | Description |
|---|---|
iosevka-bold.woff2 | |
iosevka-italic.woff2 | |
iosevka-regular.woff2 |
js/
media/
| File | Description |
|---|---|
android-chrome-192x192.png | |
android-chrome-512x512.png | |
apple-touch-icon.png | |
favicon-16x16.png | |
favicon-32x32.png | |
favicon.ico |
templates/
| File | Description |
|---|---|
base.html.tera | |
index.html.tera | |
pretty.html.tera |
tools/
| File | Description |
|---|---|
prepush |
builder-dashboard/
| File | Description |
|---|---|
.gitignore | |
.prettierrc.json | |
.whitesource | |
[CachyOS Builder Dashboard.code-workspace](https://github.com/Interested-Deving-1896/fork-sync-all/blob/main/vendor/infra-dashboard/builder-dashboard/CachyOS Builder Dashboard.code-workspace) | |
README.md | Project overview, mirror chain diagram, workflow count |
bun.lock | |
components.json | |
eslint.config.mjs | |
next.config.ts | |
package.json | |
postcss.config.mjs | |
tsconfig.json |
.github/
workflows/
| File | Description |
|---|---|
deploy.yml |
public/
| File | Description |
|---|---|
cachyos-logo-white.svg | |
cachyos-logo.svg |
src/
app/
| File | Description |
|---|---|
apple-icon.png | |
favicon.ico | |
globals.css | |
icon.png | |
layout.tsx | |
manifest.ts | |
page.tsx | |
robots.ts |
actions/
| File | Description |
|---|---|
audit-logs.ts | |
custom.ts | |
packages.ts | |
repo-actions.ts | |
session.ts | |
stats.ts | |
users.ts |
api/
logs/
[march]/
[pkgbase]/
| File | Description |
|---|---|
route.ts |
dashboard/
| File | Description |
|---|---|
layout.tsx |
audit-logs/
| File | Description |
|---|---|
page.tsx |
custom/
| File | Description |
|---|---|
_tabs.tsx | |
layout.tsx | |
page.tsx |
maintainers/
| File | Description |
|---|---|
page.tsx |
[username]/
| File | Description |
|---|---|
page.tsx |
packages/
| File | Description |
|---|---|
page.tsx |
repos/
| File | Description |
|---|---|
page.tsx |
[id]/
| File | Description |
|---|---|
page.tsx |
submissions/
| File | Description |
|---|---|
_bulk-dialog.tsx | |
_filter-bar.tsx | |
_row.tsx | |
_selection-bar.tsx | |
_types.ts | |
_use-bulk-actions.ts | |
page.tsx |
[id]/
| File | Description |
|---|---|
_header.tsx | |
_history-card.tsx | |
_logs-card.tsx | |
_review-note-card.tsx | |
_source-card.tsx | |
_timeline-card.tsx | |
page.tsx |
logs/
[march]/
[pkgbase]/
| File | Description |
|---|---|
page.tsx |
package-list/
| File | Description |
|---|---|
page.tsx |
profile/
| File | Description |
|---|---|
page.tsx |
[username]/
| File | Description |
|---|---|
page.tsx |
rebuild-queue/
| File | Description |
|---|---|
page.tsx |
repo-actions/
| File | Description |
|---|---|
page.tsx |
statistics/
| File | Description |
|---|---|
page.tsx |
validate/
| File | Description |
|---|---|
page.tsx |
components/
custom/
| File | Description |
|---|---|
add-maintainer-dialog.tsx | |
package-status.ts | |
review-note-dialog.tsx | |
submission-status.ts | |
submit-package-dialog.tsx |
ui/
hooks/
| File | Description |
|---|---|
use-keyboard-shortcut-listener.ts | |
use-mobile.ts |
lib/
| File | Description |
|---|---|
saved-views.ts | |
session.ts | |
toast-action.ts | |
typings.ts | |
utils.tsx |
api/
| File | Description |
|---|---|
audit-logs.ts | |
base.ts | |
custom.ts | |
helpers.ts | |
index.ts | |
maintainers.ts | |
packages.ts | |
repo-actions.ts | |
stats.ts | |
users.ts |
hooks/
| File | Description |
|---|---|
use-infinite-list.ts |
mirrorlist/
| File | Description |
|---|---|
cachyos-mirrorlist |
mirrorlist-proxy/
| File | Description |
|---|---|
.air.toml | |
.gitignore | |
Dockerfile | |
LICENSE | |
README.md | Project overview, mirror chain diagram, workflow count |
docker-compose.yml | |
go.mod | |
main.go |
public-dashboard/
| File | Description |
|---|---|
.dockerignore | |
.env.example | |
.gitignore | |
.oxlintrc.json | |
Dockerfile | |
LICENSE | |
README.md | Project overview, mirror chain diagram, workflow count |
biome.json | |
bun.lock | |
components.json | |
docker-compose.yml | |
example-dark.png | |
example-light.png | |
package.json | |
server.mjs | |
tsconfig.json | |
vite.config.ts |
.github/
workflows/
| File | Description |
|---|---|
checks.yml |
public/
| File | Description |
|---|---|
favicon.ico | |
icon-192.png | |
icon-512.png | |
icon.svg | |
manifest.json |
scripts/
| File | Description |
|---|---|
prefill-cache.ts |
src/
| File | Description |
|---|---|
routeTree.gen.ts | |
router.tsx |
assets/
| File | Description |
|---|---|
icon.svg |
components/
ui/
| File | Description |
|---|---|
alert.tsx | |
badge.tsx | |
button.tsx | |
card.tsx | |
collapsible.tsx | |
dropdown-menu.tsx | |
input.tsx | |
label.tsx | |
select.tsx | |
skeleton.tsx | |
table.tsx |
hooks/
| File | Description |
|---|---|
use-keyboard-shortcut-listener.ts |
lib/
| File | Description |
|---|---|
archlinux.ts | |
errors.ts | |
fetcher.test.ts | |
fetcher.ts | |
github.ts | |
mirrors-client.ts | |
mirrors.ts | |
query-actions.ts | |
types.ts | |
utils.test.ts | |
utils.ts |
server/
| File | Description |
|---|---|
actions.ts | |
source-url.ts | |
swr-cache.test.ts | |
swr-cache.ts |
routes/
| File | Description |
|---|---|
__root.tsx | |
index.tsx | |
mirrors.tsx | |
package.$repo.$arch.$pkgname.tsx |
api/
| File | Description |
|---|---|
package.$repo.$arch.$pkgname.files.ts | |
search.ts |
styles/
| File | Description |
|---|---|
globals.css |
rate-mirrors/
| File | Description |
|---|---|
.gitignore | |
.ignore | |
CHANGELOG.md | |
Cargo.lock | |
Cargo.toml | |
LICENSE | |
Makefile | |
README.md | Project overview, mirror chain diagram, workflow count |
rustfmt.toml | |
stdin.txt |
.github/
workflows/
| File | Description |
|---|---|
release.yml |
src/
| File | Description |
|---|---|
config.rs | |
countries.rs | |
lib.rs | |
main.rs | |
mirror.rs | |
speed_test.rs |
target_configs/
| File | Description |
|---|---|
arch4edu.rs | |
archarm.rs | |
archlinux.rs | |
archlinuxcn.rs | |
arcolinux.rs | |
artix.rs | |
blackarch.rs | |
cachyos.rs | |
chaotic.rs | |
endeavouros.rs | |
manjaro.rs | |
mod.rs | |
openbsd.rs | |
rebornos.rs | |
stdin.rs |
targets/
| File | Description |
|---|---|
arch4edu.rs | |
archarm.rs | |
archlinux.rs | |
archlinuxcn.rs | |
arcolinux.rs | |
artix.rs | |
blackarch.rs | |
cachyos.rs | |
chaotic.rs | |
endeavouros.rs | |
manjaro.rs | |
mod.rs | |
openbsd.rs | |
rebornos.rs | |
stdin.rs |
statuspage/
| File | Description |
|---|---|
.gitattributes | |
.upptimerc.yml | |
LICENSE | |
README.md | Project overview, mirror chain diagram, workflow count |
.github/
ISSUE_TEMPLATE/
| File | Description |
|---|---|
bug_report.md | |
config.yml | |
maintainance-event.md |
workflows/
| File | Description |
|---|---|
graphs.yml | |
response-time.yml | |
setup.yml | |
site.yml | |
summary.yml | |
update-template.yml | |
updates.yml | |
uptime.yml |
api/
austria-mirror/
bangladesh-mirror/
canada-mirror/
canada-mirror-quebec/
cdn-77-cdn-worldwide/
china-mirror-nanjing/
china-mirror-ustc/
discuss/
finland-mirror/
france-mirror/
germany-mirror/
italy-mirror-m1k-cloud/
italy-mirror-next-works/
netherlands-mirror/
norway-mirror/
russia-mirror-archlinux-gay/
russia-mirror-cachy-arch-ru/
russia-mirror-jura12/
russia-mirror-metrosg-ru/
sweden-mirror/
switzerland-mirror/
usa-cdn-michigan/
usa-mirror/
usa-mirror-michigan/
usa-mirror-minnesota/
website/
wiki/
assets/
| File | Description |
|---|---|
upptime-icon.svg |
graphs/
austria-mirror/
| File | Description |
|---|---|
response-time-day.png | |
response-time-month.png | |
response-time-week.png | |
response-time-year.png | |
response-time.png |
bangladesh-mirror/
| File | Description |
|---|---|
response-time-day.png | |
response-time-month.png | |
response-time-week.png | |
response-time-year.png | |
response-time.png |
canada-mirror/
| File | Description |
|---|---|
response-time-day.png | |
response-time-month.png | |
response-time-week.png | |
response-time-year.png | |
response-time.png |
canada-mirror-quebec/
| File | Description |
|---|---|
response-time-day.png | |
response-time-month.png | |
response-time-week.png | |
response-time-year.png | |
response-time.png |
cdn-77-cdn-worldwide/
| File | Description |
|---|---|
response-time-day.png | |
response-time-month.png | |
response-time-week.png | |
response-time-year.png | |
response-time.png |
china-mirror-nanjing/
| File | Description |
|---|---|
response-time-day.png | |
response-time-month.png | |
response-time-week.png | |
response-time-year.png | |
response-time.png |
china-mirror-ustc/
| File | Description |
|---|---|
response-time-day.png | |
response-time-month.png | |
response-time-week.png | |
response-time-year.png | |
response-time.png |
discuss/
| File | Description |
|---|---|
response-time-day.png | |
response-time-month.png | |
response-time-week.png | |
response-time-year.png | |
response-time.png |
finland-mirror/
| File | Description |
|---|---|
response-time-day.png | |
response-time-month.png | |
response-time-week.png | |
response-time-year.png | |
response-time.png |
france-mirror/
| File | Description |
|---|---|
response-time-day.png | |
response-time-month.png | |
response-time-week.png | |
response-time-year.png | |
response-time.png |
germany-mirror/
| File | Description |
|---|---|
response-time-day.png | |
response-time-month.png | |
response-time-week.png | |
response-time-year.png | |
response-time.png |
italy-mirror-m1k-cloud/
| File | Description |
|---|---|
response-time-day.png | |
response-time-month.png | |
response-time-week.png | |
response-time-year.png | |
response-time.png |
italy-mirror-next-works/
| File | Description |
|---|---|
response-time-day.png | |
response-time-month.png | |
response-time-week.png | |
response-time-year.png | |
response-time.png |
netherlands-mirror/
| File | Description |
|---|---|
response-time-day.png | |
response-time-month.png | |
response-time-week.png | |
response-time-year.png | |
response-time.png |
norway-mirror/
| File | Description |
|---|---|
response-time-day.png | |
response-time-month.png | |
response-time-week.png | |
response-time-year.png | |
response-time.png |
russia-mirror-archlinux-gay/
| File | Description |
|---|---|
response-time-day.png | |
response-time-month.png | |
response-time-week.png | |
response-time-year.png | |
response-time.png |
russia-mirror-cachy-arch-ru/
| File | Description |
|---|---|
response-time-day.png | |
response-time-month.png | |
response-time-week.png | |
response-time-year.png | |
response-time.png |
russia-mirror-jura12/
| File | Description |
|---|---|
response-time-day.png | |
response-time-month.png | |
response-time-week.png | |
response-time-year.png | |
response-time.png |
russia-mirror-metrosg-ru/
| File | Description |
|---|---|
response-time-day.png | |
response-time-month.png | |
response-time-week.png | |
response-time-year.png | |
response-time.png |
sweden-mirror/
| File | Description |
|---|---|
response-time-day.png | |
response-time-month.png | |
response-time-week.png | |
response-time-year.png | |
response-time.png |
switzerland-mirror/
| File | Description |
|---|---|
response-time-day.png | |
response-time-month.png | |
response-time-week.png | |
response-time-year.png | |
response-time.png |
usa-cdn-michigan/
| File | Description |
|---|---|
response-time-day.png | |
response-time-month.png | |
response-time-week.png | |
response-time-year.png | |
response-time.png |
usa-mirror/
| File | Description |
|---|---|
response-time-day.png | |
response-time-month.png | |
response-time-week.png | |
response-time-year.png | |
response-time.png |
usa-mirror-michigan/
| File | Description |
|---|---|
response-time-day.png | |
response-time-month.png | |
response-time-week.png | |
response-time-year.png | |
response-time.png |
usa-mirror-minnesota/
| File | Description |
|---|---|
response-time-day.png | |
response-time-month.png | |
response-time-week.png | |
response-time-year.png | |
response-time.png |
website/
| File | Description |
|---|---|
response-time-day.png | |
response-time-month.png | |
response-time-week.png | |
response-time-year.png | |
response-time.png |
wiki/
| File | Description |
|---|---|
response-time-day.png | |
response-time-month.png | |
response-time-week.png | |
response-time-year.png | |
response-time.png |
history/
| File | Description |
|---|---|
LICENSE |
notifications-ui/
| File | Description |
|---|---|
index.html |
shell-tools/
Vendored shell utility repos (22 tools)
| File | Description |
|---|---|
README.md | Project overview, mirror chain diagram, workflow count |
Smart-File-Organizer/
| File | Description |
|---|---|
.keep |
User-Filesystem/
| File | Description |
|---|---|
.keep |
achievements/
| File | Description |
|---|---|
.keep |
bibhelper/
| File | Description |
|---|---|
.keep |
fswatch-Filesystem-Events-Watchfolder-Shell-Script/
| File | Description |
|---|---|
.keep |
git-release-shell/
| File | Description |
|---|---|
.keep |
hrsync/
| File | Description |
|---|---|
.keep |
ipinfo/
| File | Description |
|---|---|
.keep |
jail-sh/
| File | Description |
|---|---|
.keep |
linux-shell-script-archive/
| File | Description |
|---|---|
.keep |
mass_clone/
| File | Description |
|---|---|
.keep |
mist.sh/
| File | Description |
|---|---|
.keep |
mkinitcpio-dir/
| File | Description |
|---|---|
.keep |
namefix/
| File | Description |
|---|---|
.keep |
operation-phantom-shell/
| File | Description |
|---|---|
.keep |
remote-sync/
| File | Description |
|---|---|
.keep |
rm-safely/
| File | Description |
|---|---|
.keep |
shellqueue/
| File | Description |
|---|---|
.keep |
simple-deploy/
| File | Description |
|---|---|
.keep |
sizes/
| File | Description |
|---|---|
.keep |
smartcd/
| File | Description |
|---|---|
.keep |
swap.sh/
| File | Description |
|---|---|
.keep |
tomb/
| File | Description |
|---|---|
.keep |
utility_shell/
| File | Description |
|---|---|
.keep |
unified-agnostic-api/
Shell-based HTTP API framework with platform adapters
| File | Description |
|---|---|
.gitignore | |
README.md | Project overview, mirror chain diagram, workflow count |
.github/
workflows/
| File | Description |
|---|---|
ci.yml | |
server-test.yml |
Glossary
Auto-generated 2026-07-03 by
scripts/generate-book-pages.py
Definitions for every term, acronym, and concept used across fork-sync-all.
Index
A: ACTOR_TZ · AGENTS.md · autonomous mode
B: book-engine · brand.yml · budget.sh
C: chain position · consumer repo · critical-deploy
D: DRY_RUN
E: Etc/GMT+N
F: FSA API · fsa-mode.sh · fsa-node-identity.sh · full-chain-flush
G: generate-book-pages.py · gh-api.sh · GitLab subgroup · GraphQL · GROUP_SORT_KEYS
I: IANA timezone · infra-core profile
M: managed mode · MCP server · mdBook · MIN_QUOTA · mirror chain
N: node identity
O: OOC · OSP · OSP-bound repo · OTA
P: platform-adapter.sh · pre-flush-prep · priority tiers
Q: queue-manager · quota-reserve · quota-snapshot.sh
R: registered-imports.json
S: SUMMARY.md · SYNC_TOKEN
T: template-manifest.yml · time_format.py
V: vendor/
W: workflow-quota-costs.yml · WORLD_ZONES
- ACTOR_TZ
- IANA timezone of the person who triggered a workflow. Set via `ACTOR_TZ`, `TRIGGERER_TZ`, or `GITHUB_ACTOR_TZ` env vars. Highlighted in world_table() output.
- AGENTS.md
- Convention file for AI agents working in this repo. Defines logging rules, YAML-safe shell patterns, quota management, workflow patterns, and known pitfalls.
- autonomous mode
- Operating mode when fork-sync-all is not present alongside a consumer repo. Bundled workflows activate and self-manage, scoped to the repo's own owner.
- book-engine
- Agnostic documentation export backend in `vendor/book-engine/`. Supports mdBook, MkDocs, Docusaurus, GitBook CLI, and Pandoc from a single Markdown source.
- brand.yml
- Single source of truth for fork-sync-all branding: logo URL, color palette, substitution tokens (`{{FSA_NAME}}` etc.), and book theme settings.
- budget.sh
- Shared include providing `budget_init`, `budget_check`, `budget_report`, `osp_priority_repos`, and `workflow_min_quota`. Reads per-workflow `min_quota` from `workflow-quota-costs.yml`.
- chain position
- Where a fork-sync-all instance sits in the mirror chain: `source` (Interested-Deving-1896), `mirror` (OSP/OOC), or `downstream-fork` (independent fork).
- consumer repo
- Any repo that receives template files from fork-sync-all via `sync-template.sh`. Defined in `config/template-consumers.yml`.
- critical-deploy
- Fast-lane workflow for emergency deployments: commit + push → aggressive queue clear → priority dispatch. Manual trigger only.
- DRY_RUN
- Environment variable flag. When `true`, scripts print what they would do without making any changes. Supported by all major scripts.
- Etc/GMT+N
- IANA timezone notation where the sign is inverted from UTC offset convention. `Etc/GMT+5` = UTC-5 (EST). All 484 IANA zones are included in `time_format.py`.
- FSA API
- The `ona-mcp-server.py` MCP server exposing 5 tools: `list_projects`, `get_project`, `create_environment`, `sync_projects`, `get_config_summary`. Runs on port 8788.
- fsa-mode.sh
- Three-tier managed/autonomous detection: (B) `FSA_MANAGED` repo variable → (A) GET `/repos/{owner}/fork-sync-all` → (C) token owner's fork-sync-all existence.
- fsa-node-identity.sh
- Extends fsa-mode.sh with chain position detection. Exports `FSA_NODE_POSITION`, `FSA_NODE_OWNER`, `FSA_UPSTREAM_OWNER`, `FSA_CHAIN_DEPTH`.
- full-chain-flush
- End-to-end pipeline: pre-flush-prep → mirror chain → post-flush-prep. Triggered manually or by critical-deploy.
- generate-book-pages.py
- Script that generates `DOCS/generated/` pages from live config sources. Also injects index + glossary into workflow-triggers.md.
- gh-api.sh
- Shared include providing `gh_api`, `gh_get`, `gh_api_graphql`, `merge_upstream`, `get_default_sha`. All status messages use `>&2`.
- GitLab subgroup
- Organizational unit in the `openos-project` GitLab group. Defined in `config/gitlab-subgroups.yml`. 14 subgroups covering ~225 repos.
- GraphQL
- Preferred over paginated REST for any loop fetching the same data for multiple repos. Counts as 1 REST call regardless of how many repos are queried.
- GROUP_SORT_KEYS
- Dict in `generate-workflow-triggers-doc.py` mapping group names to filename-substring lists for non-alphabetical display ordering.
- IANA timezone
- Standard timezone identifier from the IANA Time Zone Database (e.g. `America/Toronto`, `Europe/Paris`). `time_format.py` covers all 484 zones.
- infra-core profile
- Template profile providing CI hygiene + autonomous-fallback workflows. Includes PR automation, token rotation, branch cleanup, mdBook workflows, OTA, accessibility.
- managed mode
- Default operating mode when fork-sync-all is present. Bundled autonomous-fallback workflows detect this and skip themselves.
- MCP server
- Model Context Protocol server. `ona-mcp-server.py` exposes FSA operations as MCP tools consumable by any MCP-compatible AI agent.
- mdBook
- Rust-based static site generator used as the primary book engine. Source in `DOCS/`, config in `book.toml`, deployed to GitHub Pages by `deploy-book.yml`.
- MIN_QUOTA
- Minimum remaining REST quota required before a workflow proceeds. Set per-workflow in `config/workflow-quota-costs.yml`. Typically 500–1500.
- mirror chain
- Three-org pipeline: Interested-Deving-1896 → OpenOS-Project-OSP (GitHub) → openos-project (GitLab). Managed by mirror-to-osp.yml, mirror-osp-to-gitlab.yml.
- node identity
- The position of a fork-sync-all instance in the mirror chain. See `fsa-node-identity.sh`. Determines which operations the instance runs.
- OOC
- OpenOS-Project-Ecosystem-OOC — the third org in the mirror chain (GitHub). Receives mirrors from OSP.
- OSP
- OpenOS-Project-OSP — the second org in the mirror chain (GitHub). Receives mirrors from Interested-Deving-1896.
- OSP-bound repo
- A repo in Interested-Deving-1896 that is mirrored into OSP and managed by fork-sync-all (README updates, badge injection, CI checks, etc.).
- OTA
- Over-the-air update system. Delivers workflow and config updates from fork-sync-all to consumer repos without requiring manual PRs.
- platform-adapter.sh
- Uniform interface for GitHub, GitLab, Gitea, Forgejo, and Codeberg. Abstracts API differences behind a common shell interface.
- pre-flush-prep
- Pre-flight workflow run before full-chain-flush. Checks quota, validates configs, merges pending PRs, cleans stale branches.
- priority tiers
- Four-tier workflow priority system: Tier 1 CRITICAL (never cancelled), Tier 2 HIGH (mirror/sync), Tier 3 MEDIUM (READMEs/CI), Tier 4 LOW (translation/maintenance).
- queue-manager
- Workflow that deduplicates queued runs (keeps newest per workflow) and evicts runs queued > 25 min. Runs every 30 min.
- quota-reserve
- Workflow that cancels low-priority queued runs when quota drops below 1000. Uses per-workflow `min_quota` for cost-aware cancellation.
- quota-snapshot.sh
- Shared include that captures a REST quota snapshot and writes it to a GitHub Actions variable. Must run after `actions/checkout`.
- registered-imports.json
- Registry of upstream repos to keep in sync. Read by `sync-registered-imports.sh` and `sync-registry-sources.yml`.
- SUMMARY.md
- mdBook navigation file. Defines the book's table of contents. All book-engine adapters translate this into their native nav format.
- SYNC_TOKEN
- GitHub token used for cross-org operations. Shares the same 5000 req/hr REST bucket as `GH_TOKEN` (same user ID 202036334).
- template-manifest.yml
- Defines 6 named propagation profiles (full, mirror, infra-core, upstream-sync, standalone, shell-tools) and their file inclusion lists.
- time_format.py
- Shared Python module providing dual 12h/24h format across all 484 IANA timezones. Includes actor/runner timezone detection and `--test` self-test.
- vendor/
- Third-party components hosted/deployed by fork-sync-all. Not first-party scripts. Contains infra-dashboard, shell-tools, unified-agnostic-api, book-engine.
- workflow-quota-costs.yml
- Per-workflow REST call cost registry. Drives quota-reserve.sh cancellation, budget.sh pre-flight, and DOCS/quota-costs.md documentation.
- WORLD_ZONES
- Dynamic list of all 484 IANA timezone zones in `time_format.py`. Built at import time from `zoneinfo.available_timezones()`, sorted west→east.
Eco Audit
Generated 2026-06-29 by
scripts/eco/eco-audit.shAligned with KDE Eco / Blue Angel DE-UZ 215 criteria.
Score: 🟡 14/20 (70%) — B — Good
| Check | Score | Detail |
|---|---|---|
| ❌ green hosting | 0/2 | Green hosting (❌ Not verified green — hosted by unknown) |
| ✅ foss license | 2/2 | FOSS license present (LICENSE) + REUSE/SPDX compliant (.reuse/dep5 + LICENSES/) |
| ✅ no telemetry | 2/2 | No telemetry/tracking found |
| ⚠️ no forced updates | 1/2 | Possible forced update patterns (7 hits — review manually) |
| ✅ concurrency groups | 2/2 | Concurrency groups: 164/181 workflows (90%) |
| ✅ graphql adoption | 2/2 | GraphQL adopted in 35 scripts (reduces API quota consumption) |
| ✅ dep minimalism | 2/2 | Low dependency footprint: 0.2 installs/workflow avg |
| ⚠️ carbon estimate | 1/2 | Carbon estimate available: ~27.13 kg CO2e/year (stub — KEcoLab needed for precision) |
| ❌ keco lab | 0/2 | KEcoLab: not yet configured (stub — requires GitLab CI + physical hardware) |
| ✅ old hardware | 2/2 | No minimum hardware requirements specified (shell scripts run on any hardware) |
Carbon Footprint Estimate
| Parameter | Value | Source |
|---|---|---|
| Daily workflow runs | ~100 | Estimate |
| Avg job duration | ~3 min | Estimate |
| Runner TDP | ~30W | GitHub ubuntu-latest (2-core shared VM) |
| Azure PUE | 1.18 | Microsoft 2023 Sustainability Report |
| Grid intensity | 420 gCO2/kWh | EPA eGRID 2022, MROW (Azure North Central US) |
| Annual estimate | ~27.13 kg CO2e/year | Proxy — not measured |
⚠️ This is a proxy estimate. Precise measurement requires KEcoLab.
Green Hosting
- URL checked:
https://interested-deving-1896.github.io/fork-sync-all/ - Result: ❌ Not verified green — hosted by unknown
- Checker: Green Web Foundation
KEcoLab (GitLab Stub)
KEcoLab is KDE's remote energy measurement lab. It uses a physical power meter connected to test hardware to measure actual watt-hours consumed per use case.
This cannot run on GitHub Actions — it requires physical hardware at KDE's infrastructure. The stub below is ready to activate when hosted on GitLab.
Setup steps
- Write
KdeEcoTestscripts simulating user interactions with your software - Add
.gitlab-ci-eco.ymlto your repo (template:scripts/eco/gitlab-ci-eco.yml.tpl) - Submit to KEcoLab: https://invent.kde.org/teams/eco/remote-eco-lab
- Receive energy consumption report (watt-hours per use case)
- Apply for Blue Angel DE-UZ 215 if criteria are met
Resources
| Resource | URL |
|---|---|
| KEcoLab repository | https://invent.kde.org/teams/eco/remote-eco-lab |
| KDE Eco Handbook | https://eco.kde.org/be4foss-handbook |
| KdeEcoTest tool | https://invent.kde.org/teams/eco/feep/-/tree/master/tools/KdeEcoTest |
| Blue Angel criteria | https://www.blauer-engel.de/en/certification/criteria |
| Criteria PDF (DE-UZ 215) | https://www.blauer-engel.de/sites/default/files/vergabegrundlagen-dokumente/DE-UZ-215-Vergabegrundlagen-2020-01-01.pdf |
CI Efficiency Stats
| Metric | Value |
|---|---|
| Total workflows | 181 |
| Workflows with concurrency groups | 164 (90%) |
| Scripts using GraphQL | 35 |
| apt-get install calls | 20 |
| pip install calls | 18 |
| npm/yarn/bun install calls | 6 |
Blue Angel DE-UZ 215 Checklist
| Criterion | Status | Notes |
|---|---|---|
| FOSS license | ✅ | Open source — transparency by design |
| No telemetry / tracking | ✅ | No analytics, beacons, or tracking scripts |
| No forced updates | ✅ | All updates are opt-in via OTA system |
| Runs on old hardware | ✅ | Shell scripts — no minimum spec |
| User data control | ✅ | No user data collected |
| Energy measurement | ⏳ Stub | Requires KEcoLab (GitLab) |
| Documented energy use | ⏳ Stub | Pending KEcoLab measurement |
| Green hosting | ❌ Not verified green — hosted by unknown | GitHub Pages via Azure |
Full glossary: Glossary · Eco resources: eco.kde.org
Pre-Flush Checklist
Steps to verify before triggering flush-lifecycle.yml (the recommended entry
point) or full-chain-flush.yml directly (bypass mode only).
Most are zero-API-call operations — safe to run while quota is exhausted.
1. Check quota
curl -sf -H "Authorization: token $SYNC_TOKEN" \
"https://api.github.com/rate_limit" | python3 -c "
import sys, json
from datetime import datetime, timezone
d = json.load(sys.stdin)
core = d['resources']['core']
reset = datetime.fromtimestamp(core['reset'], tz=timezone.utc)
now = datetime.now(tz=timezone.utc)
eta = max(0, int((reset - now).total_seconds()))
print(f'Remaining : {core[\"remaining\"]}/{core[\"limit\"]}')
print(f'Reset at : {reset.strftime(\"%H:%M:%S UTC\")}')
print(f'ETA : {eta//60}m {eta%60}s')
"
pre-flush-prep requires at least 500 remaining to proceed past its quota
pre-flight. Below that it exits 1 and emits a log line that
rate-limit-rerun.yml detects — it will re-dispatch automatically after the
reset. The flush itself needs ~1000–1500 to complete without hitting the reserve
floor mid-way.
2. Run config validators
All must pass with zero errors.
python3 scripts/validate-gitlab-subgroups.py config/gitlab-subgroups.yml
python3 scripts/validate-registered-imports.py registered-imports.json
python3 scripts/validate-registered-imports.py registered-imports.json --vouch-check
python3 scripts/validate-cost-profiles.py config/workflow-cost-profiles.yml
python3 scripts/validate-priority-tiers.py config/workflow-priority-tiers.yml
python3 scripts/validate-template-config.py
python3 scripts/validate-workflow-guards.py
Expected output pattern:
config/gitlab-subgroups.yml: 14 subgroups, N repos — ✅ Valid
validate-registered-imports: 157 entry/entries valid (157 unique targets, 157 unique sources)
vouch-check: 0 unvouched upstream org(s)
validate-cost-profiles: 42 profile(s) valid
validate-priority-tiers: N entries valid (tier1=19, tier2=19, tier3=62, tier4=54)
validate-template-config: 7 profile(s) valid, 80 consumer(s) valid
validate-workflow-guards: all checks passed (N workflows, ...)
If --vouch-check reports unvouched orgs, add them to .github/VOUCHED-upstreams.td
after reviewing the upstream for supply-chain risk, then re-run.
3. Run the test suite
python3 -m pytest tests/ -v --tb=short
All tests must pass. Current baseline: 340 tests. A lower count means a test file was accidentally deleted or a conftest broke collection.
4. ShellCheck modified scripts
git diff --name-only HEAD~5 -- 'scripts/*.sh' | xargs -r shellcheck --severity=warning
SC1091 (not following sourced files) is expected and acceptable across all
scripts that source includes/budget.sh, includes/gh-api.sh, or
includes/pr-lifecycle.sh.
5. Check for open PRs
Open PRs that are green and mergeable should be merged before the flush.
pre-flush-prep Step 2 auto-merges eligible PRs (mergeable_state == "clean"),
but GitHub only computes mergeability after CI runs — ensure CI has completed
on all open PRs before triggering.
Dependency-update PRs (chore(deps): update workflow dependencies) are safe
to merge without review.
6. Check vendor/ agnostic state
bash scripts/check-vendor-agnostic.sh vendor
Must exit 0. Violations mean a vendored component has deployment-identity values hardcoded — fix before flushing.
7. Verify working tree is clean
git status --short
git log --oneline -5
Uncommitted changes won't be picked up by the flush. Commit or stash everything.
8. PR lifecycle guard health
The PR lifecycle guard (pr-lifecycle-guard.yml) gates OTA Release, Upstream
PRs, and Rebase PRs. Verify quota-reserve.yml has run recently and the
reserve floor is healthy (>=1000 remaining after reserve). If quota is tight,
the guard will defer those workflows automatically — no manual action needed.
9. Vouch system state
# Confirm VOUCHED.td is current
cat .github/VOUCHED.td
# Confirm no unvouched upstream orgs
python3 scripts/validate-registered-imports.py registered-imports.json --vouch-check
If new repos were added to registered-imports.json since the last flush,
their upstream orgs may not yet be in VOUCHED-upstreams.td. Add them before
flushing so the advisory check stays clean.
10. Trigger
Once all the above are green:
- Go to flush-lifecycle.yml
- Click Run workflow
- Leave all inputs at defaults for a standard flush
flush-lifecycle.yml sets FLUSH_ACTIVE=true, holds a sentinel runner slot,
then dispatches pre-flush-prep → full-chain-flush → post-flush-prep in
sequence with quota reservation active throughout.
Bypass mode (advanced): trigger pre-flush-prep.yml directly if you need
control over its inputs (skip_merge_prs, skip_cleanup, quota_wait_min).
pre-flush-prep dispatches full-chain-flush automatically at the end of
Step 8. Do not trigger full-chain-flush directly unless bypassing both the
lifecycle wrapper and prep intentionally.
Quick reference — pre-flush-prep steps
| Step | Action | Skippable |
|---|---|---|
| Quota pre-flight | Exit 1 + emit rate-limit log if < 500 remaining | No |
| 1 | Cancel stale/queued runs older than STALE_MIN | No |
| 2 | Merge green PRs on main (mergeable_state == clean) | skip_merge_prs=true |
| 3 | Validate all configs (gate — aborts on failure) | No |
| 4 | Clean up merged branch debris across the org | skip_cleanup=true |
| 5 | Remove stray template files from consumer repos | skip_cleanup=true |
| 6 | Resolve CI failures across configured targets | skip_resolve_failures=true |
| 7 | Quota gate — wait up to QUOTA_WAIT_MIN for headroom | No |
| 8 | Dispatch full-chain-flush | No |
What happens after the flush
post-flush-prep.yml fires automatically via workflow_run: Full Chain Flush.
It runs four verification checks and posts a summary. If it reports failures,
check the step summary for which repos failed and why before re-flushing.
Template propagation (vouch workflows, SBOM pipeline, PR lifecycle guard) is
delivered to the 80 consumer repos during the flush via sync-template.sh.
No manual action is needed — the flush handles it.
Runbooks
Operational procedures for common and emergency situations.
Quota exhaustion
Symptoms: workflows fail with 403, gh api calls return empty, validate-config
skips with "quota too low".
Check current state:
curl -sf -H "Authorization: token $SYNC_TOKEN" \
"https://api.github.com/rate_limit" | \
python3 -c "
import sys, json
from datetime import datetime, timezone
d = json.load(sys.stdin)
core = d['resources']['core']
reset = datetime.fromtimestamp(core['reset'], tz=timezone.utc)
now = datetime.now(tz=timezone.utc)
eta = max(0, int((reset - now).total_seconds()))
print(f'Remaining : {core[\"remaining\"]}/{core[\"limit\"]}')
print(f'Reset at : {reset.strftime(\"%H:%M:%S UTC\")}')
print(f'ETA : {eta//60}m {eta%60}s')
"
Recovery:
- Wait for the reset (up to 1 hour). The reset time is shown above.
- While waiting, use the time productively — all local operations (config validation, ShellCheck, pytest, file edits) work without quota.
- After reset, trigger
pre-flush-prep.ymlto clear the queue and restart the mirror chain cleanly.
Prevention: quota-reserve.yml cancels low-priority runs at < 1000 remaining.
If exhaustion is recurring, check config/workflow-quota-costs.yml for
unexpectedly expensive workflows (the cost_high and min_quota fields) and
consider raising MIN_QUOTA thresholds. config/workflow-cost-profiles.yml
has the detailed per-call breakdown if you need to trace where calls are going.
Queue pile-up
Symptoms: many workflows stuck in "queued" state, runners appear busy but nothing is completing.
Check:
# Via GitHub CLI (requires quota)
gh run list --repo Interested-Deving-1896/fork-sync-all --status queued --limit 50
Recovery:
- Trigger
queue-manager.ymlmanually — it deduplicates and evicts runs queued > 25 minutes. - If the queue is severely backed up, trigger
pre-flush-prep.ymlwithskip_merge_prs=trueandskip_cleanup=true— Step 1 aggressively clears stale runs before dispatching the flush. - As a last resort, trigger
critical-deploy.yml— it performs an aggressive queue clear and dispatches with priority.
Token expiry
Symptoms: token-health.yml opens an issue labelled token-monitor, or
workflows fail with 401.
Check expiry:
bash scripts/token-monitor.sh
Rotate a token:
- Generate a new PAT at https://github.com/settings/tokens
- Go to
rotate-token.yml→ Run workflow - Select the secret name from the dropdown
- Paste the new token value
- Leave
validatechecked - Update the expiry date in
AGENTS.mdtoken rotation table
For OSP org secrets (MIRROR_TOKEN, ORG_MIRROR_OSP_TO_OOC), see the
Token Rotation section in AGENTS.md — these
require a separate PAT with admin:org on OpenOS-Project-OSP.
Mirror chain broken
Symptoms: repos in OSP or OOC are behind I-D-1896 by more than one cycle, or GitLab mirrors show stale commits.
Diagnose:
# Check GitLab sync status (requires quota)
gh workflow run check-gitlab-sync.yml --repo Interested-Deving-1896/fork-sync-all
Recovery by leg:
| Broken leg | Fix |
|---|---|
| I-D-1896 → OSP | Trigger mirror-to-osp.yml manually |
| OSP → OOC | Trigger mirror-osp-to-ooc.yaml manually |
| OSP → GitLab | Trigger mirror-osp-to-gitlab.yml manually |
| GitLab → I-D-1896 | Trigger sync-from-gitlab.yml manually |
For a full chain reset, trigger flush-lifecycle.yml — it runs pre-flush-prep,
full-chain-flush, and post-flush-prep in sequence with quota reservation and the
FLUSH_ACTIVE mutex active throughout. Trigger full-chain-flush.yml directly
only when intentionally bypassing the lifecycle wrapper (e.g. quota is already
reserved and pre-flight was run manually).
Config validation failure
Symptoms: validate-config.yml fails on push, blocking the flush.
Run locally to see the error:
python3 scripts/validate-gitlab-subgroups.py config/gitlab-subgroups.yml
python3 scripts/validate-registered-imports.py registered-imports.json
python3 scripts/validate-cost-profiles.py config/workflow-cost-profiles.yml
python3 scripts/validate-priority-tiers.py config/workflow-priority-tiers.yml
python3 scripts/validate-template-config.py
python3 scripts/validate-workflow-guards.py
Common causes:
- Duplicate repo name in
gitlab-subgroups.yml - Duplicate
source_urlortarget_nameinregistered-imports.json - Workflow added to
.github/workflows/but not registered inworkflow-priority-tiers.ymlorworkflow-sync.yml - Duplicate name in
workflow-priority-tiers.yml
Vendor component agnostic check failure
Symptoms: enforce-agnostic-vendor.yml fails on a PR touching vendor/.
Run locally:
bash scripts/check-vendor-agnostic.sh vendor
The output shows the exact file, line, and category of violation. Fix by:
- Removing the hardcoded fallback value (set to empty string)
- Moving the value to a CI variable / repo var
- Adding
# check-vendor-agnostic: ignoreif the value is genuinely deployment-agnostic (rare — document why)
README render failure
Symptoms: validate-readme-render.yml fails on a PR.
Run locally:
bash scripts/check-readme-render.sh README.md
# Also run the self-test to verify the checker itself is working:
bash scripts/tests/test-check-readme-render-mobile.sh
Common causes: unclosed fences, leaked log lines, bare [text] links without
URLs, raw angle brackets, broken tables, missing H1.
OTA delivery failure
Symptoms: ota-release.yml fails for one or more forks, or a fork's
ota-self-update.yml fails.
For a single fork:
- Check the fork's
ota-self-update.ymlrun logs for the specific error - Common causes: fork has diverged significantly,
pinned_shais stale, or the fork's.ota/config.ymlhas an invalid field - To reset: update
pinned_shain the fork's.ota/config.ymlto the current upstream HEAD SHA, then re-triggerota-self-update.yml
To skip a fork temporarily:
Set disabled: true in its config/ota-registry.yml entry.
To re-deliver to all forks:
Push a new semver tag to fork-sync-all — ota-release.yml triggers automatically.
Incident response checklist
For any production incident affecting the mirror chain:
- Check quota — if exhausted, wait for reset before doing anything else
- Check queue — trigger
queue-manager.ymlto clear pile-ups - Identify the broken leg — use
check-gitlab-sync.ymland manual inspection - Fix the specific leg — trigger the relevant mirror workflow directly
- Validate config — run all validators locally before triggering a flush
- Run pre-flush-prep — let it clean up and restart the chain
- Monitor — watch the first few workflow runs after recovery for secondary failures
Accessibility
This page documents the accessibility system built into fork-sync-all and
propagated to all infra-core and upstream-sync consumer repos.
What the system does
Every repo in the OSP stack is audited for accessibility on every push to
main and weekly via check-accessibility.yml. The audit covers five layers:
| Layer | Tool | What it checks |
|---|---|---|
| CODEOWNERS | github-codeowners | Ownership coverage %, unowned files, CODEOWNERS validation |
| README scan | Built-in | Missing alt text, non-descriptive links, table headers, reading level, bare URLs |
| WCAG 2.1 AA | pa11y + axe-core | HTML accessibility violations in generated docs |
| Audio overview | espeak-ng | README → MP3 audio for visually impaired users |
| Braille output | liblouis | README → Grade 2 English Braille (.brl file) |
Accessibility artifacts
Each repo that has run check-accessibility.yml will have these files committed
to its default branch:
| File | Format | Audience |
|---|---|---|
README.audio.mp3 | MP3 audio | Screen reader users, visually impaired developers |
README.brl | Braille Grade 2 | Braille display users |
accessibility-report.json | JSON | CI systems, dashboards, automation |
Running the audit
On push: automatically triggered when README.md or CODEOWNERS changes.
Weekly: runs every Monday at 04:17 UTC.
Manually:
# Via GitHub CLI
gh workflow run check-accessibility.yml
# With options
gh workflow run check-accessibility.yml \
-f repo=my-repo \
-f fail_on_error=true
Locally (requires espeak-ng, python3-louis, pa11y):
sudo apt-get install espeak-ng ffmpeg python3-louis liblouis-data
npm install -g pa11y github-codeowners
REPO_DIR=. OWNER=my-org REPO=my-repo \
AUDIO_ENABLED=true BRAILLE_ENABLED=true WCAG_ENABLED=true \
bash scripts/check-accessibility.sh
Installing the runner dependencies
The check-accessibility.yml workflow installs these automatically on the
GitHub Actions runner. For local use:
# Ubuntu / Debian
sudo apt-get install espeak-ng ffmpeg python3-louis liblouis-data
# macOS (Homebrew)
brew install espeak liblouis ffmpeg
pip3 install louis
# Node tools
npm install -g pa11y github-codeowners
CODEOWNERS coverage
Ownership coverage is measured by github-codeowners audit. Thresholds:
| Coverage | Status |
|---|---|
| ≥ 80% | ✅ Pass |
| 50–79% | ⚠️ Warning |
| < 50% | ❌ Error |
To see unowned files:
cd <repo>
github-codeowners audit -u
To validate your CODEOWNERS file:
github-codeowners validate
README accessibility standards
The README scan checks for:
- Missing alt text — every
![]()image must have descriptive alt text - Non-descriptive links — avoid
[click here],[here],[link],[read more] - Table headers — every markdown table must have a
|---|---|separator row - Bare URLs — wrap URLs in descriptive link text:
[description](url) - Reading level — avg sentence length ≤ 20 words is accessible; > 30 is flagged
- H1 heading — every README must start with a
# Title
WCAG 2.1 AA compliance
HTML docs in DOCS/generated/ are scanned with pa11y against the
WCAG 2.1 AA standard. Common issues:
| Issue | Fix |
|---|---|
Missing alt on <img> | Add descriptive alt text |
| Low colour contrast | Ensure 4.5:1 ratio for normal text, 3:1 for large text |
| Missing form labels | Associate <label> with every <input> |
| Missing landmark regions | Wrap content in <main>, <nav>, <header> |
| Empty links | Add descriptive text inside <a> tags |
Audio overview
README.audio.mp3 is generated by espeak-ng,
a lightweight open source TTS engine. The README is stripped of markdown syntax
before synthesis for cleaner output.
Playback:
# Any media player
mpv README.audio.mp3
vlc README.audio.mp3
# Command line
ffplay README.audio.mp3
Braille output
README.brl is generated by liblouis,
the standard open source Braille translation library used by NVDA, JAWS, and
VoiceOver. Output is Unified English Braille (UEB) Grade 2.
To display on a Braille terminal:
# Most Braille displays accept .brl files directly via their driver software
# On Linux with brltty:
brltty -f README.brl
Upstream tools tracked
All accessibility tools are forked into Interested-Deving-1896 and mirrored
to the accessibility_deving GitLab subgroup:
| Tool | Purpose | Upstream |
|---|---|---|
| nvda | Screen reader for Windows | nvaccess/nvda |
| osara | REAPER accessibility (audio production) | jcsteh/osara |
| liblouis | Braille translation library | liblouis/liblouis |
| espeak-ng | Text-to-speech engine | espeak-ng/espeak-ng |
| axe-core | WCAG rules engine | dequelabs/axe-core |
| pa11y | CLI WCAG auditing | pa11y/pa11y |
| github-codeowners | CODEOWNERS auditing | kohofinancial/github-codeowners |
| target-size-highlighter | WCAG 2.5.5 pointer target visualiser | accessibility-tools/target-size-highlighter |
| z-index-focus-override | WCAG 2.4.11 focus indicator bookmarklet | accessibility-tools/z-index-focus-override |
| README | Accessible HTML doc generator (no-JS) | canalplus/README |
Further reading
- WCAG 2.1 Quick Reference
- GitHub ReadME Project — Accessibility
- Coding accessibility: Building autonomy with AI
- NVDA: Software by the blind, for the blind
- WebAIM: Introduction to Web Accessibility
- Deque University — axe-core rules
- NV Access — the non-profit behind NVDA
Contributing
Conventions for adding workflows, scripts, config entries, and vendor components.
Adding a workflow
-
Create the workflow file in
.github/workflows/ -
Register in priority tiers — add an entry to
config/workflow-priority-tiers.ymlusing the workflow'sname:field (not the filename):- name: "My New Workflow" tier: 3 # MEDIUM — adjust based on criticalityTier guide: 1=CRITICAL (never cancelled), 2=HIGH (mirror chain), 3=MEDIUM (default), 4=LOW (cancelled first under quota pressure)
-
Register in workflow-sync — add to
config/workflow-sync.yml:- Under
github_onlyif it has no GitLab CI counterpart (most workflows) - Under
pairedif it has a matching GitLab CI job
- Under
-
Add a concurrency group if triggered by
scheduleorworkflow_run:concurrency: group: my-workflow-name cancel-in-progress: true -
Add a quota pre-flight if the workflow makes API calls and runs frequently. Use the shared include — do not inline the curl block:
- name: Checkout uses: actions/checkout@v4 - name: Quota pre-flight id: quota env: GH_TOKEN: ${{ secrets.SYNC_TOKEN }} MIN_QUOTA: "500" # adjust to your workflow's actual cost run: | source scripts/includes/quota-snapshot.sh quota_snapshotCheckout must come before the quota pre-flight step.
quota-snapshot.shis sourced from the checked-out repo — if checkout runs after, the runner cannot find the file and the step fails withNo such file or directory.Gate subsequent steps with
if: steps.quota.outputs.skip == 'false'.The include writes
remaining,reset_time, andskiptoGITHUB_OUTPUTand a status line toGITHUB_STEP_SUMMARY. It also supports an optionalQUOTA_WRITE_VAR: "true"env var that writes aQUOTA_SNAPSHOTrepo Actions variable — useful for chain entry/exit points so downstream workflows can read quota state without an API call via${{ vars.QUOTA_SNAPSHOT }}. Currently enabled onpre-flush-prep,full-chain-flush, andpost-flush-prep.Fork note:
QUOTA_WRITE_VARrequires the token to havereposcope (classic PAT) orvariables: write(fine-grained PAT). If the write fails the workflow continues — it logs a warning and the snapshot is simply not updated. Thevariables: writepermission must also be declared at the workflow level:permissions: actions: write contents: read variables: write -
Validate:
python3 scripts/validate-workflow-guards.py python3 scripts/validate-priority-tiers.py config/workflow-priority-tiers.yml -
Update the workflow triggers doc — if the workflow belongs to a group where display order matters (e.g. Full Pipeline, Mirror Chain), add its filename pattern to
GROUP_SORT_KEYSinscripts/generate-workflow-triggers-doc.py, then regenerate:python3 scripts/generate-workflow-triggers-doc.py cp docs/workflow-triggers.md DOCS/workflow-triggers.mdGROUP_SORT_KEYSmaps group names to filename-substring lists in the desired display order. Workflows not listed sort alphabetically after the pinned ones. Groups without an entry sort fully alphabetically — only add an entry when alphabetical order is wrong for that group.
Adding a script
Scripts live in scripts/. All logging must go to stderr — never stdout —
because many functions are called inside $(...) captures where stdout becomes
the captured value.
info() { echo "[my-script] $*" >&2; }
warn() { echo "[warn] $*" >&2; }
If the script sources includes/budget.sh or includes/gh-api.sh, add the
shellcheck directive:
# shellcheck source=includes/budget.sh
source "$(dirname "${BASH_SOURCE[0]}")/includes/budget.sh"
Run ShellCheck before committing:
shellcheck --severity=warning scripts/my-script.sh
Adding a config entry
New Ona project
Add to config/ona-projects.yml under projects::
my-repo:
repo: https://github.com/OpenOS-Project-OSP/my-repo
name: "my-repo"
project_id: "" # populated by sync-ona-projects workflow on first run
branch: main
classes: [Regular]
description: "Brief description of the project"
tags: [osp-bound]
Then trigger sync-ona-projects.yml with dry_run=true to preview, or
dry_run=false to create the project in Ona (requires ONA_TOKEN secret).
New repo to GitLab mirror chain
Add to config/gitlab-subgroups.yml under the appropriate subgroup:
rust-systems_deving:
repos:
- my-new-repo
Then validate:
python3 scripts/validate-gitlab-subgroups.py config/gitlab-subgroups.yml
New repo to upstream sync
Add to registered-imports.json:
{
"source_url": "https://github.com/upstream-org/repo-name",
"target_name": "repo-name",
"platform": "github",
"added": "2026-06-07T00:00:00Z"
}
Then validate:
python3 scripts/validate-registered-imports.py registered-imports.json
New workflow priority tier entry
See "Adding a workflow" above — step 2.
Adding a vendor component
vendor/ is for third-party components that fork-sync-all hosts or deploys.
It is not for first-party scripts or config.
Before adding:
- Confirm the component is genuinely third-party (not a script you wrote)
- Confirm it will be deployed or served by fork-sync-all (not just referenced)
When adding:
- Place under
vendor/<component-name>/ - Strip all distro-specific or org-specific hardcoded defaults — see the agnostic rule below
- Add a
README.mdwith a "Before the first deploy" section covering all required CI variables - Run the agnostic check:
bash scripts/check-vendor-agnostic.sh vendor/<component-name>
Agnostic rule
No deployment-identity values may appear as hardcoded fallback defaults in vendored components. This includes:
- Public URLs:
${VITE_ENDPOINT_URL:-https://api.myorg.com}❌ - Org/repo slugs:
${MIRRORLIST_REPO:-MyOrg/my-repo}❌ - Arch/repo paths:
${MIRROR_REPO_PATHS:-x86_64/core}❌ - Distro names:
${DISTRO:-cachyos}❌
Allowed:
- Localhost dev URLs:
${API_URL:-http://localhost:5862}✅ - Generic paths:
${MIRRORLIST_PATH:-mirrorlist/mirrorlist}✅ - Single-word tokens:
${LOG_LEVEL:-info}✅ - UI strings:
${APP_NAME:-Infra Dashboard}✅
To suppress a specific line that is intentionally non-agnostic:
SOME_VAR="${SOME_VAR:-value}" # check-vendor-agnostic: ignore
enforce-agnostic-vendor.yml runs automatically on every push/PR touching vendor/.
Commit conventions
Follow the existing commit message style:
scope: short description
Longer explanation if needed. Focus on why, not what.
Common scopes: fix, feat, config, docs, vendor, scripts, ci.
Before opening a PR
# Config validators
python3 scripts/validate-gitlab-subgroups.py config/gitlab-subgroups.yml
python3 scripts/validate-registered-imports.py registered-imports.json
python3 scripts/validate-cost-profiles.py config/workflow-cost-profiles.yml
python3 scripts/validate-priority-tiers.py config/workflow-priority-tiers.yml
python3 scripts/validate-template-config.py
python3 scripts/validate-workflow-guards.py
# ^ also validates workflow-quota-costs.yml entry counts and consistency
# Test suites
python3 -m pytest tests/ -v --tb=short
bash scripts/tests/test-check-readme-render-mobile.sh
# ShellCheck (for any .sh files changed)
git diff --name-only HEAD -- 'scripts/*.sh' | xargs shellcheck --severity=warning
# Vendor check (if vendor/ was touched)
bash scripts/check-vendor-agnostic.sh vendor
# README render check
bash scripts/check-readme-render.sh README.md
All must pass before the PR is ready for merge.
Forking this repo
If you fork fork-sync-all into your own org, a few things need attention:
Required secrets
Copy all secrets from the secrets table in README.md.
At minimum SYNC_TOKEN is required — most workflows will skip or fail without it.
Token scope for QUOTA_SNAPSHOT
Three workflows (pre-flush-prep, full-chain-flush, post-flush-prep) write
a QUOTA_SNAPSHOT repo Actions variable after their quota pre-flight. This
variable lets downstream chained workflows read quota state without an API call
via ${{ vars.QUOTA_SNAPSHOT }}.
The write requires:
- Classic PAT —
reposcope is sufficient (already needed by most workflows) - Fine-grained PAT — must include
variables: writerepository permission
If the write fails (wrong scope, token too restricted) the workflow logs a
warning to stderr and continues — nothing breaks, QUOTA_SNAPSHOT just won't
be updated for that run. Downstream workflows reading ${{ vars.QUOTA_SNAPSHOT }}
will see the last successfully written value, or an empty string on first run.
To confirm the variable is being written, check the "Quota pre-flight" step log
for QUOTA_SNAPSHOT variable updated (HTTP 204). If you see
QUOTA_SNAPSHOT variable write failed (HTTP 403), your token needs the
variables: write permission and the workflow needs:
permissions:
variables: write
FSA mode detection
Forked instances are detected as downstream-fork by fsa-node-identity.sh
and skip source-only operations (readmes, badges, fork-sync, templates,
translate) to prevent duplicate work. See Architecture for
the full node identity model.
Config files to update
| File | What to change |
|---|---|
config/gitlab-subgroups.yml | Your GitLab group and subgroup names |
registered-imports.json | Your upstream repos |
config/template-consumers.yml | Your consumer repos |
AGENTS.md | Update org names throughout |