pi-effect-harness

a harness specifically for writing Effect v4 code

Packages

Package details

extensionskill

Install pi-effect-harness from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:pi-effect-harness
Package
pi-effect-harness
Version
0.3.0
Published
May 29, 2026
Downloads
456/mo · 13/wk
Author
mpsuesser
License
MIT
Types
extension, skill
Size
1.2 MB
Dependencies
5 dependencies · 1 peer
Pi manifest JSON
{
  "extensions": [
    "./src/index.ts"
  ],
  "skills": [
    "./skills"
  ]
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

pi-effect-harness

Table of contents


What it does

When /toggle-effect-harness mode is enabled in the active Pi session:

  • A gold effect badge appears in the Pi footer; mode state persists per-project.
  • The system prompt is augmented every turn with effect-first-development.md (40+ rules covering errors, schemas, layers, services, retries, timeouts, structured concurrency, and observability), a progressive-disclosure agent rules doc, and a "loaded N/5 effect-* skills on this branch" preview.
  • Tool calls that would write Effect code are blocked until at least 5 effect-* skills have been read on the active branch. The check uses a prospective write projection: it looks at the resulting file, so deletion-only changes that leave no Effect code are not blocked.
  • After every successful write, the post-write file is matched against 46 pattern detectors. Matches are sorted by severity and replied back to the agent in-band as a single user message — including the pattern's transformation guidance and a hint to load any suggested skills.
  • A shallow clone of Effect-TS/effect-smol is maintained at ~/.cache/effect-v4/ and refreshed to the latest Effect v4 beta source. The agent reads from this shared user cache to verify v4 APIs instead of guessing.

Everything else about your Pi session is unchanged. Toggle /toggle-effect-harness off and the harness disengages cleanly — the system prompt reverts on the next turn, the gate stops firing, and the pattern loop stops emitting feedback.


Install

pi install npm:pi-effect-harness

This registers the extension and all 41 effect-* skills via the package's pi manifest. Pi auto-loads on the next session start.

The first time you enable /toggle-effect-harness, the harness creates a shared user-level effect-smol clone at ~/.cache/effect-v4/ (≈30s, shallow, fail-silent). Later sessions reuse that single cache and refresh it to the latest Effect v4 beta source.


Usage

Toggle /toggle-effect-harness (interactive), or Tab then E via Pi's mode toggle UI
Status Gold effect badge in the footer
Persistence Project-scoped Pi session state; survives session restart
Skill metrics /effect-skill-stats [--since 30d] [--json]
Activation cost First time per user cache: shallow clone of effect-smol; later enabled turns do a shallow refresh
Per-turn cost ~3 KB of system-prompt headers + the merged guidance docs

When mode is off, no policy header is injected and no write gate or pattern feedback fires. The harness may still rebuild its command/skill catalog and record successful effect-* skill reads as invisible branch metadata and as append-only usage metrics, so the loaded-skill count and /effect-skill-stats report are ready if you re-enable the mode later.


How it works

The harness is a thin shell around an Effect ManagedRuntime. Pi events are forwarded to a HarnessController, which fans them out to a RuleSet and a HookSet. Rules return Decision values; a DecisionExecutor translates those decisions back into Pi ExtensionAPI calls.

Lifecycle

session_start ─► restore mode state · clear pending skill reads · rebuild SkillCatalog
              · ensure ReferenceClone if enabled

session_tree  ─► sync mode badge · clear pending skill reads · rebuild SkillCatalog

before_agent_start
  ├─► HookSet
  │     └─► EnsureReferenceClone (if enabled, refresh shared user cache)
  └─► RuleSet
        └─► InjectEffectPolicyHeader
              └─► Decision.InjectSystemPrompt

tool_call
  ├─► HookSet
  │     └─► TrackSkillRead (Read paths matching effect-* skills)
  │           └─► PendingSkillReads.remember(toolCallId, skillName)
  └─► RuleSet
        └─► RequireLoadedSkillsForEffectWrites
              ├─► WriteProjection.prospective(cwd, writeIntent)
              └─► Decision.BlockToolCall  (if Effect code present and skills < 5)

tool_result
  ├─► HookSet
  │     └─► EmitSkillLoadedEntry (successful tracked skill reads)
  │           └─► Decision.AppendCustomEntry
  │                 (customType: "pi-effect-harness:skill-loaded")
  └─► RuleSet
        └─► SendPatternFeedbackAfterWrite
              ├─► WriteProjection.actual(cwd, writeIntent)
              ├─► PatternMatcher × 46 patterns
              └─► Decision.InjectUserMessage

session_shutdown ─► unregister mode badge

Three rules plus session/tool hooks. Session hooks keep the skill catalog and shared reference clone current; tool events record skill reads and run write checks. Successful skill reads are written both to invisible session entries (pi-effect-harness:skill-read) and to ~/.pi/agent/pi-effect-harness/skill-reads.jsonl for aggregate reporting. Everything that touches Pi from rule/hook code runs through Decision; global metrics are handled by the telemetry service.

The skill gate

Effect v4 is wide. A model writing Effect cold — without any in-context skill — will reliably produce v3 patterns: Effect.catchAll, Schema.parseJson, Data.TaggedError, OptionFromSelf, compose(...) instead of decodeTo(...), untraced Effect.gen everywhere. The skill gate exists to make the agent stop and read before writing.

What counts as a skill. Each subdirectory under skills/ has a SKILL.md with frontmatter. Pi exposes these as /skill:effect-error-handling commands. The harness watches every successful Read tool call: when the read path resolves to a known effect-* skill (matched against the live skill catalog), it remembers the pending read keyed by toolCallId. On tool_result, if the read succeeded, it appends an invisible branch-metadata entry shaped like:

{
	customType: "pi-effect-harness:skill-loaded",
	data: {
		name: "effect-error-handling",
		path: "/absolute/path/to/effect-error-handling/SKILL.md"
	}
}

What "loaded" means. Loaded-skill state is derived, not stored. The activeBranchLoadedEffectSkills atom scans the current branch's entries for those custom entries and returns the resulting ReadonlySet<string>. This means:

  • /compact, /fork, and /clone reset the count by default — re-loading skills after a context reset is a feature, not a bug.
  • The count is monotonic within a branch.
  • Counting pending reads in addition to confirmed loads avoids a race where the gate fires between the Read tool call and its result.

The threshold. MIN_EFFECT_SKILLS = 5. Schema, Error Handling, and Layers cover ~70% of any Effect codebase; the remaining two should be task-relevant (AI, SQL, HTTP, CLI, RPC, Workflow, Stream, Testing, Observability, etc.). Five is calibrated, not arbitrary — fewer and the model still hallucinates; more and the activation friction outweighs the benefit.

Why prospective projection matters. The gate runs on WriteProjection.prospective(cwd, writeIntent), which reconstructs what the file will look like after the write/edit applies. A change whose resulting file no longer matches \bEffect\b|from\s+['"]effect.*['"] is allowed through. A change whose resulting file contains Effect code is gated. This means deletion-only Effect cleanup can proceed without artificially incrementing the skill counter.

The block message quotes the loaded count, the missing count, and a hint to read from ~/.cache/effect-v4/ if any API is unclear. The agent retries after loading more skills.

Skill read metrics. Every successful read of a known effect-* skill is also recorded as a pi-effect-harness:skill-read session entry and appended to the global metrics log at ~/.pi/agent/pi-effect-harness/skill-reads.jsonl. Explicit /skill:effect-* commands are recorded as source: "skill-command". Run /effect-skill-stats, optionally with --since 30d or --json, to see most-read skills, least-read skills, skills read at least once, rare skills, and neglected skills from the current live skill catalog.

Use this when reviewing skill coverage. For example, if a future session asks "what are the least used Effect skills?", run /effect-skill-stats and inspect the Least-read skills, Rare skills, and Neglected skills sections. --since 30d limits the window; --json returns the same summary data for ad-hoc sorting or deeper analysis.

From a source checkout, you can seed the global log from historical Pi sessions with bun run backfill:effect-skills --write. The backfill scans ~/.pi/agent/sessions/**/*.jsonl, pairs assistant read tool calls with successful toolResult entries by toolCallId, matches only paths under skills/effect-*, skips tool-call records already present in the global log, and does not mutate old session files. Run without --write for a dry run.

The policy header

Every turn while mode is enabled, InjectEffectPolicyHeader emits a Decision.InjectSystemPrompt whose content is the merged contents of harnesses/effect/guidance/:

File Contents
effect-first-development.md The full Effect-first specification: 40+ numbered laws (EF-1 … EF-40) covering tagged errors, Option, schema, canonical imports, Match, services & layers, Clock, observability, Duration, JSON via Schema, scoped resources, retries, timeouts, structured concurrency, parallel concurrency, Config, Redacted, defects vs. failures, layer memoization isolation, schema-first domain modeling, schema defaults, branded guards, equivalence, transformations, native sort, dual APIs. Followed by copy-paste templates and a 45-item LLM review checklist.
post__effect-and-the-near-inexpressible-majesty-of-layers.md A long-form essay defending Effect's Layer type. Included for the same reason a system prompt cites a style guide: priors matter.
post__parse-dont-validate.md A long-form essay on type-driven design: push parsing to boundaries, refine data into more precise types, and make illegal states unrepresentable instead of re-checking validated-but-unrefined inputs.
progressive-disclosure-guidance.md Short, imperative agent rules: "load AT LEAST 5 effect-* skills before any Effect work; if anything is unclear, read from ~/.cache/effect-v4/." It includes the reference clone's generated AI docs, major user-facing guides, cookbook material, and source directory.

Followed by a runtime line:

pi-effect-harness policy:
- Before planning or writing Effect code, read at least 5 relevant effect-* skills.
  Loaded on this branch: 3/5 (effect-error-handling, effect-layer-design, effect-schema-v4).
- If any Effect v4 API is unclear, read from the local Effect reference clone instead of guessing.
- Key reference paths:
  - ~/.cache/effect-v4/LLMS.md — generated task-oriented guide and example index
  - ~/.cache/effect-v4/ai-docs/src/ — source examples behind LLMS.md, organized by topic
  - ~/.cache/effect-v4/packages/effect/SCHEMA.md — Schema reference
  - ~/.cache/effect-v4/packages/effect/HTTPAPI.md — HttpApi, HttpApiClient, and HttpApiBuilder reference
  - ~/.cache/effect-v4/packages/effect/CONFIG.md — Config and ConfigProvider reference
  - ~/.cache/effect-v4/packages/effect/MCP.md — MCP server reference
  - ~/.cache/effect-v4/packages/effect/OPTIC.md — Optic reference
  - ~/.cache/effect-v4/packages/vitest/README.md — @effect/vitest testing reference
  - ~/.cache/effect-v4/cookbooks/schedule.md — Schedule recipes and traps
  - ~/.cache/effect-v4/packages/effect/src/ — source of truth for every exported module

The skill preview is sorted, capped at 5 names, with (+N more) for overflow. The full guidance is loaded once at layer construction and re-emitted from memory each turn.

The pattern feedback loop

After a successful write, every pattern under patterns/ is matched against the actual post-write file via PatternMatcher. Each pattern is a markdown file with YAML frontmatter:

---
action: context
tool: (edit|write)
event: after
name: avoid-data-tagged-error
description: Use Schema.TaggedErrorClass instead of Data.TaggedError for serialization and RPC compatibility
glob: '**/*.{ts,tsx}'
detector: ast
pattern: Data.TaggedError($$$)
level: warning
suggestSkills:
    - effect-error-handling
---

# Use `Schema.TaggedErrorClass` Instead of `Data.TaggedError`
…

Detectors are either ast-grep rules (single pattern, list of patterns, or full rule object with inside / constraints) or regex with comment-skipping. Severity levels are critical, high, medium, warning, info. Matches are de-duplicated, sorted by severity, and emitted as a single Decision.InjectUserMessage:

pi-effect-harness review request:
File: `src/services/MyThing.ts`

I noticed potential Effect-pattern issues in the write you just completed.
Please inspect this change now.
If the warning is valid, revise the code before continuing.
If you believe it is a false positive or an intentional exception, briefly say so and continue.

Matched patterns:
- avoid-data-tagged-error [warning]: Use Schema.TaggedErrorClass instead of Data.TaggedError…

Relevant guidance:
## avoid-data-tagged-error
…(the full body of the pattern's markdown, plus suggested skills hints)…

The pattern bodies use a Haskell-style transformation diagram convention — type signatures for the bad and good forms, then a one-paragraph rationale. This is harness-internal style, not a requirement; you can fork the patterns and use whatever rationale format you prefer.

The suggestedSkills field is appended to the matched-pattern feedback as: "If you have not loaded the effect-error-handling skill, you should load it before continuing." This closes the feedback loop: a pattern miss surfaces both the rule and the skill that documents it.

The reference clone

Effect v4 is moving fast. Beta releases ship with API renames in nearly every minor (catchAll → catch, parseJson → fromJsonString, Either → Result, compose → decodeTo, the entire *FromSelf suffix removal, etc.). The most reliable way to keep an agent honest is to give it the source.

After /toggle-effect-harness is enabled, and again on enabled session starts / before agent turns, EnsureReferenceClone maintains a single user-scoped clone of Effect-TS/effect-smol at ~/.cache/effect-v4/. If the cache is absent, it runs git clone --depth 1 --single-branch into ~/.cache/effect-v4.cloning/ and atomically renames it into place. If the cache already exists, it refreshes origin, updates origin/HEAD, and hard-resets to the latest Effect v4 beta source commit.

Properties:

  • Atomic first clone: the initial clone happens in a temp directory and is rename()-d into place. Either ~/.cache/effect-v4/ is present and complete, or it is absent.
  • Shared: the cache is user-scoped, not project-scoped; all projects with Effect mode enabled reuse the same clone.
  • Always refreshed: existing clones fetch origin with depth 1, update origin/HEAD, reset to it, and clean untracked files. No project-local effect version is detected or matched.
  • Single-flight: a module-level clonePromise deduplicates concurrent invocations across hooks, and a lightweight cache lock avoids cross-process clone/update races.
  • Fail-silent: a clone or refresh failure (no network, git not on PATH) never blocks the agent. The harness continues without the reference; the policy header still tells the agent the paths to look for.

The agent doesn't have to know any of this. It sees the generated docs, major user-facing guides, cookbook material, and source directory from ~/.cache/effect-v4/ mentioned in the policy header, and reads them like any other file.


Skill catalog

41 skills, all loaded into Pi's /skill: namespace.

AI / LLM (6)

Skill Description
effect-ai-chat Stateful AI chat sessions with the Effect Chat module — multi-turn conversations, agentic tool-calling loops, persistence, streaming, structured object generation.
effect-ai-language-model The Effect AI LanguageModel service — text generation, structured output, streaming, tool calling, schema-validated responses.
effect-ai-prompt The complete Prompt API for constructing, merging, and manipulating LLM conversations using messages, parts, and composition operators.
effect-ai-provider @effect/ai provider layers (Anthropic, OpenAI, OpenAI-Compat, OpenRouter) with config management, model abstraction, ExecutionPlan fallback, runtime overrides.
effect-ai-streaming Streaming response patterns: start/delta/end protocol, accumulation strategies, resource-safe consumption, history management with SubscriptionRef.
effect-ai-tool Tool and Toolkit APIs — type-safe tool definitions, parameter validation, handler implementations, user- and provider-defined tools.

Schema & domain modeling (8)

Skill Description
effect-schema-v4 Authoritative reference for Effect Schema v4 API changes and v3 → v4 migration. Find-and-replace tables, breaking changes, idiom shifts.
effect-schema-composition Schema.decodeTo, transformations, filters, multi-stage validation.
effect-domain-modeling Production-ready domain models with Schema.TaggedStruct — ADTs, predicates, orders, guards, match functions.
effect-domain-predicates Comprehensive predicates and orders for domain types using typeclass patterns.
effect-typeclass-design Curried signatures and dual data-first / data-last APIs.
effect-pattern-matching Data.TaggedEnum, $match, $is, Match.typeTags, Effect.match. Avoid manual _tag checks.
effect-context-witness When to use Context.Service witness vs. capability patterns; coupling trade-offs.
effect-optics Iso, Lens, Prism, Optional, Traversal — composable, type-safe access and immutable updates to nested data.

Layers, services, runtime (5)

Skill Description
effect-layer-design Designing and composing layers for clean dependency management.
effect-service-implementation Fine-grained service capabilities; avoiding monolithic designs.
effect-managed-runtime Bridging Effect into non-Effect frameworks (Hono, Express, Fastify, Lambda, Workers) via ManagedRuntime.
effect-platform-abstraction Cross-platform file I/O, process spawning, HTTP clients, terminal — the abstraction itself.
effect-platform-layers Structuring platform-layer provision for cross-platform applications.

Errors, config, observability (4)

Skill Description
effect-error-handling Schema.TaggedErrorClass, catchTag/catchTags, catchReason/catchReasons, Cause, ErrorReporter, recovery patterns.
effect-config Config and ConfigProvider — env vars, structured config, test config, .env, JSON, custom sources.
effect-observability Structured logging, distributed tracing, metrics; OTLP/Prometheus export.
effect-wide-events Wide events (canonical log lines) for observability. Conceptual guide for instrumentation strategy.

Data, IO, concurrency (7)

Skill Description
effect-stream Pull-based streaming pipelines — creation, transformation, consumption, encoding (NDJSON/Msgpack), concurrency, resource safety.
effect-batching Request, RequestResolver, SqlResolver — N+1 elimination, batched data-fetching layers, request caching.
effect-pubsub-event-bus Typed event buses with PubSub and Stream.
effect-filesystem Cross-platform file I/O across Node.js, Bun, browser.
effect-path Cross-platform path operations — joining, resolving, URL conversion.
effect-command-executor ChildProcess — shell commands, captured output, piping, streaming, scoped lifecycle.
effect-concurrency-testing Testing PubSub, Deferred, Latch, Fiber, SubscriptionRef, Stream.

Persistence & networking (4)

Skill Description
effect-sql SqlClient, SqlSchema, SqlModel (CRUD repos), SqlResolver, Migrator.
effect-http-api HttpApi, HttpApiClient, HttpApiBuilder — typed endpoints, security middleware, OpenAPI, derived clients.
effect-rpc-cluster RPC endpoints, cluster routing, workflow patterns with Effect RPC and Cluster.
effect-workflow Durable workflows with Workflow, Activity, DurableClock, DurableDeferred — execution that survives restarts, compensation (saga), distribution via Cluster.

CLI & MCP (2)

Skill Description
effect-cli Type-safe CLI applications — argument parsing, options, commands, dependency injection.
effect-mcp-server MCP servers with McpServer, McpSchema, Tool, Toolkit; stdio and HTTP transports.

Testing & migration (2)

Skill Description
effect-testing @effect/vitest and it.effect(...) — services, layers, time-dependent effects, error handling, property-based testing.
effect-incremental-migration Migrating async/Promise-based modules to Effect services while preserving backward compatibility.

React (3)

Skill Description
effect-atom-state Reactive state management with Effect Atom for React applications.
effect-react-composition Composable React components using Effect Atom; avoiding boolean props; integrating with Effect's reactive state.
effect-react-vm The VM (View Model) pattern for reactive, testable frontend state management.

Pattern catalog

46 patterns run after successful edit/write tool calls when the written path matches the pattern's frontmatter glob. Most target TypeScript/TSX, but some use narrower or negated globs. Detectors are declared per pattern as either ast-grep rules or comment-skipping regex.

avoid-* (20)

Pattern Level Description
avoid-any warning as any and as unknown type assertions.
avoid-data-tagged-error warning Data.TaggedError — use Schema.TaggedErrorClass for serialization and RPC compatibility.
avoid-direct-json info JSON.parse / JSON.stringify — use Schema.fromJsonString or Schema.UnknownFromJsonString.
avoid-direct-tag-checks warning Direct _tag property checks; use exported refinements/predicates.
avoid-expect-in-if warning expect() calls nested inside if blocks in tests.
avoid-mutable-state info let bindings inside Effect services; prefer Ref.
avoid-native-fetch warning Native fetch — use Effect HTTP modules.
avoid-node-imports warning Catch-all for node: imports not covered by a dedicated use-*-service rule.
avoid-non-null-assertion warning ! non-null assertion operator.
avoid-object-type warning Object and {} as types.
avoid-option-getorthrow warning Option.getOrThrow — use Option.match or Option.getOrElse.
avoid-platform-coupling warning Binding packages importing platform-specific packages like @effect/platform-bun.
avoid-process-env warning process.env — use Config.*.
avoid-react-hooks high useState/useEffect/useReducer etc. — use VMs with Effect Atom.
avoid-schema-suffix info Schema constants suffixed with Schema; name them after the domain type.
avoid-sync-fs high Synchronous filesystem operations.
avoid-try-catch warning try/catch in Effect code — use Effect.try or typed errors.
avoid-ts-ignore warning @ts-ignore and @ts-expect-error.
avoid-untagged-errors warning new Error(...) and instanceof Error for recoverable failures — use Schema.TaggedErrorClass.
avoid-yield-ref warning Direct yield* Ref/Deferred/Fiber/Latch (removed in v4); use explicit method calls.

prefer-* (7)

Pattern Level Description
prefer-arr-sort warning Arr.sort with explicit Order over native Array.prototype.sort.
prefer-duration-values warning Duration helpers over numeric literals for time.
prefer-effect-fn warning Effect.fn for service methods (automatic tracing) over plain Effect.gen wrappers.
prefer-match-over-switch warning Match over native switch.
prefer-option-over-null info Option over T | null unions.
prefer-redacted-config warning Config.redacted / Schema.Redacted for secrets.
prefer-schema-class warning Schema.Class over Schema.Struct for object/domain schemas.

use-* (8)

Pattern Level Description
use-clock-service warning Clock / DateTime over new Date(...) and Date.* statics.
use-command-executor-service warning ChildProcessSpawner / CommandExecutor over node:child_process.
use-console-service warning Console / Effect.log* over console.*.
use-filesystem-service high FileSystem service over direct node:fs / node:fs/promises imports.
use-http-client-service warning Effect HttpClient over node:http / node:https.
use-path-service warning Path service over direct node:path imports.
use-random-service warning Random service over Math.random().
use-temp-file-scoped warning makeTempFileScoped / makeTempDirectoryScoped over os.tmpdir() or non-scoped variants.

Other (11)

Pattern Level Description
casting-awareness info Type assertions in general — use type-safe alternatives.
context-tag-extends warning Context.Tag, Effect.Service, and legacy ServiceMap.* APIs — use Context.Service.
effect-catchall-default warning Broad Effect.catch defaults in domain logic — use catchTag unless it's an explicit boundary fallback.
effect-promise-vs-trypromise warning Effect.promise over Effect.tryPromise (loses error handling).
effect-run-in-body warning Effect.runSync / runPromise outside entry points.
imperative-loops warning for / for...of / while / do...while loops — use functional transformations or Effect.forEach.
require-effect-concurrency warning Effect.forEach / all / validate without explicit concurrency on non-trivial fan-out.
stream-large-files info Whole-file reads when the path looks large or unbounded.
throw-in-effect-gen critical throw inside Effect.gen — use yield* Effect.fail().
vm-in-wrong-file critical View Model definitions outside .vm.ts files.
yield-in-for-loop warning yield* in for loops — use Effect.forEach / STM.forEach.

Each pattern's full markdown body — usually a Haskell-style transformation diagram, rationale, and a hint to load specific effect-* skills — is what gets sent back to the agent on a match.


Configuration

Reference clone location and refresh

The reference clone is hardcoded to ~/.cache/effect-v4/ (path.join(os.homedir(), '.cache', 'effect-v4')). It is shared across every project on the machine. The harness does not read node_modules/effect/package.json, does not compute an effect@<version> tag, and does not create project-local reference directories.

When Effect mode is enabled, session-start and before-turn hooks ensure the cache exists and refresh existing clones to the latest Effect v4 beta source in Effect-TS/effect-smol.

Skill threshold

MIN_EFFECT_SKILLS = 5, defined in harnesses/effect/src/constants.ts. Not currently configurable per-project; if you want a different threshold, fork.

Effect-code regex

\bEffect\b|from\s+['"]effect(?:\/[^'"]*)?['"]

Matches an Effect identifier or any from "effect..." import. The gate is intentionally permissive — false positives on the gate are safe (the agent reads more skills); false negatives are not.

What this extension never does

  • Modifies application source files directly. It may create/update ~/.cache/effect-v4/ for the shared reference clone and Pi's project-scoped session-state file for mode persistence.
  • Blocks Read tool calls. The gate fires on writes only.
  • Persists state across projects. Mode state is project-scoped.
  • Calls the network outside git clone / git fetch for the reference repo.
  • Talks to Pi events outside the lifecycle listed above.

Caveats

  • Beta on beta. Effect v4 is itself in beta, and so is this harness. Keep your project dependency current deliberately. The reference clone tracks the latest Effect v4 beta source rather than any project-local dependency version, so still trust typecheck/tests for ABI compatibility.
  • The patterns are tripwires, not a linter. They catch the common v3 → v4 confusions and the most expensive-to-debug Effect-specific mistakes. They do not replace bun run check && bun run test. Treat a clean pattern run as "the agent didn't trigger the obvious traps," not as "the code is correct."
  • The skill gate is branch-scoped, not session-scoped. /compact, /fork, and /clone reset the loaded-skill set. This is deliberate: post-compaction, the agent has a smaller working memory, and re-establishing the relevant skill context is cheaper than letting it write Effect code from a partial summary.
  • First cache creation and refresh require git on PATH and network access. If clone/refresh fails, the harness continues without blocking the agent. The policy header still points at the cache path; re-toggling /toggle-effect-harness or starting the next turn retries.
  • The pattern-feedback loop runs after every successful write. On a large refactor the agent may receive several pattern-feedback messages in a row. This is by design — each one is severity-sorted and de-duplicated, but the rate is determined by the rate of writes.

Development

bun install
bun run check    # dprint format + oxlint + tsgo typecheck
bun run test     # vitest run (all tests)

See AGENTS.md and CONTRIBUTING.md for project structure, code style, and PR guidelines.

The harness is built on a small internal kernel (packages/harness-kit) that wraps Pi's ExtensionAPI in Effect — Decision, HarnessRule, HookSet, RuleEngine, WriteProjection, PatternCatalog, PatternMatcher. The kernel may eventually be lifted out as a standalone library for building other Pi harnesses; for now treat the Effect harness as the product and the kernel as an implementation detail.


License

MIT © Marc Suesser