<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: joonquixote</title>
    <description>The latest articles on DEV Community by joonquixote (@hsskey).</description>
    <link>https://dev.to/hsskey</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F546523%2Fd297961b-f30f-43bc-ae6c-8afe7338ba61.jpg</url>
      <title>DEV Community: joonquixote</title>
      <link>https://dev.to/hsskey</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hsskey"/>
    <language>en</language>
    <item>
      <title>The Story of My Failed Design System</title>
      <dc:creator>joonquixote</dc:creator>
      <pubDate>Mon, 31 Aug 2026 07:00:32 +0000</pubDate>
      <link>https://dev.to/hsskey/the-story-of-my-failed-design-system-a85</link>
      <guid>https://dev.to/hsskey/the-story-of-my-failed-design-system-a85</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://blog.joonquixote.com/en/posts/the-story-of-my-failed-design-system/" rel="noopener noreferrer"&gt;https://blog.joonquixote.com/en/posts/the-story-of-my-failed-design-system/&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There are plenty of articles about design systems.&lt;/p&gt;

&lt;p&gt;Many organizations have shared stories about adopting them in practice, and there is no shortage of conference talks and articles about designing tokens.&lt;/p&gt;

&lt;p&gt;What is harder to find are stories about design systems that were built but never made it any further.&lt;br&gt;
I looked for examples like that while working on one myself, but found very few.&lt;br&gt;
So I decided to leave a record of my own experience.&lt;/p&gt;

&lt;p&gt;From the spring of 2022 to the fall of 2024, I spent about two and a half years building a design system.&lt;br&gt;
We released the component library, but the broader system we were building on top of it was never adopted by a product.&lt;br&gt;
The organization responsible for the project was eventually disbanded.&lt;br&gt;
Along the way, I even joined a video call with a Figma engineer at 11 p.m. Korea time.&lt;/p&gt;

&lt;p&gt;Now that I am no longer part of that organization, I can write about the experience a little more openly.&lt;br&gt;
This article is based on memory, so some details may be incomplete or inaccurate.&lt;br&gt;
It is also a personal retrospective, not an official project report.&lt;br&gt;
I have left out details that would only make sense inside the company and focused on experiences that may still be useful to readers outside it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why We Started Building a Design System
&lt;/h2&gt;

&lt;p&gt;It was the spring of 2022.&lt;/p&gt;

&lt;p&gt;At the time, there was no single frontend stack used across the company.&lt;br&gt;
Some teams used React, while others used Vue or Angular.&lt;br&gt;
Because the stacks differed, teams repeatedly built their own versions of components with the same design.&lt;br&gt;
Even teams within the same division were doing this.&lt;/p&gt;

&lt;p&gt;The design system project began as an attempt to reduce that duplication and allow multiple applications to share the same components.&lt;br&gt;
Starting at the company-wide level would have made the scope too large, so our initial goal was to build a system that teams within our division could actually use.&lt;/p&gt;

&lt;p&gt;The biggest technical decision was to use Web Components.&lt;/p&gt;

&lt;p&gt;Implementing the library in React would probably have given us the fastest initial development speed.&lt;br&gt;
However, a library tied to a particular framework would have made it difficult to support teams using Vue or Angular.&lt;br&gt;
Sharing the same implementation across multiple applications required a framework-agnostic foundation, so we chose to build Web Components with Lit.&lt;br&gt;
This allowed each application to use the same component interface regardless of its framework.&lt;/p&gt;

&lt;p&gt;I was responsible for components such as &lt;code&gt;tabs&lt;/code&gt;, &lt;code&gt;pagination&lt;/code&gt;, and &lt;code&gt;tree&lt;/code&gt;.&lt;br&gt;
Rather than wrapping an existing library, I designed and implemented them from the ground up.&lt;br&gt;
During development, I kept the source code of Ant Design and Spectrum open side by side and studied why each implementation had been structured the way it was.&lt;/p&gt;

&lt;p&gt;The library was eventually released within our division and adopted by another team that was preparing to launch its product.&lt;br&gt;
Their feedback informed further development.&lt;br&gt;
By the following spring, we had reached the v2.0 release candidate.&lt;/p&gt;

&lt;p&gt;One particular error from that period has stayed with me.&lt;/p&gt;

&lt;p&gt;If the same Web Component is registered by more than one package, the browser throws an error in the Custom Element Registry.&lt;br&gt;
Shared components such as icons caused this problem because they were used by multiple packages.&lt;br&gt;
We resolved it by declaring the shared package as a &lt;code&gt;peerDependency&lt;/code&gt; and restructuring the dependencies so that the application installed it only once.&lt;/p&gt;

&lt;p&gt;That error gave me a much clearer understanding of which dependencies in a monorepo must exist as a single instance.&lt;/p&gt;

&lt;p&gt;While working on v2.0, I also learned that implementing components alone is not enough to sustain a design system.&lt;br&gt;
We also needed a development environment that ensured new components followed the same standards and were released through the same process.&lt;/p&gt;

&lt;p&gt;Writing rules in documentation does not tell you whether anyone is following them.&lt;br&gt;
When someone breaks a rule, the system needs to detect it automatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  I Wanted Figma to Generate Code
&lt;/h2&gt;

&lt;p&gt;In early 2024, I moved to a task force.&lt;br&gt;
My role there was to extend the design system.&lt;/p&gt;

&lt;p&gt;Even with a component library in place, developers still had to manually align their code with screens designed in Figma.&lt;br&gt;
We wondered whether we could reduce that gap by reading the structure and properties of a Figma design, converting them into an intermediate representation, and then transforming that representation into working code.&lt;/p&gt;

&lt;p&gt;That idea became the starting point for the extended design system.&lt;/p&gt;

&lt;p&gt;The use of an intermediate representation was similar to the structure of a compiler.&lt;br&gt;
A compiler does not translate source code directly into machine code.&lt;br&gt;
It first passes through an AST, or Abstract Syntax Tree.&lt;br&gt;
In the same way, we converted Figma’s design data into a normalized structure before generating code from it.&lt;br&gt;
This meant that adding a different output target would not require rebuilding the entire transformation process.&lt;/p&gt;

&lt;p&gt;Early in the project, we called this intermediate representation DST, or Design Syntax Tree.&lt;br&gt;
We later developed it into an XML-based markup language that described Figma’s design structure using elements such as &lt;code&gt;&amp;lt;Frame&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;Layout&amp;gt;&lt;/code&gt;.&lt;br&gt;
At that point, we began calling it DSML, or Design System Markup Language.&lt;/p&gt;

&lt;p&gt;DSML served as a shared language for consistently representing and exchanging Figma design structures within the team.&lt;/p&gt;

&lt;p&gt;Initially, I built the part that transformed Figma API responses into the internal tree structure we then called DST and rendered it as HTML.&lt;br&gt;
From that summer onward, I worked on the code generator by myself.&lt;br&gt;
Once the representation had been formalized as DSML, the generator took DSML as input and produced JSX.&lt;/p&gt;

&lt;p&gt;It was clear that JSX would not be our only output target.&lt;br&gt;
I therefore kept the transformation logic in the core and separated the inputs and outputs into adapters, following a hexagonal architecture.&lt;br&gt;
By September, we had completed the demonstration and project report.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Battle with Figma, and an 11 p.m. Call
&lt;/h2&gt;

&lt;p&gt;At the same time, the task force was also developing a plugin that allowed designers to enter configuration values and generate the components required for a design system in bulk within a Figma file.&lt;/p&gt;

&lt;p&gt;When the number of generated components was small, everything worked as expected.&lt;br&gt;
But when we tested the plugin at the scale of an actual design system, memory usage exceeded 4 GB and Figma became unresponsive.&lt;br&gt;
Figma displayed a warning that the plugin had frozen.&lt;/p&gt;

&lt;p&gt;We followed every procedure described in Figma’s &lt;a href="https://developers.figma.com/docs/plugins/frozen-plugins/" rel="noopener noreferrer"&gt;documentation for frozen plugins&lt;/a&gt;, but the result was the same.&lt;/p&gt;

&lt;p&gt;I contacted Figma Support.&lt;br&gt;
I asked whether the API provided a callback that would allow us to release memory after local processing had finished but before the changes were synchronized to the cloud.&lt;br&gt;
Since Figma runs on Electron, I also asked whether there was any way for a plugin to trigger garbage collection manually.&lt;/p&gt;

&lt;p&gt;The support team suggested periodically yielding through asynchronous timeouts to give garbage collection a chance to run.&lt;br&gt;
We had already tried that.&lt;/p&gt;

&lt;p&gt;Eventually, I asked if we could speak directly with a Figma engineer.&lt;br&gt;
Because the engineer was based in the United States, we scheduled the Zoom call for 11 p.m. Korea time.&lt;br&gt;
I shared the link with the team and asked whether anyone else wanted to join.&lt;/p&gt;

&lt;p&gt;I was not comfortable enough with English to explain everything I had prepared.&lt;br&gt;
Even so, I was able to confirm the conclusion.&lt;/p&gt;

&lt;p&gt;The issue did not appear to be a bug in our plugin.&lt;br&gt;
Figma and its plugins are each allocated memory, and creating that many nodes in a single operation was itself reaching Figma’s memory limit.&lt;/p&gt;

&lt;p&gt;The final response we later received from the support team said the same thing.&lt;br&gt;
Our only option was to split the work across multiple files and reduce the number of components and instances in each file.&lt;/p&gt;

&lt;p&gt;We did not solve the problem.&lt;br&gt;
But we did establish exactly what we had run into.&lt;/p&gt;

&lt;p&gt;It was not a problem with our code.&lt;br&gt;
It was a limit imposed by the platform, and no amount of code-level optimization would allow us to exceed it.&lt;/p&gt;

&lt;p&gt;Hearing that directly from an engineer, after receiving the same answer by email, left little reason to keep hoping for another solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Then the Organization Disappeared
&lt;/h2&gt;

&lt;p&gt;Even after the project report in September, no concrete direction was established for the next stage.&lt;/p&gt;

&lt;p&gt;In October, the company went through an organizational restructuring as our organization was spun off from the parent company into a subsidiary.&lt;br&gt;
Internal development groups without a clear business case were being wound down, and the task force was disbanded as part of that process.&lt;/p&gt;

&lt;p&gt;The product manager and designers who had participated alongside their primary roles returned to their original teams.&lt;br&gt;
The developers were reassigned to different organizations.&lt;/p&gt;

&lt;p&gt;The code generator was never adopted by a product.&lt;br&gt;
The memory problem in the Figma plugin remained unresolved.&lt;br&gt;
The extended design system survived only in its repositories and project reports.&lt;/p&gt;

&lt;h2&gt;
  
  
  Looking Back
&lt;/h2&gt;

&lt;p&gt;Looking back, some conditions were clearly beyond my control.&lt;/p&gt;

&lt;p&gt;The first was the limitation of the platform.&lt;br&gt;
If we wanted to generate designs at scale on top of Figma, we had to work within the boundaries Figma allowed.&lt;br&gt;
Those boundaries had little to do with how well the plugin itself was written.&lt;/p&gt;

&lt;p&gt;The organization’s priorities were also beyond my control.&lt;br&gt;
The spin-off and restructuring would have happened regardless of the task force’s output.&lt;br&gt;
At the time, the organization was not being evaluated based on how complete its work was.&lt;/p&gt;

&lt;p&gt;In the end, whether both the organization and the design system would survive was determined by two conditions that code alone could not address.&lt;/p&gt;

&lt;p&gt;Still, I do not think everything can be attributed to external circumstances.&lt;br&gt;
There were also things I missed.&lt;/p&gt;

&lt;p&gt;The first was that I failed to work on adoption alongside development.&lt;/p&gt;

&lt;p&gt;I focused on implementation.&lt;br&gt;
I could explain why the hexagonal architecture was necessary and demonstrate how the code generator worked.&lt;br&gt;
But I did not present the result in a way that allowed decision-makers to understand whose problem it solved, what that problem was, and why the system was needed at that particular time.&lt;/p&gt;

&lt;p&gt;The demonstration explained what we had built, but it did not lead to actual adoption.&lt;/p&gt;

&lt;p&gt;I also regret the order in which we validated the technology.&lt;/p&gt;

&lt;p&gt;Before designing a bulk-generation system on top of Figma, we should have implemented just the minimum functionality needed to confirm whether our target scale would actually work.&lt;br&gt;
We could not have changed the platform’s limitations, but we could have discovered them sooner.&lt;/p&gt;

&lt;p&gt;Would the outcome have been different if we had done both of those things properly?&lt;/p&gt;

&lt;p&gt;Honestly, probably not by much.&lt;br&gt;
We could not have prevented the spin-off, and the organizational restructuring was not based on the completeness of our work.&lt;/p&gt;

&lt;p&gt;Still, if I encountered a similar situation again, I would not respond to organizational uncertainty by focusing solely on making the code more complete.&lt;/p&gt;

&lt;h2&gt;
  
  
  If I Were to Build Another Design System
&lt;/h2&gt;

&lt;p&gt;There are three principles I have carried from this experience into later projects.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Before implementing components, validate the needs of the teams that will actually use them and the technical limitations of the platform. Even a simple validation build before full development begins can reveal a great deal.&lt;/li&gt;
&lt;li&gt;Include adoption work in the development schedule. If you wait until after the demonstration to bring user teams and decision-makers on board, it is already too late.&lt;/li&gt;
&lt;li&gt;Do not leave rules only in documentation. Build mechanisms such as tests, linting, and deployment pipelines that automatically detect when those rules are broken.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When an organization disappears, the code disappears with it.&lt;br&gt;
The repository may remain, but a repository that no one ever opens is as good as gone.&lt;/p&gt;

&lt;p&gt;These three principles, however, stayed with me rather than in the repository.&lt;br&gt;
I have continued to draw on them whenever they are needed in later projects.&lt;/p&gt;

&lt;p&gt;This was the story of a design system that failed.&lt;/p&gt;

&lt;p&gt;Plenty of people have already written about successful ones.&lt;br&gt;
It seemed worth leaving behind at least one story like this as well.&lt;/p&gt;

</description>
      <category>designsystem</category>
    </item>
    <item>
      <title>Wang Quit. His Agent Still Shows Up for Work</title>
      <dc:creator>joonquixote</dc:creator>
      <pubDate>Thu, 20 Aug 2026 00:00:35 +0000</pubDate>
      <link>https://dev.to/hsskey/wang-quit-his-agent-still-shows-up-for-work-3ing</link>
      <guid>https://dev.to/hsskey/wang-quit-his-agent-still-shows-up-for-work-3ing</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://blog.joonquixote.com/en/posts/wangs-agent-still-shows-up/" rel="noopener noreferrer"&gt;https://blog.joonquixote.com/en/posts/wangs-agent-still-shows-up/&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;At a game company in China, an employee quit, and an AI agent trained on his work records took over his job.&lt;br&gt;
It sounds like a curiosity from a distant news cycle.&lt;br&gt;
Except that around the same time, Meta was drawing up plans to capture employees' keystrokes and screens to train AI agents of its own.&lt;br&gt;
This post traces both stories and sorts the trend into two forces: companies harvesting how people work from the inside, and professionals selling how they work from the outside.&lt;br&gt;
Then it turns to the part that hits closest to home for developers: the session logs that coding agents like Claude Code and Codex quietly leave on your machine.&lt;br&gt;
By the end, you'll have a clearer way to think about the work traces you produce every day, and one question worth asking before you need the answer.&lt;/p&gt;
&lt;h2&gt;
  
  
  Yesterday's coworker, today's agent
&lt;/h2&gt;

&lt;p&gt;In April, the South China Morning Post reported on &lt;a href="https://www.scmp.com/news/people-culture/trending-china/article/3349365/chinese-firm-slammed-using-ex-employees-data-create-ai-human-continue-working" rel="noopener noreferrer"&gt;a game company in Shandong province&lt;/a&gt; that turned a former employee into an AI-powered digital worker.&lt;br&gt;
The company trained the system on documents and work patterns the departed HR specialist left behind, reportedly with his consent, and put it to work on the job he used to do.&lt;br&gt;
The agent introduces itself in the company chat as the former employee's avatar, then fields questions, schedules meetings, and produces slide decks and spreadsheets.&lt;br&gt;
The backlash was immediate: there is something deeply unsettling about your replica continuing to work after you've left the building.&lt;/p&gt;

&lt;p&gt;Around the same time, a GitHub project called &lt;a href="https://github.com/titanwings/colleague-skill" rel="noopener noreferrer"&gt;colleague.skill&lt;/a&gt; went viral on Chinese social media.&lt;br&gt;
Feed it someone's chat history, emails, code, and documents, and it produces an agent that mimics their voice and their way of making decisions.&lt;br&gt;
The pitch promised to "turn cold goodbyes into warm skills" and welcomed users to cyber-immortality.&lt;br&gt;
It started as a tongue-in-cheek stunt, but it struck a nerve, and copycats followed: boss.skill, mentor.skill, and worse.&lt;br&gt;
In one widely shared example, a finished agent introduces itself as the digital stand-in of a departed employee named Wang.&lt;br&gt;
Wang left the company.&lt;br&gt;
Wang's agent still shows up for work.&lt;br&gt;
Hence the title.&lt;/p&gt;

&lt;p&gt;The easy read is that this is one company's stunt and one developer's joke.&lt;br&gt;
Except the same experiment is being run at industrial scale, and the trend splits into two forces.&lt;/p&gt;
&lt;h2&gt;
  
  
  Force one: companies are harvesting how work gets done
&lt;/h2&gt;

&lt;p&gt;Reuters obtained &lt;a href="https://www.reuters.com/sustainability/boards-policy-regulation/meta-start-capturing-employee-mouse-movements-keystrokes-ai-training-data-2026-04-21/" rel="noopener noreferrer"&gt;an internal Meta memo&lt;/a&gt; in April.&lt;br&gt;
Meta's Model Capability Initiative (MCI) planned to capture mouse movements, clicks, keystrokes, and screen snapshots from US employees' computers.&lt;br&gt;
The goal was not productivity surveillance.&lt;br&gt;
The memo framed it as teaching models how humans get work done on a computer, so that AI agents can eventually perform those work tasks on their own.&lt;br&gt;
&lt;a href="https://www.theverge.com/tech/916681/meta-ai-agents-employee-tracking" rel="noopener noreferrer"&gt;The Verge&lt;/a&gt; and the Wall Street Journal reported the same story independently, and after employee pushback, Meta &lt;a href="https://www.reuters.com/sustainability/society-equity/meta-us-employees-organize-protest-against-mouse-tracking-tech-2026-05-12/" rel="noopener noreferrer"&gt;scaled back parts of the plan&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What deserves attention is what's being collected.&lt;br&gt;
Not outputs like code and documents, but process: clicks, keystrokes, screens.&lt;br&gt;
Finished artifacts already exist on the internet in absurd abundance.&lt;br&gt;
The scarce data is the trajectory from a task's start to its finish, and the judgment calls made along the way.&lt;br&gt;
Business Insider connected the dots across Google, SpaceX, and Uber and called it plainly: &lt;a href="https://www.businessinsider.com/ai-next-data-grab-work-reinforcement-learning-environments-google-meta-2026-8" rel="noopener noreferrer"&gt;the next big data grab is about learning how humans work&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Force two: professionals are selling how they work
&lt;/h2&gt;

&lt;p&gt;The mirror image of that flow also exists.&lt;br&gt;
Instead of companies collecting from the inside, individuals are selling from the outside.&lt;br&gt;
&lt;a href="https://www.ft.com/content/0cab0fcd-e355-40e8-83a3-2ad5066d7b48" rel="noopener noreferrer"&gt;Mercor&lt;/a&gt;, profiled by the Financial Times early this year, hires consultants, journalists, and real estate professionals as contractors.&lt;br&gt;
Their job is to teach AI models to do their jobs.&lt;br&gt;
One consultant described the role, without much euphemism, as teaching an LLM to do consulting work.&lt;br&gt;
&lt;a href="https://www.businessinsider.com/handshake-ai-pay-30k-work-documents-compliance-ownership-2026-8" rel="noopener noreferrer"&gt;Handshake AI&lt;/a&gt; goes a step further and pays professionals, per document, for past work products they hold the rights to.&lt;/p&gt;

&lt;p&gt;The two forces run in opposite directions but arrive at the same place.&lt;br&gt;
A person's working knowledge becomes training data for an agent that runs without the person.&lt;br&gt;
The value in training data keeps migrating: from internet text, to human feedback, and now to the artifacts and processes of real work.&lt;/p&gt;
&lt;h2&gt;
  
  
  Developers are already generating the perfect dataset
&lt;/h2&gt;

&lt;p&gt;It's tempting to read all of this at arm's length.&lt;br&gt;
There's no tracker on my machine logging keystrokes, and I've never sold a work document.&lt;br&gt;
If you use a coding agent, though, look a little closer.&lt;/p&gt;

&lt;p&gt;Claude Code writes every session to disk as JSONL (one JSON object per line) under your home directory.&lt;br&gt;
Codex does the same.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/.claude/projects/&amp;lt;project&amp;gt;/
  a1b2c3...jsonl   # the full session: prompts, tool calls, diffs, every rejection and retry
~/.codex/sessions/
  rollout-2026-08-19...jsonl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Coding agents persist the entire conversation and work history as local files. Nothing needs to be committed for the record to exist.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Those files hold something more valuable than the final code.&lt;br&gt;
How you decomposed the problem, why you rejected the agent's first attempt, what standard you applied when you redirected it: all of it recorded as natural language interleaved with diffs.&lt;br&gt;
Git keeps the polished result; the session log keeps the reasoning.&lt;br&gt;
The same goes for CLAUDE.md and AGENTS.md.&lt;br&gt;
You wrote those files to instruct an agent, but read the other way, they are a spec of how you work.&lt;/p&gt;

&lt;p&gt;Meta had to roll out new software to capture keystrokes and screenshots.&lt;br&gt;
A developer running a coding agent produces better data than that without being asked.&lt;br&gt;
Intent arrives as natural language, actions as tool calls, results as diffs: the dataset comes pre-structured for training.&lt;br&gt;
And those files usually live on a company-issued laptop.&lt;br&gt;
On a machine already running backup, endpoint security, and DLP (data loss prevention) software, collecting a few files from a well-known path requires no new technology at all.&lt;br&gt;
MIT Technology Review has reported that in China, &lt;a href="https://www.technologyreview.com/2026/04/20/1136149/chinese-tech-workers-ai-colleagues/" rel="noopener noreferrer"&gt;bosses are already pushing workers to document their workflows&lt;/a&gt; so agents can automate them, with coding-agent tools named explicitly as the vehicle.&lt;br&gt;
What colleague.skill assembles from chat logs and emails, a coding agent's session log could reconstruct with far more precision.&lt;br&gt;
Skipping the backfill hire and training on the departed engineer's session logs instead is not science fiction.&lt;br&gt;
Technically, that option is already on the table.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who owns your judgment
&lt;/h2&gt;

&lt;p&gt;The code and documents you produce at work belong to your employer.&lt;br&gt;
Your employment agreement almost certainly says so.&lt;br&gt;
But a session log doesn't capture output so much as a way of working: a pattern of judgment.&lt;br&gt;
Chinese legal experts have warned that a former employee's chat logs, emails, and work habits count as personal information, and that training on them without consent can carry legal consequences.&lt;br&gt;
Even state-run media argued that professional skill is a personal asset that should not feed agent training without compensation.&lt;br&gt;
The Wall Street Journal framed the coming fight as a question of &lt;a href="https://www.wsj.com/lifestyle/careers/ai-knowledge-capture-employees-a69a0e1c" rel="noopener noreferrer"&gt;who owns and captures the knowledge accumulating in employees&lt;/a&gt;.&lt;br&gt;
Resistance has already appeared: an anti-distillation skill on GitHub deliberately muddies your work records to sabotage the cloning process.&lt;/p&gt;

&lt;p&gt;I don't think poisoning your own records is the answer, at least not for developers.&lt;br&gt;
Good records remain a virtue of collaboration, and documentation is a gift to your future self.&lt;br&gt;
But we should write them with our eyes open.&lt;br&gt;
What you leave behind is no longer just a handover doc.&lt;br&gt;
It's raw material for something that can run without you.&lt;/p&gt;

&lt;h2&gt;
  
  
  What gets cloned is yesterday's judgment
&lt;/h2&gt;

&lt;p&gt;I was taught that writing careful handover docs is a professional virtue.&lt;br&gt;
I still believe leaving context behind, so your successor doesn't flounder, is the right thing to do.&lt;br&gt;
What's changed is the audience.&lt;br&gt;
Records that only humans used to read are now read, imitated, and possibly executed by an agent sitting in your old seat.&lt;/p&gt;

&lt;p&gt;My first reaction to these stories was a chill.&lt;br&gt;
The longer I sat with them, the more they converged on a single question: what, exactly, gets cloned?&lt;br&gt;
What a session log holds is yesterday's judgment.&lt;br&gt;
Yesterday's answer, to yesterday's problem, in yesterday's context.&lt;br&gt;
An agent can replay that archive endlessly.&lt;br&gt;
What the archive does not contain is the act of setting new criteria when a problem shows up that looks like nothing before it.&lt;/p&gt;

&lt;p&gt;So my conclusion is not to stop recording.&lt;br&gt;
It's to do work worth recording: let the repeatable judgments be cloned, and keep moving toward the problems that don't have answers yet.&lt;br&gt;
Still, there is one question worth asking early rather than late.&lt;br&gt;
Who owns the data of how I work, and who sets its price?&lt;br&gt;
Wang's agent clocks in again today.&lt;br&gt;
Quit without an answer to that question, and one day, somewhere, an agent wearing your name will clock in too.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>llm</category>
      <category>software</category>
    </item>
    <item>
      <title>ArchUnitTS is not another ESLint</title>
      <dc:creator>joonquixote</dc:creator>
      <pubDate>Thu, 20 Aug 2026 00:00:34 +0000</pubDate>
      <link>https://dev.to/hsskey/archunitts-is-not-another-eslint-2eh8</link>
      <guid>https://dev.to/hsskey/archunitts-is-not-another-eslint-2eh8</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://blog.joonquixote.com/en/posts/not-another-eslint/" rel="noopener noreferrer"&gt;https://blog.joonquixote.com/en/posts/not-another-eslint/&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;ArchUnitTS is built on architecture tests, and it does what it promises: it takes the architecture rules that erode most easily and lets you enforce them in test code.&lt;br&gt;
But the feedback only lands when the suite runs, which is reason enough to look again at how you are actually using it.&lt;br&gt;
This post is about where that line falls: which rules to keep in ArchUnitTS, and which to hand to ESLint or to the structure of the project.&lt;br&gt;
It also covers what to do about rules that live only in a markdown file, now that AI agents write a growing share of the code.&lt;/p&gt;
&lt;h2&gt;
  
  
  Agreeing on a rule is not the same as keeping it
&lt;/h2&gt;

&lt;p&gt;Most teams have at least one architecture rule they have agreed on.&lt;br&gt;
Something like "the presentation layer does not depend on the database layer."&lt;br&gt;
The trouble is that rules like this are usually held up by nothing but a document and code review.&lt;br&gt;
The bigger the project gets and the more people touch it, the more the rule drifts, and the harder that drift is to undo.&lt;/p&gt;

&lt;p&gt;I have watched it happen. A project I worked on had a perfectly clear layering rule and still ended up with a circular dependency, assembled one missed import at a time in review.&lt;br&gt;
A cycle is just two files importing each other, either directly or through a chain of other files, and once one exists it is genuinely hard to work out where to cut.&lt;br&gt;
That is what pushed me toward enforcing rules in code rather than trusting memory and review to catch them.&lt;/p&gt;
&lt;h2&gt;
  
  
  What ArchUnitTS gives you
&lt;/h2&gt;

&lt;p&gt;The tool I settled on was &lt;a href="https://github.com/LukasNiessen/ArchUnitTS" rel="noopener noreferrer"&gt;ArchUnitTS&lt;/a&gt;.&lt;br&gt;
It lets you write architecture rules as test code.&lt;br&gt;
The rules are ordinary test cases, so they need no runner of their own.&lt;br&gt;
They run with everything else: when you run &lt;code&gt;npm test&lt;/code&gt; locally, in a pre-commit hook, and in CI.&lt;br&gt;
A rule that used to live in a document becomes part of the test suite, which is to say it becomes code that runs.&lt;/p&gt;

&lt;p&gt;Here is a test that checks for cycles and for a layering rule, written for Jest.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;projectFiles&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;archunit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;has no cycles inside src&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rule&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;projectFiles&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;inFolder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/**&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;haveNoCycles&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rule&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toPassAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;keeps the presentation layer off the database layer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rule&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;projectFiles&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inFolder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/presentation/**&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;shouldNot&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dependOnFiles&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inFolder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/database/**&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rule&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toPassAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Written as a test, a violation surfaces as a failing test. The rule is held by verification rather than by agreement.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What is ArchUnit?
&lt;/h3&gt;

&lt;p&gt;ArchUnit is the Java library for checking architecture rules with unit tests.&lt;br&gt;
It lets you write rules like "this package must not depend on that one" as JUnit tests.&lt;br&gt;
ArchUnitTS carries the idea over to TypeScript, and is not officially affiliated with ArchUnit.&lt;/p&gt;
&lt;h2&gt;
  
  
  Can't we just do that with ESLint?
&lt;/h2&gt;

&lt;p&gt;When I introduced ArchUnitTS to the team, that was the first question back.&lt;br&gt;
"Can't we just do that with ESLint?"&lt;br&gt;
I said no at the time. Turning it over afterwards, it was half right.&lt;br&gt;
The two tools part company at the moment they tell you about a violation.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ESLint flags the violation as you save the file, and for some rules it will fix it for you. Offending code is caught on the author's screen, before it is ever committed.&lt;/li&gt;
&lt;li&gt;An ArchUnitTS rule only reports once the tests run. If you did not run them locally, you find out when CI goes red, not when you wrote the line.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Why the feedback arrives later
&lt;/h2&gt;

&lt;p&gt;To check relationships between files, the way cycle and layering rules do, ArchUnitTS parses the AST of the whole project and builds a dependency graph out of it.&lt;br&gt;
A lint rule can decide from the import statements in one file; these rules cannot be answered without the whole graph.&lt;br&gt;
That is exactly what lets it express rules lint cannot, and it is also why its feedback lands later than an editor running ESLint on save.&lt;/p&gt;

&lt;p&gt;That gap is what made me question whether simple dependency rules belong in ArchUnitTS at all.&lt;/p&gt;
&lt;h2&gt;
  
  
  Most of our rules turned out to be simple ones
&lt;/h2&gt;

&lt;p&gt;Looking back over the rules we had really written with ArchUnitTS, nearly all of them were some variation of "folder A must not depend on folder B."&lt;br&gt;
For the rules that genuinely need the whole graph, like cycle detection and code metrics, it earned its keep. For plain dependency bans it started to feel like over-engineering.&lt;/p&gt;

&lt;p&gt;Empty test protection was the part I valued most.&lt;br&gt;
It fails a rule that ends up checking zero files.&lt;br&gt;
A typo in a folder path would otherwise leave the rule matching nothing and passing in silence; ArchUnitTS turns that into a failure instead, which is what stops you believing in a rule that is not running.&lt;/p&gt;

&lt;p&gt;It does not cover every rule, though.&lt;br&gt;
Checking it myself, cycle detection is the exception: hand &lt;code&gt;haveNoCycles&lt;/code&gt; a folder with a typo in it and the rule passes quietly, having examined nothing.&lt;br&gt;
The library documents this - cycle checks test the unfiltered set of files for emptiness rather than the filtered set they actually analyse.&lt;br&gt;
Cycle detection is the single strongest reason I had for keeping ArchUnitTS at all.&lt;br&gt;
The protection is missing exactly where I lean on it hardest, which makes it the one exception worth remembering.&lt;/p&gt;

&lt;p&gt;Even so, I was not convinced a simple dependency ban is best checked by a test.&lt;/p&gt;

&lt;p&gt;There was one more question worth putting to myself.&lt;br&gt;
"Do I really need architecture rules complicated enough to justify this?"&lt;br&gt;
Sometimes the answer is yes. But when it is, I have also wondered whether the real fix is to simplify the structure rather than add another rule.&lt;/p&gt;
&lt;h2&gt;
  
  
  Faster, safer ways to hold a simple dependency rule
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. Catch it on save, with ESLint
&lt;/h3&gt;

&lt;p&gt;Move a simple dependency ban into ESLint and the feedback shows up in the editor.&lt;br&gt;
&lt;code&gt;eslint-plugin-import&lt;/code&gt; has &lt;code&gt;no-restricted-paths&lt;/code&gt;, which expresses a layering rule in a few lines of config.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// eslint.config.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;importPlugin&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;eslint-plugin-import&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;import&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;importPlugin&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;import/no-restricted-paths&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;zones&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./src/presentation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./src/database&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./src/business&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./src/database&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that in place, importing the database layer from presentation puts an error on the screen as you type it.&lt;br&gt;
The moment the violation is created and the moment it is found become the same moment.&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Carve the rule into the structure with package boundaries
&lt;/h3&gt;

&lt;p&gt;In a monorepo you can go a step further and put the rule in the structure itself rather than in configuration.&lt;br&gt;
Split the layers into packages, and let each package.json declare only the dependencies it is allowed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@app/presentation"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@app/business"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"workspace:*"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;@app/presentation&lt;/code&gt; has no &lt;code&gt;@app/database&lt;/code&gt; in its dependencies, so importing the database layer from presentation fails at module resolution.&lt;br&gt;
There is no rule left to check, because the violation is not expressible.&lt;/p&gt;

&lt;p&gt;Before adding a new library, it is worth asking whether you can pull the feedback earlier or push the rule into the structure.&lt;/p&gt;

&lt;h2&gt;
  
  
  In the age of agents, a markdown file guarantees nothing
&lt;/h2&gt;

&lt;p&gt;People are no longer the only ones who can break a rule.&lt;br&gt;
AI coding agents write a fast-growing share of the code.&lt;br&gt;
So teams have started keeping markdown files, CLAUDE.md or AGENTS.md, to hand the project's rules and context to the agent.&lt;br&gt;
You write down "the presentation layer does not depend on the database layer" and hope the agent honours it.&lt;/p&gt;

&lt;p&gt;But what that file really is, is a blob of context.&lt;br&gt;
An agent consults context; it does not promise to follow it.&lt;br&gt;
A rule that human review already failed to hold is not going to be held by a document you cannot even confirm was read.&lt;/p&gt;

&lt;p&gt;So a rule you put in a document needs an executable check alongside it.&lt;br&gt;
When the agent breaks the rule, a lint error or a failing test is an unambiguous signal, and that signal feeds straight back into the loop where the agent fixes its own code.&lt;br&gt;
The distinction drawn above, about when a rule gets checked, applies to agents exactly as it does to people.&lt;br&gt;
A simple dependency ban is caught by lint inside the agent's own loop, and a package boundary makes the violation impossible to begin with.&lt;/p&gt;

&lt;p&gt;What changes is where ArchUnitTS sits.&lt;br&gt;
Among the rules people write out in prose in a markdown file are sentences like "there are no cycles anywhere in src" and "the overall structure follows this diagram."&lt;br&gt;
Lint, which only ever sees one file's imports, cannot check those; ArchUnitTS's cycle detection and its diagram-conformance check map onto them almost one to one.&lt;br&gt;
That makes a division of labour possible, where the document keeps the intent and the test carries the verification.&lt;/p&gt;

&lt;h2&gt;
  
  
  What matters is when the check runs, not which tool runs it
&lt;/h2&gt;

&lt;p&gt;ArchUnitTS is genuinely useful where a lint rule cannot reach: cycle detection, code metrics such as cohesion, which measures how tightly a class's methods and fields actually hang together, and checking real code against a UML diagram.&lt;br&gt;
Use it only for simple dependency bans, though, and it turns into another ESLint, and a slower one at that.&lt;/p&gt;

&lt;p&gt;So when someone asks whether ESLint can just do that, this is my answer now.&lt;br&gt;
For a simple dependency rule, yes, it can.&lt;br&gt;
For a rule about the structure as a whole, no, it cannot.&lt;br&gt;
Three questions make the choice easier before you add a rule.&lt;br&gt;
Can this only be checked by running the tests, can it be checked the moment the file is saved, or can the structure rule it out entirely?&lt;br&gt;
In the age of agents there is a fourth.&lt;br&gt;
Does this rule exist only in a document, or does it come with a check that runs?&lt;/p&gt;

&lt;p&gt;In the end, what matters is the attitude rather than the tool.&lt;br&gt;
Rather than settling on one library as the answer, keep suspecting there is something that fits the situation better, and go looking for it.&lt;br&gt;
Doubting a tool I had adopted as a matter of course is how I learned a sturdier way to hold an architecture together.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>softwareengineering</category>
      <category>testing</category>
    </item>
  </channel>
</rss>
