feat: export guidelines - the guideline pages as a generated GUIDELINES.md, pushed into the captured repositories behind the Guideline Push Gate (#179)
CI / verify (push) Successful in 5m40s
CI / pwsh (push) Successful in 1m59s
Release / release (push) Successful in 35s

Files changed:
- AGENTS.md
- CHANGES.md
- README.md
- VERSION
- docs/why-gates-are-code.md
- instructions/gates.md
- instructions/kb-profiles.md
- kb/CONTRACT.md
- kb/CONVENTIONS.md
- kb/CONVENTIONS.md.template
- raw/CONTRACT.md
- tools/CONTRACT.md
- tools/README.md
- tools/chemenu/cli.py
- tools/chemenu/cli_contract.py
- tools/chemenu/commands/export_cmd.py
- tools/chemenu/commands/page_ops.py
- tools/chemenu/commands/raw_cmd.py
- tools/chemenu/commands/search.py
- tools/chemenu/guideline_export.py
- tools/chemenu/kb_scan.py
- tools/chemenu/repo_capture.py
- tools/chemenu/search/filters.py
- tools/chemenu/tests/test_cli.py
- tools/chemenu/tests/test_export_guidelines.py

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SnAJ7Z3CpVD3PRbN73QtU2
This commit is contained in:
torbenandClaude Opus 5.5 committed 2026-10-06 06:48:07 +02:00
1 parent ccede04b97
commit 283cdae8be
25 files changed
+1753 -68

No files matched your search

+22 -10
View File
@@ -1,17 +1,18 @@
# Why gates are code
Chemenu has four hard limits - the Mass-Update Gate, the Publish-Remote Gate, the Upload Review
Gate, and the Iteration Budget Gate - and all four live inside `tools/wikitool`, not in a
Chemenu has five hard limits - the Mass-Update Gate, the Publish-Remote Gate, the Upload Review
Gate, the Guideline Push Gate, and the Iteration Budget Gate - and all five live inside
`tools/wikitool`, not in a
paragraph of instructions an agent reads and follows. The rules themselves, and what to do when
one trips, are in [AGENTS.md § Gates](../AGENTS.md#gates) and
[instructions/gates.md](../instructions/gates.md). This page is only about the design choice
underneath them: why code, and why these four mechanisms in particular.
underneath them: why code, and why these mechanisms in particular.
<!-- wikitool:toc -->
## Contents
- [A suggestion an agent can talk itself past](#a-suggestion-an-agent-can-talk-itself-past)
- [Why four different mechanisms, not one](#why-four-different-mechanisms-not-one)
- [Why different mechanisms, not one](#why-different-mechanisms-not-one)
- [Exit 42 is a posture, and it outgrew the gates](#exit-42-is-a-posture-and-it-outgrew-the-gates)
- [A gate in code still has to be reachable](#a-gate-in-code-still-has-to-be-reachable)
- [Numbers that come from measurement, not intuition](#numbers-that-come-from-measurement-not-intuition)
@@ -31,10 +32,10 @@ conversation at all. It runs before the command dispatches, regardless of how co
case for skipping it seemed a moment earlier. The difference isn't that code is smarter than a
well-written instruction - it's that code doesn't get talked into anything.
## Why four different mechanisms, not one
## Why different mechanisms, not one
The four gates ask four different questions, and each one's shape follows from what kind of
question it is.
The five gates ask four different kinds of question, and each one's shape follows from what kind
of question it is.
The Mass-Update Gate asks *is this change too large to publish unreviewed* - a judgment that
varies changeset by changeset, so it clears with a `--confirm` token tied to the specific
@@ -56,6 +57,17 @@ is answering, so nothing about the mechanism needed to change - only the boundar
did, since the submission lives in a quarantine the ordinary pipeline never reads at all rather
than in the working tree `publish` is about to commit.
The Guideline Push Gate asks the same question once more, at the boundary facing outwards: *is
this content right for these repositories, now?* `export guidelines --push` writes a generated
file straight onto another repository's branch, with no review on the receiving side, and a
public target publishes it the moment it lands. That is a per-run judgment - the guidelines
change, the set of opted-in repositories changes, a branch moves - so it takes the token shape,
digesting exactly what would be written where. It deliberately does not take the Publish-Remote
Gate's shape, although it too pushes to a remote: which repositories are targets is already a
standing, committed declaration - the capture manifests under `raw/` - and asking for the same
URLs in an allowlist as well would be a second declaration of one fact. What is left to ask is
the per-run question, and that is the one a token answers.
The Iteration Budget Gate asks a fourth kind of question - not "is this instance correct" but
"has this session stopped making progress." That's read from the shape of the call history
itself (call count, repeated identical calls), not from anything about the content of any one
@@ -63,13 +75,13 @@ call.
## Exit 42 is a posture, and it outgrew the gates
Those four are the named gates, and they are not the only thing that exits 42 any more. When the
Those five are the named gates, and they are not the only thing that exits 42 any more. When the
task-tracker provider layer arrived, it brought a case that looks like a gate from the outside and
is not one: a provider whose API cannot create a project (Super Productivity's local REST API
reads projects but does not write them) raises `HumanInterventionRequired`, and the command prints
what a human has to do and exits 42.
Reusing the code was deliberate, and so was not calling it a fifth gate. What the four gates share
Reusing the code was deliberate, and so was not calling it another gate. What the named gates share
is a *refusal*: the operation was possible and the tool declined to perform it unreviewed. This is
the opposite situation - the operation is not possible at all, and no token could make it
possible. What the two have in common is only what the exit code actually communicates: **stop,
@@ -106,7 +118,7 @@ That failure has no symptom of its own. A gate that fires announces that it exis
*cannot* fire looks identical to a gate nobody happened to need - the same clean runs, the same
silence - and what finally told the two apart was reading a trace for an unrelated reason. So
there is a third property to keep alongside living in code and carrying measured numbers: each
gate has to leave evidence that it can still fire. The three that clear by token or by a
gate has to leave evidence that it can still fire. The ones that clear by token or by a
deliberate edit have it by construction, because clearing one is a visible event in somebody's
terminal. The budget gate, whose ordinary outcome is silence, is the one that had to be given
it - which is why its session id now carries where it came from, into both the trace and