GitHub governance
Agentstration uses trunk-based development: short-lived branches are merged through pull requests into main, normally with squash merge. GitFlow and long-lived integration branches are intentionally not part of the workflow.
Versioned repository configuration
The repository keeps reviewable governance files in Git:
.github/workflows/ci.ymlclassifies changed paths, restores, builds, tests, verifies formatting on changed .NET files, checks Windows host lifecycle behavior, and builds the container on Linux;.github/workflows/pull-request-metadata.ymlvalidates pull request titles and descriptions whenever their content or source revision changes;.github/workflows/codeql.ymlscans C# on pull requests,main, and a weekly schedule;.github/workflows/dependency-review.ymlblocks pull requests that introduce known vulnerabilities of moderate severity or higher;.github/workflows/release.ymlvalidates version tags, rebuilds and retests the product, packages the server and Workplace, and creates GitHub prereleases;.github/workflows/release-source-registry-tool.ymlindependently rebuilds, tests, packages, and publishes timestamped development or version-aligned release packages of the Source Registry tool;.github/dependabot.ymlchecks the root and autonomous AEP NuGet manifests plus GitHub Actions each week;.github/CODEOWNERS, the pull request template, and issue forms provide lightweight contribution ownership and prompts;.github/rulesets/main.jsonis the reproducible source definition formainprotection;.github/labels.jsonis the reproducible catalog for issue classification, priority, agent-triage, and AI-defect labels.
Documentation validation and publication remain independent in documentation.yml and publish-documentation.yml. Publication is manual and has the only workflow permissions needed for GitHub Pages.
Issue intake and triage
Blank issues are disabled. Contributors choose one of the structured forms under .github/ISSUE_TEMPLATE/:
| Form | Use when | Default label |
|---|---|---|
| Bug report | Existing behavior contradicts an expectation and can be reproduced | bug |
| Feature request | The primary outcome is a new user-facing or product capability | enhancement |
| Technical task | The primary motivation is architecture, refactoring, performance, testing, security, technical debt, technical documentation, or developer experience | technical-task |
Issue titles and bodies use English. Titles describe the outcome without [Bug], [Feature], or priority prefixes. The forms collect the affected area and classification as structured fields; maintainers may translate them into more specific labels during triage.
Priority is assigned through labels after impact, urgency, dependencies, and scope have been reviewed. Do not encode priority in the title.
| Priority | Criteria |
|---|---|
priority:P1 | Critical or blocking impact with no safe workaround, including confirmed high-impact security, data loss or corruption, broken workspace isolation, or an unusable essential path |
priority:P2 | Important correctness, reliability, performance, maintainability, or committed-roadmap impact, with a viable workaround and no immediate critical risk |
priority:P3 | Non-urgent improvement, localized technical debt, documentation, cleanup, or low-impact optimization |
| No priority label | Impact or urgency is not sufficiently evidenced |
Use exactly one priority label when evidence is sufficient. The issue's impact must justify it. Effort, implementation size, and dependency position do not determine priority by themselves.
For feature requests, reserve priority:P1 for a missing capability that blocks a committed release or essential product use with no safe workaround. Use priority:P2 for an important committed-roadmap or core-product capability that is not immediately blocking. Use priority:P3 for optional, exploratory, incremental, or currently uncommitted capabilities.
Agent-led triage uses an explicit lifecycle:
- Add
triage:agentandtriage:pending-reviewwhen an agent independently selects classification, area, or priority. - A maintainer reviews the issue and either adjusts the triage or confirms it.
- On confirmation, replace
triage:pending-reviewwithtriage:confirmed. - Preserve
triage:agentto retain provenance.
When a maintainer supplied the complete classification and the agent only applied it, agent-triage labels are unnecessary.
GitHub API clients do not execute issue forms. Automation and coding agents must therefore reproduce the selected form's required sections, labels, and ordering explicitly. Repository-wide instructions for coding agents are maintained in AGENTS.md.
Issue hierarchy and relationships
When an issue is a genuine child or decomposition of a parent issue, create it and attach it to the parent with GitHub's native Sub-issue relationship. A textual Parent: #123 or Child of #123 reference, reciprocal links in issue bodies, or a checklist entry never replaces that relationship. Textual references may remain as a readability aid.
Use Depends on / Blocked by for execution dependencies and Related to for non-hierarchical relationships. These relationships serve different purposes: an issue can be a Sub-issue of one parent and also depend on another issue. Before closing a parent, verify that all its Sub-issues are closed or that an explicit maintainer-approved exception is documented on the parent issue.
UX test scenario follow-up
A feature request that adds or materially changes a Console or Workplace journey records its UX impact and planned browser scenario in the feature form. After the feature request has a number, create a distinct child issue with the Technical task form and both technical-task and test-scenario-task labels. Attach it to the parent as a native Sub-issue and link the two issues in both bodies for readability before opening the UX implementation pull request. The child describes the routes, deterministic prerequisites, user actions, and observable success and expected-failure assertions. If an existing Playwright journey already covers the change, document that evidence and mark the follow-up Not applicable instead.
The UX pull request links the child in its Validation section. It still includes tests for behavior changes, repairs affected existing Playwright tests, and reports desktop and mobile smoke results. Only the new reusable Playwright journey is deferred. Mark the child blocked until the maintainer explicitly validates the UX in the pull request or parent issue and the UX pull request merges. Record the validation and merged pull request in the child before starting its implementation.
Keep the parent feature request open until the child scenario merges and the catalog marks its surface covered, unless a maintainer documents an explicit reasoned waiver. Before closing the parent, verify that every Sub-issue is closed or a maintainer-approved exception is documented on the parent. The UX-only pull request must not auto-close the parent issue.
Architecture documentation reconciliation
Architecture documentation uses a transverse reconciliation task when a planned review is due or when accumulated implementation changes warrant a repository-wide comparison. Individual feature and technical issues still update directly affected documentation; they do not each need to audit the entire DAT.
Create the reconciliation with the Technical task form. Apply technical-task as its one issue type, then add documentation and documentation:architecture. documentation identifies documentation work generally; documentation:architecture specializes it for DAT, C4, architectural diagrams, and related maintenance. This classification is independent from test-scenario-task, which is reserved for the deferred UX automation workflow.
The issue records a baseline or change range and inspects:
- executable composition, module/storage boundaries, architecture tests, and other implementation evidence;
- the shared LikeC4 model and published L1–L3 views;
- DAT narrative plus Mermaid dynamic and deployment views;
- links to accepted ADRs and whether the documented consequences still match implementation.
Reconciliation may update documentation to reflect behavior that is both implemented and already decided. It may also report a discrepancy or a missing decision. It must not silently rewrite an accepted ADR, normalize implementation drift as if it were intentional, or invent a product architecture choice. A significant missing choice remains owned by the feature or technical change that introduced or proposes it, and that owning change supplies the ADR.
Validation includes LikeC4 validation and the complete Docusaurus build. Run or cite focused architecture tests when the reconciliation touches or makes claims about enforced project boundaries.
AI defect learning
The ai-defect label marks a structural, architectural, behavioral, or code-quality defect introduced by an AI-generated or AI-assisted change. It supplements the issue's type and priority labels; it does not replace either.
When an agent resolves a labeled issue, the corrective pull request must also carry ai-defect and add or update one AI Defect CAR. The CAR uses the issue number as its identifier and captures evidence, faulty assumptions, missed signals, safeguard gaps, the correction, prevention, and completed validation. This is distinct from an ADR: a CAR identifies and addresses the causes of a defect, while an ADR records a durable architectural decision.
The pull request metadata check runs when labels change and rejects an ai-defect pull request that does not change a numbered CAR under docs/ai-defects/ or link that CAR from the pull request description.
Apply the issue label catalog
GitHub stores labels remotely. Committing .github/labels.json documents the intended classification, priority, and agent-triage labels but does not create them by itself.
Preview the label catalog without changing GitHub:
./scripts/github/apply-issue-labels.ps1 -DryRun
Create missing labels and update the color and description of existing labels:
./scripts/github/apply-issue-labels.ps1
To target a repository explicitly:
./scripts/github/apply-issue-labels.ps1 -Repository "gbaudrit/agentstration"
The script requires an authenticated GitHub CLI with permission to manage labels. It is idempotent, updates only labels declared in the catalog, and never deletes unrelated labels.
Checks and pull requests
Pull requests to main run these workflows:
| Check | Purpose | Required by the prepared ruleset |
|---|---|---|
pull-request-metadata | Require PR metadata and an AI Defect CAR for ai-defect remediation | Yes |
build-and-test | Restore, Release build, tests, and changed-file formatting for Agentstration and the complete AEP solution | Yes |
container | Validate the production Docker build after code validation | No |
CodeQL / C# | Static security analysis | No; review after initial successful scans |
dependency-review | Reject vulnerable dependency additions | No; recommended after repository feature availability is confirmed |
The stable required-check contexts are build-and-test and pull-request-metadata. Do not rename either job without updating the ruleset and reconfiguring GitHub.
The CI workflow keeps build-and-test present for documentation-only pull requests but short-circuits its expensive .NET steps when no product or build input changed. Complete AEP validation runs only when the autonomous subtree or its shared CI inputs change. Container validation is path-aware, runs independently from the required .NET check, and uses the GitHub Actions BuildKit cache. Linux and Windows .NET jobs cache the NuGet global-packages folder while still running restore and NuGet audit on every relevant revision. The C# CodeQL workflow also ignores documentation-only pull requests and pushes; its scheduled and manual scans remain complete.
Format verification is deliberately incremental: the current codebase has pre-existing dotnet format debt, so CI verifies every changed C# or Razor file without forcing an unrelated repository-wide rewrite. A separate cleanup can establish a clean full-repository baseline later.
Pull request titles use the same Conventional Commit form as commits: type(scope): description, with optional scope and optional ! for a breaking change. Descriptions use the repository template in this order: Summary, Changes, Validation, then Breaking changes. Keep the summary outcome-focused and the changes concise. Validation must report only checks actually completed, with test totals and optional skips when known; UI changes also report desktop and mobile smoke testing against the local executable. Backward-compatible changes state None. under Breaking changes, while incompatible changes describe both impact and migration. The pull-request-metadata check enforces the title, exact section order, non-empty content, and bullet lists for Changes and Validation.
The ruleset requires pull requests, resolved review conversations, linear history, squash merges, an up-to-date branch, and the build-and-test and pull-request-metadata checks. It prevents branch deletion and force pushes. Because the project currently has one principal maintainer, it requests no mandatory approval and does not require a CODEOWNER approval; reviews remain strongly encouraged.
Bootstrap and apply the ruleset
GitHub stores active rulesets remotely. Committing .github/rulesets/main.json documents the intended state but does not protect main by itself.
Rulesets and protected branches are not available for a private repository owned by a GitHub Free personal account. While this repository remains private on that plan, the definition stays prepared but cannot be applied. Application becomes available after making the repository public, upgrading the owner to GitHub Pro, or moving an organization-owned repository to an eligible Team/Enterprise plan. CODEOWNERS likewise remains versioned but cannot be enforced as a private-repository code-owner rule on GitHub Free.
Bootstrap in this order because GitHub may not accept or expose a status check until it has run:
- Merge or push
.github/workflows/ci.yml. - Let CI complete successfully at least once.
- Verify that the
build-and-testcheck exists. - Preview the ruleset application.
- Apply the ruleset and confirm that
build-and-testis required.
./scripts/github/apply-main-ruleset.ps1 -DryRun
./scripts/github/apply-main-ruleset.ps1
To target a repository explicitly:
./scripts/github/apply-main-ruleset.ps1 -Repository "gbaudrit/agentstration"
The script requires an authenticated GitHub CLI (gh auth login) whose token can administer repository rules. It discovers the current repository when -Repository is omitted, creates main-protection when absent, and updates the existing branch ruleset with that name. It never reads or stores a token in the repository.
-DryRun validates and prints the local definition without calling the Rulesets API, so it also works while the private repository is on GitHub Free. A real application reports the plan limitation explicitly when GitHub returns it.
Private-repository feature availability
The core build-and-test, container, documentation, and Dependabot workflows remain usable for a private repository on GitHub Free. GitHub-hosted CodeQL code scanning and Dependency Review are different: for private repositories they require an organization with GitHub Code Security or GitHub Advanced Security; GitHub Pro alone does not enable them.
Consequently, the CodeQL and Dependency Review jobs run automatically for public repositories and are skipped while this repository is private. If the repository later moves to an eligible organization and Code Security is enabled, create the repository Actions variable ENABLE_GITHUB_CODE_SECURITY=true to activate both jobs without changing the workflows.
GitHub settings
The following settings are remote and must be checked in the repository UI:
- enable squash merging and automatic deletion of head branches;
- disable merge commits; disable rebase merging unless maintainers deliberately want a second linear merge path;
- enable the dependency graph, Dependabot alerts, and Dependabot security updates;
- enable secret scanning, push protection, and private vulnerability reporting when available for the repository and plan;
- enable code scanning with this repository's advanced CodeQL workflow, not a duplicate default setup;
- confirm Actions workflow permissions remain read-only by default.
After CodeQL and Dependency Review have completed successfully and their repository features are available, maintainers may add them as required checks. Keep that decision separate from the initial bootstrap so a plan limitation or first-run setup cannot deadlock main.
Product releases
The root Directory.Build.props is the product-version source of truth. A release requires a matching notes file under docs/releases/ and a tag named v<version> on a commit already contained in main. The release workflow rejects mismatched versions and non-main commits before building artifacts.
Docker Hub publication requires an existing agentstration/agentstration repository and these GitHub Actions repository secrets:
DOCKERHUB_USERNAME: the Docker Hub account allowed to push the repository;DOCKERHUB_TOKEN: a scoped Docker Hub access token with write permission. Do not store an account password.
For example, after the release change has merged, the version and release notes have been advanced to a new immutable version, and all required checks have passed:
git switch main
git pull --ff-only
$version = "0.2.0-alpha.2" # Example; it must match Directory.Build.props and docs/releases/$version.md.
git tag -a "v$version" -m "Agentstration $version"
git push origin "v$version"
GitHub Actions then repeats restore, Release build, and tests; publishes framework-dependent server and Workplace ZIPs plus SHA256SUMS; pushes the server/Console image to Docker Hub for linux/amd64 and linux/arm64; records its manifest digest; and creates a GitHub prerelease using the version-specific notes. Alpha container releases publish the immutable version tag and the moving alpha channel, never latest. Do not move or reuse a published tag. Correct a failed release through a reviewed commit and a new prerelease identifier.
Source Registry tool releases
Agentstration.SourceRegistry.Tool deliberately shares the central product version because it implements the contracts accepted by that Agentstration release. The dedicated release-source-registry-tool.yml workflow has two publication paths:
- a relevant push to
mainpublishes a development prerelease such as0.3.0-alpha.1.dev.20260910213045.<run-id>.<attempt>; the UTC timestamp makes the build recognizable, while the run identity and attempt make concurrent runs and reruns unique; - the shared immutable
v<version>tag publishes the exact central version. A suffix such as-alpha.2produces an official NuGet prerelease, while a version without a suffix produces a stable package.
Both paths run the focused tests and installed-package smoke test before publication. There is no independent tool tag or version file. Development packages are CI snapshots, not release identities, and consumers must pin their full exact version.
NuGet.org publication uses trusted publishing and does not use a long-lived API-key secret. The NuGet account gbaudrit must own Agentstration.SourceRegistry.Tool and configure a trusted publishing policy with:
- repository owner:
gbaudrit; - repository:
agentstration; - workflow file:
release-source-registry-tool.yml; - environment: empty, because the release job does not select a GitHub environment.
The policy may remain pending until its first successful publication. Create or reactivate it before merging a change that should publish the first development package, or before pushing the shared release tag. NuGet.org uses the dedicated workflow's GitHub OIDC identity to activate and bind the policy. The package and its SHA256SUMS are retained as workflow artifacts, while the product workflow remains responsible for the shared GitHub Release. Package versions are immutable and must never be reused.