Skip to content

Adopt anti-slop, automation, and typed lint rules and fix the code to pass them - #51

Merged
K-Mistele merged 14 commits into
mainfrom
analyze-kyle-anti-slop-viteplus-config-for-fold-j2c8f7
Oct 2, 2026
Merged

K-Mistele merged 14 commits into
mainfrom
analyze-kyle-anti-slop-viteplus-config-for-fold-j2c8f7

Conversation

@K-Mistele

Copy link
Copy Markdown
Contributor

Summary

Brings the kyle-anti-slop (anti-slop, anti-slop-effect), automation, and typed lint rules into fold, turns them on, and fixes the code to pass them. The TUI and test folders are exempt from the stricter rules.

Lint setup

  • Vendors the rule plugins under tools/oxlint/ and tools/typed/; bun run lint runs oxlint (with the @effect/tsgo preset) and then the typed rules.
  • Every @effect/tsgo preset rule that ships as a warning is now an error.
  • Drops fold's older automation/no-manual-tag-comparison, no-manual-tagged-construction, and prefer-effect-match; the stricter anti-slop-effect rules with the same names replace them.
  • Left off on purpose: no-comments, no-reexport-only-modules, no-effect-asvoid, no-optional-function-parameters, private-function-prefix, no-multiple-function-params, no-single-use-private-functions.

Services carried in types (no-service-constructor-imports)

  • Tools, agents, subagents, event logs, skill sources, and models say which host services they need in a type parameter; startSession requires them, and the app provides them once at the top.
  • Codex, xAI, and OpenCode credential stores and logins are services with layers. Each model builds its login from its own provider name and fold home, which fixes logins saved under a non-default provider name being ignored.
  • Models use the app's HTTP client and filesystem instead of building their own.
  • The Subagents and AgentProvisioner services are replaced by plain functions (dispatchSubagent, forkSubagent, resumeSubagent, continueSubagent, provisionAgentRuntime) that take the session's services from their surroundings. This removes the placeholder startSession used to break their construction loop. A new SessionAgents service carries the registry, tool realization, the root agent's current setup, and the auto-compact policy.

Other rule fixes

  • Conditional spreads: lists are built from values known to be present (Option + Arr.getSomes, .filter(Predicate.isNotUndefined), defaults where options are read).
  • Manual _tag: internal tagged unions are declared with Data.TaggedEnum, and log-entry variants use the named entry types. Fold's copy of the rule allows _tag: Schema.tag(...) / Schema.tagDefaultOmit(...) schema fields.
  • Known-value widening: option objects are written in one expression (Struct.pick for optional pass-through fields) instead of Mutable<...> builders; lookup tables use as const satisfies Record<...>.
  • Earlier passes: parse at boundaries with Schema, keep errors in the error channel, and clear all lint warnings.

Testing

  • bun run typecheck, bun run lint, and bun run format:check pass.
  • bun run test passes in every package; CodexModelCredentials.vi.test.ts is new and covers the non-default provider-name login fix.

🤖 Generated with Claude Code

K-Mistele and others added 14 commits September 29, 2026 17:44
- Upgrade oxlint/@oxlint/plugins 1.86.0, oxlint-tsgolint 7.0.2003, @effect/tsgo 0.47.0; patch oxlint in
  `prepare` and extend the @effect/tsgo recommended preset.
- Enable type-aware built-ins plus complexity (20), no-eq-null, no-empty-function, no-misused-spread, and
  fix the code they flagged.
- Vendor the full kyle-anti-slop plugin (generic + Effect), the upstream automation rules, the
  import-extensions plugin, and the typed rule engine; enable every rule the codebase already passes.
- Run the typed rules as part of `bun run lint`; replace array `.length` emptiness checks with Effect Array
  predicates.
- Move fold-codex tests and example that need fold-agent into fold-agent, removing the reverse dependency.
- Keep TUI code exempt from rules it violates. Rules still off are listed in tools/oxlint/README.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HumanLayer-Session: https://app.dev.codelayer.gg/sessions/01a0ef65-e340-707e-9917-609260f74450
Turn on no-reprovide-ambient-service, no-switch, no-in-operator,
no-unknown-returns, no-direct-fetch, no-shape-in-symbol-names,
no-reflect-get, max-ternary-depth, the type-assertion rules, and
no-global-json (code only), and fix every hit:

- Layers yield their services once and define methods over them, so
  ToolRuntime, AgentRuntime, Compaction and skill sources no longer
  re-provide captured services.
- Switches become exhaustive Match.
- JSON and unknown values decode through Schema (fromJsonString).
- fetch becomes HttpClient; the CLI provides FetchHttpClient.layer.
- Add effect to root devDependencies for scripts/.

Tests are exempt from the cast rules and no-global-json.
no-reexport-only-modules stays off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HumanLayer-Session: https://app.dev.codelayer.gg/sessions/01a0ef65-e340-707e-9917-609260f74450
Turn on no-try-catch, no-typeof-object, no-runtime-typeof,
no-unknown-parameters and no-unsafe-dictionary-type for code (tests and
the TUI are exempt), exclude scripts/ and postinstall.mjs from lint, and
fix every hit plus every remaining warning:

- Image pipeline: Photon service, scoped image memory, tagged errors.
- Tools can declare a layer the session builds once; read, web fetch and
  web search use it for Photon and the HTTP client.
- ManagedBinaries: a service over FileSystem, ChildProcessSpawner and
  HttpClient with an Effect cache; failures always logged.
- One schema-based SKILL.md frontmatter parser with tagged errors.
- Shared message-content helpers; auth files, JWT claims, and tool
  inputs decoded with Schema; Codex stalls are tagged errors.
- Custom event log and skill sources die on setup failure instead of
  leaking unknown errors; the TUI session host carries real error types.
- Effect language-service fixes (Schema.Finite, typed decoders, etc.).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HumanLayer-Session: https://app.dev.codelayer.gg/sessions/01a0ef65-e340-707e-9917-609260f74450
Tools, agents, subagents, event logs, skill sources, and sessions now record
the host services they need in their types (FoldTool<R>, AgentDefinition<R>,
FoldSession<R>, ...), so startSession requires exactly what its tools use and
the host provides it once. This replaces the untyped grab-and-cast of
platform services in startSession and the per-tool `layer` option.

- defineTool infers a tool's needs from its handler; the `dependencies` and
  `layer` options and the PlatformServices alias are gone.
- The subagent roster rides on the tool value instead of a hidden WeakMap.
- OutputStore is keyed by a directory; the bash tool asks for it, Launch
  provides one per session, and the retention sweep is a plain function.
- fold-cli provides Photon at the top; fold-agent exports
  layerCodingToolServices for hosts that start sessions themselves.
- Refresh the vendored-rule counts in tools/oxlint/README.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HumanLayer-Session: https://app.dev.codelayer.gg/sessions/01a0ef65-e340-707e-9917-609260f74450
- Rename helpers that build plain values, not services: ansiPalette, the
  CLI output renderers, toolStateServiceBuilder, and the issuer HTTP clients.
- storedLogEntry takes the event id instead of the whole Ids service.
- The Codex and Grok compatibility loaders return a FoldSkills descriptor
  (codexSkills / grokSkills), like skillsFromDisk, instead of a built source.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HumanLayer-Session: https://app.dev.codelayer.gg/sessions/01a0ef65-e340-707e-9917-609260f74450
SessionControls and Profiles now export layerSessionControls/layerProfiles
instead of make functions that callers wrapped in Layer.effect. The hook
runner, toolset resolver, and system prompt builders already returned layers,
so they are renamed to layerHookRunner/layerToolsetResolver/layerSystemPrompt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HumanLayer-Session: https://app.dev.codelayer.gg/sessions/01a0ef65-e340-707e-9917-609260f74450
…ervices

Codex, xAI and OpenCode credential stores and logins are now services with
layers. Each model builds its login from its own provider name and fold home,
so logins saved under a non-default provider name are no longer ignored.

FoldModel carries the services its `make` needs, like tools do. The built-in
OpenAI/Anthropic models and the provider models use the app's HTTP client and
filesystem instead of building their own.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HumanLayer-Session: https://app.dev.codelayer.gg/sessions/01a0ef65-e340-707e-9917-609260f74450
…o-service-constructor-imports

The Subagents and AgentProvisioner services needed each other, so startSession
installed a placeholder Subagents and filled it in after construction. Both
services are gone: dispatchSubagent, forkSubagent, resumeSubagent,
continueSubagent and provisionAgentRuntime are plain Effects that take the
session's services from their surroundings, so a subagent's tools calling them
again is ordinary recursion.

A new SessionAgents service carries the registry, tool realization, the root
agent's current setup and the auto-compact policy. ToolHandlerServices lists
the session services every tool runs inside; stored handlers still require
only the per-call services. The session handle is the one place that runs
work inside the session's services.

Turn on anti-slop-effect/no-service-constructor-imports (TUI and tests exempt).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HumanLayer-Session: https://app.dev.codelayer.gg/sessions/01a0ef65-e340-707e-9917-609260f74450
…les errors

Build lists from values that are known to be present instead of spreading
conditionals: optional option lists get defaults where they are read,
"maybe one item" lists are built from Options with Arr.getSomes (or filtered
with Predicate.isNotUndefined), a possibly-empty home directory is an
Option<string>, and resume flags use small valueFlag/switchFlag helpers.

Turn on anti-slop/no-conditional-spread and no-conditional-empty-array-spread
(TUI and tests exempt), and set every @effect/tsgo preset rule that ships as a
warning to error so they stay at zero.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HumanLayer-Session: https://app.dev.codelayer.gg/sessions/01a0ef65-e340-707e-9917-609260f74450
Declare hand-written tagged unions with Data.TaggedEnum next to their
existing Data.taggedEnum constructors, and name log-entry variants with the
exported entry types instead of Extract<LogEntry, { _tag: ... }>.

The vendored rule now allows `_tag: Schema.tag(...)` and
`Schema.tagDefaultOmit(...)` schema fields, which declare a tag rather than
build a tagged value (the OpenCode device-token response carries none).
TUI, tests, fixtures and examples are exempt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HumanLayer-Session: https://app.dev.codelayer.gg/sessions/01a0ef65-e340-707e-9917-609260f74450
Build option objects in one expression instead of field by field through
Mutable<...>: Struct.pick copies optional fields only when set, null-backed
values choose between two explicit shapes, and Effect library options take
`value ?? undefined`. Lookup tables use `as const satisfies Record<...>`,
managed binary checksums are a ReadonlyMap, resolveCredentials returns only
the credential field it has, and inline return types are inferred.

The CLI commands, TUI and tests are exempt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HumanLayer-Session: https://app.dev.codelayer.gg/sessions/01a0ef65-e340-707e-9917-609260f74450
automation/no-manual-tag-comparison, no-manual-tagged-construction, and
prefer-effect-match overlap the stricter anti-slop-effect rules of the same
names, which stay on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HumanLayer-Session: https://app.dev.codelayer.gg/sessions/01a0ef65-e340-707e-9917-609260f74450
…d-j2c8f7

Resolve conflicts with main's file-tools bundle and alchemy-cloudflare example:
- package.json keeps main's examples workspace in typecheck/test and this
  branch's lint command.
- codingTools uses main's fileTools with this branch's service types; the
  `tools/files` entry also exports Photon, which the read tool needs.
- startSession ports main's fix that keeps a tool's session services over a
  turn's own (Workers carry their own FileSystem), using the host services
  the session already holds.
- The alchemy-cloudflare example moves to this branch's APIs (storedLogEntry,
  no Subagents stub, Photon and HttpClient provided) and passes the lint
  rules: structured log annotations instead of JSON.stringify, Effect.try and
  Schema instead of try/catch, typeof, and `in`, and decoded tool results in
  its test helper.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HumanLayer-Session: https://app.dev.codelayer.gg/sessions/01a0ef65-e340-707e-9917-609260f74450
@K-Mistele
K-Mistele merged commit 91bf475 into main Oct 2, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant