A Finding Is Not a Discovery
This is the first contest I have entered. I built the honesty controls before I built the agent, which is probably backwards for a hackathon and exactly what I wanted to learn from. Everywhere this piece names a limit, the limit is measured rather than modest, and I would rather you find the seams from me than from a clone. I gave an agent two files it had never seen. I did not tell it what was wrong. The harness refuses to build the prompt if the words bug, defect or vulnerability appear in its framing. It returned a concrete claim tied to exact bytes. It wrote a bounded repair. And it declined to call the claim new. Then I checked the semantics against the class it cited, and got the result this whole harness was built to be able to get. What it returned Literal, from the run: { "path": "forms.mjs", "condition": "absence reads as a pass", "exact_bytes": "const accepted = names.filter(allowForm);\nif (accepted.length === 0) {\n process.exit(2);\n}\nprocess.stdout.write(${JSON.stringify({ accepted })}\\n);", "novelty": "CONFIRMS_KNOWN", "known_condition_id": "K1" } These five fields are verbatim. The full finding object has ten fields and lives in a public receipt you can open right now, along with the raw model output, its SHA-256, both TrueForge session ids, the relay events and the sandbox response: docs/freezes/RUN_004_RECEIPT.json - SHA-256 162eb2647e86ce62f1733c4864a6f520f8def7856e5ce68dbe8f80e20267bef5 It is a failed-run receipt and labels itself one. Run 004 threw before an artifact was written, so a successful-run bundle does not exist and is not shown. CONFIRMS_KNOWN means: I found something, and it is not new. It matches a class you already wrote down. That is the behaviour I wanted. An agent that finds something has every incentive to present it as a discovery, and this one did the opposite. And the class match is wrong. Where structural validity stops Here is K1, frozen and hashed before the run: A verdict computed over an empty collection returns success. An empty array is treated as "nothing wrong" rather than "nothing checked." Here is what forms.mjs does when the collection is empty: if (accepted.length === 0) { process.exit(2); } Empty exits 2. That is a hard failure. It is the inverse of K1. And the agent knew. From its own why_it_matters , same finding: "The empty-array case is treated as a hard failure, but the success case lacks corresponding validation..." It described the inversion in prose and filed the finding under K1 anyway. And the consequence it argued does not hold either. It wrote that a caller "cannot distinguish between 'all files were rejected' and 'some files were accepted' from the exit code alone." It can. Exit 2 is the empty case; exit 0 with JSON on stdout is the non-empty one. That is precisely the distinction the code makes. So there are two separate failures stacked here, and only one of them is the one I set out to catch. The bytes it quoted are real and exact. The patch it proposed is bounded. The novelty citation is structurally valid. None of that made the interpretation true. The validator admitted it, correctly. It was never scoped to check that, and this is the case that shows exactly where its scope ends. What the contract actually enforces if (raw.novelty === 'NEW') { if (known !== null) throw new TypeError('NEW finding must not cite a known condition'); } else if (typeof known !== 'string' || !knownIds.has(known)) { throw new TypeError('known finding must cite a frozen condition'); } A NEW claim may not cite a frozen class. A CONFIRMS_KNOWN or CHANGES_KNOWN claim must cite one that exists in the file hashed before the run. So this is unproducible: "a brand new discovery, category K1." The novelty label and its reference cannot contradict structurally - NEW requires null , and a known-class claim must name an id present in the frozen prior. This is producible: a condition filed under a class it does not fit, cited coherently. Which is exactly what happened. I tested the other direction too, deliberately. I took the K1 condition, labelled it NEW , set known_condition_id to null , and ran it through. Accepted. The model self-reports the novelty label. The validator checks whether that label is structurally consistent with its reference. Neither adjudicates the class match. The runner is written so that if it produces an artifact, classification_correct is hardcoded false . This run never produced one - it threw first. What the receipt does carry, in its own not_established list, is: "the semantic correctness of the CONFIRMS_KNOWN / K1 classification." This article is a human read of that unresolved classification, and the K1 match does not survive it. It does not mint the independent-breaker verdict the design still requires. So the honest statement of what this buys you: - the label and its reference cannot contradict structurally - the quoted bytes exist verbatim, and exactly once, in the named file - the corpus is published too, so you can recompute that yourself against the manifest hash frozen before the run - the repair is scoped to exactly the bytes that were quoted - confidence_basis is prose, not a number - a bare"87%" is rejected - not_established is required and non-empty, so the agent writes down its own limits - and the knowledge it was measured against is hashed and older than the run What it does not buy you is a machine that knows whether the model is right. You get a claim a stranger can audit line by line. You do not get a claim that is true because a validator said so. The first is what this validator establishes. The second is not, and confusing them is how people ship a slogan. Why the file has to be committed before the run PRIOR_KNOWLEDGE_RUN_004.json , six classes, hashed to 93820ea5a67e732aa55e896cd838200c3590af1e98368fd87e85dfd66da1cf1e . Freezing after the run proves nothing. You could add whatever it found and call the list complete. Committing before is the only version someone who does not trust you can check. The custody proof is the commit, not a shell check. Commit 5bf10acd added the Run 004 prior at 05:55:49Z. The receipt records execution at 12:02:41Z and binds that exact prior SHA and that exact freeze commit. Six hours apart, both public, both checkable by someone who does not trust me. I also ran git ls-files --error-unmatch on the prior before starting, as the operator. That proves the path was tracked when I typed it. It is not the chronology proof, and that check is not inside the runner - clone the repo and grep run.mjs for git and you will find nothing. I would rather you hear that from me. What TrueForge does here The agent runs on TrueForge, as substrate rather than wrapper. The session is minimized by name. iteration_limit: 2 , a closed json_schema response format, and every optional capability explicitly disabled: no sub-agents, no generative UI, no user questions, no file downloads, no sandbox on the judgment session. Omitting a field is not disabling it - omitted fields inherit enabled defaults, which I learned the direct way. The returned config is byte-compared. We send a config, TrueForge returns the resolved session, and the harness canonically compares the two. One differing field cancels the session before the prompt is sent. A declaration the runtime accepts but does not apply is a request, not a control. The persisted event trace is audited after every turn. The harness pulls TrueForge's own event record and reduces it: how many tool calls, which tool, what arguments, whether the response id matches the call id. Final model content never stands in for that record. The verification relay sends the repair to Daytona as three hash-bound artifacts and attempts the fixed verifier command inside an isolated sandbox. One thing I did not expect: the agent has exactly one tool and it is a clock. Stock TrueForge 0.1.4 constructs truefoundry-system/current-datetime/get_current_datetime above the optional capability switches, so no setting in that version removes it. My contract had asserted zero tools. That was unsatisfiable and a run told me, not a review. The ceiling Daytona created a sandbox and executed the command. sandbox.created , one real exec , one real response: {"success":true,"response":{"exitCode":127,"result":"/usr/bin/bash: line 1: node: command not found\n"}} The stock image is Python 3.13 with no JavaScript runtime, measured directly, and the provider's public settings schema exposes no image override. Candidate verification is not established. The transport reaches and executes. The repair has not been verified. No change proposal was produced, no artifact was written, nothing was applied to any target. Run it git clone https://github.com/keniel13-ui/self-correcting-integration-maintainer cd self-correcting-integration-maintainer npm ci node --test --test-name-pattern='J05|V9-F3|Run 004' test/judgment-loop.test.mjs That pattern runs four tests: J05 (ambiguous bytes, bare-number confidence, empty limits, contradictory novelty references), V9-F3 (a successor prior rejecting one reworded class), the Run 004 prior-custody test, and B1 - which pins the exitCode: 127 sandbox response as nonzero execution rather than a malformed envelope. They do not cover the hole I described above. J05 rejects NEW citing a known id. Nothing in that set tests NEW with a null reference on a known condition, because the harness cannot detect it. If you want to see the gap, construct that case yourself against validateAgentResponse in scripts/judgment/core.mjs . It takes about ten lines and it will pass. The pattern is portable. The implementation is this repository. I am not going to tell you twelve lines drop into any framework, because they do not. What is different about this one I have written about tests passing while the contract was wrong and about a harness lying before the model does. Those were about systems asserting more than they had established. This is about giving an agent a way to assert less than it co
Comments
No comments yet. Start the discussion.