Why Polydeukes?
Polydeukes is a development discipline framework for people working with an AI coding partner, or applying the same practices to their own commits. It makes selected promises explicit, judges the evidence a connected surface can observe, and records what happened. Its purpose is to reduce the supervision needed to verify work, not to claim that every action is visible or every generated change is correct.
The problem is unverifiable completion
Section titled “The problem is unverifiable completion”An agent saying “done, tests pass” is not the same as evidence that the relevant tests ran. A prompt can describe a good practice, but the instruction alone does not show whether it was followed. A useful development system must distinguish a passing check, a detected violation, a check that could not run, and work that never entered its observation boundary.
This distinction came from developing Polydeukes itself. A file edit could be refused while a script produced the same contents outside the observed tool path. A supposedly safe test probe could miss routing entirely. An overly broad path comparison could reject legitimate operations. These were different defects, not interchangeable examples of a successful block.
The response is to make narrower, testable claims: which path was observed, what evidence was available, which comparison ran, and which result was recorded. More blocking is not necessarily better verification.
What exists now
Section titled “What exists now”Six packages provide a shared input vocabulary, three session adapters, a TypeScript client
for programs, and the polydeukes umbrella, which carries the judge and the pdks command.
Two observation surfaces serve different purposes:
- The session surface judges one call before it runs — an input IR on stdin. Claude Code,
Grok, and Codex have installers, and a program reaches the same surface through
@polydeukes/sdk-ts; what history and witness each host can prove differs. An adapter uses stable host events to assemble that evidence rather than treating an undocumented transcript format as a contract. - The change-set surface judges a unified diff read from stdin — a staged diff piped by a pre-commit hook, or any diff a tool produces. It works without an AI agent. A project may connect either or both surfaces according to its needs.
A discipline is written in one of three config lists, and the list follows from what its
declaration reads. disciplines holds what both surfaces can judge — declarations reading only
the changed file. sessionDisciplines holds what only a live call carries — the command line,
the conversation history, the actor. changeSetDisciplines holds what only a finished change set
carries. The loader refuses an entry written in a list whose surface cannot observe its
channels, so the config file itself says where each discipline stands, and pdks explain
prints the same placement per surface.
A discipline is configuration data with extraction steps and relations. Seven relations and
eighteen mechanism names form the current vocabulary; delegated-scope is reserved rather than
usable. The mechanism restricts a declaration’s shape, while the surface determines which evidence
it can supply. An added-only declaration can tolerate existing matches; this is not the behavior
of every discipline. A pairing declaration, for example, compares the selected key sets.
See how judgment works, write disciplines, and the configuration reference.
Principles and their limits
Section titled “Principles and their limits”Shared covenants
Section titled “Shared covenants”A covenant is a promise the developer accepts too, not a restriction imposed only on an AI. Configured protection applies to the observed action, regardless of who initiated it. It does not prevent every possible edit outside connected surfaces. Protecting the discovered config file is a built-in behavior; protecting other source files depends on the configured paths.
A human witness can allow a blocking judgment without rewriting the policy. In a supported session, the token must stand alone on the first line of a human message and remain within its TTL. The change-set surface has no prompt: the valve is the session surface’s TTL witness, and the change-set surface only emits an exit code that the user’s hook consumes. The valve is consulted after judgment and does not repair a broken assembly.
Deterministic judgment, explicit enforcement
Section titled “Deterministic judgment, explicit enforcement”The judge evaluates supplied data without opening files or making network requests. Reproducing a verdict requires the same declaration and supplied evidence, not merely the same path name. The two surfaces need not produce the same result when their observations differ.
An ordinary discipline defaults to advise. Promotion to block is the author’s decision after
exercising both valid and violating cases. A surface’s level and an entry’s level compose with the
lenient side winning. Assembly errors remain failures; telemetry write failures do not change a
verdict. Missing evidence follows the declared supply policy rather than an invented empty source.
One call leaves one row, and one component writes it. An agent adapter translates a host’s payload into the judge’s input and hands it over; it decides nothing and records nothing. That holds on the failure path too: when an adapter cannot build the input, it sends the reason to the judge instead of recording the failure itself, so the writer never changes with the outcome.
Evidence with a stated boundary
Section titled “Evidence with a stated boundary”passed, blocked, witnessed, advised, and skipped describe judgment outcomes.
unattributed records a baseline finding, not a verdict. An empty observation, a skipped
registration, or a successful command exit is not proof that the whole project meets its promises.
Arbitrary child-process writes are not individually observed as session tool calls. Baseline comparison can reveal unexplained protected changes afterward, but cannot reconstruct the missing judgment. Logs and baseline files are local state; a Git clone does not transfer the history. Instructions read by an agent are also not proof that a host invokes the installed hook.
What the measurements say
Section titled “What the measurements say”These are historical observations from this repository, not a benchmark of other projects or a measurement of the current release. The dated development posts retain the circumstances and terminology of their periods.
| Period | Recorded observations |
|---|---|
| First self-use ticket | 133 rows: 75 passes, 2 blocks, 56 valve openings. |
| v0.1 milestone | 1,020 verdicts across three tickets: 455 passes, 13 blocks, 552 valve openings. The milestone audit also found five path-matching escapes to repair. |
| Five rounds before the advisory-default decision | No measured case of a real-time block preventing a bad edit; 93% of human valve openings concerned repairs to the judging chain. These are findings within those rounds, not proof that blocking is always useless. |
| Through 2026-08-26, five weeks | 7,446 rows: 6,438 passed, 686 skipped, 173 blocked, 88 advised, 47 unattributed, 14 witnessed. |
| v0.5.0 advisory round | 73 of 735 advised rows, or 9.9%, had a later pass on the same target in the same session. One read-first discipline reached 77%; another reached 0% across 292 rows. |
| v0.5.0 blocking observations | 88% of 162 blocks protected the judging chain; no false-block reports were filed. An assembly failure refused and recorded eight calls in 71 seconds. |
The advisory denominator counts calls, not independent decisions. An ignored advisory may recur. A later pass is the measurement’s operational definition of consumption, not proof that advice caused improvement. No false-block reports is not proof that no false blocks occurred.
There is also selection bias: an agent may reshape a call before submitting it to avoid a predicted
refusal. In the project’s interpretation, passed is an upper bound on compliance and blocked
a lower bound on intended violations. Neither count measures unsubmitted actions. The earlier
aspiration of “90-plus” predictability is a design goal, not an achieved rate.
The measurements motivated advice by default, a time-limited witness, and more explicit observation records. They do not establish that the current delivery of advice is sufficient. In the recorded host probe, stderr advice did not reach the model; the generated skill therefore asks the agent to read telemetry at task boundaries. Host behavior must be checked rather than assumed.
Decisions the measurements forced
Section titled “Decisions the measurements forced”Five incidents changed a mechanism rather than a number. They are listed here because the current design is hard to explain without them.
- A banned word that edits respected and a shell heredoc did not. The tool axis refused an edit carrying a banned word. The same content inside a heredoc reached the repository without a row, because the call never reached judgment. The shell axis gained heredoc-aware analysis and write detection for redirects (development post #1).
- A token that opened the valve from the middle of a sentence. The witness token was matched anywhere in a human message, so asking when the witness would expire extended the window. The rule became first line, alone (development post #2).
- A request accepted as evidence. The first
precedentjudgment counted a call that had merely been issued, soecho "npm view yaml"satisfied it more cheaply than running the check. Evidence now means a call that ran and reported success. - One file protected through its ancestors. Protecting a single path by ancestry made the
whole home directory protected;
cdinto it was refused for two weeks before anyone noticed. That path is now judged by full-path equality, and anything above the project root is out of scope. - Two hosts that agreed, and a third that did not. Routing a call to the covenants that might judge it read the tool’s arguments, while the judgment itself read the proven file change. Two hosts name their target in both places, so the disagreement stayed invisible until a third arrived whose edits carry a patch text and no path argument: its calls were routed nowhere and recorded as passed. Routing now reads the proven change as well. Passing on two hosts said they spell a path twice, not that the layer beneath them was right.
What remains a plan
Section titled “What remains a plan”A verifiable ledger, searchable local memory, and adversarial verification are roadmap components, not shipped services. Telemetry is not the future ledger, documentation search is not a memory system, and running a test suite is not an implemented adversarial review service.
Polydeukes is not an agent runtime or a sandbox. It complements linters and tests: some declarations compare file contents, others require observed process evidence. It does not execute a fresh benchmark during judgment or prove that a natural-language explanation is true.
The name’s story is in STORY.md. To try the implemented system, follow the first-judgment tutorial. For current limits and recovery, see troubleshooting. The project is in beta; its claims should be read with those limits, not as a promise of complete supervision-free development.