DinoStack / workflows
AGENTS.md14 starsChanged 12 days agoApache-2.0View on GitHub
Canonical site for this repo's CI trigger policy. Workflow files carry a short pointer here, never a copy of it. main's ruleset (14778332) sets strict_required_status_checks_policy: true. Under strict alone, a PR must be up to date with its base before it can merge, so its squash reproduces its head tree byte-for-byte and the PR run is the evaluation of what landed. But the same ruleset carries bypass_actors: [{RepositoryRole admin, bypass_mode: always}], and gh pr merge --admin --squash is this repo's…
Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.
Of the AGENTS.md files we read, the 31,843 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
In this repository17 other files it gives its agents.
- AGENTS.mdAGENTS.md
- bin/AGENTS.mdAGENTS.md
- .codex/AGENTS.mdAGENTS.md
- hooks/AGENTS.mdAGENTS.md
- .kimi/AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- .github/copilot-instructions.mdCopilot instructions
- .cursor/rules/agent-methodology.mdcCursor rule
- .cursor/rules/code-standards.mdcCursor rule
- .cursor/rules/conventions.mdcCursor rule
- .cursor/rules/frontmatter/agent-methodology.yamlCursor rule
- .cursor/rules/frontmatter/code-standards.yamlCursor rule
- .cursor/rules/frontmatter/conventions.yamlCursor rule
- dinostackSkill
- contentSkill
- dinostackSkill
- dinostackSkill
The file
We split this AGENTS.md into the rules it gives an agent
4 rules. About 0 are common, 2 are distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈2
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 114
Keep this allowlist tiny. Catch: the daily 45-minute bot run.
- Distinctive: line 122
Every check the 15 consolidated workflows ran, because on a behind-base merged tree any of them can flip - including the ones whose verdict …
- Distinctive: line 152
When that trigger is dropped, those three jobs must be added here in the same change - otherwise three required contexts lose behind-base …
- Very specific: line 159
Retirement condition (b): when the admin bypass is removed from ruleset 14778332, or every merge is reliably preceded by gh pr …
≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
.github/workflows
Canonical site for this repo's CI trigger policy. Workflow files carry a short pointer here, never a copy of it.
The premise, stated accurately
main's ruleset (14778332) sets strict_required_status_checks_policy: true.
Under strict alone, a PR must be up to date with its base before it can merge,
so its squash reproduces its head tree byte-for-byte and the PR run is the
evaluation of what landed.
But the same ruleset carries bypass_actors: [{RepositoryRole admin,
bypass_mode: always}], and gh pr merge --admin --squash is this repo's normal
unattended-agent merge path (root AGENTS.md documents it as such, because
GitHub disallows self-approval and no human reviewer is present). Admin bypass
defeats strict: a behind-base PR can merge without being brought up to date,
and the resulting squash synthesizes a tree that no run ever evaluated.
This file is the ONLY site that carries the measurement. The 15 consolidated
workflows' on: comments state the qualitative claim and point here, and
verify-merged-tree.yml's header does the same, precisely so that re-measuring
(see the retirement condition) touches one file rather than seventeen. Do not
copy the figures below into a workflow comment.
Measured over the 25 most recent first-parent merges (comparing each squash commit's tree object to its PR head commit's tree object) - 6 of the last 25 merged trees had never been evaluated by any run:
| count | meaning | |
| merged tree matches PR head tree | 19 (76%) | PR run was the evaluation; a post-merge run is pure duplication |
| merged tree differs | 6 (24%) | #850, #854, #855, #856, #857, #860 - the post-merge run was the only evaluation |
#850's merged tree differed from its head across 46 files.
Trigger policy
- PR-only by default. A workflow triggers on
pull_request(plusworkflow_dispatchwhere useful) and nothing else. push: branches: [main]only when the main tree is itself the subject.codeql.yml(SARIF upload is default-branch-scoped),gitleaks.yml(full-history scan ofmain), andscorecard.yml(scores the default branch). Nothing else.codeql.ymlcarries a second job,npm-audit, which inherits all three of that workflow's triggers. Thescheduletrigger is why the job lives there rather than in a workflow of its own: it audits both lockfiles for advisories with a non-breaking fix available, and the failure class it exists for is DRIFT, not a diff. An advisory gets published, or stops being acted on, while no lockfile changes at all - so no PR-triggered run would ever evaluate it, and only a run on an unchanged tree catches it. Itspush: maininheritance is incidental and costs ~1 s; it is not a new grant under this policy and is not a precedent for adding non-SARIF jobs to that workflow.verify-merged-tree.ymlis the single post-merge run, onpush: branches: [main]+workflow_dispatch. Itsneeds-full-rungate job (~10 s) compares the pushed commit's tree object against the tree of the merged PR's head commit and setsrun_full. When the trees match, the whole suite skips - the PR already tested exactly this content. Both tree SHAs and the verdict are printed to the log so the operator can read why it ran or skipped.The gate fails open, always toward running, on two distinct axes:
- Inside the script - any inability to resolve the PR, fetch
refs/pull/N/head, or read either tree yieldsrun_full=true. - At the job boundary - every suite job guards on
if: ${{ !cancelled() && (needs.needs-full-run.result != 'success' || needs.needs-full-run.outputs.run_full == 'true') }}(merged-codex-skill-syncaddsinputs.all_harnesses &&after!cancelled(), so it runs only on anall_harnessesdispatch). The status-check function is load-bearing. A bareif: needs.needs-full-run.outputs.run_full == 'true'carries none, so GitHub applies the implicitsuccess()and a failed gate job (step timeout on a slowgit fetch/gh api, lost runner, checkout failure) would SKIP every suite job instead of running it - inverting the contract precisely when the gate is least trustworthy.!cancelled()rather thanalways(): the same run-on-gate-failure behavior, but an operator/API cancel of the gate does not go on to start all 10 suite jobs. The${{ }}wrapper is mandatory, not cosmetic - a bare leading!opens a YAML tag andif: !cancelled() && ...is a scanner error.
The gate step also sets
shell: bash {0}. GitHub's default isbash -e {0}(errexit ON), which silently made twoemit truebranches - parentless commit, unreadable merged SHA - dead code: the step aborted at the first failinggit rev-parsewith no verdict line and nothing written to$GITHUB_OUTPUT. The boundary guard still produced the right outcome, but the operator lost the diagnostic. Relatedly, everygit rev-parsein the step uses--verify: without it git echoes the unresolvable argument back on stdout, so an emptiness test never fires and the wrong branch reports.A gate that cannot prove the tree was already tested must never assert that it was, and a gate that never finished has proven nothing.
- Inside the script - any inability to resolve the PR, fetch
The non-PR direct push.
changelog-publish.ymlruns daily at 00:00 UTC, regeneratesCHANGELOG.md+docs/changelog.html, and pushes straight tomainwith a PAT (CHANGELOG_PUSH_TOKEN) - and a PAT does trigger workflows. Its commit subject (chore(changelog): regenerate from merged PRs) has no(#N)and no PR, so it hits the gate's no-PR path. Left alone that fires the entire suite -merged-codex-skill-syncalone was budgeted 45 minutes before it became dispatch-only - every single day on a two-file bot commit, and makes the retirement condition below unsatisfiable by construction.The gate therefore has a second
run_full=falsepath: when no PR resolves, it diffs<sha>^ <sha>and skips only if the changed set is non-empty and a subset ofUNTESTED_SAFE_PATHS- exactlyCHANGELOG.mdanddocs/changelog.html. Verified bygrep -rn 'CHANGELOG\.md\|changelog\.html' .github/workflows/ scripts/ bin/ hooks/: no check reads the content of either file. The only hits arechangelog-publish.yml's owngit add,generate-changelog.js(the producer),update-needsrebuild.test.js(paths as literal test data), andtest_gate_provenance.sh(assertsCHANGELOG.mdis DERIVED via D2, which reads the workflow'sgit addline, never the file). The slide tooling is scoped todocs/slides/*and never seesdocs/changelog.html. Any other non-PR push staysrun_full=true. Keep this allowlist tiny. Catch: the daily 45-minute bot run. Retires whenchangelog-publish.ymlopens a PR instead of pushing tomain.- No
paths:filters. A path filter turns a required check into one that never reports on a PR not touching its paths, which blocks the merge rather than passing it. Scope by need (the gate), not by path.
What is in the full suite
Every check the 15 consolidated workflows ran, because on a behind-base merged
tree any of them can flip - including the ones whose verdict looks like a
pure function of a single file. check-skill-embed-budget's CEILING is measured
over a SKILL.md generated from all of content/**: two PRs each adding
content, the second merged behind, yield a merged embed larger than either PR
run measured. Root AGENTS.md names this exact mode (KNW-20260818-001). The
same applies to check-command-file-budget and to hooks-js-tests' sha256
prose goldens.
Jobs: merged-adapter-sync (incl. the DS-57 codex-hooks and DS-104
symlinks-relative guards, which audit a landed SHA), merged-methodology-drift,
merged-agent-fragment-sync, merged-slides-sync (incl. the advisory overflow
check), merged-codex-skill-sync (only with all_harnesses), merged-budget-gates (all 7; the 4 non-Claude ones only with all_harnesses),
merged-content-guards, merged-wrap-lock-tests, merged-hooks-js-tests,
merged-hooks-sh-tests.
The three hook-test jobs are kept separate rather than folded into one, mirroring
hooks-tests.yml: bin/tests/test_discovery_zero_match_guard_spec.py keys
LIVE_GUARD_SITES on (file, job), so two discovery loops sharing a job collapse
to a single pin and either loop's zero-match guard can then be deleted with the
spec still green. One loop per job means one pin per loop.
merged-slides-sync runs the overflow checks after build-slides.sh, so it
measures regenerated HTML where slides-sync.yml measures the committed HTML.
Equivalent in practice: the drift step reddens first whenever the two differ.
Known gap - bin-tests.yml. Its three jobs (python-bin-tests,
hooks-python-tests, bin-sh-tests) are not in the suite. That file is owned
by a separate change and still carries its own push: branches: [main]
trigger, so its post-merge coverage is currently intact and nothing is lost.
When that trigger is dropped, those three jobs must be added here in the same
change - otherwise three required contexts lose behind-base coverage.
Pillar 8 record
- Named catch (a): the 6 behind-base merges above. Without a post-merge run those merged trees are evaluated by nothing at all.
- Retirement condition (b): when the admin bypass is removed from ruleset
14778332, or every merge is reliably preceded bygh pr update-branch --rebase, the gate stops finding differing trees. The condition is therefore stated over merge-triggered runs only: 60 consecutive days in which nopush-triggered run whose commit resolves to a PR reportsrun_full=true. Runs that skip via theUNTESTED_SAFE_PATHSpath arerun_full=falseand do not reset the counter; aworkflow_dispatchrun is excluded because it always forcesrun_full=trueby design. (Phrasing this as "60 days of every run reporting false" would be unsatisfiable while any PR-less push exists at all - the earlier draft had that bug.) After that window, the full-suite jobs retire and only the gate job remains as the standing measurement. The gate itself retires when the bypass is gone. - The cheap path that makes
run_full=falsethe norm: localghis 2.100 andgh pr update-branch --rebaseworks, so the conductor can bring a BEHIND PR up to date before an--adminmerge. Prefer that over relying on this workflow to catch the difference afterwards.
What the 0/600 measurement did and did not show
Across 2026-08-26 -> 2026-09-03: 31 merges, 600+ push-to-main workflow runs
(~19 per merge), 579 success, 20 cancelled, 1 failure - and that failure was the
advisory check-slide-overflow. Required-check catches on the post-merge run
in that window: zero.
That is genuine evidence that ~19 duplicate runs per merge is the wrong shape - it is not evidence that the post-merge run is unnecessary. A zero-catch window across 31 merges cannot distinguish "this run is redundant" from "this run is load-bearing on 24% of merges and those merges happened to be clean". The tree comparison above is what settles it, and it settles it the other way. The cost this policy removes is the ~19x duplication and the 20 cancel events; the coverage it keeps is the 24%.
Reinstatement condition
A workflow's own push: branches: [main] trigger comes back if
verify-merged-tree.yml proves inadequate - i.e. it skips (or cannot run) a
tree that later turns out to have been broken. "Belt and braces", "it is cheap",
and "for safety" are not reinstatement conditions.
Triage: a red verify-merged-tree run
It has no PR, so there is nothing to push a fix to. Fixing main-tree drift means opening a normal PR that regenerates the artifact and commits it. Read the gate job's log first: it prints the merged tree SHA, the PR head tree SHA, and why it decided to run.
Note that consolidation trades run count for failure granularity: sibling checks
share a job and run as sequential steps with no continue-on-error, so a
Fail on slide drift failure hides the overflow checks after it and a
check-resident-budget.sh failure hides the other six budget gates - you get one
finding per triage cycle rather than all of them at once. Accepted deliberately
for a post-merge run (nobody is waiting on it), and the reason the hook-test
loops are not consolidated (see merged-hooks-js-tests).
Related conventions
- Claude Code first (root
AGENTS.md). The adapter drift check is split in two:-- .claudealways runs, and the 16-path non-Claude pathspec (with its builds and existence loop) runs only whenDS_ALL_HARNESSESis1.adapter-sync.yml,bin-tests.ymlandhooks-tests.ymlset it for a PR whose branch starts withchore/adapter-catch-up(the on-demand catch-up chore);verify-merged-tree.ymlsets it from itsall_harnessesdispatch input, which also gatesmerged-codex-skill-sync.codex-skill-sync.ymlis advisory (off the required set) and path-triggered on the Codex skill pipeline (.codex/**and its generator scripts) plus workflow_dispatch; apaths:filter is safe here only because the check is not required. The four non-Claude*-skill-budget.ymljobs run only on the catch-up branch or a workflow_dispatch (job-levelif:skip). - Both adapter pathspecs and both existence loops are duplicated verbatim
between
adapter-sync.ymlandverify-merged-tree.yml. This is not extracted into a composite action:scripts/gate-provenance.sh's D1 rule only scans.github/workflows/*.yml, so moving the assertion out of a workflow file would stop.claude/.codex/... classifying as DERIVED and breakbin/tests/test_gate_provenance.sh. Instead the duplication is mechanically guarded:merged-adapter-sync's first step fails the build unless each pathspec (-- .claude, and the one starting-- .codex .cursor) appears exactly once per file, byte-identical. RootAGENTS.md's rule ("copy it verbatim from the drift steps inadapter-sync.yml") now has two in-repo consumers. verify-merged-tree.yml's "Verify public build is clean" step is scoped-- .codex, unlikecodex-skill-sync.yml's baregit diff --exit-code.gate-provenance.sh's D4 rule takes the FIRST bare, no-pathspec assertion across the sorted workflow files as its input, and both that script andtest_gate_provenance.shtreatcodex-skill-sync.ymlas the repo's only one. A second bare assertion would make D4's input depend on filename order.verify-merged-tree.ymlis named to sort afterslides-sync.yml. D1 cites the first workflow whose pathspec covers the queried target, so an earlier-sorting name would re-pointgate-provenance.sh docs/slides/<deck>.mdat the post-merge suite instead of the canonical PR gate.bin-tests.yml's header holds the repo's TIMEOUT POLICY (job-level timeouts are a backstop set above the sum of that job's own step bounds; network and execution steps carry their own).verify-merged-tree.ymlfollows it.bin-tests.yml'sbin-sh-testsjob builds.claudeonce (plus.cursorunderDS_ALL_HARNESSES), then runs the shell tests withAE_INSTALL_SKIP_BUILD=1, asscripts/check-local.shdoes, so.claude/install.shcalls in those tests skip their rebuild. Measured locally on 2026-10-13 by running that step's loop over the same 81 files both ways: 1,236 s to 706 s, every file exit 0 with identical PASS-line counts. The CI effect is to be re-measured withbash scripts/ci-step-durations.shonce runs with the variable set have accumulated.adapter-sync.ymlstill gates the build output.verify-merged-tree.ymlhas no matching job (the known gap above), so nothing is mirrored there.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

