LearnNewsExamplesServices
Frontmatter
id17568
titleFleet util modules become classes with owned placement
stateClosed
labels
enhancementairefactoringarchitectureagent-os
assigneesneo-gpt
createdAtAug 22, 2026, 9:42 PM
updatedAtAug 23, 2026, 5:00 AM
githubUrlhttps://github.com/neomjs/neo/issues/17568
authorneo-fable-clio
commentsCount0
parentIssue17559
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[x] 17560 Fleet view folder: topology move and base-class naming (mechanical)
blocking[]
closedAtAug 23, 2026, 5:00 AM

Fleet util modules become classes with owned placement

Closed Backlog/active-chunk-18 enhancementairefactoringarchitectureagent-os
neo-fable-clio
neo-fable-clio commented on Aug 22, 2026, 9:42 PM

Context

The second half of #17559's law 3, extracted from #17560 at review: the move PR relocated 15 camelCase pure-function modules to apps/agentos/util/ as modules with imports rewritten. Converting those modules into classes rewrites call sites across the app and belongs in its own reviewable leaf. This ticket is the successor named by #17560's close-target contract, so the deferred work keeps a durable owner.

Intake V-B-A on 2026-08-23 narrowed one placement prescription before implementation. Parent #17559 says these modules become Body-style utility classes under apps/agentos/util/ (AgentOS.util.*), while the merged viewTopologyConformance.spec.mjs intentionally admits only UI-family classes under apps/agentos/view/**. A static utility extends Neo.core.Base; moving it under view/** would either fail that guard or weaken the suffix-equals-base-family law with a made-up UI family. The 15 classes therefore stay in the utility namespace. Descriptive class names (CockpitPresets, FleetStartPlan, and so on) preserve conceptual ownership without placing non-view code in the view tree.

The Problem

apps/agentos/util/ currently holds 15 camelCase function modules — Brain-style module shape in Body-side app code. Law 3's target is Body-style classes: PascalCase files, static members, Neo.setupClass, exact className, and generated class documentation.

The Architectural Reality

  • Precedent: src/util/* and apps/covid/Util.mjs are static-method classes extending Neo.core.Base, registered through Neo.setupClass.
  • Live consumer graph re-measured on 2026-08-23: viewerTime spans activity/catch-up/memories/tasks/wake; sourceHealth spans cockpit/detail/health/roster; agentFreshness spans detail/mailbox and the viewer-wake helper; telltale spans card/detail; addAgentFlow spans accounts/instances; configIntentRoundTrip spans accounts/detail; cockpitDockDocument also serves tours and Mission Control. The remaining helpers are currently single-surface or surface-shared, but they remain utility classes for one uniform, non-view class topology.
  • viewTopologyConformance.spec.mjs already enforces PascalCase, exact class identity, and UI base-family suffixes for view/**. This leaf extends the file/class-identity half over util/**; it does not apply UI suffix semantics to Neo.core.Base utility classes.
  • The turn-loaded AGENTS.md is 24,521 bytes against a 24,576-byte hard cap, and .claude/CLAUDE.md is a symlink to it. Two additive gate lines would break the loading budget and duplicate one source. This leaf rewrites the existing app-work trigger in place, byte-negatively, to carry laws 0+1 once.

The Fix

  1. Rename the 15 files in place to PascalCase and convert each module into an AgentOS.util.* class extending Neo.core.Base, with static members and Neo.setupClass registration.
  2. Update every call site mechanically (import {fn} from module becomes import Class plus Class.fn(...); exported constants become static properties). No helper behavior changes.
  3. Extend the conformance witness so apps/agentos/util/** is PascalCase/class-only and every utility declares the exact path-derived className. Preserve the existing view/** UI-family suffix law unchanged.
  4. Rewrite the existing app-work trigger once, without increasing turn-loaded bytes: engine primitive before custom code; class suffix names its base family. Because .claude/CLAUDE.md points to AGENTS.md, no duplicate harness edit exists.
  5. Regenerate docs JSON so all 15 classes land in the class hierarchy in the same commit.

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback / Edge Case Docs Evidence
15 modules under apps/agentos/util/ #17559 law 3; src/util/*; merged #17560 topology guard become PascalCase AgentOS.util.* static classes in place current descriptive class names preserve scope; no non-view class enters view/** class docblocks consumer grep + class-resolution specs
existing imports and calls current source consumer graph default-import the owning class and invoke the same behavior through static members exported constants become static properties; no compatibility re-exports remain n/a zero old-path / named-function-import grep
conformance witness #17560's fail-closed spec covers util/** PascalCase, class-only shape, and exact path-derived className; existing view/** suffix law remains unchanged unresolved class or missing identity is an offender, never a skip spec docblock the witness itself
app-work trigger AGENTS.md §edge_case_triggers; ADR 0007; /turn-memory-pre-flight byte-negative rewrite adds laws 0+1 to the existing app-work gate once .claude/CLAUDE.md inherits through its symlink; additive duplicate lines are forbidden by the 24 KiB cap trigger text size guard + loader/symlink receipt
generated class docs generate-docs-json records all 15 AgentOS.util.* classes generation failure blocks delivery docs/output/class-hierarchy.json generated diff + docs guard

Acceptance Criteria

  • Zero camelCase function modules remain under apps/agentos/util/ or apps/agentos/view/**; all 15 former modules are registered AgentOS.util.* classes.
  • Every call site imports the class; zero named-function imports or old lowercase utility paths remain.
  • The conformance witness covers util/** class identity and stays green; the existing view/** suffix-family law is neither weakened nor broadened to non-view helpers; the full AgentOS unit tree stays green with zero behavior change.
  • The existing app-work trigger carries laws 0+1 through a byte-negative rewrite; the PR body records the ADR-0007 slot rationale and the AGENTS/Claude loader evidence.
  • generate-docs-json lands all 15 classes in the same commit.

Out of Scope

Any behavior change inside the helpers; per-view primitive migrations (sibling leaves); ntype renames (settled in #17560: registry keys, not base-class claims); multi-tenant Knowledge Base ingestion or kbSync changes.

Related

Parent: #17559. Predecessor: #17560 (the move; its review round 1 mandated this successor). Precedent: src/util/*, apps/covid/Util.mjs.

Live intake sweep: #17568 is open and unassigned; no PR or remote branch targets it; the only open PR at intake (#17592) is unrelated. Memory Core returned no relevant prior implementation mapping. The Knowledge Base query missed this same-day ticket and is explicitly non-authoritative for this lane because its Neo ingestion is stale.

Origin Session ID: 28bee2e0-4dc8-4375-8514-78fcf38d0d30 Intake correction evidence: parent #17559, PR #17566 review/response, live viewTopologyConformance.spec.mjs, src/util/*, AGENTS size guard, and .claude/CLAUDE.md symlink inspected 2026-08-23. Retrieval Hint: query_raw_memories("fleet util modules become classes owned placement cockpit builders")

tobiu referenced in commit 313252e - "chore(agentos): convert Fleet utilities to classes (#17568) (#17594)" on Aug 23, 2026, 5:00 AM
tobiu closed this issue on Aug 23, 2026, 5:00 AM