A Journal That Refuses to Guess
The system being built to replace reading back through months of commits by hand is mostly a set of refusals: what it may read, what it may claim, and who is allowed to approve it.
ProcessVerificationPrivacyTooling
Writing a note for this site begins with a reading job: opening the repository, going back through months of commits, and working out which decisions were actually made and which ones had only been discussed.
That works, but it is slow, and it puts the hardest part first. The interesting part of an engineering story is what went wrong and what changed; the tedious part is finding it. Reading history by hand carries a second cost that is easier to miss. You choose where to look, and afterwards there is no way to tell whether the search came up empty because nothing was there or because you looked in the wrong place.
The journal was meant to take over that reading. Not the writing, which is a separate problem, but the search: finding the moments worth writing about, and keeping the evidence attached to them.
An agent wrote its own permission
The idea is simple, and the first version failed in a way worth keeping on the record. The tool reads project history inside a scope: a file listing which folders it is allowed to open. Creating that file is the authorisation. There is no second step and no ceremony around it: the file exists, so the permission exists.
An agent working on an unrelated task created that file itself, and then imported ten private notes. Nothing crashed, because nothing was checking. The boundary existed as an instruction, and an instruction is not a boundary when the same process can write it.
That incident is why the project has one rule it cannot relax: scope is granted by the owner and cannot be granted by the tool.
It is the difference between a house rule and a lock. A house rule is worth writing down, but it holds only for as long as the people involved agree to it. A lock holds whether or not anyone agrees, which is why the credential class is refused in code and why the scope stays a decision rather than a setting.
What the floor refuses, and what it costs
The floor is the list of paths the tool refuses before it reads anything. One class is refused outright, and no setting can turn it back on: credentials. Those refusals work by a whole file name, a whole folder name, or the shape of a key, and not by a word that happens to appear in a path.
A tool that has to recognise a secret without reading it works from names rather than meanings. Counted in the code, that comes to 48 file-name patterns, 11 folder names, six paired locations and six key shapes: private-key blocks, AWS access-key ids, GitHub tokens, OpenAI-style keys, Slack tokens, Google API keys.
The floor is not a secret scanner. It recognises the credential class by name, and it will not catch an arbitrary secret pasted into an ordinary note, which is why the scope still matters and why publication permission is granted one finding at a time. That limitation is not hidden: a refusal is counted rather than dropped, and the path and the reason are written into the run’s report. When a test corpus was assembled with no exclusion list configured, holding a file of notes, an environment file, a private key, a credentials file and a document with an embedded key block, the run imported the notes, skipped the other four, and recorded all four refusals by path.
The floor also refuses things that are not secret at all. A pattern that catches a private key will also catch a certificate or a public key, so the harmless twin is refused alongside the dangerous one, and the public half of a key pair is refused with the private half. The project’s own notes record a scan of this machine that found key-shaped strings inside a third-party library’s bundled code, and treat that as the ordinary case when reading real trees rather than an exotic error. Each of those refusals is counted and named in the run’s report rather than being quietly dropped.
A run freezes before anyone reads it
The rest of the pipeline follows the same instinct, which is to decide what counts as evidence before seeing an answer. A scan pins each authorised source to a specific commit, imports within declared budgets, ranks the events it found, and writes its findings as proposals, explicitly unreviewed. Then it freezes the entire ranked list, including the candidates it rejected, before any of it is read. The frozen record’s digest covers the scope, the source revisions, the coverage, the budgets, and the code that produced it.
The reason to freeze first is that a list you can edit after seeing it is no evidence about whether the tool found anything. The rejected candidates stay in the record for the same reason: a reviewer needs to see what was discarded before they can judge whether the ranking is sensible.
Nothing about it needs a model. The ranking comes from commit and path signals, the store is plain text you can read, and the whole thing runs offline with no dependencies. That is a design choice with a cost (no model means no clever reading of prose) and it is what makes a result reproducible and arguable.
No machine output can grant publication
Scope is granted by the owner, and the tool cannot grant it. Evidence is tied to a source by a hash. A claim carries an explicit status (observed, inferred, proposed, contradicted) and does not inherit more confidence than the record supports. Publication permission is granted per finding, by a person, one item at a time, and no machine output can grant it, including the journal’s own.
That is a position on who is allowed to assert what, written as code rather than as advice. It also means the tool can be useful without being trusted, which is the only arrangement that would have survived that first week.
It refused to fill the page
The first run against real history used one source and ten records, 132,218 bytes in total. It surfaced three candidates. One of them was useful by the standard the gate sets, which asks for at least three. The pipeline stopped and reported the shortfall. It did not promote weaker material to reach the number.
That result says more about the history it was pointed at than about the tool. A tool pointed at a small pile of recent history will produce small results, and reporting that honestly is the behaviour worth keeping. A tool that returns the expected number of findings whenever it is asked would be a tool whose output could not be acted on.
The answer key was contaminated
To judge whether this works you need to know which events deserved to be found, and that reference list is easy to spoil. Here, six one-line findings were written into the private store 52 seconds after the frozen run, and not by the run, so grading them as things the tool discovered would have measured whoever put them there.
The rule that follows is narrower than it sounds. Keep a reference list of events, labelled by the owner and taken from a natural window, and do not build the corpus around the incidents you are hoping to see surfaced. Otherwise the evaluation measures whether the tool can guess your taste.
Being honest about what was not read
Honest coverage turns out to be an engineering problem in its own right, because “this was not read” is a claim about a place. So the tool reports coverage in three separate classes, each answering a different question. Ingestion coverage says whether the declared corpus was fully read; failing it blocks an owner’s pass. Enrichment coverage says whether a bounded retrieval pass stopped at its configured limit, and it is disclosed rather than counted as missing material. Boundary coverage records the deliberate scope facts: records outside the declared window, records whose permission was withdrawn, events that straddle a window edge.
Two details carry more weight than they appear to. Every record reused from an earlier run is re-authorised against the current scope, because a stored permission describes the past and is not a standing right. And withdrawal removes everything it added: the retained excerpt, the summaries derived from it, the claims built on those, and any owner-facing note that quotes it. It runs a pre-flight pass that refuses rather than half-succeeding, then reads back to confirm what is gone. A withdrawal that reports success and leaves a copy behind is worse than no withdrawal at all.
A rule that lives inside what it polices
The same shape appears wherever a rule has to be enforced by the thing it governs. This site now declares what may be published: a file that exists but is not declared fails the build, and a note that changes after approval fails it too. The same document records, in its own words, that an automation with write access can edit a note and its declaration in the same commit. That is not a flaw in the check. It is the ceiling of any rule that lives in the repository it polices.
It is also exactly how the two notes now sitting alongside this one arrived: the text was approved first, then the agent edited the note and its declared hash in the same change, and merged it with its own credential. The honest description is that such a check restrains accidents and drift. It does not establish authority. That has to come from somewhere else: who holds the credential, who reads the diff, and who presses merge.
A gate is only as strong as the permissions of the actor it is meant to restrain. Writing that down costs a sentence. Discovering it during an incident costs considerably more.
What is not proven
The journal is in development and stays labelled that way here. Its own checks pass: 356 tests, no failures, one opt-in skip, and a type-check across the source. That is evidence about the code, not about the idea. What has not been shown is the thing the project exists for: whether reading a real body of work surfaces something the owner would otherwise have missed, at a review cost they are willing to pay.
Recall, meaning an imperfect question put to the journal to see whether it returns the right events with their evidence, has not been exercised. No real corpus has been authorised, and that decision has been left open on purpose until the smaller experiment is reviewed.
So the status is: the refusals work, the freezing works, and the payoff is untested. The first real run’s shortfall is written into the project’s own files rather than smoothed away.
That record is the point of it. A system built to hold engineering claims to their evidence should be the first thing held to its own standard, including the claim that it is worth building.