Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
71ba4ae
docs(standards): add organization health defaults
scttbnsn Aug 13, 2026
22feaaa
ci(greptile): require manual review requests (#11)
scttbnsn Aug 14, 2026
932eb95
chore(sync): reconcile main before promotion
scttbnsn Aug 14, 2026
bc5ab59
ci(workflows): add reusable CI foundation (#13)
scttbnsn Aug 14, 2026
5ee1885
chore(sync): reconcile main before promotion
scttbnsn Aug 14, 2026
16a6680
feat(quality): standardize long-run reporting (#15)
scttbnsn Aug 14, 2026
cd3c68f
chore(sync): reconcile main before promotion
scttbnsn Aug 14, 2026
99a7a99
fix(quality): enforce report contract boundaries
scttbnsn Aug 14, 2026
9a5362a
fix(quality): decode reports as utf-8
scttbnsn Aug 14, 2026
a39c5bd
test(quality): pin fixture encoding
scttbnsn Aug 14, 2026
7be30f3
ci(profile): make asset generation read-only (#10)
scttbnsn Aug 14, 2026
55c58e8
ci(review): add deduplicated Greptile summon (#9)
scttbnsn Aug 14, 2026
e30a84d
chore(sync): reconcile main before promotion
scttbnsn Aug 14, 2026
6e7a78d
ci(workflows): add run-test and run-lint toggles to go-ci (#19)
scttbnsn Aug 16, 2026
f347593
chore(sync): reconcile main before promotion
scttbnsn Aug 16, 2026
04ad251
ci(workflows): add module-directory input to node-ci (#22)
scttbnsn Aug 16, 2026
67d152a
chore(sync): reconcile main before promotion
scttbnsn Aug 16, 2026
7f9be8b
docs(onboarding): record the qlty alignment baseline (#24)
scttbnsn Aug 16, 2026
922de8f
chore(sync): reconcile main before promotion
scttbnsn Aug 16, 2026
f4c1d50
docs(onboarding): align with the codified standards registry (#26)
scttbnsn Aug 16, 2026
e211199
chore(sync): reconcile main before promotion
scttbnsn Aug 16, 2026
5ac2e3f
chore(repo): meet our own onboarding checklist (#28)
scttbnsn Aug 16, 2026
5bc5208
chore(sync): reconcile main before promotion
scttbnsn Aug 16, 2026
30d6b13
docs(community): org-default code of conduct + community checklist (#30)
scttbnsn Aug 17, 2026
3e80630
chore(sync): reconcile main before promotion
scttbnsn Aug 17, 2026
dd74a99
feat(workflows): add the shared star-chart refresh reusable workflow …
scttbnsn Aug 20, 2026
82f48ca
chore(sync): reconcile main before promotion
scttbnsn Aug 20, 2026
79801af
Main-is-released check, and the codified star-chart shape (#34)
scttbnsn Aug 21, 2026
e2c03ba
chore(sync): reconcile main before promotion
scttbnsn Aug 21, 2026
58c1fd4
fix(workflows): close three shared-workflow defects (#36)
scttbnsn Aug 21, 2026
22d2706
chore(sync): reconcile main before promotion
scttbnsn Aug 21, 2026
0dd3d77
chore: gitignore .claude/ so a nested worktree can't be staged as a g…
scttbnsn Aug 27, 2026
54f1b86
fix(starchart): the documented dispatch step needs actions:write (#39)
scttbnsn Aug 27, 2026
0151d3e
chore(renovate): tidy go.sum after a gomod update (#40)
scttbnsn Aug 27, 2026
759794f
chore(sync): reconcile main before promotion
scttbnsn Aug 27, 2026
eb74985
chore(renovate): move the vite ecosystem as one group (#42)
scttbnsn Aug 27, 2026
d2120bc
chore(sync): reconcile main before promotion
scttbnsn Aug 27, 2026
eddc1af
chore(renovate): scope Portwing lock maintenance exception (#44)
scttbnsn Aug 30, 2026
5d4b724
chore(sync): reconcile main before promotion
scttbnsn Aug 30, 2026
d0f3e5b
fix(renovate): scope lock maintenance to npm
scttbnsn Aug 30, 2026
0aa77c2
docs(onboarding): add the .planning/ gitignore checkbox (#46)
scttbnsn Sep 7, 2026
495a52a
chore(sync): reconcile main before promotion
scttbnsn Sep 7, 2026
49a5982
fix(quality): isolate validation and pace hosted work (#48)
scttbnsn Oct 25, 2026
6bc2e35
chore(sync): reconcile main before promotion
scttbnsn Oct 25, 2026
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
9 changes: 6 additions & 3 deletions .coderabbit.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
# Review feature PRs that follow the CodesWhat dev-branch flow. CodeRabbit
# reviews the default branch without an explicit base-branch entry.
# Request the first review only after the coordinator admits a stable candidate.
# Later fix batches need an explicit review request; pushes do not spend capacity.
language: en-US

reviews:
auto_review:
enabled: true
enabled: false
auto_incremental_review: false
drafts: false
labels:
- "review-ready"
base_branches:
- "^dev/.*$"
9 changes: 4 additions & 5 deletions .github/tests/community_health_contract_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,11 +171,10 @@ def test_standards_workflow_pins_actions_and_runs_every_contract(self):
for expected in (
"persist-credentials: false",
"community_health_contract_test.py",
"python3 -m compileall -q .",
"YAML.parse_file",
"json.load",
"markdownlint-cli2@0.23.2",
"markdownlint-profile.yaml",
"python3 .github/tests/tracked_validation_test.py",
"python3 scripts/validate_tracked_files.py python",
"python3 scripts/validate_tracked_files.py data",
"python3 scripts/validate_tracked_files.py markdown",
"actionlint",
"zizmorcore/zizmor-action@",
"github/codeql-action/init@",
Expand Down
102 changes: 102 additions & 0 deletions .github/tests/tracked_validation_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
from pathlib import Path
import subprocess
import sys
import tempfile
import unittest


ROOT = Path(__file__).resolve().parents[2]
VALIDATOR = ROOT / "scripts/validate_tracked_files.py"


class TrackedValidationTest(unittest.TestCase):
def setUp(self):
self.temp = tempfile.TemporaryDirectory(prefix="tracked-validation-")
self.addCleanup(self.temp.cleanup)
self.repo = Path(self.temp.name)
subprocess.run(
["git", "init", "--quiet", str(self.repo)], check=True,
capture_output=True,
)
self.write(".gitignore", ".planning/\n.claude/\n__pycache__/\n", tracked=True)

def write(self, name, content, tracked=False):
path = self.repo / name
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(content)
if tracked:
subprocess.run(
["git", "add", "--", name], cwd=self.repo, check=True,
capture_output=True,
)

def run_validation(self, kind):
return subprocess.run(
[sys.executable, str(VALIDATOR), kind], cwd=self.repo,
capture_output=True, text=True, timeout=60,
)

def assert_valid(self, kind):
result = self.run_validation(kind)
self.assertEqual(0, result.returncode, result.stdout + result.stderr)

def assert_invalid(self, kind, diagnostic):
result = self.run_validation(kind)
self.assertNotEqual(0, result.returncode, result.stdout + result.stderr)
self.assertIn(diagnostic, result.stdout + result.stderr)

def test_ignored_and_untracked_files_are_not_validation_inputs(self):
for directory in (".planning", ".claude/worktrees/other", "scratch"):
for suffix, content in (
("py", "def broken(:\n"), ("json", "{broken"),
("yml", "broken: ["), ("yaml", "broken: ["),
("md", "no heading\n"),
):
self.write(f"{directory}/bad.{suffix}", content)
self.write("scripts/space [x]\nname.py", "answer = 42\n", tracked=True)
self.write(".github/data [x].json", '{"ok": true}\n', tracked=True)
self.write(".github/data.yml", "ok: true\n", tracked=True)
self.write("docs/a [x].md", "# Valid\n", tracked=True)
for kind in ("python", "data", "markdown"):
with self.subTest(kind=kind):
self.assert_valid(kind)

def test_invalid_tracked_python_fails(self):
self.write(".github/bad [x].py", "def broken(:\n", tracked=True)
self.assert_invalid("python", "SyntaxError")

def test_invalid_tracked_json_fails(self):
self.write(".github/bad [x].json", "{broken", tracked=True)
self.assert_invalid("data", "JSONDecodeError")

def test_invalid_tracked_yaml_fails(self):
for suffix in ("yml", "yaml"):
with self.subTest(suffix=suffix):
name = f".github/bad.{suffix}"
self.write(name, "broken: [", tracked=True)
self.assert_invalid("data", "Psych::SyntaxError")
self.write(name, "ok: true\n", tracked=True)

def test_invalid_tracked_markdown_paths_are_literal(self):
for name in ("docs/bad [x].md", ".github/hidden.md", "#note.md"):
with self.subTest(name=name):
self.write(name, "no heading\n", tracked=True)
self.assert_invalid("markdown", "MD041")
self.write(name, "# Valid\n", tracked=True)

def test_profile_keeps_its_separate_rules(self):
self.write("profile/README.md", "<div>Profile</div>\n", tracked=True)
config = ".github/markdownlint-profile.yaml"
self.write(config, (ROOT / config).read_text(), tracked=True)
self.assert_valid("markdown")
self.write("profile/README.md", "<div>Profile</div> \n", tracked=True)
self.assert_invalid("markdown", "MD009")

def test_empty_tracked_input_sets_succeed(self):
for kind in ("python", "data", "markdown"):
with self.subTest(kind=kind):
self.assert_valid(kind)


if __name__ == "__main__":
unittest.main()
9 changes: 4 additions & 5 deletions .github/workflows/standards-validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,15 @@ jobs:
run: |
python3 .github/tests/community_health_contract_test.py
python3 .github/tests/greptile_summon_contract_test.py
python3 .github/tests/tracked_validation_test.py

- name: Compile Python
run: python3 -m compileall -q .
run: python3 scripts/validate_tracked_files.py python

- name: Parse YAML and JSON
run: |
set -euo pipefail
ruby -e 'require "yaml"; Dir.glob("**/*.{yml,yaml}", File::FNM_DOTMATCH).sort.each { |path| YAML.parse_file(path) }'
python3 -c 'import json; from pathlib import Path; [json.load(path.open()) for path in Path(".").rglob("*.json")]'
python3 scripts/validate_tracked_files.py data
python3 .github/tests/greptile_config_contract_test.py
python3 .github/tests/quality_report_contract_test.py
python3 .github/tests/reusable_ci_contract_test.py
Expand All @@ -60,8 +60,7 @@ jobs:
- name: Lint Markdown
run: |
set -euo pipefail
npx --yes markdownlint-cli2@0.23.2 "**/*.md" "#profile/README.md"
npx --yes markdownlint-cli2@0.23.2 "profile/README.md" --config .github/markdownlint-profile.yaml
python3 scripts/validate_tracked_files.py markdown

- name: Validate workflows with actionlint
run: |
Expand Down
13 changes: 10 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,16 @@ contract tests that pin the shapes other repositories depend on.
Verify promotions with tree equality
(`git diff --quiet origin/main origin/dev/repository-standards`), never
commit ancestry.
- CodeRabbit auto-reviews PRs against `dev/*` branches only (scoped in
`.coderabbit.yaml`); summon it explicitly anywhere else and read its
inline comments before merging.
- Admit new hosted review/heavy CI work through the shared capacity roster.
Keep preparation local while queued. After admission, add `review-ready` for
the first CodeRabbit review; request subsequent fix-batch reviews explicitly.
Freeze pushes while review runs, read its output and verify the covered head.
`.coderabbit.yaml` keeps default/dev targets but disables automatic review on
ordinary pushes. Required review and protection remain effective.
- Approve ordinary dependency updates in the Renovate dashboard only after
admission. This repo's wrapper limits ordinary PRs/branches to one at a time
and one new PR per hour. The shared preset is unchanged; urgent vulnerability
updates keep their separate handling.
- Commits are plain Conventional Commits, `<type>(scope): <description>`,
no emoji, no AI attribution trailers.
- Never weaken branch protection or rulesets to land a change.
Expand Down
150 changes: 102 additions & 48 deletions REPOSITORY_ONBOARDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,27 +107,67 @@ repositories. Language-specific tests do not.
- [ ] Confirm the Renovate GitHub app can access the repository. App access is
managed at the organization level; do not widen a public-only installation
to private repositories as an onboarding shortcut.
- [ ] Add a root `.coderabbit.yaml` based on a current CodesWhat product, then
replace its product-specific tone, ignored paths, and path instructions.
Keep automatic review enabled. If PRs target a non-default integration
branch, include that branch under `reviews.auto_review.base_branches` and
request an explicit CodeRabbit review on the first PR to prove it works.
- [ ] Where CodeRabbit is adopted, use a root `.coderabbit.yaml` appropriate to
the repository. Adopt intentional admission rather than automatically spending
review capacity on every in-progress push. Scope opt-in and incremental-review
changes through normal review, preserving required review evidence. Verify
non-default integration targets and stacked PR behavior before relying on them.
- [ ] Confirm CodeRabbit can access the repository and posts an actual review
comment. A green check without review output is not enough for this test.
Automated Pro-level reviews are free on public repositories only; on
private repositories the free plan rate-limits automated reviews, and they
have not fired for this organization in practice. Organization policy: on a
private repository skip both CodeRabbit items, use cross-account human
review, and add the config when the repository goes public.
Inspect the effective plan, selected-file limit and remaining capacity; public
repository visibility is not a promise of unlimited review. A quota-only green
check is not delivered review. Required non-author approval still applies, and
multiple accounts operated by one person are not independent human review.
- [ ] Keep `greptile.json` at exactly `{"skipReview": "AUTOMATIC"}`
(contract-tested in this repository) so Greptile never reviews unbidden. A
repository that wants opt-in second opinions adds a label-gated caller
workflow (`.github/workflows/greptile.yml`, firing on the `second-opinion`
label) that calls this repository's `greptile-summon.yml` at a pinned full
commit SHA. Pair the caller with a CodeRabbit `labeling_instructions` entry
for `second-opinion` and `auto_apply_labels` enabled, so applying the label
is criteria-driven rather than left to memory. The label is Greptile's only
trigger; never wire it to review every PR directly.
for `second-opinion` without automatic label application. Applying it is an
explicit, consequence-based admission decision with available capacity.
The label is Greptile's only automatic caller trigger; do not wire it to
review every PR directly. Inspect the provider's resolved configuration and
delivered review rather than assuming a legacy file or summon proves coverage.

### Capacity and queued development

Public projects use queue-first development, with adoption work recorded in
their private internal roadmaps. Begin with one newly admitted hosted-review or
heavy-CI candidate across public projects for a seven-day measured pilot. Finish
existing in-flight work safely. A named coordinator records the candidate's
owner, head/base, dependencies, local verification, services, review-pass count,
blocked reason and next eligible time before new expensive work starts.

Keep one active change per repo and at most one small dependent successor local.
Pilot two-layer stacks for genuine dependencies; verify trunk, bot and merge
compatibility. Draft and stacked PRs can still run CI and deploys. Keep diffs
small, aiming around 25 changed files and within the actual reviewer limit;
batching many unrelated items into one oversized PR is not admission control.

Freeze pushes during review, then submit one batch of fixes per pass. Prioritize
finishing admitted work over opening another PR. Keep the three-pass cap, all
required checks and valid approvals. Record cooldowns and wait for recovery
without repeated review summons, workflow reruns or indefinite polling. Review
capacity after the pilot using actual service pools before expanding concurrency.

Admit one new deployment-producing web candidate per shared deployment pool
initially. Pilot ordinary dependency arrivals at one concurrent PR and one new
PR/hour per repo, with staggered schedules or dashboard admission and urgent
vulnerability handling retained. Retain the monthly Qlty reporting policy below.
Provider settings, bot controls and required CI changes need scoped reviewed
rollouts; documentation alone does not configure them. Metadata-only projects
record applicable controls without installing irrelevant tools or paid services.

This shared repository pilots the controls in its own configuration, without
changing the live Renovate preset for consumers. The coordinator approves an
ordinary dependency update in the dashboard only after admission; the local
wrapper permits one ordinary PR/branch and one new PR per hour. Urgent
vulnerability handling remains separate. After admitting a stable review
candidate, apply `review-ready` for its first CodeRabbit review. Later fix
batches use an explicit review request; pushes do not automatically start
another review. Verify the provider's resolved configuration and delivered head
after landing these settings before claiming the pilot is operational.

### Local gates

Expand Down Expand Up @@ -294,41 +334,55 @@ Add these only when the behavior exists:

### Qlty

Qlty appears in three places. The committed configuration and the repository-run
gates are the alignment surface; the Qlty Cloud GitHub App is not.

- [ ] Commit `.qlty/qlty.toml` (`config_version = "0"`) with the organization
exclude baseline for generated, minified, and vendored paths. Drydock's file
is the reference posture and Portwing's is its Go-repo mirror; start from the
closer of the two. Do not copy the trivy plugin block from either reference:
trivy is deprecated in favor of Grype and its removal from both files is
tracked (drydock#753, portwing#135). The trufflehog plugin stays. The same
file drives the local CLI and Qlty Cloud, so changes to it are quality-gate
changes, not formatting.
- [ ] Add the repository's Qlty gate script (`scripts/qlty-check-gate.sh all`)
to `pre-push`, fail-fast like every other local gate. An advisory smells
gate may run alongside it (Drydock pattern) but must not mask the gating
script's failure.
- [ ] Gate Qlty in CI with the repository-run check, which needs no Qlty Cloud
account. Go repositories call `go-ci.yml` with `run-qlty` enabled,
`qlty-egress-policy: block`, and the proven endpoint allowlist — copy the
allowlist from Portwing's `ci-verify.yml` rather than re-deriving it, and do
not widen it. Node repositories run the SHA-pinned
`qltysh/qlty-action/install` plus the same gate script inside their own
workflow (Drydock pattern).

The Qlty Cloud GitHub App's statuses (`qlty check`, `qlty coverage`,
`qlty coverage diff`) currently error organization-wide with out-of-minutes
billing failures. Treat them as non-gating: never add them to required status
checks, and do not chase these failures on PRs — the repository-run gate above
is the enforced check. Coverage reporting is Codecov's job (decided
2026-08-16): upload coverage to Codecov and carry its badge in the README.
The Qlty Cloud App and its maintainability badge stay installed, but its
coverage upload is not the coverage system and its checks stay non-required.
Qlty Cloud enrollment and usage data are not an organization-wide
prerequisite; do not make a Cloud upload or check required
until the repository is enrolled and the check has proved stable. Local Qlty
checks may still be stricter than this baseline.
Public projects run routine quality checks in their own CI and useful local
hooks. Keep Qlty CLI where it aggregates useful checks; effective native tools
are also valid. Qlty Cloud supplies periodic reporting for existing dashboards
and README metrics. A Cloud subscription is not needed for standalone CLI checks.

- [ ] Record adoption work or a concrete applicability decision in the project's
private internal roadmap, with an owner, next action and checkable completion
conditions. Metadata-only repositories do not need a new scanner or dashboard
without a useful signal.
- [ ] Where Qlty CLI is used, commit `.qlty/qlty.toml` with exclusions for
generated, minified and vendored paths. Review changes to shared CLI/Cloud
configuration as quality-gate changes. Preserve useful existing checks rather
than duplicating them through another tool.
- [ ] Run the repository's quality gate in CI and useful local hooks. Advisory
duplication/complexity reports must not mask a gate failure. The shared
`go-ci.yml` supports `run-qlty`, which invokes `scripts/ci/go-qlty.sh` in the
caller repository. Keep the existing input default and check name; consumers
adopt changes through deliberate full-SHA pin updates. Node repositories can
use the SHA-pinned `qltysh/qlty-action/install` and their own gate script.
- [ ] For existing Qlty Cloud maintainability reporting, set default-branch
Analysis Frequency to `1 month` in Project Settings > General. A manual scan
for a release or important change is acceptable within the usage budget. The
README maintainability grade represents the last completed scan and may be up
to a month behind the current default branch.
- [ ] Avoid redundant hosted PR analysis after equivalent repository-owned CI
gates are verified. Verify the control stops analysis compute; turning off
comments or commit statuses alone does not establish that scans stop. Do not
weaken branch protection. Any replacement for a required gate goes through a
reviewed repository change and must be verified on the intended commit first.
- [ ] Preserve useful coverage reporting, enforcement and badges, including
Codecov where already adopted. Each Qlty coverage upload costs one standard
analysis minute, including each separately uploaded server-merge part. Count
all workspace scans, uploads, runner multipliers and retries before claiming
the allowance is sufficient. Do not silently reduce PR coverage enforcement
to save reporting minutes.
- [ ] Verify provider-side commit identity, actual analysis/coverage content and
badge freshness after changing settings. Classify quota failures separately
from real analysis/upload failures; a successful upload step or status alone
does not establish delivery or a completed scan.

This operating policy retains useful Qlty CLI and periodic Cloud reporting. It
does not introduce Sonar, require a paid upgrade, or automatically enroll every
repository in a hosted service. The reusable workflows keep their existing
interfaces and opt-in defaults; a caller's workflow does not configure Qlty
Cloud's service-side scheduling.

See Qlty's [analysis frequency](https://docs.qlty.sh/cloud/analysis-frequency),
[analysis-minute accounting](https://docs.qlty.sh/cloud/billing/analysis-minutes),
and [CLI versus Cloud](https://docs.qlty.sh/cli-vs-cloud) documentation.

## 5. Add delivery controls only for shipped artifacts

Expand Down
6 changes: 5 additions & 1 deletion renovate.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["local>CodesWhat/.github:renovate-config"]
"extends": ["local>CodesWhat/.github:renovate-config"],
"dependencyDashboardApproval": true,
"prConcurrentLimit": 1,
"prHourlyLimit": 1,
"branchConcurrentLimit": 1
}
Loading
Loading