Repository navigation
docs: define the agent change process and in-repo design records - #225
Merged
Merged
Conversation
Design rationale for DialCache changes has lived in GitHub issue bodies that are rewritten in place, in a design folder on one laptop, and in Claude memory. Codex agents, which open about half of recent pull requests, can see none of the last two, and the edit history of a rewritten issue is not searchable. Recent examples: #132 shipped the compression design that #60 had closed as not planned without linking it; #117's body was rewritten six times; #219 exported CacheUseCaseOptions against #218's design while #218's decision checklist stayed unticked. Add design/ with a README and a template. A record is required before a new or changed portable contract, a new conformance profile, a redesign of the conformance machinery, a cross-port or reshaping public API change, or a reversal of an earlier decision. Decisions stay Open until a maintainer confirms them, the implementing pull request stays in draft until then, a changed decision keeps its earlier choice under Rejected, and departures from the record go to its Deviations section in the same pull request. Records explain decisions; Quint and the formal guides remain the definition of behavior. AGENTS.md gains a structure entry and one convention bullet, since it is the only instruction every agent reads. design/README.md joins the relative-link check because it links into formal/guides/; records themselves are unchecked. No source-audit or go-parity pin changes: neither ledger covers AGENTS.md, design/ or scripts/.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #225 +/- ##
=======================================
Coverage 93.73% 93.73%
=======================================
Files 78 78
Lines 11357 11357
Branches 656 656
=======================================
+ Hits 10645 10646 +1
+ Misses 642 641 -1
Partials 70 70
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Process rules were scattered across AGENTS.md convention bullets, AUTHORING.md, VALIDATION.md, docs/authoring.md and docs/maintainers.md, and recent PRs show the cost: #190, #197, #198 and #213 merged without a full run on their head; Python was left out of guides and checks after #200; #219 exported a type its design kept private; an agent merged PRs and agent reviews read like approvals. Rewrite AGENTS.md around one section, "Make a change": classify the change by type (each type sets the record, the steps and the validation required before a PR leaves draft), stop at five maintainer gates, follow the type's path, refresh pinned ledgers, validate the head commit, open the PR as a draft from the template, and finish against a checklist. Agents never submit approving reviews, and agent-posted GitHub text begins with "Agent:". Critical behavior and the conventions stay; the directory tree goes, and the stale claims it carried are corrected. Supporting changes: - CLAUDE.md imports AGENTS.md for Claude Code builds that do not read AGENTS.md natively. - .github/pull_request_template.md is the description shape AGENTS.md tells agents to fill, with Open questions, a port table and per-run commits. - formal/catalogs/README.md gains "Refresh after an edit": what each ledger pins and the order to refresh them. - design/README.md and TEMPLATE.md align with the gates: implementation waits for an Accepted record, searches include pull requests, unmerged pre-record PRs get records, and confirmations link or quote the approval. - AGENTS.md joins the relative-link check. None of these files is pinned by a ledger; make audit passes unchanged.
lan17
marked this pull request as draft
October 13, 2026 23:45
lan17
commented
Oct 14, 2026
AGENTS.md is written for agents: exact steps, gates and commands. Add DEVELOPMENT_PROCESS.md for people who want to understand the workflow itself: how behavior is defined once in contracts and Quint and replayed by every port, the life of a change, the three validation levels and why ledgers exist, the change types, the design-record lifecycle, what only the maintainer decides, a portable feature end to end, and releasing. Four Mermaid diagrams render on GitHub; each was checked under Mermaid 11. The guide links to AGENTS.md as the authoritative rule set instead of restating commands, and AGENTS.md now says a change to "Make a change" updates the guide in the same PR. The file is named for its purpose rather than CONTRIBUTING.md, which GitHub shows to outside contributors and would imply a policy for them. It joins the relative-link check.
The full formal run takes about two and a half hours, and 136 of those minutes are the model-fault campaign, which reads only the Quint models, the challenge catalog and the Quint toolchain. Port changes cannot alter its result, yet the process asked for the whole run on every behavior change, so it was skipped (#190, #198 merged with no run) or re-run on intermediate pushes (63 green runs on superseded commits since September). Give formal-full.yaml a mode input. replay generates the corpus and completes every port replay, about 15 minutes. mutations adds the three port mutation campaigns, about 50 minutes. full, the default and the weekly schedule, adds check-models with the campaign. Lanes a mode does not select are skipped, and the aggregate requires them to be skipped, so a dispatch cannot pass as a stronger mode than it ran. The run name carries the mode. The generate job restores .formal-traces from a cache keyed on every input generation reads: the models, formal/replay, formal/tools, formal/generated, the catalogs other than the three review ledgers, the committed witness fixtures, the Quint pin, the Makefile and the lockfile. Generation is deterministic in content, so an exact key stands for a regenerated corpus; no partial key may restore. A branch that adds Quint regressions misses the cache and regenerates, so its histories enter the corpus that every port must pass. AGENTS.md, DEVELOPMENT_PROCESS.md, VALIDATION.md and maintainers.md state the tiers and when each applies: Replay for port, driver and regression-only changes; Mutations when a catalogued mutant's file is edited; Full when a transition, invariant, the kernel library or the Quint toolchain changes. A green run on an earlier commit still covers a head whose difference is prose, design records or ledger pins. The workflow-shape test pins the mode options, the lane conditions, the cache key inputs and each mode's gate; a flipped gate expectation fails it. The two pinned guides' ledger entries are refreshed.
Review of the mode change found these gaps. The concurrency group was keyed on the ref alone, so a replay dispatched while a full run was in progress on the same branch waited for it, up to two and a half hours. The group now includes the mode; same-mode dispatches still queue. The weekly scheduled run regenerates even on a cache hit, so a freshly installed toolchain re-exports the committed fixtures and vectors once a week; the save stays skipped when the entry already exists. A new challenge is measured only by the model-fault campaign, so the Bug fix row sends a changed challenge to Full. A layout move keeps Full with exploration, because exploration snapshots the source tree. The mutant rule reads the same in every document: a file a catalogued mutant rewrites, or a mutant catalog. The carry-over rule names Markdown files and ledger pins instead of "prose". maintainers.md, VALIDATION.md and AUTHORING.md no longer require full validation for every behavior change. The workflow-shape test pins the cache key and the restore step id exactly, and the gate line for line, so an added exclusion, a non-hashFiles key component or a loosened arm fails it.
# Conflicts: # formal/catalogs/go-parity.json # formal/catalogs/source-audit.json
# Conflicts: # formal/catalogs/source-audit.json
#236 added formal/tools/where.mjs, which prints where one contract is stated, tested, challenged and mapped. That is the navigation the Bug fix path and the formal convention in AGENTS.md asked agents to assemble by hand, so both name the command, and DEVELOPMENT_PROCESS.md lists it under Where to look.
lan17
marked this pull request as ready for review
October 15, 2026 08:10
# Conflicts: # AGENTS.md # formal/catalogs/source-audit.json
…iers Main's rewritten formal/README.md and the glossary still said the aggregate requires every lane and that any behavior change needs the full workflow before merge. With the mode input both are false, not stricter, and the README is where AGENTS.md sends agents for formal work. Both now describe the modes, and VALIDATION.md names formal/tools/ among the inputs that need full and the symbolic lane among what replay runs. Lessons 14 and 17 send a replay-driver change and the capstone's regression-only change to replay mode. AGENTS.md gains the rule the design README already had, that a change of any type reversing a recorded decision needs a record; names the two Go replay files the driver patterns missed; separates the completion and witness gates in formal/tools/ from the workflow's lane selection in the classification table; and splits three long sentences. The corpus cache key leaves out the Markdown under formal/ and the style allowlist, which generation never reads, so a README or allowlist edit no longer forces a regeneration. The workflow-shape test pins the new key.
The maintainer decided in session that an unmerged pull request from before records existed, such as #219, needs no backfilled record. Its review checks the decisions in its issue, and an unconfirmed decision is a question for him.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
DialCache is built by one maintainer and many coding agents that open pull requests from his account. The rules those agents followed were spread across
AGENTS.mdconvention bullets,AUTHORING.md,VALIDATION.md,docs/authoring.mdanddocs/maintainers.md, and the reasons behind designs lived in rewritten issue bodies, a folder on one laptop and Claude memory. The history shows the cost:mainfor three weekly runs.CacheUseCaseOptionsagainst Add exact-key delete for one cached result (child of #217) #218's design, and Add exact-key delete for one cached result (child of #217) #218's decision checklist was never ticked.This began as an evaluation of OpenSpec. Its
specs/tree would restate behavior that Quint andCONTRACTS.mdalready define, with no IDs and a hardcoded grammar, so only its change-record idea was adopted, as a plain convention with no CLI.Change
Type: Docs plus Tooling (the formal workflow and the docs link checker). No design record: this PR defines the convention.
The process in one line
Classify the change; stop where only the maintainer decides; follow the steps for the type; validate at the tier the change needs; open a draft PR; leave draft when the finish list holds; the maintainer merges.
1. Classify the change
AGENTS.mdopens with a table of nine change types. The type fixes three things: whether a design record is needed, which path of steps applies, and which validation tier the PR needs before it leaves draft.CONTRACTS.mdobligation added, changed or removed; a new conformance profile.qntfile or a replay driver changes; Full with exploration for a moveA change spanning types follows every matching path and the strictest tier. Any change that reverses a decision made in an earlier record, issue or pull request needs a record. The mutant rule fires when a change edits a file that an entry in
mutations.jsonorrust-mutations.jsonnames, or edits those catalogs.2. Write a design record before the code
A record is one Markdown file under
design/, written fromdesign/TEMPLATE.md: context, proposal, out of scope, contract and model changes, decisions, impact, plan and deviations.Open. Only the maintainer confirms one, and the record links or quotes the approval. A comment or review an agent wrote is not an approval, whichever account posted it.Accepted.Proposedand the PR to draft until the new choice is confirmed.CONTRACTS.md,SPEC.md,PROTOCOL.mdanddocs/do, and documentation never cites a record as the source of a guarantee.Before changing a feature, an agent searches
design/, issues and pull requests for the contract IDs and API names, and runsnode formal/tools/where.mjs <ID>for each contract involved.3. Stop at the gates
A gate is a decision only the maintainer makes. An agent that reaches one asks in the session; when he is away it pushes a draft PR with the open questions in the description and ends its turn. The gates:
main, dispatchingRelease, deleting a branch or tag, changing repository settings.Approval is the maintainer's own words, typed in a session or written by him on GitHub. Every issue, comment or review an agent posts begins with
Agent:, and an agent never submits an approving review, because GitHub would count an approval from his account.4. Validate at the tier the change needs
formal-full.yamlnow takes amodeinput. Each mode adds to the one before it.mode=replay)mode=mutations)mode=full, the default)main, with explorationWhy the split is safe: 136 of the full run's minutes are the model-fault campaign, which reads only the Quint models, the challenge catalog and the Quint toolchain, so a port change cannot alter its result. Lanes a mode does not select are skipped, and the aggregate requires them to report skipped, so a run cannot pass as a stronger mode than it ran. The run name carries the mode, and the concurrency group is keyed by ref and mode, so a replay never queues behind a full run.
The corpus is cached under an exact hash of every generation input: the models,
formal/replay/,formal/tools/,formal/generated/, the catalogs other than the three review ledgers and the style allowlist, the committed witness fixtures, the Quint pin, theMakefileand the package manifests, with Markdown excluded. Generation is deterministic in content, so a hit equals a fresh corpus, and only an exact key may restore. A branch that adds Quint regressions misses the cache and regenerates, so its histories enter the corpus every port must pass. The weekly run regenerates even on a hit. Committing the corpus was rejected: it is 35 MiB and changes on every model edit, and the 17 smoke histories already are the committed subset.The tier runs once, on the final candidate, after review comments are addressed and PR CI is green. A green run on an earlier commit covers the head when PR CI is green there and the difference is only Markdown or ledger pins; anything else, a rebase included, needs a new run.
5. Open the PR and finish
PRs open as drafts from
.github/pull_request_template.md(Problem, Change, Open questions, Ports, Validation, Follow-ups). A PR leaves draft only when every step of its path is done, its record isAcceptedorImplemented, its tier is green on the head, no open questions remain, and the description reads true as the squash commit body. Commits and descriptions carry no Co-Authored-By trailer, generated-by footer or agent signature.What changed, file by file
AGENTS.md: rewritten around "Make a change": classify, gates, one path per type, ledgers, validate, open, finish. Critical behavior and the conventions stay; the directory tree goes, and the stale claims it carried are corrected. Main's rule about the course underformal/guides/course/is merged in.CLAUDE.md:@AGENTS.md, for Claude Code builds that read onlyCLAUDE.md.DEVELOPMENT_PROCESS.md: the same process for human readers, with Mermaid diagrams: how behavior is defined, the life of a change, the record lifecycle, and a portable feature end to end.AGENTS.mdrequires a change to its process section to update this guide in the same PR.design/README.md,design/TEMPLATE.md: when a change needs a record, how to find earlier decisions, the record lifecycle, the template..github/pull_request_template.md: the description shape agents fill with--body-file..github/workflows/formal-full.yaml: themodeinput, lane conditions, per-mode gate, run name with the mode, concurrency group per ref and mode, corpus cache restore and save, weekly regenerate on a hit.typescript/test/formal-validation.test.ts: pins the mode options and default, the lane conditions, the exact cache key and restore step id, the step order, and the gate line for line. Flipping one gate expectation fails it.formal/guides/VALIDATION.md,AUTHORING.md,docs/maintainers.md,formal/README.md,GLOSSARY.md, course lessons 14 and 17: the tiers replace "full validation before merge"; the reviewed-guide pins are re-keyed withcheck-source-audit.mjs --refresh.formal/catalogs/README.md: "Refresh after an edit", the ordered recipe over feat(formal): add in-repo ledger refresh commands #228's--refreshand--refresh-inputscommands.scripts/check-docs.mjs:AGENTS.md,DEVELOPMENT_PROCESS.mdanddesign/README.mdjoin the relative-link check, with a test.Decisions the maintainer confirmed in session (2026-10-24)
Accepted.Agent:.AGENTS.mdstays one file (321 lines, 21.7 KB).Left out on purpose
specs/tree and CLI.fullrun onmainis the backstop.gh pr create --body, soAGENTS.mdcarries the rule.Ports
typescript/test/Validation
Head:
dd7b2fd. The last commit changed onlydesign/README.md, so the runs on8d5cec1cover it under the carry-over rule once PR CI is green there.dd7b2fd: every check green,test,quint,differential (1)to(4),Build documentationandValidate PR titleincluded.replay) at8d5cec1: green. Cache miss, because this commit changed the key; generate 10 min 45 s; the parity lanes then waited about nine minutes for runners behind the concurrent mutations run; 29 min wall.mutations) at8d5cec1: green in 46 min 28 s. All 19 mutation shards and their three merges passed,check-modelswas skipped as the mode requires, and the aggregate accepted that combination, so themutationsgate arm and theinputs.mode != 'replay'lane conditions have run once before merge.296eede(miss, 17 min 14 s), 38613028985 at296eede(hit, 8 min 16 s), 38617177083 at6490055(hit, 6 min 11 s), 38651601005 at8667553, 38702974816 at788142aand 40116954099 at95e00c3(misses after merges ofmain, 15 to 19 min).8d5cec1:make audit, including the ledger checks, the course citations and the Quint style caps; 86 tests acrossformal-validation,formal-course,formal-style,formal-source-auditandformal-go-parity; thescripts/check-docstests and link check over 53 pages; every anchor into the rewrittenformal/README.mdresolves.AGENTS.mdshapes judged against a rule inventory and a study of agent failures in test(formal): parse the witness corpus once in the completion gates #176 to docs: define the agent change process and in-repo design records #225; six simulated agents walked the result through real tasks; a fact-checker verified every claim against the repo and the ruleset; four reviewers checked the mode and cache change; a three-lane review of the merged branch against currentmain. Their fixes are in this head.Not run:
fullmode on this branch. The PR changes no model, challenge or Quint input, soreplayis its tier; thefullarm's only changes are the per-mode concurrency group and the schedule condition, exercised by the replay runs through the same file.Follow-ups
BEHAVIOR.md,GO-PARITY.md,SEMANTIC-COVERAGE.md,PORTING.md,WALKTHROUGH.md,go/README.mdanddocs/authoring.mdstill say behavior changes need full validation. That is stricter than the new policy, so it is harmless until their next ledger refresh.