Files
AgentCompany/builtin-skills/software-engineer/clean-architecture/references/frame-domain-purity.md
T
ZacharyZhang-NY e74dafcd36 Silence render-disposed spam, unbreak bundled skills, drop board wake
Three independently ugly bugs that all fed the same log flood:

* Electron's `WebFrameMain.send` writes every "Render frame was disposed"
  to stderr via `console.error`. When the worker fans a second
  agent-event past a reloading renderer, we produced thousands of
  identical lines and stalled the main loop on stderr I/O. Added a
  `mainFrame.detached` guard so the send is short-circuited before
  Electron's own catch block fires, and installed a targeted filter in
  `suppress-warnings.ts` (now actually imported from the entry point)
  so the specific `console.error("Error sending from webFrameMain:"…)`
  noise never reaches the terminal. Any other payload still surfaces.

* `dispatchAgentMessage` accepted the human-reader sentinel as a wake
  target when an agent replied to `__board__` — `wakeAgentIfPossible`
  then called `db.getAgent("__board__")`, threw, and the dispatcher
  kept repeating on every send. Strip `HUMAN_SENDER_ID` at
  `resolveMessageWakeTargets`, and keep a defense-in-depth guard in the
  heartbeat so a stray caller (future automation fan-out) cannot
  reintroduce the crash.

* Pi's skills loader rejects any SKILL.md whose frontmatter `name`
  diverges from its parent directory. The four bundled `my-writing-style`
  copies declared `name: writing-style-skill`, so every install emitted
  a warning and dropped the skill. They also lived as orphan gitlinks
  (mode 160000 without .gitmodules), and the global `*.md` gitignore
  hid every other SKILL.md from version control. Fixed the frontmatter
  to match the dir, converted the dangling submodules to plain trees,
  and allowlisted `builtin-skills/**/*.md` so a fresh clone carries the
  catalogue instead of silently losing it.
2026-04-20 08:13:48 -04:00

3.5 KiB

title, impact, impactDescription, tags
title impact impactDescription tags
Domain Layer Has Zero Framework Dependencies MEDIUM enables framework migration, pure unit tests frame, domain, purity, dependencies

Domain Layer Has Zero Framework Dependencies

The domain layer (entities and domain services) should have zero dependencies on frameworks, ORMs, or external libraries. Only language primitives and domain-specific code.

Incorrect (domain depends on framework):

// Domain entity with framework dependencies
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using Newtonsoft.Json;

namespace Domain.Entities
{
    [Table("products")]
    public class Product
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }

        [Required]
        [MaxLength(100)]
        [JsonProperty("product_name")]
        public string Name { get; set; }

        [Column(TypeName = "decimal(18,2)")]
        public decimal Price { get; set; }

        // EF Core navigation property
        public virtual Category Category { get; set; }

        // Framework-specific validation
        public IEnumerable<ValidationResult> Validate(ValidationContext context)
        {
            if (Price < 0)
                yield return new ValidationResult("Price cannot be negative");
        }
    }
}
// Domain now depends on: EF Core, DataAnnotations, Newtonsoft.Json
// Cannot exist without these frameworks

Correct (pure domain):

// Domain entity - zero framework dependencies
namespace Domain.Entities
{
    public class Product
    {
        public ProductId Id { get; }
        public string Name { get; private set; }
        public Money Price { get; private set; }
        public CategoryId CategoryId { get; private set; }

        public Product(ProductId id, string name, Money price, CategoryId categoryId)
        {
            if (string.IsNullOrWhiteSpace(name))
                throw new InvalidProductNameException();
            if (name.Length > 100)
                throw new ProductNameTooLongException(name.Length, 100);
            if (price.IsNegative)
                throw new NegativePriceException(price);

            Id = id;
            Name = name;
            Price = price;
            CategoryId = categoryId;
        }

        public void UpdatePrice(Money newPrice)
        {
            if (newPrice.IsNegative)
                throw new NegativePriceException(newPrice);
            Price = newPrice;
        }
    }
}

// Infrastructure - framework dependencies isolated here
namespace Infrastructure.Persistence
{
    using Microsoft.EntityFrameworkCore;

    [Table("products")]
    internal class ProductEntity
    {
        [Key] public int Id { get; set; }
        [MaxLength(100)] public string Name { get; set; }
        [Column(TypeName = "decimal(18,2)")] public decimal Price { get; set; }
        public int CategoryId { get; set; }
    }

    internal class ProductMapper
    {
        public Product ToDomain(ProductEntity entity) => /* ... */
        public ProductEntity ToEntity(Product product) => /* ... */
    }
}

How to check domain purity:

# Domain project should have no package references
dotnet list Domain.csproj package
# Should return: No packages found

# Or in package.json
# "dependencies": {} should be empty or only contain domain libraries

Reference: Clean Architecture - Frameworks are Details