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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 72 additions & 5 deletions .github/copilot-instructions.md

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
#
# github-actions is the only ecosystem this repo ships. Dual-target (main + develop) so both branches
# stay current independently of the develop -> main release cadence; the merge-bot auto-merges each
# base with its per-base method. See catalog/snippets/configs/dependabot.yml for the multi-ecosystem
# reference (nuget, uv) a code-shipping repo uses.
# The github-actions ecosystem is the only one this repo ships.
# Both main and develop are targeted so each stays current independently of the develop to main release cadence.
# The merge-bot auto-merges each base with its per-base method.
# See catalog/snippets/configs/dependabot.yml for the multi-ecosystem reference, covering nuget and uv, that a code-shipping repo uses.
version: 2
updates:

Expand Down
27 changes: 15 additions & 12 deletions .github/workflows/merge-bot-pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@ name: Merge bot pull request action
# Auto-merges in-repo bot PRs (Dependabot, codegen): enable on opened/reopened, disable on a maintainer push.
# - Merge method by base: develop = squash, main = merge.
# - App token, not GITHUB_TOKEN: fires downstream workflows on merge, and grants write on read-only Dependabot PRs.
# - pull_request_target, not pull_request: jobs hold the App key, so the workflow + action SHAs resolve from the
# trusted base, not PR head. Safe because no job checks out PR code (each runs gh pr merge by URL).
# - pull_request_target rather than pull_request, since jobs hold the App key, so the workflow and action SHAs resolve from the trusted base rather than the PR head.
# This is safe because no job checks out PR code, each one running gh pr merge by URL.
on:
pull_request_target:
types: [opened, reopened, synchronize]

# Concurrency keys on the PR number, not github.ref (the base branch under pull_request_target, which would
# serialize every bot PR against it), so each PR queues independently. cancel-in-progress: false so a follow-up
# synchronize doesn't cancel an in-flight opened run before it enables auto-merge.
# Concurrency keys on the PR number rather than on github.ref, which under pull_request_target is the base branch and would serialize every bot PR against it, so each PR queues independently.
# The cancel-in-progress setting is false so a follow-up synchronize does not cancel an in-flight opened run before it enables auto-merge.
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
cancel-in-progress: false
Expand All @@ -21,7 +20,8 @@ jobs:
merge-dependabot:
name: Merge dependabot pull request job
runs-on: ubuntu-latest
# Dependabot PRs from this repo (not forks). Only on opened/reopened so the disable job stays sticky.
# Dependabot PRs from this repo rather than from forks.
# Only on opened or reopened, so the disable job stays sticky.
if: >-
(github.event.action == 'opened' || github.event.action == 'reopened') &&
github.event.pull_request.user.login == 'dependabot[bot]' &&
Expand Down Expand Up @@ -59,8 +59,9 @@ jobs:
merge-codegen:
name: Merge codegen pull request job
runs-on: ubuntu-latest
# Codegen PRs from this repo. Head/base pairing is enforced strictly (codegen-main->main, codegen-develop->
# develop). Only on opened/reopened so the disable job stays sticky.
# Codegen PRs from this repo.
# Head and base pairing is enforced strictly, codegen-main to main and codegen-develop to develop.
# Only on opened or reopened, so the disable job stays sticky.
if: >-
(github.event.action == 'opened' || github.event.action == 'reopened') &&
github.event.pull_request.user.login == 'ptr727-codegen[bot]' &&
Expand Down Expand Up @@ -101,8 +102,9 @@ jobs:
merge-upstream-version:
name: Merge upstream version pull request job
runs-on: ubuntu-latest
# Upstream-version bump PRs from the App. Head/base pairing is enforced (upstream-version-main->main,
# upstream-version-develop->develop). Only on opened/reopened so the disable job stays sticky.
# Upstream-version bump PRs from the App.
# Head and base pairing is enforced, upstream-version-main to main and upstream-version-develop to develop.
# Only on opened or reopened, so the disable job stays sticky.
if: >-
(github.event.action == 'opened' || github.event.action == 'reopened') &&
github.event.pull_request.user.login == 'ptr727-codegen[bot]' &&
Expand Down Expand Up @@ -143,8 +145,9 @@ jobs:
disable-auto-merge-on-maintainer-push:
name: Disable auto-merge on maintainer push job
runs-on: ubuntu-latest
# Fires when a maintainer pushes to a bot's branch (synchronize, actor != bot). Disables auto-merge so the
# maintainer's commits don't merge with the bot's, and they re-enable it manually. The disable call is idempotent.
# Fires when a maintainer pushes to a bot's branch, meaning a synchronize whose actor is not the bot.
# It disables auto-merge so the maintainer's commits do not merge with the bot's, and the maintainer re-enables it manually.
# The disable call is idempotent.
if: >-
github.event.action == 'synchronize' &&
github.event.pull_request.head.repo.full_name == github.repository &&
Expand Down
13 changes: 7 additions & 6 deletions .github/workflows/publish-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ name: Publish project release action
on:
workflow_dispatch:

# A publish is a deliberate dispatch, so runs serialize on one group and queue rather than cancel, so a run is
# never left with a half-created GitHub release.
# A publish is a deliberate dispatch, so runs serialize on one group and queue rather than cancel.
# That leaves no run with a half-created GitHub release.
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: false
Expand All @@ -18,8 +18,9 @@ jobs:
permissions:
contents: read

# Publish the dispatched branch (main => release, develop => prerelease): NBGV computes the tag from the ref, then
# a GitHub release is created (tag + auto source archive + README + LICENSE). Source-only repo - no build targets.
# Publish the dispatched branch, where main gives a release and develop a prerelease.
# NBGV computes the tag from the ref, then a GitHub release is created carrying the tag, the auto source archive, README and LICENSE.
# This repo is source-only, so it has no build targets.
publish:
name: Publish project release job
runs-on: ubuntu-latest
Expand Down Expand Up @@ -56,8 +57,8 @@ jobs:

# Create-or-refresh: every trigger here is a dispatch, so an existing tag is refreshed, never skipped
# (the exists-gate belongs to the multi-trigger reusable form, where a scheduled re-run must no-op).
# target_commitish pins the tag to the exact built commit (GitCommitId), not the default branch. The release is
# the tag plus GitHub's auto source archive, README, and LICENSE - no build assets (source-only).
# The target_commitish input pins the tag to the exact built commit, GitCommitId, rather than to the default branch.
# The release is the tag plus GitHub's auto source archive, README and LICENSE, carrying no build assets because the repo is source-only.
- name: Create GitHub release step
uses: softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b # v3.0.1
with:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/test-pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ jobs:
permissions:
contents: read

# GitHub Actions does not support required status checks on conditional jobs, so a single always-run aggregator gates
# the merge. Its name is the ruleset-bound required status-check context - rename it and the ruleset context together.
# GitHub Actions does not support required status checks on conditional jobs, so a single always-run aggregator gates the merge.
# Its name is the ruleset-bound required status-check context, so rename it and the ruleset context together.
check-workflow-status:
name: Check pull request workflow status job
runs-on: ubuntu-latest
Expand Down
10 changes: 6 additions & 4 deletions .github/workflows/validate-task.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,24 +55,26 @@ jobs:
# Each gate in scripts/ is proven by a case that reintroduces the fault it catches.
# Standard library only, so no install step and no dependency to pin.
# The audit engine self-test is offline, so it runs here rather than only on an owner sweep.
# The write-guard self-test is offline too, and it otherwise runs only when a host installs the hook, which is where a regression in it would surface as a broken machine.
- name: Run script self-tests step
run: |
set -Eeuo pipefail
python3 scripts/test_prose_lint.py
python3 scripts/test_repo_gate.py
python3 scripts/test_pr_review.py
python3 spec/audit.py --selftest
python3 host-setup/agent-safety/gh-write-guard.py --selftest
- name: Check repo gates step
run: python3 scripts/repo_gate.py

# The charset, duplicate-word and spelling rules are clean tree-wide, so they gate.
# The charset, duplicate-word, spelling and comment rules are clean tree-wide, so they gate.
# Every other prose rule reports in the step below without gating.
- name: Check prose step
run: python3 scripts/prose_lint.py . --check charset --check dupword --check spelling
run: python3 scripts/prose_lint.py . --check charset --check dupword --check spelling --check comment-wrap --check comment-case

# Warn-only, and visible rather than absent: an unrun check is one nobody acts on.
# The backlog is corrected as each file is next edited, never swept.
# The backlog is corrected as each file is next edited, or cleared in a deliberate batch.
- name: Report prose backlog step
continue-on-error: true
run: python3 scripts/prose_lint.py . --check charset-unknown --check semicolon --check dash --check comment-wrap --check comment-case --summary
run: python3 scripts/prose_lint.py . --check charset-unknown --check semicolon --check dash --summary
6 changes: 3 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Treat this file and `GOVERNANCE.md` as authoritative for cross-cutting rules, an

## Fleet Bootstrap

This repository is governed by a shared template, and the canonical rules, machine-readable spec, and procedures live in `github.com/ptr727/ProjectTemplate`. Fetch that repository before acting on anything about conformance, carried content, repository settings, or standing a repository up, because a carried copy here can be stale or absent and the hub is the only authority on what this repository is supposed to hold. This section is byte-locked across every repository in the fleet, so it reads identically wherever it is found, and it is the entry point whenever nothing else present says where the rules are.
This repository is governed by a shared template, and the canonical rules, machine-readable spec, and procedures live in `github.com/ptr727/ProjectTemplate`, the repository these rules call the hub. Fetch that repository before acting on anything about conformance, carried content, repository settings, or standing a repository up, because a carried copy here can be stale or absent and the hub is the only authority on what this repository is supposed to hold. This section is byte-locked across every repository in the fleet, so it reads identically wherever it is found, and it is the entry point whenever nothing else present says where the rules are.

Route by what this repository currently holds rather than by what it is expected to hold, since the two differ exactly when this section matters most.

Expand All @@ -17,7 +17,7 @@ Route by what this repository currently holds rather than by what it is expected
- **A repository with the instruction set, current or stale.** Follow the hub's `AUDIT.md` end to end, then apply what it finds per its section 10. An audit that reports drift and stops is half the procedure.
- **A repository that believes it is conformant.** Run the audit anyway and commit the report, because conformance asserted without a report is conformance nobody can check. This is the same procedure as the case above and is listed separately only because it is the one most often skipped.

Two rules bound every path above. **Read the hub's `main` branch as ground truth**, since that is the promoted and gated state, and read `develop` only to detect divergence. And **the audit is read-only**: it produces a report and never edits the repository it measures, so a fix is a separate, reviewable change.
Three rules bound every path above. **Read the hub's `main` branch as ground truth**, since that is the promoted and gated state, and read `develop` only to detect divergence. **Reach the hub as a checkout of your own and fetch it immediately before reading it**, because a clone is whatever it last fetched rather than the branch it names, and work only in that checkout rather than in one that another task is using, per [`GOVERNANCE.md`](./GOVERNANCE.md) "Repository Boundaries and Write Safety" and "Hub-Hosted Tooling". And **the audit is read-only**: it produces a report and never edits the repository it measures, so a fix is a separate, reviewable change.

## Context and Delegation Discipline

Expand Down Expand Up @@ -68,7 +68,7 @@ Every rule below is a level-two section of [`GOVERNANCE.md`](./GOVERNANCE.md). R
| --- | --- |
| Why the rules are shaped this way | `Foundational Principles` |
| Recording a durable lesson or updating governance | `Durable Knowledge and Self-Improvement` |
| Any push, API mutation, comment, label, or merge | `Repository Boundaries and Write Safety` |
| Any push, API mutation, comment, label, or merge, or which checkout the work happens in | `Repository Boundaries and Write Safety` |
| Quoting data into a comment, commit, test, or doc | `Representative Data in Agent-Authored Text` |
| Committing, signing, rebasing, force-pushing | `Git and Commit Rules` |
| Branch choice, promotion, keeping branches in sync | `Branching Model` |
Expand Down
Loading