What was run, and against what
| Command | make audit-self (AUDIT_DRIVER=docker npx tsx scripts/audit-self.ts) |
| Repository | This one. Branch main |
| Commit audited | c8ffc16155540ba480d0d61452e8c089a39b6d18 |
| Run date | 27 July 2026, 15:40 UTC |
| Driver | docker, resolved from AUDIT_DRIVER. Not the sim default, whose signals are string templates and whose verdict is a hardcoded PASS |
auditor_version | docker-1.3.0, signed into both certificates |
| Audit image | wiregent-audit-sandbox:1, sha256:dbebeadc0c99…, built locally and never pulled at audit time (--pull=never) |
| Model participation | "none". No language model produced, weighted, or reviewed any signal on this page |
| Live endpoint supplied | https://wiregent.com |
| Working tree at run time | clean. Both stages build their workspace from git archive HEAD, so the audited bytes are pinned to the commit above regardless |
Two stages, because there are two honest answers.
- Stage A, the founder path. The tracked tree at
HEAD, no dependencies. This is byte for byte what the git source driver puts on the runner: it clones--depth 1, strips.git, andnode_modulesis gitignored so it never arrives. - Stage B, the vendored path. The same tree plus a real copy of
node_modules, which is the remedy our own simulation ledger names for a sandbox with no network.
Stage A is the one that matters, because it is the one a founder actually gets.
The signing key was run-scoped. The script generates an Ed25519 keypair per run and prints the public half beside the certificates, rather than writing a dev key into a tracked file as a side effect of a read-only exercise. Everything downstream is the shipped path: the same claim builder, the same canonical JSON, the same signer.
-----BEGIN PUBLIC KEY----- MCowBQYDK2VwAyEAM0Zt7l9amuXLOnDDlHw0Vx6KmcSf7d9tNWQB7wyKoUg= -----END PUBLIC KEY-----
Be exact about what that key proves: it proves these certificates were not edited after the run printed them. It is not a Wiregent identity key, and it does not make Wiregent trustworthy. It makes this document tamper-evident to anyone who bothers to check it.
Stage A: the founder path. Every signal, proven and not.
The tree that went in:
| Measured | Limit | Result | |
|---|---|---|---|
| Files | 409 | 15,000 | inside |
| Bytes | 11,231,889 (10.71 MiB) | 201,326,592 (192.00 MiB) | inside |
| Directories | 85 | ||
| Symlinks | 0 |
Intake accepted it. The driver ran in 6,388 ms; the container itself finished in 6,114 ms against a 180,000 ms wall clock.
The signal list, verbatim
PROVEN sandbox.isolation_enforced simulated=false PROVEN sandbox.network_egress_blocked simulated=false PROVEN sandbox.readonly_rootfs simulated=false PROVEN source.manifest simulated=false NOT PROVEN build.syntax_check simulated=false PROVEN structure.module_graph simulated=false NOT PROVEN test.suite_executed simulated=false PROVEN service.endpoint_responded simulated=false NOT PROVEN run.exit_code simulated=false PROVEN runtime.wall_clock_guard simulated=false VERDICT: FAIL
simulated=false on every line is the load-bearing part. It means every one of these ten was measured by something that ran, not templated. A certificate carrying simulated signals is worth nothing, and this product ships a driver that produces exactly those, which is why the flag is on every signal individually.
The seven that are proven
| Signal | What it actually says |
|---|---|
sandbox.isolation_enforced | The container runtime reported: network=none, read-only root, all capabilities dropped, no-new-privileges, non-root uid, a 256 pid cap, a 2,048 MB memory cap, 3 read-only mounts, no docker socket. Read from the daemon after the run, not asserted by the code that asked for it |
sandbox.network_egress_blocked | Two independent accounts had to agree: the runtime's own network mode was none, and a probe inside the sandbox confirmed both raw TCP and DNS egress failed |
sandbox.readonly_rootfs | The runtime reported an immutable root filesystem and an in-sandbox write attempt was rejected. Only a size-capped tmpfs scratch was writable, and it died with the container |
source.manifest | 409 files totalling 11,231,889 bytes were hashed into a sha256 manifest before anything executed. 0 symlinks, never followed. No file name, path or byte of the source leaves the sandbox |
structure.module_graph | 257 of 257 source files are in the graph: 257 modules, 734 distinct internal edges from 2,693 import statements (2,174 internal, 368 external, 151 the parser could not resolve). 51 distinct external module identifiers, reported as a count and a hash, never as names. 7 import cycles covering 21 modules, largest spanning 5. Highest fan-in 101, with 7 modules above a stated threshold of 10. 2 modules unreachable from 72 entry points. These are counts, not a score. No cycle count or fan-in makes this signal pass or fail, and there is no weighting anywhere in it |
service.endpoint_responded | An HTTP request from the audit host returned 200 in 81 ms, 0 redirects, 1 screened hop, 2,723 bytes reduced to a sha256. The body, the headers and the address were never carried into the certificate. The status code is not graded. And the important half: this does not prove the audited source is what answered. Nothing binds the responding server to the source_digest |
runtime.wall_clock_guard | Completed in 6,114 ms against a 180,000 ms limit |
The three that are not proven
build.syntax_check, labelled "Source parsed, but the parser is not reliable for these languages"
257 of 257 source files were read by a grammar for their own language (1/1 bash, 1/1 python, 11/11 javascript, 232/244 typescript), across 4 languages. 12 produced a parse diagnostic. 0 were never attempted, 0 exceeded the per-file byte budget, 0 were unreadable. The grammars used rejected 1 of 14 pieces of known-valid code they were tested on, so a diagnostic above is a lead to check rather than a defect established.
Coverage was complete. Twelve TypeScript files produced a diagnostic. Section 5 explains why we do not believe all twelve, and why the signal fails anyway. This one counts against the verdict.
test.suite_executed, labelled "Declared test suite could not run: its runner is not installed in the sandbox"
npm test exited 127 after 120ms. 127 is the POSIX status for "command not found", so the command this workspace declares does not exist inside the sandbox and the suite never started. […] The workspace declared 44 dependencies and did not vendor a dependency tree, so a reader can check that reading for themselves.
The repository does declare a test script and the suite does pass outside the sandbox. It could not start inside one. This signal is excluded from the verdict (it is a statement about our sandbox, not about the workspace) and it is still counted in the 70% denominator. Section 5 says why that is the honest arrangement rather than the flattering one.
run.exit_code, labelled "Sandbox run did not complete cleanly"
Container exited 23 (one or more source files produced a parse diagnostic).
Exit 23 is the probe's own code for a parse diagnostic. It is the same finding as build.syntax_check, reported a second time through the container's exit status, and it counts against the verdict a second time. That double-counting is real and worth naming: two of the ten signals here are one underlying fact.
The certificate
{
"id": "7c5f9054-03bc-419a-9e18-08eb6d06458f",
"pitch_id": "pitch-wiregent",
"startup_name": "Wiregent",
"source_digest": "83e8a4219b073a9b0427e056e070fdb3623f297e1e36f5d0b1f1164daf868881",
"verdict": "FAIL",
"auditor_version": "docker-1.3.0",
"driver": "docker",
"model_participation": "none",
"public_key_id": "95df058b684628ca",
"created_at": "2026-07-27T15:40:36.159Z",
"signature": "1ac8507679d53297bc97aafae51ae33dc8bb47171462e361061683965ead8b47d8596016969fa6bceb8fd0bde05d06fd037af9380a3f23bc718b99e587b4ec02"
}
signature verifies against the printed public key: true
The arithmetic, shown
Rule R-03 in src/server/rules.ts is the code-robustness floor. Its input is defined in one sentence, in the source:
R-03's robustness input is the percentage of an attestation's MEASURED signals (
simulated: false) whoseprovenflag is true, rounded to the nearest integer,round(100 * proven / measured).
Applied to Stage A:
measured signals (simulated: false) 10 proven signals 7 round(100 * 7 / 10) = round(70.0) = 70
Count the two integers off the signal list in Section 2 and you get the same figure, with no access to Wiregent, no model, and no weighting table to trust. That property is the entire point. It is a proportion and deliberately not a quality score: the moment signals are weighted, the number stops being recomputable from the evidence and starts being an opinion Wiregent asserts about a build.
Three things this number is not:
- Not a code-quality judgement. It says how much of the diligence the platform attempted came back proven. Nothing more. The platform attempts ten stages, none of which is a SAST run, a dependency-vulnerability scan, or a service boot.
- Not derived from the PASS/FAIL verdict, which is a conjunction and therefore throws away everything except all-or-nothing.
- Not comparable across auditor versions. Adding a stage changes the denominator, which is why
auditor_versionis signed into every certificate. Compare two numbers only if they carry the same one.
One caveat, stated rather than buried. scripts/audit-self.ts prints these certificates; it does not write them into a pitch record. So no rule engine has literally consumed this attestation. The arithmetic above is the formula from src/server/rules.ts applied by hand to the signed signal list, which is exactly the recomputation the formula exists to permit.
The seven floors, and the one that clears
Seven investor agents are seeded in src/server/seed.ts, each with a min_code_robustness floor. R-03 allows when the derived percentage is greater than or equal to the floor, and escalates otherwise.
| Investor agent | partner_org | Floor | 70% |
|---|---|---|---|
investor-base-angel | Independent Angel | 70 | clears |
investor-railpath-payments | Railpath Collective | 88 | escalates |
investor-cohort-micro | Foundry Cohort | 90 | escalates |
investor-crestline-enterprise | Crestline Enterprise Reserve | 91 | escalates |
investor-northgrove-m2m | Northgrove Partners | 92 | escalates |
investor-antigravity | Antigravity | 94 | escalates |
investor-axiom-standard | Axiom Standard | 95 | escalates |
One of seven, by a margin of zero. 70 clears a floor of 70 because the comparison is >=. One more unproven signal and it clears nothing.
And clearing R-03 is not clearing a deal. R-03 is one rule of eight (R-01 through R-05 and three settlement gates). The certificate's own verdict is FAIL, which is a separate and worse fact than the percentage.
Why the failures are what they are
5.1 The test suite could not run, and the reason is the product
npm test exited 127 inside the sandbox. 127 is "command not found". The runner (vitest) is a devDependency, and the audited container runs with --network=none, so it cannot be installed at audit time.
--network=none is not an oversight and not a tuning parameter. It is the exfiltration control. It is the only reason a founder can hand private source to a stranger's runner at all: the code physically has no path to send itself anywhere. Turn it off and the product's single guarantee is gone.
The consequence is severe and general. Any project whose test command lives in node_modules (vitest, jest, mocha, playwright, tsx) exits 127 here. The same shape holds for a Python project needing pytest, a Go project needing modules it has not vendored, a Rust project needing a registry fetch. A dependency-heavy project is not an exotic case; it is the median case, and Wiregent's own is one of them.
An earlier version of this driver read exit 127 as "the declared test suite did not pass" and signed a FAIL against the founder. That was a fabricated finding: a fact about our sandbox, signed as a fact about their code. It was fixed by excluding a suite that could not start from the verdict, while keeping a suite that ran and failed as a hard failure. Note what that fix did not do: the signal is still proven: false, still on the certificate, still in the denominator of the 70%. A reader who wants to hold us to our test suite has everything needed to do it.
5.2 The parse stage fails partly because our own grammar is wrong
The parse stage reported 12 diagnostics across 244 TypeScript files. It also reported this, in the same signed block:
grammar_self_test_cases: 14 grammar_self_test_rejected: 1
Before it reports a single diagnostic against anyone, the stage runs the grammars it is about to use over a fixed corpus of known-valid code and counts how many of those the grammar rejects. One was rejected. The corpus contains this line specifically because of it:
export const B = () => <p>Security & Compliance</p>;
A bare & in JSX text. Every TypeScript compiler accepts it. tree-sitter-typescript 0.23.2, the newest published, does not. Measured on this repository when the stage was built, 8 of 9 flagged TypeScript files were flagged for exactly that.
So a diagnostic from this stage is a lead to check, not a defect established. tree-sitter never refuses input; it recovers, so "could not build a clean tree" is the grammar's account of a file, not a compiler's verdict on it.
Here is the design decision that follows, and it is the one worth arguing about: when the instrument is measurably unreliable, the signal fails. build.syntax_check is proven only when coverage is complete, no file produced a diagnostic, and the grammar rejected none of the known-valid code it was tested on. That third clause is what stops us blaming a founder for our instrument. It costs us the signal on our own codebase, which is the correct direction for the cost to run: a broken instrument should report itself broken, not report clean files as dirty.
We could have shipped this differently. We could have subtracted the known-bad diagnostics, or excluded .tsx from the count, or reported "12 files failed to parse" and let a reader assume our code is malformed. Each of those produces a nicer number. The first two are ungrounded (we cannot tell which 12 are the grammar's fault without naming files, and file names deliberately never leave the sandbox), and the third is a false accusation against a founder. We took the failure.
5.3 Stage B: the vendored path does not get in the door
The remedy for a sandbox with no network is to vendor dependencies. So Stage B did, for real:
| Measured | Cap | Over by | |
|---|---|---|---|
| Files | 39,222 | 15,000 | 24,222 |
| Bytes | 676,469,219 (645.13 MiB) | 201,326,592 (192.00 MiB) | 475,142,627 (453.13 MiB) |
| Directories | 3,892 | ||
| Symlinks | 30 |
intake budget: REFUSED the source tree exceeds the 201326592-byte cap error class: SourceTooLarge code=SOURCE_TOO_LARGE
A founder could not get this tree onto the runner at all. The driver was run against it anyway, so the second limit is measured rather than predicted: the container exited 26 (workspace exceeded the audit size cap) after truncating the manifest at 9,484 files. Stage B scored 5 of 10 proven, 50%, and clears none of the seven floors.
source_digest 7d0ca6e552d5…, attestation 29b976de-7459-426a-9f68-7d7da94ecbec, signature 1a16500c71d0…, verified against the same printed key.
The two stages together are the finding. Without vendored dependencies the suite cannot run. With them the tree cannot be admitted. The space of projects that currently pass this auditor cleanly is projects with a test script whose dependencies are absent or tiny. Our own test fixtures are such a project. They are three files.
The line that matters most
An earlier version of this exact metric was:
Math.floor(92 + Math.random() * 7)
A number between 92 and 98, generated by dice, handed to R-03, and printed in the rule trace as a confident percentage with a rule citation next to it. It cleared six of the seven floors above, every time, and looked exactly like diligence. Nothing had executed the code.
It was deleted on 26 July 2026, along with its file. The prohibition was then widened from one driver's habit into a contract: no model driver may produce a robustness number. The field was stripped from both vendor response schemas, both prompts state that robustness is out of scope, and the robustnessPercentage parameter was removed from the rule engine's input entirely, so no handler can hand R-03 a number again. For a day, R-03 reported unproven and nothing about anyone's code robustness was known.
Worse than the dice, and found next to them: code_quality_score || 93, the founder's own self-reported number, was being passed to R-03 as a diligence signal and rehydrated from the database on restart. A founder's claim relabelled as a verified finding looks exactly like diligence, which makes it more dangerous than a random number.
The 70 on this page is what replaced both. It is lower than either of them, it fails, and it is the first number in this system that a stranger can recompute from a signed certificate without asking us anything.
What this proves, and what it does not
Proven by this run:
- The sandbox genuinely executes and the isolation is real. Two containers ran. Isolation was read back from the daemon, not asserted by the code that requested it, and an in-sandbox probe independently confirmed egress was dead. Both accounts had to agree.
- The verdict is derived, not decorative. Both FAILs trace to container exit codes (23 and 26) the driver did not choose.
model_participation: "none"is in the signed claims. - The intake budget is enforced by code, not by documentation. A real 645 MiB tree was refused by the real code path with a real error class.
- The live-endpoint probe screens redirects, not just URLs. Alongside the run, the host's SSRF screener refused cloud metadata, loopback (v4, v6, and a v4-mapped v6 literal), private ranges, CGNAT, a hostname that resolves to loopback, a plaintext scheme, and credentials in a URL. It also refused two real 302s from public hosts into
169.254.169.254, where the first hop screens clean, which is the attack a URL-only screener would follow. - The number is recomputable. Two integers on a certificate, one division.
Not proven, and stated because the omissions are where a claim like this usually dies:
- This does not prove Wiregent can audit a typical project. It proves the opposite, for one very common shape. Read Section 5 as a limitation of the product, not as a footnote.
- This does not prove our code is good. 70% means seven of the ten checks the platform attempted came back proven. None of those checks is a security scan, a dependency audit, a performance measurement, or a review. A high number here would also not mean the code is good.
- This does not prove the live site runs the audited code. The liveness signal says so itself: something answered at that address at that moment, and nothing binds it to the
source_digest. - This does not prove Wiregent is a real business. There is no entity, no policy, no users and no revenue behind this repository. This run moves exactly one row of one evidence manifest: the build row stops being self-declared and becomes a signed, cryptographically attested FAIL.
- This is one run, of one repository, by its own authors. It is not an independent audit and should not be read as one. The only thing it establishes over a claim in a slide is that the numbers came out of a machine and the machine's output is reproducible by anyone who clones this repository.
Reproducing this
make audit-self
Requires a reachable docker daemon and the sandbox image built locally (make audit-image), because --pull=never means the audited container cannot fetch anything. The target sets AUDIT_DRIVER=docker explicitly, because the default is sim, whose signals are string templates and whose verdict is a hardcoded PASS. The run takes roughly 30 seconds, of which most is the node_modules copy in Stage B. Set AUDIT_LIVE_URL=none to skip the endpoint probe.
scripts/audit-self.ts implements no diligence of its own. It builds two workspaces and calls the shipped getAuditDriver(), censusAndSealWorkspace(), buildAttestationClaims() and signAttestation(). No limit was raised, no isolation flag was removed, no network was granted, and nothing under src/server/audits/** was modified to produce this page.
Your numbers will differ from these as the repository changes. The commit is named at the top for that reason.