Contributing · 7. Submitting a change
No human approval is required to merge, so your commit body and your PR description are the review. Write them for a reader who was not in your head. This chapter tells you what the log actually looks like, which parts of the local convention you should copy, and which parts you cannot.
This is a how-to. It assumes your change already passes the gates in chapter 5.
7.1 Before you open a pull request
Run the checklist from 5.11. Then check these five, which are specific to submitting rather than to code:
| Check | Why |
|---|---|
| Did you add a new crate? | It needs crates/<name>/AGENTS.md, 60 lines or fewer, or Verify agent-doc references resolve fails. Section 7.7 |
| Did you rename a public symbol? | If docs/agent/repo-manifest.yaml references it, the same required check fails. Section 7.7 |
Did you edit a document linked from llms.txt? | Regenerate llms-full.txt with bash scripts/build-llms-full.sh |
| Is your change user-facing? | Add an entry to CHANGELOG.md under [Unreleased]. Section 7.8 |
| Did you introduce a new domain term? | Add it to _typos.toml or Lint goes red |
7.2 Fork, branch, push
The process in CONTRIBUTING.md:50 is the standard one and it is accurate as far as it goes:
gh repo fork CueCrux/Crux --clone
cd Crux
git checkout -b <type>/<short-description>
# make your change
git push -u origin <type>/<short-description>
gh pr create --fill
Branch names in the merge log follow <type>/<kebab-description>. Real examples from the tree: fix/studio-library-and-heading, feat/execplan-board-drift-layer3, docs/vaultcrux-upload-script, console/surfaces-remediation. The prefix is a loose type or a domain; both appear.
Merges use merge_method: MERGE, so the log carries merge commits reading Merge pull request #NNN from CueCrux/<branch>.
7.3 The commit convention, derived from the log
CONTRIBUTING.md:54 says only "clear, descriptive commits". That is not what the log looks like, and a newcomer following it produces commits that stand out immediately.
The actual convention is Conventional-Commits-flavoured but uses domain scopes rather than the standard type vocabulary. Real subjects from main:
console(studio): route the Library section; heading reads Studio (post-#519 fix)
daemon+cli(studio): central template library — signed catalog, install-by-id with provenance
daemon(integrations): generic sync scheduler + markdown-vault FileWatcher runtime (I4)
daemon(outbound): enforce declared NetworkAccess.allowed_hosts + SafetyPolicy budgets (I3.1)
console(rail+workspaces+settings): pages-rendering fix, icons-only rail, single switcher (M17)
ci: unwrap ratchet baseline +55 — PR #519 HTTP test fixtures in http/tests.rs only
docs: in-depth developer guide — extending the Crux Daemon (D1)
chore(release): v0.5.52
The observable rules:
| Rule | Detail |
|---|---|
| Scope first, not type first | console, daemon, cli, ci, docs. Compounds are common: daemon+cli, console+daemon |
| Sub-scope in parentheses | console(studio), daemon(integrations), daemon(outbound). Multiple sub-scopes are joined with + |
| Standard types appear but do not dominate | feat, fix, chore show up; scope-first is the majority form |
| Bodies are long and explanatory | The convention is a narrative: why it broke, what changed, how it was verified |
| A verification line closes the body | Real example shape: smoke PASS; console tests 118 pass; Playwright 33/33, 0 pageerrors. |
Co-Authored-By: trailers | Used for AI-assisted commits |
chore(release): v<version> | Produced by scripts/cut-release.sh. Do not write one by hand |
Copy all of the above. A commit subject of console(studio): route the Library section with a body explaining the cause and the verification is exactly what a maintainer wants to read.
7.4 The milestone tags, and what you should do instead
Look again at the log and you will see trailing parenthesised tags: (M17), (I4), (I3.1), (D1), (L1+L2 daemon). They are near-universal on feature commits.
These tags reference ExecPlans in PlanCrux, a private monorepo you do not have and cannot see.
(M17)means "milestone 17 of a named plan"; the plan is not in this repository, not on GitHub, and not resolvable from anything you have access to. The repository even runs a CI workflow,Private Paths Guard, whose entire job is to stopPlanCrux/paths leaking into public source and documentation, while the commit subjects reference that same private planning system by milestone number.
What to do: do not imitate them. Omit the trailing tag entirely. If your change is one step in a larger piece of work, say so in plain English in the body, and reference a public artefact:
daemon(config): validate mutually exclusive embedding sources at startup
Second of two changes adding startup validation for the embedding lane.
The first (#NNN) added the config fields; this one rejects the invalid
combinations in validate_embedding_selection so a bad configuration
fails at boot instead of at first query.
Verified: cargo test -p corecruxd config (14 new cases), manual boot
with each rejected combination.
Reference pull request numbers, issue numbers, or commit SHAs. Those resolve for everyone.
This is a known gap in CONTRIBUTING.md, and it points at a real decision the project has not yet made: either explain the tags publicly or stop putting them in public commit subjects.
7.5 The pull-request template
.github/PULL_REQUEST_TEMPLATE.md has four sections.
Summary. What the PR does.
Type. One of Bug fix, New feature, Refactoring, Documentation, Test coverage.
Checklist, as shipped:
| Item | Note |
|---|---|
cargo fmt --check passes | Remember max_width = 120 |
cargo clippy --workspace passes with no new warnings | CI adds -D warnings |
cargo test --workspace passes | Use --locked |
| Coverage does not decrease | The gate has twelve floors. See 5.8 |
CHANGELOG.md updated if user-facing | Section 7.8 |
| Documentation updated if the API changed |
Integration Packs, completed only for PRs touching integrations/community/:
| Item |
|---|
The pack manifest uses crux.integration.v1 |
| A manifest hash and an Ed25519 Passport signature are included |
The pack is declarative-only, with no external_helper |
| Capabilities, network hosts and data access are documented in the pack README |
Dangerous capabilities include a maintainer-approved review.json |
The checklist omits the three gates that fail newcomers most often:
typos, the licence-header check, and the unwrap ratchet. Tick the boxes, then run 5.11 anyway.
7.6 What review actually means here
| Expectation | Reality |
|---|---|
| Someone will approve my PR | required_approving_review_count is 0. Nobody has to review it, but from a fork, somebody must approve the workflow run before checks start (§5.0) |
| A code owner will be assigned | .github/CODEOWNERS is * @myles plus explicit entries for the trust-core, retrieval and MCP crates. require_code_owner_reviews is false, so it is advisory |
| The checks are the gate | Correct. Eleven of them. See 5.2 |
| Merging is automatic once green | It goes through the merge queue, usually via gh pr merge --auto. A batch merges only if the whole group passes |
| My branch must be current | Yes. strict: true on branch protection. The queue handles the rebasing |
Two consequences follow, and both are on you.
Your description is the review. Nobody is obliged to ask you what you meant. Say what changed, why, and how you verified it.
Green does not mean correct. Semver Compatibility cannot fail (5.2). Route-auth scope enforcement is shadow by default at runtime (3.3). Coverage floors are ratchets, not targets. If your change touches a trust-core crate, say in the description what you did to convince yourself it is safe.
7.7 The obligations CONTRIBUTING.md omits
Sixteen things are missing from CONTRIBUTING.md. Most are covered elsewhere in this set; these three are specific to submitting and have no other home.
The per-crate AGENTS.md obligation
A new crate needs crates/<name>/AGENTS.md, 60 lines or fewer. All 28 existing crates have one. scripts/check-agent-docs.sh enforces both existence and the line cap, and it backs the required check Verify agent-doc references resolve. Write it as you write the crate; retrofitting is worse.
The repo-manifest symbol contract
docs/agent/repo-manifest.yaml carries a ci_assertions block naming symbols, tests, crate directories and fuzz targets that must exist in the tree. The same script asserts every one of them.
Renaming a symbol that appears there fails a required check. Two things follow:
| Situation | Do |
|---|---|
You renamed a symbol named in ci_assertions | Update the manifest in the same commit |
| You added a symbol that agent docs should reference | Add it to ci_assertions, and anchor the reference by symbol name, never line number; that is on the "Never" list at AGENTS.md:75 |
Check locally:
bash scripts/check-agent-docs.sh --exec
There is no CLA, and no DCO bot
Verified: no .github/workflows/dco.yml, no CLA application in the required-check list, and no CLA document anywhere in the tree.
The contribution grant lives in the licence itself. LICENSE:130, Submission of Contributions, verbatim:
"Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions."
This is inbound=outbound: contributions are licensed under Apache-2.0 on the same terms as the rest of the work. You keep your own copyright; there is no separate CLA document to sign. See 8.4.
Opening a pull request is the act that grants it. If that is not acceptable to you or your employer, do not open one.
7.8 The changelog
CHANGELOG.md follows Keep a Changelog 1.1.0 and Semantic Versioning.
Structure: ## [Unreleased] at the top, then ## [X.Y.Z] - YYYY-MM-DD headings descending. Sections are ### Added, ### Changed, ### Fixed, ### Security.
Style: entries are a bold lead sentence followed by an explanatory paragraph, not a one-line bullet. Feature entries in the existing file carry a trailing ExecPlan back-reference in italics; as with commit tags, omit that since it does not resolve for outside readers.
Add your entry under [Unreleased] in the section that matches. If your change is not user-facing, do not add one.
The cadence note at CHANGELOG.md:8 is the project's own rule: weekly rolling builds are cut from main, versioned releases ship every four to eight weeks, and "if you tag a release, you write its entry." That rule is not currently being kept, see 9.7.
7.9 Issues, and where to raise things
| You want to | Route |
|---|---|
| Report a bug | .github/ISSUE_TEMPLATE/bug_report.yml. Blank issues are disabled |
| Request a feature | .github/ISSUE_TEMPLATE/feature_request.yml |
| Report a security vulnerability | Not GitHub. Email security@cuecrux.com. See 8.6 |
| Propose an "Ask first" change, a new on-disk artifact type, a receipt or seal-material change, a default port change | Open an issue or discussion before writing the code. AGENTS.md:70 |
| Find something to work on | There are no open issues. See chapter 10 |
Labels that exist: bug, documentation, duplicate, enhancement, good first issue, help wanted, invalid, question, wontfix, ci:fallback. Dependabot adds dependencies and ci. Note that good first issue is currently applied to nothing.
CONTRIBUTING.md:41 names the contribution types the project welcomes: bug fixes with a clear description of the issue and how you verified the fix; corrections to documentation or code comments; performance improvements with benchmark evidence; and test-coverage improvements. Take the benchmark-evidence requirement literally, a performance claim without a measurement is not reviewable.
Sources
- CONTRIBUTING.md:41, welcomed contribution types
- CONTRIBUTING.md:50, the five-step PR process
- CONTRIBUTING.md:66, the licence statement
- .github/PULL_REQUEST_TEMPLATE.md, Summary, Type, Checklist, Integration Packs
- LICENSE:130, Submission of Contributions, verbatim
- CHANGELOG.md:8, the cadence rule
- AGENTS.md:70, the "Ask first" list
- AGENTS.md:75, the "Never" list, including line-number anchors
- scripts/check-agent-docs.sh, the
ci_assertionsandAGENTS.mdenforcement - docs/agent/repo-manifest.yaml, the symbol contract
- .github/CODEOWNERS, advisory ownership

