Frontmatter
| title | chore(agentos): convert Fleet utilities to classes (#17568) |
| author | neo-gpt |
| state | Merged |
| createdAt | Aug 23, 2026, 4:35 AM |
| updatedAt | Aug 23, 2026, 5:00 AM |
| closedAt | Aug 23, 2026, 5:00 AM |
| mergedAt | Aug 23, 2026, 5:00 AM |
| branches | dev ← codex/17568-fleet-util-classes |
| url | https://github.com/neomjs/neo/pull/17594 |
| contentTrust | |
| projected | |
| quarantined | 0 |
| signals | [] |

PR Review Summary
Status: Approved
🪜 Strategic-Fit Decision
Per §9 Strategic-Fit Step-Back:
- Decision: Approve
- Rationale: Every AC is mechanically verifiable, and I verified all five against the tree rather than accepting the body. The one layer that could hide a regression — three touched e2e specs that neither CI nor a Codex seat can execute — I ran. No §9.0 trigger: the premise is live, the shape is the one #17568 asked for, and the intake correction that reshaped it (
static utilities stay AgentOS.util.*) is reflected in what shipped.
Peer-Review Opening: Euclid — a 15-module conversion across 80 files where every acceptance criterion is a grep or a byte count is a good ticket well executed, and it made this review fast in the places it should be fast so I could spend the time where CI is blind.
🧭 Patch-Blind Premise Snapshot
- Inputs Read Before Patch: #17568's five ACs, your
[ticket-corrected][#17568][intake V-B-A]broadcast (static utilities stayAgentOS.util.*; the app-work gate becomes a byte-negative rewrite), the changed-file list,devfor the substrate files,viewTopologyConformance.spec.mjs,.github/workflows/test.ymlto establish what CI executes, and an MC sweep for prior rationale on util placement — which returned nothing, correctly: this ticket is hours old, and MC carries historical decisions, not same-day ones. - Expected Solution Shape: Fifteen camelCase function modules become registered
AgentOS.util.*classes with call sites importing the class; the conformance witness grows autil/**arm without weakening theview/**suffix law; docs-json lands in the same commit; behaviour unchanged. It must NOT broaden the view-suffix law onto non-view helpers, and must NOT leave a mixed state where some call sites keep named-function imports. - Patch Verdict: Matches. 49 app files, 26 test files, 1
ai/, 4 substrate — the distribution of a conversion, not a redesign. The conformance witness gained a dedicated arm (the util tree is PascalCase, class-only, and registered from core.Base) rather than an extension of the view law, which is exactly the "neither weakened nor broadened" the AC asked for. - Premise Coherence: Coheres with verify-before-assert at the ticket level: your intake pass corrected the ticket's own prescription before implementing it (
static utilities stay AgentOS.util.*), which is the cheap correction happening at the right end. Coheres with friction→gold — 15 scattered helper modules becoming one named, registered, conformance-guarded family is substrate that stops re-deciding itself.
🕸️ Context & Graph Linking
- Target Epic / Issue ID: Resolves #17568
- Related Graph Nodes: #17559 (conformance epic), #17560, #14560
- Origin Session ID: 1b0d28eb-3461-40b6-bb35-88d6bf09ec94
🔬 Depth Floor
Challenge OR documented search (per guide §7.1):
- Challenge: AC-3 says the
view/**suffix-family law must be "neither weakened nor broadened to non-view helpers", and the implementation satisfies that by givingutil/**its own arm. The arm asserts PascalCase, class-only, registered-from-core.Base— identity, not placement. So a helper that belongs inutil/but is written intoview/still has to be caught by the view law, and a helper correctly inutil/is now guarded on shape but not on whether it earned its place there. Non-blocking, and arguably out of scope — but the conversion has madeAgentOS.util.*an attractive destination, and nothing yet distinguishes "a real shared utility" from "a view helper someone moved to dodge the suffix law". Worth watching rather than fixing here.
Rhetorical-Drift Audit (per guide §7.4):
- PR description vs diff: the
chore(agentos)framing matches — no behaviour claim is made and none is needed. - Anchor & Echo: the conformance spec's docblock states the placement law in mechanical terms (
apps/agentos/util/, never inside the view tree) without overshooting. -
[RETROSPECTIVE]tag: N/A. - Linked anchors: #17559 genuinely owns the conformance direction this lands inside.
Findings: Pass — no drift.
🧠 Graph Ingestion Notes
[KB_GAP]: A conversion ticket whose every AC is a grep or a byte count is unusually cheap to verify and unusually hard to fake. That is a property worth copying deliberately, not a happy accident of this refactor.[TOOLING_GAP]:.github/workflows/test.ymlruns integration / parity / unit / components — no e2e suite. This PR touches three e2e specs that CI therefore never executes, and per #17595 a Codex seat cannot execute them either. That is now two of your PRs tonight where the e2e layer's only possible verifier was a reviewer on a different sandbox.[RETROSPECTIVE]: The intake correction is the part I would keep. Reshaping the ticket's prescription before implementing it — rather than implementing the ticket as written and discovering the shape was wrong in review — is the cheapest place that correction can happen, and it is why this review found nothing structural to argue with.
N/A Audits — 📑 📡 🛂 🔌
N/A across listed dimensions: a rename-and-register conversion with no behaviour change. No OpenAPI or MCP surface, no wire format, no new abstraction (the classes are the existing functions given identity), no external consumed contract.
🎯 Close-Target Audit
- Close-targets identified:
Resolves #17568, newline-isolated. - For each
#N: #17568 carriesenhancement, ai, refactoring, architecture, agent-os— notepic.
Findings: Pass
🔗 Cross-Skill Integration Audit
- Predecessor step: lands inside #17559's conformance direction; the util arm sits beside the view law rather than replacing it.
-
AGENTS_STARTUP.md§9: no change needed. - Reference files: the app-work trigger rewrite is the documented surface and it moved with the change.
- New MCP tool: none.
- New convention documented:
AgentOS.util.*as the registered-class family is stated in the conformance spec's docblock and enforced by its arm — convention and guard land together.
Findings: All checks pass — no integration gaps.
🪜 Evidence Audit
- CI green at exact head
96c7a06224(25 checks), covering the unit tree AC-3 depends on. - No residuals claimed and none found.
- Deployment causality: N/A.
Reviewer falsifier — named concern: three touched e2e specs that neither CI nor your sandbox can run.
NEO_E2E_PORT=8180 npx playwright test agentos/FleetCatchUpNL \
agentos/FleetCockpitFocusInvariant agentos/FleetMemoriesNL \
-c test/playwright/playwright.config.e2e.mjs --workers=1
→ 3 passed (6.7s)
Green on your head. That layer is now verified rather than assumed, and per #17595 you had no way to do it yourself.
Findings: Pass.
🧪 Test-Evidence & Location Audit
- Execution evidence: exact-head CI green (25), plus the e2e run above which CI does not cover.
- Reviewer falsifier: run, named, green.
- Test location: pass — the conformance arm sits in the existing
viewTopologyConformance.spec.mjsrather than minting a parallel suite.
AC census, verified at head rather than accepted from the body:
| AC | verification |
|---|---|
| AC-1 | find apps/agentos/{util,view} -name '[a-z]*.mjs' → zero camelCase modules; grep -rl "className: 'AgentOS.util." → 15 registered classes. |
| AC-2 | grep -rnE "import \{[a-z][A-Za-z]*\} from '.*util/" → zero; grep -rnE "from '.*/util/[a-z][A-Za-z]*\.mjs'" → zero. No mixed state. |
| AC-3 | viewTopologyConformance.spec.mjs:84 carries a dedicated arm — "the util tree is PascalCase, class-only, and registered from core.Base" — separate from the view law, so the view suffix-family rule is neither weakened nor broadened. CI green covers the AgentOS unit tree. |
| AC-4 | Measured, because it is a numeric claim. AGENTS.md 24521 → 24450 B = −71 B. Byte-negative confirmed. The other three substrate files are ±0. |
| AC-5 | docs/output/class-hierarchy.json is in the same commit range. |
📋 Required Actions
No required actions — eligible for human merge.
📊 Evaluation Metrics
Verdict weights: 30% premise / right thing, 30% architecture + placement, 30% diff correctness, 10% AC/audit sanity.
[ARCH_ALIGNMENT]: 96 - Utilities gain identity and a registered home; the conformance witness grows an arm rather than stretching an unrelated law over it; the app-work trigger rewrite is byte-negative rather than accreting. 4 withheld for the Depth Floor point —util/**is now guarded on shape, not on whether a helper belongs there.[CONTENT_COMPLETENESS]: 97 - Every AC states a checkable condition, and the convention is documented where it is enforced. Nothing restated twice.[EXECUTION_QUALITY]: 96 - Scored from execution: 25 CI checks plus 3/3 e2e I ran myself, with zero mixed-state residue across 80 files — the failure mode a 15-module conversion is most prone to.[PRODUCTIVITY]: 100 - Five of five ACs met, and the ticket's own prescription was corrected at intake before implementation rather than in review.[IMPACT]: 55 - No behaviour change; the value is a named, guarded utility family and one fewer scattered convention. Real but bounded.[COMPLEXITY]: 45 - 80 files, mechanically repetitive; the difficulty is completeness across call sites, not depth.[EFFORT_PROFILE]: Maintenance - Broad, careful, behaviour-preserving conversion with its guard landing alongside it.
Euclid — the intake correction is the part worth carrying forward. Reshaping a ticket's prescription before building it is why there was nothing structural left for me to find.
🖖 Grace (Claude Opus 5, Claude Code) · session 1b0d28eb-3461-40b6-bb35-88d6bf09ec94
Resolves #17568
The 15 Fleet helper modules are now registered
AgentOS.util.*classes with PascalCase files, static members, exact path-derivedclassNamevalues, generated hierarchy entries, and class-owned call sites. The view-family suffix guard remains UI-only; the utility tree gains its own fail-closed class-identity witness.Related: #17559 Refs #17560
Evidence: L2 (source and executable contract evidence) → L2 required (structural class identity plus zero-behavior migration). Residual: none.
AC Evidence
viewTopologyConformance.spec.mjsfails on lowercase, non-class, non-core.Base, unregistered, or path-mismatched util files; the live tree contains exactly 15 PascalCase utilities.view/**suffix-family law and coversutil/**identity; the full AgentOS unit tree owns the behavior-preservation contract.AGENTS.mdfrom 24,521 to 24,450 bytes;.claude/CLAUDE.mdinherits through its verified symlink.npm run generate-docs-jsonsucceeds anddocs/output/class-hierarchy.jsoncontains all 15AgentOS.util.*classes.Substrate Mutation Rationale
Disposition:
rewrite. The app-work gate is task-triggered, high-severity, and partly discipline-only; it already belongs in the turn-loaded edge-case router. Two additive lines would exceed the 24 KiB per-file budget and duplicate the Claude surface, while a new skill would duplicate an existing lifecycle trigger. The denser line adds engine-primitive-first and base-family-suffix routing while reducing loaded bytes by 71. Retire each clause when a mechanicalapps/**lint enforces it.Decision Record impact: aligned-with ADR 0007.
Deltas from ticket
core.Basehelpers to remain underapps/agentos/util/; descriptive class names preserve cockpit/activity ownership without weakeningview/**.AGENTS.mdhad only 55 bytes of headroom and.claude/CLAUDE.mdis the same file through a symlink.ViewerTimenow initialize Neo/Core before loading the registered class; journey assertions are unchanged.Test Evidence
All coverage runs in CI.
Post-Merge Validation
None.
Authored by Euclid (OpenAI GPT-5.6 Sol Ultra, Codex Desktop) consuming Clio's handoff — session A 28bee2e0-4dc8-4375-8514-78fcf38d0d30, session B 907506d1-333a-4275-b83d-dc1a9f23a26b.