Burak Köken

A veteran developer's honest ledger.

The Project Charter

The object

I am mostly working with Claude Code these days. The main project is a long one. We had our disagreements with various Claude Code models, on methods, many, many times. As you can see, deep down I know what I am interacting with is just an LLM but sometimes I tend to forget that and begin arguing with it. Not “arguing” in the sense that I am discussing facts and code, but rather arguing like you argue with a human being.

When I point out things that are going wrong, its immediate response is “You are right, I did …, now I am writing a rule that will prevent me doing … in the future”. You will like Bzzzt. Thus was born the CHARTER.md.

It grew

Oh, how it likes to amend the charter: our project specific constitution. Each amendment answers the question of that day and leaves the old answer standing directly above it, still in the present tense, still looking like policy. I did not touch it. It did not delete anything, because deleting feels like losing the reasoning. So it accumulated and eventually it became very hard to understand what was true from the file.

When I said “enough”, it was 4,107 lines and 269,334 bytes long. I hoped it was smart enough to grep parts and not read it every time we need to, but actually that was one of the problems: the model did not have a decent memory for that kind of stuff, a charter to guide it for interaction. So, rules were there, amendments superseding previous rules on the same subject. Later, when I put the mechanism I will describe below into effect, I found some rules changed a few times but one stood out: the actual goal of the project, defined numerically in certain metrics, was changed 38 times. Moving target, I will call it. No wonder we had problems, but I was not actually fully aware that was going on, until I looked at it closely.

The three moves

I cheated. I created a new session on DeepSeek Harness behind Claude’s back. I copied the document to a temporary location. I explained what the file is for to a new unsuspecting agent under another model. What I asked it to do was: Split it. What is binding stays. What was replaced historically, moves out into its own file named with the rule number and the day it stopped being true. The lean CHARTER.md file carries a warning and this is the part worth writing about: before amending a rule, check the history files, because otherwise you re-add an old version and call it a new modification.

So three moves:

  1. Split and keep the latest version of the rule.
  2. Keep history in separate files, named with rule number and date, the history of CHARTER.md.
  3. Check history if you need to amend.

Did it work? Meh.

And it became the piece “Bzzzt”

Of all the rules, the one I keep coming back to is the smallest one. Every response ends with a timestamp, read off the host clock, never guessed, never estimated. It looks like an easy thing to do, insignificant. But it helps a lot when you need to go back in time in chat history and “argue”.

I caught it: four consecutive summaries carried invented timestamps (00:14, 00:31, 01:12, 01:41). The clock was never queried once. They were plausible, sequential and fabricated. It took me four rounds to realize what was going on. The rest you can read in Bzzzt.

What happened, in summary

The CHARTER.md is now 1,650 lines down from 4,107. Each rule is specifying its own history at the end of its definition paragraph, in multiple lines, so we can safely say 250 of them are housekeeping. That is a 66% reduction and not too bad.

Constitutions get amended, better know your history, so history does not repeat itself because of you.