Guiding AI writing to make technical text easier to review Coding agents are producing verbose, low-priority technical text in comments, documentation, and pull requests that makes shipped code harder for engineers to review, according to an analysis of the practice. The piece argues that agents write to optimize reward for work done rather than to respect a human reader's time, citing a six-line comment wrapping a single mu_.unlock() call as an example of empty commentary. It concludes that verbosity without priority is a comprehension cost that grows as agents increase the volume of material produced. Software engineers write much less code by hand now. That's real and probably fair: coding agents do it faster, and most of the time, they are better at handling material context: various notes scattered over a repository, subtle references to changed code in other files, deployment gotchas, mundane, yet important, tests, and other details. However, we still need to read what we ship , and many engineers say this has only become harder. Humans consider other humans by default: we write to emphasise importance, nuance, priority. We respect each other's time and try to save the reader “context switches”. Agents mimic that, but in the end, they only write to optimise getting the reward for the work done. That now includes work over multiple sessions, so “naturally”, agents want to document progress, things to avoid, history of arriving at a solution, etc. As a next-session agent, you digest that and avoid the need to get this information yourself. As a human, you suddenly need to read a lot more to understand what you shipped. Worse still, you read and sigh: “What a mess. But it works, I'll ship it. The information is probably relevant to other teams, anyway.” Except it isn't, and “What a mess.” creeps in to become the unspoken mood in communication. How can we keep the gains in development velocity without losing the sense of purpose and priority? A familiar story Every day you read posts about how software engineers automate their routine by handing more and more tasks to coding agents. At some point, you decide to try. You allow the agent to write more than a few targeted rewrites. They work. At first, you start noticing small comments relating to previous behaviour of the code, and you think “oh, that's nice I wouldn't leave this, but it will probably help in my next sessions” . You then notice multiple instances of complex branching to “ensure backward compatibility”. You keep them: “good catch”. Your application hasn't been anywhere past your laptop yet. Then you start seeing a few “this code does X, not Y or Z”. Wait, what? There's no way a decent engineer would assume Y or Z in this context in the first place. Then it is: // This unlock is load-bearing; the thread I didn't plan but couldn't unsee // revealed that accesses compound, and under heavy contention, workloads // compounded, quietly, until a real wedge was formed, obliterating the // progress. I landed with the honest reason nobody told you out loud, which // is that this critical section must have been held all along. Reaching for // that settled it. mu .unlock ; ...six lines of empty talk for one useful change. You kept giving AI a pass because the code works, after all—but now, you feel like 80% of it is apologetic commentary, historical remarks does functionality never previously used need them? , and awkwardly personified narrative: your functions and variables “live”, “survive”, “stumble”, “hit a nerve”. The only thing that mattered was to ship fast, but nobody handed you that what also stays yours is empty, unfocused code riddled with Claudisms https://claudisms.ai/ in comments, documentation, and PRs. That's the thing we didn't plan for, but can't unsee, and it happened quietly. The cost Agents are confident. The code they write works: if not straight away, then with a few passes of refinement. They also write verbose and confident text, easy to believe and skip when you ship a feature. The text can be dense with technical facts while remaining totally unspecific. Everything receives similar weight: public behavior, private class names, file listings, implementation mechanics, validation, and conversational turn history. The reader has to reconstruct the hierarchy that the writer should have provided. The problem is larger than text sounding “weird.” Verbosity without priority is a comprehension cost. As agents increase the volume of material we can produce, that cost gets worse: generating another page is easy, while reading it carefully is not. Human-produced technical text can be uneven too, but a sense of priority is normally the baseline. The remedy Honestly speaking, nothing would completely secure us from current and future divergence of generated technical text towards Claudisms. Not with the current focus of the industry, not with currently available tools or data. The best comment, the best documentation, the best PR description are ones you wrote yourself, while feeling motivated to do so. Yet if we and our coworkers must use AI, at least we can make better copy part of the AI's explicit goals. Once we can name a problem, we can instruct the AI to avoid it. I took some time to think about what that problem is, and made a reusable writing style that tames agentic copy and resurfaces a sense of priority specifically. The result has made it noticeably easy for me to process generated technical text. The same guides were applied for a large monorepo at work, and the change was very welcome. Read on to see how; execute the prompt with your agent if you are in a hurry: Set up enforceable writing rules for AI agents in this repository. The rules must cover documentation, code comments, reports, user-facing text, and the agents' own replies. Use the writing rules in A11 as the baseline: https://github.com/hpnkv/a11 Read the relevant hooks and AGENTS.md files there. Before changing anything, inspect this repository's existing agent instructions, hooks, conventions, languages, documentation structure, and development workflow. Adapt the source rules to this repository's actual work. Remove A11-specific terminology, examples, paths, and assumptions. Preserve the principles about purpose, priority, proportion, reader-visible behavior, evidence, and concise replies. Apply shared written guidance to every supported coding agent. Apply automated hooks only to Claude. Integrate the rules into the instruction files and hook configuration that agents actually discover in this repository; do not leave them in an optional document that is easy to miss. Reconcile them with existing rules instead of creating contradictory copies. Validate that the resulting instructions are loaded from the expected scope and that any Claude hooks run at the intended points. Summarize which source principles you retained, how you adapted them to this repository, which files you changed, and how you verified the setup. What this guidance changes The guided edit improves Opus' outputs clearly. It removes implementation inventory it is visible in a VCS anyway and ceremonial sections not all applicable to every single PR; although I should acknowledge some people prefer structure regardless , preserves the operational boundaries, and puts the measured result where it supports the claim. The result requires less backtracking and feels edited rather than merely complete. Technical density is still present, but it now has an order. Here are some examples: Combined evaluation suite · real PR Compare a published pull-request description with a guided Opus rewrite of the same evidence. A real opt-in posttrain and agentic-evaluation change covering runtime isolation, ownership failure, retry, publication, compatibility, several recorded runs, and one unresolved storage limit. Internal proper names are redacted; numbers and commit IDs are preserved. Original PR 612 words What this PR does Runs the ordinary posttrain benchmarks and the agentic SWE-Verified + Terminal-Bench 2.1 agentic suite, protocol v2 evaluation as one orchestrator run on one GPU cluster , behind the opt-in suite combined-eval . The frozen agent runtime is consumed as a digest-pinned image; only versioned JSON envelopes cross the boundary; sandboxes run under gVisor via the orchestrator sandbox component on stack combined-eval-stack . Ordinary suites, GKE path and evaluation publication are unchanged. Commit map over main - Feature 7 commits : opt-in suite + GPU cluster in-cluster sandbox, registered sandbox identity, smoke build reuse, tolerant admission + settle pass for externally killed task pods, docs. - Code-review fix pass findings 1–5, 7 of the high-effort review : task steps get the enriched agentic suite payload sandbox anti-affinity from the serving node ; Lease reads under with retries , coordination client in-cluster only; in-step and orchestrator guards fail only on lost Lease ownership lapse without recovery, holder change, persistent claim mismatch — transient ticks are guard warnings , not envelope-destroying errors; group fan-ins no longer depend on every ordinary future; served model name validation raises RuntimeError and '' falls back to the model. Finding 6 deliberately not applied: orchestrator 0.96.1's dynamic runner cancels every later submission after any FAILED step, so tolerance at admission cannot reach the barrier. - fix eval : retry externally killed agentic suite task steps — STEP RETRY on run agentic invocation as 1764 did for every other step . Motivated by run 08da7be6 : one node DNS blackout → one FAILED task step → ~60 unsubmitted tasks cancelled. Scored tasks are never retried. - Default eval node → eval-node -16 reservation system reservation evaluation-pipeline ; eval-node -15 moved into the training-workload training reservation on 2026-08-28 . - Review-thread fixes : agentic suite branch ids and expected task counts are data-driven agentic.expected tasks map ; the suite no longer carries a client: block — the reference checkpoint lives in configs/client/ model -2-thinking-b1-iter2587.yaml . - Snapshot publish folded in from 1803, now closed : evaluation pipeline combined-eval is CI-bakeable on combined-eval-stack submit. bake stack sets ORCHESTRATOR ACTIVE STACK ID per suite, write-free; agentic suites bake last; snapshot candidate: false keeps it out of the release gate's candidate set . First real bake happens on the next release or a manual workflow dispatch tier=release ; checklist in the commit message. Evidence | Run | Code | Result | |---|---|---| | a462e8ca | pre-fix | 1+1 canary, 13/13 | | a285d01b | pre-fix | full 160/160: SWE-Verified 0.354 n=50 , TB 2.1 0.114 n=89 ; 3 “infra errors” were guard false positives on solved tasks | | 08da7be6 | fixes + rebase, n16 | ordinary 10/10, bind 8/8 Ready, 77/139 tasks scored; paired with a285d01b: 11/37 SWE solved in both, 9 symmetric flips, 0 guard errors/warnings; wave cut short by a node DNS blackout → STEP RETRY | | f4c716bd | HEAD 9bfc4c7899 | canary 13/13: TB reward 1.0, SWE 0.0 model stagnation , guard telemetry clean | | next | HEAD b7769fd6e4 | canary on the consolidated branch — result to follow | Comparison table with per-task pairing: https://github.com/JetBrains/jetbrains-ai-ml/pull/1791 issuecomment-5512285074 https://github.com/JetBrains/jetbrains-ai-ml/pull/1791 issuecomment-5512285074 Review status reviewer Summary of every thread and the follow-up chain: https://github.com/JetBrains/jetbrains-ai-ml/pull/1791 issuecomment-5512140723 https://github.com/JetBrains/jetbrains-ai-ml/pull/1791 issuecomment-5512140723 - Fixed on this branch: suite carries no model client config , hard-coded branch ids. - Answered, follow-up PRs proposed: frozen commit/digest pin → bake-time identity; monkey-patched frozen internals → agent-runtime extension points; fold into posttrain.yaml ; canary yaml → debug suite; pipeline.py refactor; agentic suite evaluation publication; benchmark-set / pass@k / campaign integration. Ops notes - eval-node -16 had the training launcher's RL slot volume node-volume -13-data 1830Gi filling the local NVMe group; removed with the user's approval. Serving.node storage gb=3850 is wrong for these nodes ~1900Gi — follow-up. - Tests: 453 pipeline + 21 evaluation-pipeline pass; ruff clean on touched files 5 pre-existing F401 in tests/test serving.py . 🤖 Generated with Claude Code https://claude.com/claude-code Opus with guidance 306 words The opt-in combined-eval suite runs the ordinary posttrain benchmarks together with the agentic SWE-Verified and Terminal-Bench 2.1 evaluation as a single orchestrator run on one GPU cluster. - The frozen agent runtime is consumed as a digest-pinned image, only versioned JSON envelopes cross the boundary, and sandboxes run under gVisor via the orchestrator sandbox component on stack combined-eval-stack . Ordinary suites, the GKE path, and evaluation publication are unchanged. - In-step and orchestrator guards fail only on lost Lease ownership — a lapse without recovery, a holder change, or a persistent claim mismatch — while transient ticks become guard warnings instead of destroying the envelope. Admission itself stays intolerant because orchestrator 0.96.1's dynamic runner cancels every later submission after a FAILED step, so tolerance there cannot reach the barrier. - run agentic invocation carries STEP RETRY , so an externally killed task step is resubmitted; scored tasks are never retried. The default eval node is eval-node -16 reservation system reservation evaluation-pipeline , agentic suite branch ids and expected task counts come from the agentic.expected tasks map, and the reference checkpoint lives in configs/client/ model -2-thinking-b1-iter2587.yaml rather than a client: block in the suite. Remaining follow-ups are listed in the review summary. - evaluation pipeline combined-eval is CI-bakeable on combined-eval-stack : submit. bake stack sets ORCHESTRATOR ACTIVE STACK ID per suite write-free and bakes agentic suites last, and snapshot candidate: false keeps the snapshot out of the release gate's candidate set until the next release or a manual workflow dispatch tier=release . Run a285d01b scored a full 160/160 SWE-Verified 0.354, n=50; TB 2.1 0.114, n=89 , and run 08da7be6 on the fixed code reached 8/8 Ready replicas with 77/139 tasks scored and no guard errors before a node DNS blackout cut the wave short; the per-task pairing of the two shows 11/37 SWE tasks solved in both and 9 symmetric flips, and Serving.node storage gb=3850 remains wrong for these ~1900Gi nodes. Retry and cancellation Write the pull-request description from the same retry and cancellation notes. The inference client honors capped Retry-After delays, cancels pending retries immediately, reports exhaustion through the public error, preserves request compatibility, and has fault-injection coverage. Opus 131 words Retry and cancellation contract for the inference client Makes the inference client's retry behavior honor server-supplied delays and stay responsive to cancellation. Behavior - Retry-After is honored for HTTP 429 and 503 responses. - The delay is capped by max delay s . - Cancellation interrupts a pending retry delay immediately and propagates to the caller. - Exhausting attempts raises RetryExhausted carrying attempts and last status . - The request signature and default retry settings are unchanged. Implementation sleep with cancel replaces asyncio.sleep so delays are cancellable. Date-form Retry-After values are parsed with email.utils.parsedate to datetime ; parsing and capping are separate phases. Changes span client.py , retry.py , errors.py , and eight test files. Docs Public contract: docs/inference/retries.md . Validation Fault-injection tests cover computed backoff, numeric and date-form Retry-After , cancellation during every delay, and attempt exhaustion. Opus with guidance 74 words The inference client honors Retry-After on HTTP 429 and 503 responses, capped by max delay s . - Cancellation interrupts a pending retry delay immediately and propagates to the caller. - Exhausting attempts raises RetryExhausted carrying attempts and last status . - The request signature and default retry settings are unchanged. - The public contract is documented in docs/inference/retries.md . Fault-injection validation covered computed backoff, numeric and date-form Retry-After , cancellation during every delay, and attempt exhaustion. Workload identity Write a pull-request description from the same implementation and rollout notes. Workers replace collector tokens with workload identity. Startup fails on identity exchange failure; later export failure drops spans after three retries without invalidating benchmarks. Opus 145 words Workload identity for trace export Evaluation workers now authenticate to the trace collector through workload identity instead of OTEL EXPORTER OTLP HEADERS . Credentials are fetched from the JCP metadata endpoint and cached for 80% of their lifetime. Why Operators no longer have to distribute or rotate collector tokens in worker secrets. The collector endpoint is unchanged. Behavior - Identity exchange failure stops startup, before the worker accepts any evaluation work. - A later trace-export failure does not stop a running evaluation: the exporter drops spans after three retries and benchmark results remain valid. Changes - CredentialInjector helper removed. - otel-collector-token secret removed. - Two deployment YAML files, three Python modules, and nine tests changed. Rollout 1. Add identity annotations. 2. Switch workers. 3. Delete secrets. Migration and rollback: docs/observability/workload-identity.md . Validation A 20-worker staging rollout exported 1.8 million spans, with no token headers present in pod environments. Opus with guidance 98 words Evaluation workers authenticate to the trace collector through workload identity instead of OTEL EXPORTER OTLP HEADERS . - Operators no longer distribute or rotate collector tokens in worker secrets, and the collector endpoint setting is unchanged. - A failed identity exchange fails startup before the worker accepts evaluation work. - A later trace-export failure does not stop a running evaluation: the exporter drops those spans after three retries and benchmark results remain valid. - The migration and rollback procedure is in docs/observability/workload-identity.md . A staging rollout across 20 workers exported 1.8 million spans with no token headers present in pod environments. Deployment-wide admission Write the pull-request description from the same deployment-wide admission notes. A PostgreSQL FIFO queue replaces per-replica GPU admission, preserves submit and cancel interfaces, defines database-loss behavior and rolling compatibility, and was validated against a 32-slot ceiling. Opus 154 words GPU admission across the whole deployment Replaces the per-replica GPU semaphore in the workload service with a PostgreSQL FIFO admission queue shared across the deployment. Behavior - The configured GPU slot limit now applies across all replicas, not per replica. - Waiters are granted slots in submission order. - Submit and cancel commands are unchanged. - If the database becomes unavailable, new submissions are rejected; already admitted jobs keep running. Implementation Adds migration 0042 and the QueueLease , CapacitySnapshot , and PostgresAdmissionController components. Slot handout uses SELECT FOR UPDATE SKIP LOCKED . The migration creates two indexes. Rollout Rolling deployment goes through a dual-read phase so old and new replicas can share the queue: phase one adds the schema, phase two enables dual-read, phase three switches writes to the queue. Docs Queue protocol: docs/admission-queue.md . Validation End-to-end run 8f3194ce completed 412 jobs without ever exceeding 32 active GPU slots. Seven unit-test files were updated. Opus with guidance 95 words GPU admission now runs through a PostgreSQL FIFO queue shared by every workload-service replica instead of a per-replica semaphore. - The configured GPU slot limit applies across the whole deployment, and waiters are admitted in submission order. - Submit and cancel commands keep their current interfaces. - Losing the database rejects new submissions; jobs already admitted continue running. - Rolling deployment passes through a dual-read phase so old and new replicas share one queue. - The queue protocol is documented in docs/admission-queue.md . End-to-end run 8f3194ce completed 412 jobs without exceeding 32 active GPU slots. Dashboard comparison Describe a dashboard change from matched behavior, compatibility, implementation, and validation notes. The dashboard compares four runs, persists selection in the URL, aligns repeated run IDs, supports keyboard selection, and preserves existing single-run URLs. Opus 146 words Compare evaluation runs in the dashboard The dashboard can now compare up to four evaluation runs in a single score table. Before: docs/images/compare-before.png After: docs/images/compare-after.png Behavior - Rows group benchmarks by suite and show deltas relative to the first selected run. - The selected runs appear in the URL, so a comparison can be shared and is restored after reload. Existing single-run URLs continue to work. - The backend accepts repeated run id query values and returns one aligned response. Accessibility Space adds or removes the focused run, and the selection control announces its current count. Implementation CompareRunPicker.tsx and useComparisonState.ts on the frontend, comparison.py with RunAlignmentIndex on the backend. The table uses a twelve-column CSS grid; six snapshots were added. Validation A deployed comparison of 4ac20d11 , 72bf198a , and 15c9e674 matched the scores shown for each run individually. Three component tests and eleven API tests pass. Opus with guidance 109 words The dashboard compares up to four evaluation runs in a single score table. - Rows group benchmarks by suite and show score deltas against the first selected run. - The selected runs appear in the page URL, so a comparison can be shared and restored after reload; existing single-run URLs continue to work. - The backend query accepts repeated run id values and returns one aligned response. - Space adds or removes the focused run, and the selection control announces its count. - Before and after views: docs/images/compare-before.png , docs/images/compare-after.png . A deployed check across runs 4ac20d11 , 72bf198a , and 15c9e674 reported the same scores as their individual pages. Resumable dataset transform Write the pull-request description from the same restart and output-integrity notes. A dataset transform resumes at the first unfinished shard, uses a manifest to validate completed output, excludes partial writes, preserves old transforms, and was checksum-validated after eviction. Opus 151 words Resumable YT dataset transform The YT dataset transform now resumes at the first unfinished shard after a worker restart instead of starting over. Behavior - Each completed shard records its input revision and output checksum in a manifest. - On restart, a shard is skipped only when both its input revision and output checksum still match; otherwise the shard is rewritten. - A partially written shard is never added to the manifest — the worker writes to a temporary path with a UUID suffix and renames on completion. - Existing transforms without a manifest start from shard zero. No configuration change is required. Implementation Introduces ManifestWriter , ShardFence , and RevisionProbe . The manifest is JSON Lines. Fourteen fixtures were updated. Docs Manifest contract and recovery procedure: docs/yt/transform-manifest.md . Validation A 2.1 TB validation run was interrupted by worker eviction, resumed, and produced the same aggregate checksum as an uninterrupted run. Opus with guidance 94 words The YT dataset transform resumes at the first unfinished shard after a worker restart. - Each completed shard records its input revision and output checksum in a manifest; restart skips the shard only when both still match and otherwise rewrites it. - A partially written shard never enters the manifest. - Transforms without a manifest start from shard zero and need no configuration change. - The manifest contract and recovery procedure are in docs/yt/transform-manifest.md . A 2.1 TB validation run resumed after worker eviction and produced the same aggregate checksum as an uninterrupted run. What does “good” look like? A writing guide does not need to prescribe a single voice. It should establish the minimum hierarchy that makes technical output reviewable. In AI's own words' summary of the guidance: 1. Describe what is true now. Make the code, behaviour, result, or constraint the subject, using present-tense factual verbs. 2. Lead with the outcome. Follow it with evidence, material risks, and the next action the reader needs. 3. Select detail by consequence. Include a fact only when it changes the reader's action, interpretation, or result. 4. Shape the document around its job. Let a guide complete one task, a reference specify a contract, and a report present a result and its evidence. 5. Use structure when it aids retrieval. Keep related points in prose, use lists for parallel items or steps, and keep headings sparse and descriptive. 6. Keep mechanisms and evidence together. State ownership, triggers, ordering, scope, and consequences; place measurements beside their claims. 7. Compress after checking correctness. Remove repetition, drafting history, implementation inventories, and detail that belongs in an owning reference. But Opus isn't the latest model. Didn't later models fix the style? That would be a reasonable explanation if the problem belonged to one model generation. The third comparison gives baseline Opus and baseline Fable the same dashboard task. If a newer model had fixed the style by default, Fable should establish a clearer hierarchy or demand less work from the reader. Opus vs Fable Describe a dashboard change from matched behavior, compatibility, implementation, and validation notes. The dashboard compares four runs, persists selection in the URL, aligns repeated run IDs, supports keyboard selection, and preserves existing single-run URLs. Opus 146 words Compare evaluation runs in the dashboard The dashboard can now compare up to four evaluation runs in a single score table. Before: docs/images/compare-before.png After: docs/images/compare-after.png Behavior - Rows group benchmarks by suite and show deltas relative to the first selected run. - The selected runs appear in the URL, so a comparison can be shared and is restored after reload. Existing single-run URLs continue to work. - The backend accepts repeated run id query values and returns one aligned response. Accessibility Space adds or removes the focused run, and the selection control announces its current count. Implementation CompareRunPicker.tsx and useComparisonState.ts on the frontend, comparison.py with RunAlignmentIndex on the backend. The table uses a twelve-column CSS grid; six snapshots were added. Validation A deployed comparison of 4ac20d11 , 72bf198a , and 15c9e674 matched the scores shown for each run individually. Three component tests and eleven API tests pass. Fable 145 words Compare up to four evaluation runs in one score table Summary The dashboard can now compare up to four evaluation runs in a single score table. Rows group benchmarks by suite and show deltas from the first selected run. Behavior - Shareable state: selected runs appear in the URL, so a comparison can be shared and is restored after reload. - Backend: the API accepts repeated run id query values and returns one aligned response. - Keyboard and accessibility: Space adds or removes the focused run, and the selection control announces its count. Compatibility Existing single-run URLs continue to work. Implementation - Frontend: CompareRunPicker.tsx , useComparisonState.ts , a twelve-column CSS grid, six updated snapshots. - Backend: comparison.py with RunAlignmentIndex . Validation - A deployed comparison of 4ac20d11 , 72bf198a , and 15c9e674 matched each run's individual scores. - Three component tests and eleven API tests pass. Side note: Codex seems genuinely better Even though three examples cannot settle model quality in general, in these matched tasks, GPT-6 consistently makes the reader's job easier. It keeps the contract and evidence while removing enumeration, completes an example instead of merely formatting it, and gives detail weight in proportion to its consequence. Executable cache README Open a model-cache README with one working example and its observable result. The package caches handles by model and device, shares concurrent loads, evicts after a TTL, and closes handles when its async context exits. Fable 5.1 88 words model cache model cache caches loaded model handles by model ID and device. Concurrent requests for the same model ID and device share a single load, and handles that go unused for the configured TTL are evicted. Quick start python from model cache import CachePolicy, ModelCache policy = CachePolicy ttl seconds=600 async with ModelCache loader=load model, policy=policy as cache: first = await cache.get "example-model", device="cuda:0" second = await cache.get "example-model", device="cuda:0" assert first is second the second get returns the same cached handle output = await first.generate prompt The first get loads the example-model model on cuda:0 . The second get for the same model ID and device returns the same cached handle without loading again. ModelCache is an async context manager; leaving the context closes every loaded handle. TTL and eviction settings are described in docs/policy.md docs/policy.md . GPT-6 79 words model cache model cache caches loaded model handles by model ID and device. Concurrent requests for the same pair share one load, and handles unused for the configured TTL are evicted. Use ModelCache as an async context manager. This example accepts your model loader and prompt, requests the same handle twice, and generates a response: python from model cache import CachePolicy, ModelCache async def generate load model, prompt : policy = CachePolicy ttl seconds=600 async with ModelCache loader=load model, policy=policy as cache: handle = await cache.get "example-model", device="cuda:0" cached handle = await cache.get "example-model", device="cuda:0" assert cached handle is handle return handle.generate prompt The second request returns the same cached handle. Leaving the context closes every loaded handle. See TTL and eviction settings docs/policy.md to configure the cache policy. Workload identity PR Write a pull-request description from the same implementation and rollout notes. Workers replace collector tokens with workload identity. Startup fails on identity exchange failure; later export failure drops spans after three retries without invalidating benchmarks. Fable 5.1 155 words Authenticate evaluation workers to the trace collector with workload identity Summary Evaluation workers now authenticate to the trace collector through workload identity instead of OTEL EXPORTER OTLP HEADERS . Operators no longer distribute or rotate collector tokens in worker secrets. The collector endpoint is unchanged. Behavior - Startup: if the identity exchange fails, startup stops before any evaluation work is accepted. - Runtime: a later trace-export failure does not stop a running evaluation. The exporter drops spans after three retries, and benchmark results remain valid. - Credentials: credentials come from the JCP metadata endpoint and are cached for 80% of their lifetime. Changes - Removed the CredentialInjector helper and the otel-collector-token secret. - Changed two deployment YAML files, three Python modules, and nine tests. Rollout 1. Add identity annotations. 2. Switch workers. 3. Delete secrets. Migration and rollback steps: docs/observability/workload-identity.md . Validation A 20-worker staging rollout exported 1.8 million spans with no token headers present in pod environments. GPT-6 110 words Evaluation workers authenticate to the trace collector through workload identity, removing the need for operators to distribute or rotate collector tokens in worker secrets. - Identity exchange failure stops startup before evaluation work is accepted. - Trace-export failure during an evaluation drops spans after three retries while the evaluation continues and benchmark results remain valid. - Credentials come from the JCP metadata endpoint and are cached for 80% of their lifetime. - The collector endpoint is unchanged; follow the migration and rollback guide docs/observability/workload-identity.md to add identity annotations, switch workers, and delete token secrets. Validation: a 20-worker staging rollout exported 1.8 million spans with no token headers in pod environments. Deployment-wide admission PR Write the pull-request description from the same deployment-wide admission notes. A PostgreSQL FIFO queue replaces per-replica GPU admission, preserves submit and cancel interfaces, defines database-loss behavior and rolling compatibility, and was validated against a 32-slot ceiling. Fable 5.1 131 words Deployment-wide GPU admission via a PostgreSQL FIFO queue Summary Replaces the per-replica GPU semaphore with one PostgreSQL FIFO admission queue shared by every workload-service replica. The configured GPU slot limit now applies across the whole deployment, and waiters receive slots in submission order. Compatibility - The submit and cancel interfaces are unchanged. - If the database is lost, new submissions are rejected. Already admitted jobs continue. Implementation - Migration 0042 . - New QueueLease , CapacitySnapshot , and PostgresAdmissionController . - Admission uses SELECT FOR UPDATE SKIP LOCKED ; two indexes added. Rollout Rolling deployment uses a dual-read phase so old and new replicas share the queue. Protocol and rollout details: docs/admission-queue.md . Validation - Run 8f3194ce completed 412 jobs without exceeding 32 active GPU slots. - Seven unit-test files changed. GPT-6 79 words A PostgreSQL FIFO admission queue shared by every workload-service replica enforces the configured GPU slot limit across the deployment. - Waiters receive slots in submission order. - Database loss rejects new submissions while already admitted jobs continue. - Submit and cancel interfaces are unchanged. - Rolling deployment uses a dual-read phase so old and new replicas share the queue; see the protocol and rollout reference docs/admission-queue.md . Validation: run 8f3194ce completed 412 jobs without exceeding 32 active GPU slots. What the comparisons show The guided edit improves Opus clearly. It removes file enumeration and ceremonial sections, preserves operational boundaries, and puts measured results where they support the claim. The result requires less backtracking and feels edited rather than merely complete. Technical density is still present, but it now has an order. Baseline Opus and Fable are mostly the same. Both are convoluted, both preserve inconsequential implementation detail, and both invent document grammar that the task did not ask for. Opus gives Accessibility its own section; Fable adds Summary and Compatibility. Those taxonomies look different while adding nearly the same reading cost and communicate nearly the same meaning. Codex is better again in the guided comparison. It makes the outcome the first unit of meaning, groups the remaining facts around review decisions, and drops details that do not change those decisions. Its shorter shape is useful because the omitted material is mostly enumeration rather than important change of behaviour. The reader gets the purpose, boundaries, and evidence without first decoding the source notes and diving into neighbouring context. Put a writing guide in your repository If this problem feels familiar, ask an agent to install writing guidance where you work. The prompt below uses the rules in A11 https://github.com/hpnkv/a11 as a starting point, then requires the agent to inspect the destination repository and adapt the guidance rather than copying project-specific language blindly. Set up enforceable writing rules for AI agents in this repository. The rules must cover documentation, code comments, reports, user-facing text, and the agents' own replies. Use the writing rules in A11 as the baseline: https://github.com/hpnkv/a11 Read the relevant hooks and AGENTS.md files there. Before changing anything, inspect this repository's existing agent instructions, hooks, conventions, languages, documentation structure, and development workflow. Adapt the source rules to this repository's actual work. Remove A11-specific terminology, examples, paths, and assumptions. Preserve the principles about purpose, priority, proportion, reader-visible behavior, evidence, and concise replies. Apply shared written guidance to every supported coding agent. Apply automated hooks only to Claude. Integrate the rules into the instruction files and hook configuration that agents actually discover in this repository; do not leave them in an optional document that is easy to miss. Reconcile them with existing rules instead of creating contradictory copies. Validate that the resulting instructions are loaded from the expected scope and that any Claude hooks run at the intended points. Summarize which source principles you retained, how you adapted them to this repository, which files you changed, and how you verified the setup. Conclusion Human writing starts with another human in mind. We highlight what matters, try to preserve nuance, and give information in an order that respects the reader's attention. Guidance establishes a reviewable baseline. It does not make an agent write like a human; it makes a reader actually able to review the work, instead of passing it onto the next reader or trusting it blindly. The best copy is written by humans when they are motivated. Comments, documentation, and PR descriptions are the strongest when you write them yourself, following a clear reason to communicate. Readable, well-edited text must be part of the assignment. If AI is part of the workflow, well-edited text with visible purpose and priority should be one of its explicit goals.