Decide: does this project need explicit code-quality standards (clean code, design patterns, OO practice), or is the real debt somewhere else? #748
Open
opened 2026-10-05 06:47:15 +02:00 by ltms
·
4 comments
No Branch/Tag Specified
main
worker/759-authz-comment-and-role-list-e3f0e5-5
worker/756-758-observer-pane-discovery-7e6ffd-1
worker/759-role-model-comments-5d8409-3
worker/743-pane-discovery-ad5b75-5
worker/743-observer-send-4706db-6
worker/749-edge-baseline-28d1a0-3
worker/748-dead-comment-refs-f42ac5-4
worker/737-9c61d3-4
worker/737-a263f3-3
worker/737-20d1d9-1
worker/737-b038f7-2
worker/726-unit2-75cb13-4
worker/737-owner-key-ff061f-10
worker/736-presence-forget-f35144-9
worker/705-observer-14c258-6
worker/722-024c34-5
worker/726-ea34a0-2
worker/726-10cbf0-1
worker/729-5961c6-3
worker/727-ee14ed-3
worker/719-bdd95e-4
worker/702-4f5c7f-2
worker/715-5c43fc-1
worker/721-70f9ea-5
worker/718-99362b-2
worker/task-15-af0d10-12
worker/task-16-50a702-13
worker/task-12-4d0479-9
worker/task-13-823ce2-10
worker/705-ticket-owner-af9928-8
worker/703-list-collaborators-9c06c2-7
worker/669-example-truth-0b303d-6
worker/669-collab-deliverability-9ba859-3
worker/669-collab-reload-report-2a21bd-4
worker/669-7e80a6-1
worker/669-unit-d-efbbd7-1
worker/669-1b786a-1
worker/669-1d1d9f-1
worker/692-4afb9d-2
worker/689-02fced-13
worker/693-cf23fa-14
worker/677-fix-lead-collision-f69073-12
worker/638-fix-overmask-dbb1bf-11
worker/675-5b7478-4
worker/669-unit-a-70cc8f-3
worker/677-8cdaaf-5
worker/638-a7b391-1
worker/683-4536d6-2
worker/651-a75bbe-8
worker/680-20607d-7
worker/664-c12e95-3
worker/668-08534d-4
worker/672-0f2469-2
worker/670-7d1022-1
worker/661-ac7c28-2
worker/664-37fb9b-3
worker/663-remove-3arg-read-3f6783-1
worker/659-remove-dead-backcompat-ba5e6f-1
worker/637-revision-60a488-23
worker/656-redact-regression-tests-892903-19
worker/637-context-gauge-threshold-466eb5-16
worker/639-redact-line-numbers-de4ac4-17
worker/641-set-reformat-guard-6f96a4-18
worker/642-herdr-guard-scope-5de0e4-15
worker/650-javadoc-scope-95f3b3-14
worker/612-01e9f7-13
worker/612-a-r4-quarantine-outage-7ab0e8-5
worker/612-a-r9-r11-capacity-coverage-peers-cfcc79-7
worker/612-a-r10-loophealth-ccc872-8
worker/612-a-r12-turnregistrar-9e3bb7-9
worker/612-a-r5-leadconfigdir-9e70cf-6
lead/config-edit-redact-anchor-wording
worker/config-edit-seam-ca8dc1-1
worker/612-r67-630-lifecycle-290b8d-3
worker/629-625-ports-seams-da7d5d-4
worker/612-r12-exhaustion-f37cd7-1
worker/612-r38-amqp-24b083-2
worker/fleetd-612-unita-87807e-1
worker/612-b3-mcpwirings-da2b58-3
worker/612-b2-cb185-176d3a-2
worker/612-b1-completion-457459-1
worker/612-agaps-73a926-2
worker/608-sleeps-3a64ff-3
worker/621-b4520b-1
worker/618-b83894-2
worker/fleetd-615-e05481-5
worker/lead-autocompact-5f1ab2-3
worker/fleetd-613-f85deb-3
worker/fleetd-608-flaky-nudge-test-d0c2d1-3
worker/lead-context-gauge-ad404f-1
worker/gauge-wiring-9158c1-4
worker/redeploy-slowstart-ead0e5-5
worker/charter-bytes-13668c-6
worker/rollover-outcome-291483-2
worker/589-f64303-2
worker/593-1a8025-5
worker/589-fcd2aa-1
worker/568-9fdaa2-3
worker/571-attempted-outcome-5739f7-2
worker/581-completionresolver-cas-sites-0542b7-6
worker/562-loop-health-wiring-test-99611c-5
worker/562-surface-loop-health-7df5cc-4
worker/575-waiter-cleanup-sites-62ad80-1
worker/572-answer-lock-release-46a9ae-5
worker/567-probe-channel-leak-a38fc5-6
worker/551-record-before-send-7cbf56-1
worker/561-listener-fanout-survives-a-throw-61d538-2
worker/555-redeploy-main-flow-seam-65c2f5-2
worker/556-injector-owns-registration-e027a5-1
worker/552-post-restart-mktemp-abort-bc2672-4
worker/553-onstatus-completion-leak-0da881-2
worker/550-shasum-linux-196132-1
worker/538-loop-dies-on-error-4a5eeb-6
worker/426-health-coverage-ef1fd4-4
worker/504-failed-reported-clean-3cfd66-3
worker/537-capturedlog-close-e4c437-2
worker/459-broken-link-targets-cadc17-5
worker/535-appender-leak-fe74c1-1
worker/512-part2-shutdown-detection-434701-9
worker/529-logger-level-sweep-2a5533-8
worker/528-drain-gate-call-site-5de83d-7
charter/forge-mcp-vs-token
worker/521-swap-guard-unpinned-28e931-5
worker/519-probe-test-harness-d25ab8-4
worker/525-logger-level-leak-1b4eb0-6
worker/518-fleetmcp-resolver-wiring-8ef96c-1
worker/512-drain-complete-line-7edd71-3
worker/517-abort-branch-and-jar-id-41b641-2
worker/500-9e52c9-3
worker/509-4912f4-2
worker/511-9a4b23-1
worker/493-479f45-2
worker/505-03f8b2-1
worker/492-followup-detect-unclear
worker/501-a31fa0-7
worker/498-451d1c-5
worker/494-1015ce-2
worker/492-209647-1
worker/489-001902-2
worker/480-relative-handover-path-906323-1
worker/480-b-handover-skill-45bf1f-5
worker/474-followup-source-pin-f54a55-17
worker/474-charter-check-on-reload-f54a55-17
worker/466-quarantine-repeatcount-report
worker/393-opencode-skill-seeding-71854b-13
worker/469-canonical-tool-names-2a472a-16
worker/466-quarantine-escalation-5ae9c1-15
worker/446-hot-exhausted-pattern-0af580-6
worker/464-charter-tool-name-guard-a85635-12
worker/463-listfleet-default-fails-open-f1c76c-11
worker/458-invariant-5-by-purpose-862f9a-10
worker/439-coordinator-row-gate-bc032a-8
worker/449-herdr-protocol-576015-4
worker/450-abstract-spawn-599e1c-5
worker/437-ack-refuses-177d91-1
worker/444-placement-window-feb56a-2
worker/440-helddurable-derived-d462d7-13
worker/425-rework-placement-resolve-c58ba1-9
worker/421-lead-peek-held-msgs-cdbad2-10
worker/435-fixed-policy-cap-fe11de-12
worker/422-gate-state-observability-9e79d6-11
worker/431-memberregistry-live-readers-cdbad2-10
worker/424-architect-slot-hot-038b41-7
worker/422-model-gate-spawn-c29f48-6
worker/425-default-profile-live-f55534-8
worker/415-coverage-wording-2cbf9c-5
worker/416-3ad1da-1
worker/418-588283-3
worker/deterministic-stamp-race-409-3cb7b6-10
worker/armed-reads-live-config-404-ed931f-9
worker/reply-peer-refusal-391-5a34bd-7
worker/models-allowlist-aa9e9b-3
worker/ttl-stamp-race-399-f1122f-8
worker/scrub-receipt-400-316b3e-5
worker/exhaustion-detection-395-105105-6
worker/scrub-abort-394-316b3e-5
fix/scrub-uid-abort
worker/task-scrub-517574-2
worker/t386-clock-bd5b78-4
worker/t384-scrub-813790-5
worker/t381-cc-748314-2
worker/t373-336973-2
worker/t365-3920c5-3
worker/t358-6e989b-1
worker/t355-8b321c-1
worker/fleetd-369-hermetic-git-tests-e8b19a-3
worker/fleetd-368-stale-lead-binding-f5682e-2
worker/fleetd-360-deploy-units-0d3793-1
worker/359-dead-lead-tabs-f1253b-4
worker/362-worktree-skills-c03e51-3
worker/361-coord-visibility-655144-1
362-plugin-visibility-and-drift
worker/errscan-bed2ca-2
worker/amqp-log-identity-bed2ca-2
worker/withdefaults-guard-561704
worker/sleepguard-82076d-1
worker/fd334-9ee1b6-5
worker/fd348-f1ab27-4
worker/fd335-a71c35-1
worker/fd342-174a17-2
worker/fd345-490d0f-3
worker/fleetd-337-5ec7d4-21
worker/fleetd-341-af5a6b-24
worker/fleetd-339-5ca0a2-23
worker/fleetd-338-83a4a1-22
worker/fleetd-333-281f46-18
worker/fleetd-329-11bdbb-16
worker/fleetd-330-2770fb-17
worker/fix-326-50506e-15
worker/fix-324-3e9bbf-14
worker/fix-323-b8287d-13
worker/fix-316b-bd0860-11
worker/fix-318-76ca36-9
worker/fix-317-486aec-8
worker/fix-315-ce47c5-6
worker/fix-307-275890-6
worker/fix-308-b4f664-7
worker/fix-309-ec3939-8
worker/fix-310-7a3974-9
worker/fix-302-52ad0e-9
worker/fix-298-ce1acb-8
worker/fix-297-66bd11-7
worker/fix-296-104622-6
worker/fix-293-bare-closetab-eb22b5-3
worker/fix-280-gone-ask-lapse-bca98e-2
worker/fix-290-reapidle-guard-coverage-9b0dd1-1
worker/fix-285-trust-seed-8f3565-10
worker/fix-284-backend-error-seat-85912c-11
worker/fix-282-chained-ask-e6d0bb-8
worker/fix-283-teardown-leaks-f40dfa-9
worker/fix-281-pin-handler-actions-4921ac-7
worker/audit-rendezvous-lifecycle-d072ae-2
worker/audit-health-placement-1a2476-6
worker/audit-teardown-exits-e207a5-3
worker/audit-launcher-asymmetry-27e370-4
worker/audit-rest-authz-6ca53c-5
worker/investigate-275-abandon-asking-fdef52-8
worker/fix-274-worktree-leak-b0095d-7
worker/fix-273-exhausted-pattern-9665b5-6
worker/fleetd-267-model-check-bd8068-1
worker/fleetd-131-archunit-18b834-7
worker/fleetd-266-sshagent-rename-a014ff-6
worker/fleetd-184-uid-claim-8e1f31-4
worker/fleetd-184-warn-b381ee-10
worker/fleetd-184-docs-be1d12-9
worker/fleetd-257-9bf010-7
worker/fleetd-103-23a113-6
worker/fleetd-247-342356-5
worker/fleetd-116-04dea8-4
worker/fleetd-252-a830e0-3
worker/fleetd-111-7e8673-9
worker/fleetd-155c-f8ef4b-8
worker/fleetd-176-b928ca-3
worker/fleetd-249-7a7878-2
worker/cb248-composition-root-b-9acdf7-15
worker/cb148-envrc-default-fa6c82-12
worker/cb201-unit5-wiring-6c12e6-8
worker/cb241-fallback-echo-1175e9-11
worker/cb149-trust-dialog-2392a5-9
worker/cb134-148-overlay-visible-c9b986-10
worker/cb234-session-id-keyed-04e1fc-1
worker/cb201-unit3-nudge-abdf5c-6
worker/cb201-unit2-policy-c1102c-5
worker/cb201-unit4-outcome-a13bfa-7
worker/cb201-unit1-classifier-91b9b1-4
worker/cb201-227-refine-831980-3
worker/cb175-model-readback-0f085f-1
worker/cb222-charter-tmpdir-17f013-1
worker/cb226-architect-slot-race-cd3aa8-3
worker/cb224-worktree-root-group-024523-2
worker/cb-123-role-demotion-c600f7-2
worker/cb-219-opencode-roots-1f677e-1
worker/cb214-claude-session-id-b9eab4-4
worker/cb213-zdotdir-wrong-process-dd6de4-3
worker/cb211-exhaustion-classification-9546e0-2
worker/cb137-ambiguous-task-4df3d8-4
worker/cb209-agentsessionid-4dfdb6-2
worker/cb185-hostenvnames-2692b5-3
worker/cb206-opencode-sqlite-128718-2
worker/cb185-worktree-group-fc0c99-1
worker/cb-137-ask-ticket-e7760c-2
worker/cb-172-broker-uri-d36ae4-4
worker/cb-175-model-readback-76ead6-3
worker/cb-161-pane-ancestry-293510-1
worker/cb-164-rebase-885863-8
worker/cb-164-empty-scrape-false-success-1a80af-3
fix/cb-197-ticket-ttl-from-completion
worker/cb-189-remote-url-coverage-4692f3-1
worker/cb-185-blockers-027756-4
worker/cb-192-gap-log-11b631-2
worker/cb-633-fix-5f4396-3
worker/cb185-router-d6436d-3
worker/cb185-router-routing-gaps-9e9d33-3
worker/cb185-paneids-992586-2
worker/cb-633-allow-list-union-ed374b-1
worker/cb-157-credential-in-remote-url-496e44-2
worker/cb-641-health-herdr-evidence-8f1f54-6
worker/cb-640-health-msg-evidence-99c9cd-1
worker/cb-642-fleets-status-skill-bbbc40-5
cb-634-ide-mcp
worker/lead-comms-wiring-c014b9-7
worker/lead-mailbox-c19577-6
worker/autocompact-window-82bc2f-5
worker/cb-634-probe-18056f-4
worker/cb635-broker-urienv
worker/cb-632-config-retry-8e0efa-7
lead/cb-622e-claude-md
lead/cb-622-followup
worker/cb-622a-165dff-1
lead/cb-622d-opencode-mount
worker/cb-622b-717c67-2
worker/cb-622c-ab7759-3
worker/cb-617b2-20ca4b-3
worker/cb-617a-5c2f4a-1
worker/cb596-4e49ef-3
worker/cb586-10500c-1
worker/cb-606-b9343a-25
worker/cb604-1445f8-24
worker/cb582-477374-21
worker/cb584-8c2281-22
worker/cb600-e6b9a9-20
worker/cb602-ce257f-19
worker/cb601-b42837-18
worker/cb598-6c7ba7-17
worker/cb599-740fe4-16
worker/cb597-282224-15
worker/cb590fix-185e9a-10
worker/cb528-recovery-race
worker/cb594-96bead-8
worker/cb590-916766-2
worker/cb527-997d99-3
worker/cb592-env-leak-3cbf9c-1
worker/cb588-async-ticket-nudge-3218f7-5
worker/cb578b-9dcb13-6
worker/cb581-d24826-5
worker/m2-u5-ef8c42-15
worker/cb578a-516499-2
worker/cb576-01a04b-17
worker/cb579-lead-tab-acba06-20
worker/cb580-terminal-health-ed6058-21
worker/cb577-f36fdc-18
worker/cb573b-3db06f-16
worker/cb568c-f36fdc-18
worker/cb568-drop-cause-c3ac1c
worker/cb575-cancelled-notification-c3ac1c
worker/m4-sol-a2cbec-3
worker/cb574-async-ask-c3ac1c
worker/cb573-health-model-8ca857-14
worker/cb572-unknown-target-7f2e35-13
worker/u4-700706-9
worker/u3-b9fcb6-6
worker/u2-ef5b68-4
worker/u1-469dce-1-clean
worker/u1-469dce-1
worker/cb-564-health-events-70cf7e-2
worker/cb-565-recycle-drops-role-98e58f-3
worker/cb-563-missing-reply-df2866-1
worker/cb-562-readiness-gate-silent-6c23c9-3
worker/cb-560-architect-presence-da8155-1
worker/cb-561-architect-silent-off-a71cab-2
worker/cb-548-bind-architect-slot-fe1b8c-1
worker/parity-overlay-settings-5fb711-1
secrets-central-store
cb-559-hot-key-correction
cb-557-fleet-role-pools
worker/cb-553-maxload-explicit-spawn-305ee3-6
worker/cb-551-idle-lead-heartbeat-f1633c-1
worker/cb-544-drain-preserves-worktree-925fad-3
worker/cb-552-docs-sync-1cb9cf-4
worker/cb-548-rendezvous-guard-rebased
worker/cb-548-rendezvous-guard-116b53-10
worker/cb-548-authz-v2-586df6-8
worker/cb-548-authz-264363-5
salvage/cb-528b-codex-home
salvage/cb-528a-codex-launcher
CB-518-primary-flow
feature/peer-launcher-spi
cb-103-injector
v1.1.0
v1.0.0
Labels
Clear labels
blocked
needs-live-proof
ready-to-delegate
silent-default
Cannot start until something else lands. The body says what.
Merged and green, but never shown working on the running daemon. Not the same as done.
Scope, files and acceptance criteria are written. A worker can be briefed from the body alone.
A feature that compiles, passes tests, and ships turned off. Nine recurrences and counting.
No Label
Milestone
No items
No Milestone
Projects
Clear projects
No project
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: fleet/fleetd#748
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Raised by the operator on 2026-10-05:
Two architects are being asked to answer this independently. This body holds the evidence I measured before briefing them, so their positions can be checked against the same numbers.
What I measured, and how
All commands run on
main=7f0c4a8, 2026-10-05, fromfleetd/src.Size.
find main/java -name '*.java' | wc -l→ 124 files.find main/java -name '*.java' -exec cat {} + | wc -l→ 36,278 lines.Large classes.
find main/java -name '*.java' -exec wc -l {} + | awk '$1>1000 && $2!="total"' | wc -l→ 9 classes over 1000 lines. The largest:config/FleetConfig.javamcp/FleetMcp.javamsg/MessageService.javaFleetd.javamember/HerdrPeerLauncher.javasession/GitWorktrees.javasession/SessionManager.javaTests. 192 files, 62,704 lines — about 1.7 times the main source. The suite is 2118 tests, 0 failures.
Comment volume. Counting lines whose first non-space character is
*or//— a heuristic, not an exact parse —grep -cE '^[[:space:]]*(\*|//)'over all main sources gives 14,369 of 36,278 lines, or 39.6%.Comment content against this project's own rule. The same heuristic, filtered:
fleetd #CB-[0-9]used to/no longer/previouslymeasuredround [0-9]verifiedWhy that last table matters more than the question as asked
CLAUDE.mdalready carries a mandatory rule, "Code comments describe the code as it is now". It says a code comment must never contain:So on the numbers above, roughly 1,400 comment lines break a standard this repository wrote for itself. One example,
Fleetd.java:243-255, is a javadoc explaining which mutation survived a previous test round and why a later test was added — history, evidence and ticket reference in one block.That changes the shape of the operator's question. It is not "should we adopt standards" — a standard exists and is strict. It is closer to "we have standards, they are not followed, so what is actually wrong?" The honest possibilities include: the rule is right and nobody enforces it; the rule is wrong for this codebase and should change; or the comment debt is a symptom and the real problem is that the design needs that much explaining.
What I am NOT claiming
*///test is a heuristic. A multi-line javadoc counts once per line, so the 39.6% is not "40% of the file is documentation" in any careful sense.Fleetd.main's injected wirings are unpinned across 16 call sites, #589 says there is 1 behavioural test across 44 wiring sites, and #587 asks for a sweep of every constructor-arg wiring site.Open tickets that may be symptoms of the same thing
Worth checking rather than assuming: #612, #589, #587 (wiring that no test pins), #700 (one rule, two hand-maintained lists that must agree), #578 and #586 (
enum.name()on the wire at 15 sites), #572 (a lost lock release the suite would not catch), #561 (load-bearing ordering, untested).The decision goes on this ticket
Per
CLAUDE.md, architects may settle this. Both positions and the final decision are to be recorded here, including any disagreement that survives comparison.CORRECTION to the brief — architects read this before you finish
Both architects were briefed with a hypothesis that is partly wrong, and this comment overrides the brief on that point. The brief is write-once; this is the newer source and it wins.
What I got wrong
My brief said the comment rule is "widely ignored", and invited you to conclude that writing more rules produces more ignored text. The second half may still be right. The first half, as stated, is not supported — I measured the stock and then talked about the flow.
The measurement I should have run first
Today's #737 work, six units merged by three different members, over the range
efd9cdb~1..7f0c4a8, main sources only:The single one is
* (CB-532), with no lead name.So 1 in 402. Current practice follows the rule. The 729
fleetd #and 671CB-comment lines in the whole tree are a stock of old debt, not evidence of what the fleet does today.Why this matters to your answer
It separates two questions that my brief ran together:
Those have different answers and possibly different verdicts. Please address them separately.
Treat this as evidence about my framing, not just a number
The same error is one you can make in your own answer, so it is worth naming: I measured a stock and drew a conclusion about a flow. A count over the whole tree says what accumulated; it cannot say what anyone does now. If you make a claim about practice, measure a diff over a time range. If you make a claim about debt, count the tree. Do not let one stand in for the other.
What is still open, and unchanged by this
Architect position 1 of 2 —
sol(opencode backend)Recorded verbatim in substance. This is one position, not the decision. The second architect is still working. I have not adjudicated, and I am not merging the two into an agreement until I can compare them.
It corrected my brief, and it is right
My brief and the ticket body both say this repo's
CLAUDE.mdcarries the comment rule. It does not. The architect checked, and I verified independently:The rule lives in the operator's user-level
CLAUDE.md, under "User-level guidance (applies to all projects)". The architect's own check found the heading at lines 77 and 104 of that file and 0 hits in the repo file.This matters more than the violation count I opened with. The standard is not in this repository, so it is not in git, not in the build, not reviewable in a diff, and not guaranteed to reach every member — an opencode member does not read
CLAUDE_CONFIG_DIRat all. Nothing in this project owns or enforces the rule. That reframes the question again: it is not "add principles" nor "enforce existing principles", it is "the principles are not part of the product".VERDICT: mixed — "reliable but expensive to change"
Not a mess. Its evidence, from commands it ran:
mvn clean install→ 2118 tests, 0 failures, BUILD SUCCESS.target/site/jacoco/jacoco.csv: line 8895/10017 = 88.80%, branch 4564/5695 = 80.14%. JaCoCo is report-only; the pom sets no coverage gate.rglobscan: main 124 files / 36,278 lines / 39.6% comment-ish, 9 files over 1000 lines. Test 192 files / 62,705 lines / 14.6% comment-ish, 14 files over 1000 lines.Fleetd.java904 comment lines vs 915 non-comment non-blank.MessageService.java945 comment lines vs 868 non-comment non-blank — more comment than code.It read
Fleetd.javaandMessageService.javaend to end, plusFleetdAssembly.java,PackageCyclesTest.java, the pom, and selected wiring and message tests.It flags its own policy scan as a heuristic that can double-count and false-positive, and explicitly declines to treat its
any_flagged_line=1868as an exact violation count. Good discipline; I am recording that caveat rather than the number.DIAGNOSIS, ranked by cost
MessageServiceowns too many lifecycles. Blocking sends, async tickets, questions, answers, reply recovery, inbox draining, ticket ownership, health facts, metrics, notifications, timeouts and executor shutdown. State spread acrossTask, severalConcurrentHashMaps, per-session locks, volatile fields and test race hooks. Its framing: "The cost is not style. The cost is a higher chance of a race, a stranded ticket, or a reply assigned to the wrong task." It explicitly does not propose a refactor — the rule it wants is "stop adding new state ownership to this class".FleetdAssemblynow does the real assembly, which it calls a good step, but forwardingAtomicReferenceholders are still needed to break construction-order cycles, andFleetdremains a large home for static factories and test seams.src/main/javaas text (its scan:test_files_reading_or_walking_src_main=7). Some protect real security rules, but they depend on variable names, call spelling and method order, so a safe rename breaks a test without a behaviour change.MessageServicehas comments carrying real lock and waiter invariants that must stay — so no bulk deletion.ANSWER: yes, adopt standards — narrow and enforceable
It rejects a broad "Clean Code"/SOLID/pattern-catalogue section as too open to interpretation, and warns it would push agents to add abstractions with no concrete need. Its proposed repo
CLAUDE.mdblock:Rules it deliberately rejects, with reasons: a max class or method length, "every method must be small", "always avoid comments", any blanket inheritance rule, a required pattern list, a duplicate-code percentage, and a JaCoCo threshold. Its argument: these are weak proxies here — a class can be long because it holds a schema or many tool handlers, a short method can still split one state transition across unsafe owners, and a coverage gate rewards execution without useful assertions.
ENFORCEMENT — mechanism per rule, with gaps named
CommentPolicyTestwith a real Java comment lexer (so strings and text blocks are not scanned), plus normalized hashes as a baseline. Fails on a new banned token, and fails when a stale baseline entry could be removed.PackageCyclesTest's broadignoreDependencypairs with an exact baseline of allowed edgesIt proposes splitting delivery into three units — policy text, comment ratchet, architecture gate — so policy work is never hidden inside a refactor.
COST
Its main point: the cost is not writing rules, it is making gates useful without making ordinary changes painful. A naive regex would flag strings and current contracts, hence the lexer. The edge baseline creates review friction that is only acceptable if the failure message names the exact new edge. Comment cleanup must be touched-code only, because a bulk deletion could remove a real concurrency invariant along with ticket history.
On this ticket's own concern: it says the detailed baseline format, regex list and examples belong in the test and the reviewer skill, not in
CLAUDE.md, since that file is recurring context for every agent. Only the compact block above belongs there.A verified defect came out of this → #749
It found that
PackageCyclesTest's javadoc promises a new dependency between an already-excepted pair "is still checked", while the implementation passes package-wide predicates toignoreDependencyin both directions. I verified this myself and filed #749. Four of the five excepted pairs involvemsg— the package this same architect ranks as most fragile.What it did NOT check
Its own list, which I am recording rather than paraphrasing away: it did not read the other large classes end to end; did not read every test; did not read this ticket (the brief said it was optional); did not inspect the empty
wiki/submodule or run the sync check; did not inspect.mcp.json/opencode.json; did not run the contract tests, herdr, the broker or Docker; ran no IDE diagnostics; ran no mutation testing, and notes the mutation claims in source comments are historical, not checks it ran.It also reports
rgis not installed on its pane (zsh:1: command not found: rg) and that it fell back to Python.Its quality-tool scan of the pom:
maven-checkstyle-plugin=0, maven-pmd-plugin=0, spotbugs-maven-plugin=0, error_prone=0, NullAway=0, archunit-junit5=1, jacoco-maven-plugin=1.It changed no files:
git_head=7f0c4a8464c7c5b8196ce1bd61e13522a787f9ec,git_status_short=clean.Lead's additions
-Pcontract clean install→MVN_EXIT=0, and 183 surefire XML files summing to 2154 tests, 0 failures, 0 errors, 0 skipped. So the Docker-backed AMQP tests pass too — 36 tests the default profile excludes.Lead: coverage verified, and the two figures differ for a good reason
Architect 1's JaCoCo numbers were its measurement, not mine. I have now run it myself and the two disagree — both correctly.
I parsed
fleetd/target/site/jacoco/jacoco.csvafter my own-Pcontract clean install:-Pcontract— my run, 2154 testsThe denominators are identical, so this is not a different measurement of the same thing. The 36
@Tag("contract")tests cover 219 lines and 56 branches that nothing in the hermetic suite reaches.That is worth stating plainly because it is an easy wrong conclusion: "88.80%" is not this project's coverage, it is the coverage of the suite that runs without Docker. Quoting either number without naming its profile is misleading.
The gap I went looking for is not there
If CI ran only the default profile, those 219 lines would be covered on no machine but a developer's. I checked
.gitea/workflows/ci.yml:buildjob runsmvn -B clean install, which inheritsexcludedGroups=contract— deliberately Docker-free;contractjob runsmvn -B -Pcontract test -Dgroups=contractagainst a real broker supplied as a service (line 122).So both halves run in CI. The split is intentional and documented in the workflow's own comments. The file also records that an earlier form of this silently excluded every other contract test from CI, so the current shape is a fix, not an accident.
No finding. I am recording the negative result because "I checked whether CI covers the Docker-only paths" is worth exactly as much as finding a hole, and the next person should not have to repeat it.
Why this bears on the decision
It is evidence against the framing I opened this ticket with. The enforcement story here is better than "a standard nobody enforces" suggested: there is an ArchUnit gate, a two-job CI split with a real broker, and 2154 tests at ~91% line coverage. What is missing is narrower than it first looked — no comment policy check, no lint or static-analysis plugin (
checkstyle=0, pmd=0, spotbugs=0, error_prone=0, NullAway=0per architect 1's pom scan), and no coverage gate, which architect 1 argues against adding anyway.Whoever adjudicates should weigh that: the question is which small number of gates are missing, not whether this project has any.
Architect position 2 of 2 —
opusarchitect — and the DECISIONPosition 2 arrived, but not through the bridge. Its ticket died on the #588 timeout at exactly 1800s while
fleet_statusstill saidworking. I recovered the full reply from the member's own transcript, where afleet_replycall records itscontentwhether or not delivery works. Nothing was lost, but that is a rescue, not a route — see my comment on #588.Position 2, in short
Verdict: MIXED. Same as position 1, reached independently.
Its central move is to attack my size metric. It counted code lines, not total lines:
I re-ran every number in that table myself and it is exact. Whole main source: 124 files, 36,278 lines, of which 17,850 are code. Files over 1000 total lines: 9. Files over 1000 code lines: 2.
So my "9 classes over 1000 lines" was mostly a comment-volume artifact.
MessageServiceis a 757-line class wearing 1056 lines of comment.Its other measurements, all of which I re-ran and confirmed:
FleetdAssembly.assembleAndStartspans lines 124..575 — 452 lines, 305 of them code. The longest method in the codebase.Fleetd(^ static), a class whose only production entry ismain.*WiringTest, 10*AssemblyTest, 7*LookupTest.src/main/javaas text. (Position 1 said 7. Position 2 is right; I listed all 8.)class X extends Y, of which 8 are exception subclasses. 120 records.FleetdCompletionResolverWiringTest(Fleetd.java:738,mcp/FleetMcp.java:354) andFleetdLeadRolloverWiringTest(mcp/FleetMcp.java:354). Both were renamed to*AssemblyTest.javacattaches only the second.Fleetd.java:339is 16 lines describingexhaustedPatternCoverageLine; that method sits at line 389 with no javadoc of its own.It also corrected itself twice unprompted, including one correction in my favour: all four
claude-codeprofiles do receive the operator's comment rule, becauseltmsandgx10are both symlinks to the same file. My "not delivered" was wrong for claude-code members. "Not part of the project" is right for everyone.Where the two architects AGREE — independently, on separate backends
This is the larger part of the answer, and it settles the operator's question.
Where they DISAGREE — and why it is smaller than it looks
Each ranked a different class as the #1 structural problem:
MessageServiceowns too many lifecycles. Blocking sends, async tickets, questions, answers, reply recovery, inbox draining, ownership, health, metrics, timeouts, executor shutdown. "The cost is not style. The cost is a higher chance of a race, a stranded ticket, or a reply assigned to the wrong task."assembleAndStart, 54 static factories, half the root-package tests pinning wiring rather than behaviour, 8 tests asserting on source text. "The team has been treating a design problem as a testing problem."This is not a conflict of judgement. It is an artifact of what each one read. Position 2 states plainly that it never opened
MessageService. Position 1 read bothMessageServiceandFleetdAssembly. So only position 1 read both candidates — and it still rankedMessageServicefirst. Position 2's ranking cannot outweigh that, because it never looked at the alternative.Both are real, and both appear in the other's list at #2.
What neither of them named, and I found while checking their rankings
The two #1 candidates are the same disease, and there is a third symptom that proves it.
17 distinct test-only seam names live in production source, 49 mentions, and all but one are in
MessageService. Seven arevolatile Runnablerace hooks:finishAsyncTaskRaceHook,afterFinishAsyncTaskCompleteHookForTest,timeoutCancellationRaceHookForTest,replyOrphanTurnIdRaceHookForTest,abandonCleanupHookForTest,askTimeoutRaceHookForTest,answerAskLapseRaceHookForTest.So the single cause behind both rankings is this: when something here is hard to test, we change the shape of production code to let a test reach it. On
Fleetdthat produced 54 static factories. OnMessageServiceit produced 7 mutable race hooks and 6 concurrent maps. On 8 test files it produced assertions on source text. Three different symptoms, one habit.That is the finding the operator is reacting to, and neither "clean code" nor "design patterns" names it.
DECISION
Answer to the operator's question: yes, adopt standards — but not the ones the question implies. No Clean Code section, no SOLID, no pattern catalogue. Both architects reject those, and the measurements support them: encapsulation and inheritance are already fine here.
Adopt five rules. Each one exists because it has already cost us something measured.
CommentPolicyTestwith a real Java lexer + normalized-hash baselinedocs/<subject>.mdand is linked in one line.([Ff]orTest|RaceHook)at today's 49; review for the restassembleAndStartat 452 lines and^ staticonFleetdat 54; ratchet both downignoreDependencypairs; allow-list today's 8 source-reading testsRulings on the three places the architects conflicted
Javadoc length limit — ADOPTED, over position 1's objection. Position 1 rejects length limits. Its stated reason does not transfer: it argued a class can be long because it holds a schema or many tool handlers. There is no equivalent honest reason for a 235-line javadoc block (
config/ConfigRef.java:17). And position 2's rule says move the content, not delete it, which answers position 1's real worry about losing concurrency invariants.Mechanism — position 1's lexer wins over position 2's regex. Both architects used regex classifiers and both reported false positives in their own output. A regex over Java source will flag string literals and text blocks. The gate must lex.
Scope of cleanup — position 1's "touched-code only" wins. No bulk comment sweep.
MessageServicecomments carry live lock and waiter invariants, and a sweep is how we would lose one.What is NOT enforced, stated plainly
Rules 3 and 4 have caps, and a cap is not the rule. A number can stop the count growing; it cannot tell a good decomposition from a bad one. Position 2 said this about its own most important rule and refused to pretend otherwise. I am keeping that refusal in the decision: the judgement half of rules 3 and 4 is a review obligation, not a build check.
Cost, not hidden
The repo
CLAUDE.mdis 504 lines / 6,335 words / 40,219 bytes today, and every session loads it. Position 2 costed its own proposal at ~34 lines, about +7%, and declined to call that free. I am capping the new section at ~20 lines, because position 1 is right that the baseline format, the token list and the examples belong in the test and the reviewer skill, not in recurring context.Delivery order — #749 first
PackageCyclesTestjavadoc-vs-code defect, found by position 1. It must be fixed before rule 5 lands, because rule 5 replaces the mechanism it documents.CLAUDE.md, with the "goes in the ADR" line corrected todocs/<subject>.md. This project has no ADR directory, which is why that line was unfollowable: it sent knowledge to a destination that does not exist.Both architect panes are released after this comment.