You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This week’s bouquet is hot plastic, stale YAML, and the unmistakable musk of startsWith() pretending to understand filesystem boundaries 🤮. The project is ambitious, sure, but several core paths are held together with duplicated logic, nested-mode wishful thinking, and cleanup code that behaves like a raccoon got root access and a personal vendetta.
Prefix Based Path Checks Are Cosplaying as Security
String-prefix containment checks are a bug farm, not path safety, and this repo keeps planting crops in it 💩.
startsWith() is being used to decide whether one path is “inside” another. That means /repo/app also matches /repo/application, because apparently filesystem boundaries are now just vibes.
The same stunt appears in both root-config selection and parent-directory cleanup, so this is not one bad line; it is a small philosophy of bad lines.
Replace every path-containment startsWith() check with one shared helper based on path.relative() or the existing isPathInsideOrEqual.
Use the same helper for root selection, cleanup boundaries, and any future symlink-sensitive path logic.
Add regression cases for sibling-prefix paths like /repo/app vs /repo/application.
Nested Mode Is a Root Config Monarchy
Nested mode claims to support per-directory behavior, then quietly lets the root config rule everything like a tiny authoritarian goblin 👑.
Nested apply resolves subagents and backup behavior from rootConfig, so child .ruler directories cannot actually control those settings independently.
Nested revert resolves the agent list once from the root and reuses it for every child config, which means child-only agents can leave generated junk behind. Magnificent. No notes. Actually many notes.
Build a per-directory execution plan that resolves CLI overrides against each nested config entry separately.
Carry selectedAgentsByRulerDir through both apply and revert instead of one global selected.
Resolve backup, subagents.enabled, and cleanup_orphaned per nested config, not once from the root.
Revert Cleanup Thinks Config Toml Is Trash
The cleanup code hard-codes generic filenames like config.toml, which is the kind of idea you get right before a postmortem ☠️.
Yes, there are provenance checks, so this is not instant data loss. But the design is still reckless: generic project files are in the deletion candidate list at all.
Open Hands deliberately maps MCP config to root config.toml, so the blast radius includes an utterly normal filename many real projects already use. Fantastic footgun engineering.
case'Open Hands':
// For Open Hands, we target the main config file, not a separate mcp.jsoncandidates.push(path.join(projectRoot,'config.toml'));
Suggestions
Stop deleting generic filenames from a hard-coded list; delete only files recorded in a Ruler-owned manifest or bearing explicit provenance.
For generic files like config.toml, require both provenance and recognizable managed content before removal.
Add revert tests covering pre-existing root config.toml files with and without Ruler-managed sections.
MCP Parsing Has Been Copy Pasted Into a Small Religion
MCP normalization lives in multiple loaders with nearly identical conflict rules, which is how “one tiny change” becomes a bug lottery 🤮.
ConfigLoader normalizes agent-scoped MCP servers. UnifiedConfigLoader separately normalizes TOML servers and then does it again for legacy JSON servers. Same ideas, same conflicts, same type derivation, same opportunity for drift.
This is exactly the sort of duplication that breeds subtle divergence: one path strips a field, another forgets, a third changes warning text, and suddenly your config behavior depends on which codepath sneezed first.
if(!hasCommand&&!hasUrl){diagnostics.push({severity: 'warning',code: 'MCP_TOML_INVALID_SERVER',message: `MCP server '${name}' must have at least one of command or url`,
if(!hasCommand&&!hasUrl){diagnostics.push({severity: 'warning',code: 'MCP_JSON_INVALID_SERVER',message: `MCP server '${name}' must have at least one of command or url`,
Suggestions
Extract one shared normalizeMcpServer() utility that returns normalized data plus diagnostics.
Feed it context (agent, toml, legacy-json) instead of maintaining parallel logic branches.
Centralize warning-code generation so behavior changes happen once, not in a three-headed hydra.
Skills and Subagents Share a Twin They Pretend Not to Know
The skills and subagents processors each reinvent the same manifest and cleanup machinery, because apparently copy-paste is now a platform strategy 🫠.
Both files define the same managed-manifest name, the same relative-path sanitizer, the same manifest reader, the same empty-parent cleanup loop, and the same manifest write/remove workflow.
That means every safety fix has to be remembered twice. Which, in software terms, means it will be remembered once and forgotten once. Classic.
Extract shared managed-directory utilities for manifest IO, safe path filtering, entry removal, and empty-parent cleanup.
Keep only behavior-specific differences in the skills/subagents layers: discovery, transformation, and collision policy.
Consolidate tests around one shared filesystem contract so future fixes stop breeding twins.
TypeScript Is Politely Ignoring the Test Suite
The repo has a giant tests/ tree, and the compiler is explicitly told to avert its eyes like this is all somehow normal 🙃.
tsc only includes src, and tests is explicitly excluded. So compile-time type feedback skips the entire test harness; type breakage is discovered only when Jest happens to execute the right file.
With this many tests, that is lousy DX and weaker refactor safety. You built a second codebase and then told TypeScript to wait outside.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
This Codebase Smells!
This week’s bouquet is hot plastic, stale YAML, and the unmistakable musk of
startsWith()pretending to understand filesystem boundaries 🤮. The project is ambitious, sure, but several core paths are held together with duplicated logic, nested-mode wishful thinking, and cleanup code that behaves like a raccoon got root access and a personal vendetta.Table of Contents
Prefix Based Path Checks Are Cosplaying as Security
String-prefix containment checks are a bug farm, not path safety, and this repo keeps planting crops in it 💩.
startsWith()is being used to decide whether one path is “inside” another. That means/repo/appalso matches/repo/application, because apparently filesystem boundaries are now just vibes.Files
src/lib.tssrc/revert.tssrc/core/SkillsProcessor.tssrc/core/SubagentsProcessor.tsCode
src/lib.tsL441-L450 — linksrc/revert.tsL313-L322 — linksrc/core/SkillsProcessor.tsL365-L371 — linksrc/core/SubagentsProcessor.tsL234-L240 — linkSuggestions
startsWith()check with one shared helper based onpath.relative()or the existingisPathInsideOrEqual./repo/appvs/repo/application.Nested Mode Is a Root Config Monarchy
Nested mode claims to support per-directory behavior, then quietly lets the root config rule everything like a tiny authoritarian goblin 👑.
rootConfig, so child.rulerdirectories cannot actually control those settings independently.Files
src/lib.tssrc/revert.tsCode
src/lib.tsL248-L259 — linksrc/revert.tsL204-L208 — linksrc/revert.tsL223-L235 — linkSuggestions
selectedAgentsByRulerDirthrough both apply and revert instead of one globalselected.backup,subagents.enabled, andcleanup_orphanedper nested config, not once from the root.Revert Cleanup Thinks Config Toml Is Trash
The cleanup code hard-codes generic filenames like
config.toml, which is the kind of idea you get right before a postmortem ☠️.config.toml, so the blast radius includes an utterly normal filename many real projects already use. Fantastic footgun engineering.Files
src/core/revert-engine.tssrc/paths/mcp.tsCode
src/core/revert-engine.tsL521-L528 — linksrc/paths/mcp.tsL88-L90 — linkSuggestions
config.toml, require both provenance and recognizable managed content before removal.config.tomlfiles with and without Ruler-managed sections.MCP Parsing Has Been Copy Pasted Into a Small Religion
MCP normalization lives in multiple loaders with nearly identical conflict rules, which is how “one tiny change” becomes a bug lottery 🤮.
ConfigLoadernormalizes agent-scoped MCP servers.UnifiedConfigLoaderseparately normalizes TOML servers and then does it again for legacy JSON servers. Same ideas, same conflicts, same type derivation, same opportunity for drift.Files
src/core/ConfigLoader.tssrc/core/UnifiedConfigLoader.tsCode
src/core/ConfigLoader.tsL228-L245 — linksrc/core/ConfigLoader.tsL280-L289 — linksrc/core/UnifiedConfigLoader.tsL315-L329 — linksrc/core/UnifiedConfigLoader.tsL352-L363 — linksrc/core/UnifiedConfigLoader.tsL478-L492 — linkSuggestions
normalizeMcpServer()utility that returns normalized data plus diagnostics.agent,toml,legacy-json) instead of maintaining parallel logic branches.Skills and Subagents Share a Twin They Pretend Not to Know
The skills and subagents processors each reinvent the same manifest and cleanup machinery, because apparently copy-paste is now a platform strategy 🫠.
Files
src/core/SkillsProcessor.tssrc/core/SubagentsProcessor.tsCode
src/core/SkillsProcessor.tsL326-L350 — linksrc/core/SubagentsProcessor.tsL195-L219 — linksrc/core/SkillsProcessor.tsL414-L433 — linksrc/core/SubagentsProcessor.tsL292-L311 — linkSuggestions
TypeScript Is Politely Ignoring the Test Suite
The repo has a giant
tests/tree, and the compiler is explicitly told to avert its eyes like this is all somehow normal 🙃.tsconly includessrc, andtestsis explicitly excluded. So compile-time type feedback skips the entire test harness; type breakage is discovered only when Jest happens to execute the right file.Files
tsconfig.jsonpackage.jsonCode
tsconfig.jsonL113-L114 — linkpackage.jsonL16-L20 — linkSuggestions
tsconfig.tests.jsonthat extends the main config withnoEmitand includestests.tsc -p tsconfig.tests.jsonin CI alongside the publish/build config.All reactions