SkillAgentSearch skills...

review-architecture

Review a PR against the Pascal architectural rules — package boundaries (core/viewer/editor/nodes), the registry-driven composition model (def.geometry / def.renderer / def.system), legacy-dispatch regressions, the slots + world-scale-UV convention for new nodes/geometry, hook hygiene (useEditor/use…

Install / Use

npx skills add pascalorg/editor --skill review-architecture

Installs into whichever agent you are using.

About this skill
📄

SKILL.md

Installable skill definition

Quality Score

90/100

Supported Platforms

Universal

Our assessment of review-architecture

review-architecture scores 90/100 on our quality scale, 506th of 2,860 Development & Engineering skills we index (top 18%).

Its SKILL.md is 29 KB long, well organised into 17 sections with 2 code examples: a thorough specification that gives an agent plenty to work with.

With 24,281 GitHub stars, it is one of the more widely adopted skills in the catalogue.

Substance
30/30
Structure
18/20
Description
15/15
Adoption
19/20
Freshness
15/15

Maintenance, license and trust

  • The repository was last updated 4 days ago, so review-architecture is actively maintained.
  • It is released under the MIT license, a permissive license that allows use, modification and commercial use with attribution.
  • Its trust signals score 100/100, with no cautions. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.

review-architecture compared with similar skills

All 4 of these similar skills score higher than review-architecture; compare them before choosing.

SkillScoreStarsUpdatedFormat
review-architecture (this skill)by pascalorg9024.3k4d agoSKILL.md
Agent-Reachby Panniantong10085.7k12d agoCLAUDE.md
ai-job-searchby MadsLorentzen10044.1ktodayCLAUDE.md
claude-howtoby luongnv8910041.7k1d agoCLAUDE.md
algorithmic-artby anthropics100177.9k5d agoSKILL.md

Frequently asked questions

How do I install review-architecture?
Run npx skills add pascalorg/editor --skill review-architecture. The install tabs above show the steps for each supported agent.
Which AI agents does review-architecture work with?
It is written for Universal, as a SKILL.md file. Other agents that read the same format can often use it too.
Is review-architecture safe to use?
It is MIT-licensed and scores 100/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
Is review-architecture still maintained?
The repository was last updated 4 days ago, so review-architecture is actively maintained.

name: review-architecture description: Review a PR against the Pascal architectural rules — package boundaries (core/viewer/editor/nodes), the registry-driven composition model (def.geometry / def.renderer / def.system), legacy-dispatch regressions, the slots + world-scale-UV convention for new nodes/geometry, hook hygiene (useEditor/useScene/useViewer), and selector performance. Use when the user asks to review a PR, audit a branch, or check that changes respect the codebase's architecture. metadata: internal: true allowed-tools: Bash(git *) Bash(gh *) Read Grep Glob

Architectural review for Pascal PRs. The user will provide a PR URL, branch name, or ask to review the current branch.

1. Load the rules (required — do not skip)

Read these before reviewing any diff. They are the source of truth, not your training data:

  • wiki/architecture/layers.md
  • wiki/architecture/systems.md — core systems vs viewer systems, what each may do
  • wiki/architecture/renderers.md — renderer responsibilities and prohibitions
  • wiki/architecture/tools.md — editor tools live only in apps/editor/components/tools/ or packages/nodes/src/<kind>/
  • wiki/architecture/viewer-isolation.md — viewer must stay editor-agnostic
  • wiki/architecture/node-definitions.md — the three-checkbox composition model (geometry / renderer / system)
  • wiki/architecture/plugin-authoring.md — public contract for external node packs

Required on every review. Read the remaining pages on demand when the diff touches their subject area:

  • wiki/architecture/selection-managers.md
  • wiki/architecture/scene-registry.md
  • wiki/architecture/spatial-queries.md
  • wiki/architecture/node-schemas.md
  • wiki/architecture/inspector-field-limits.md — no arbitrary min/max on dimension fields. Read whenever the diff adds or edits parametrics.ts, a kind panel.tsx, or <SliderControl> bounds.
  • wiki/architecture/events.md
  • wiki/architecture/interaction-scope.md — the interaction state machine + the unified snapping/modifier convention. Read whenever the diff touches a tool, a move-tool / selection / endpoint / reshape file, lib/interaction/**, lib/snapping-mode.ts, or use-interaction-scope.

If anything in the diff looks like a new dispatch surface or registry concept, also skim the live charter at plans/editor-node-registry.md (in the private-editor repo) — it owns the current contract and which kind sits at which migration stage.

2. Fetch the diff

# If the user gave a PR URL or number:
gh pr diff <pr-number-or-url>

# If reviewing the current branch:
git diff main...HEAD

Also list changed files so you can map each to the relevant rule:

gh pr view <pr> --json files --jq '.files[].path'
# or
git diff --name-only main...HEAD

3. Layer classification — do this BEFORE the checklist

For every new file, new type, new store field, or new exported helper introduced by the diff, answer one question: which package does this belong to — core, viewer, editor, or nodes? If the answer is "editor" but the code lives in packages/core or packages/viewer (or vice versa), or if kind-specific code lands anywhere other than packages/nodes/src/<kind>/, flag it as a blocker. This is the most common and most damaging class of violation, and the checklist below won't reliably catch it on its own — do this pass explicitly.

The four packages and what they own

packages/core — domain data + pure logic. Owns: node schemas, the scene store (useScene), live transforms store, core systems (wall mitering, slab polygons, space detection), event bus, plain 2D/3D math helpers, sceneRegistry, the registry primitives (nodeRegistry, registerNode, loadPlugin, discoverPlugins/setPluginDiscovery, SceneApi, Plugin/NodeDefinition types). Consumed by every downstream package, including read-only embeds. Must not know about: Three.js/R3F, packages/viewer, apps/editor, packages/nodes, any rendering or UI concept, any tool/mode/phase concept, or any view-specific concept (floorplan, paint preview, cursor indicators, selection outline styling).

packages/viewer — the 3D canvas, shippable standalone. Owns: <Viewer>, the generic <NodeRenderer> / <ParametricNodeRenderer> / <GeometrySystem> / <RegisteredSystems> / <FloorplanRegistryLayer> plumbing, viewer systems (cutouts, zones, level positions, scans), the viewer store (useViewer) for genuine presentation state only (selection path, camera/level/wall/view modes, theme, display toggles, hover id), useNodeEvents. Consumed by both the editor and the read-only /viewer/[id] route. Must not know about: editor state (useEditor, tools, phases, modes), editor-only names baked into presentation modes ('delete', 'paint-ready'), editor-only state types (material preview, active paint target, floorplan anything), packages/nodes.

packages/editor (and apps/editor) — the editing experience. Owns: the tool framework (useDragAction, ParametricInspector, <MoveRegistryNodeTool>, the registry-aware dispatchers in tool-manager.tsx / MoveTool / panel-manager.tsx / helper-manager.tsx), useEditor, action menus, panels, the floorplan panel and its helpers, paint mode, selection-manager phase/mode logic, cursor badges, command palette, keyboard shortcuts — anything absent from the read-only viewer route. Injects itself into <Viewer> via children and props, never the reverse. Must not import from packages/nodes.

packages/nodes — the built-in plugin (pascal:core). Owns: one folder per node kind (packages/nodes/src/<kind>/) containing definition.ts, schema.ts, optionally geometry.ts / renderer.tsx / system.tsx / floorplan.ts / tool.tsx / move-tool.tsx / panel.tsx / parametrics.ts / preview.tsx. Exports builtinPlugin. Depends on editor, viewer, and core via their public surfaces — the same surfaces a third-party plugin uses (peer-dep style). Nothing in core/, viewer/, or editor/ may import from @pascal-app/nodes. The dependency arrow is one-way: framework code consults nodeRegistry, never reaches into a specific kind's folder.

Triggers that mean "this is probably in the wrong package"

  1. Would the read-only /viewer/[id] route need this? If no, it belongs in apps/editor / packages/editor.
  2. Does the name contain an editor-specific word? (Floorplan, Paint…, Draft…, Marquee, CursorBadge, HoverMode, …Tool, Moving…, Curving….) Default to editor and justify loudly if it's anywhere else.
  3. Does the type or field reference a tool/mode/phase vocabulary? ('delete', 'paint-ready', 'material-paint', 'site'/'structure'/'furnish', 'build'/'edit'.) Belongs in useEditor, not useViewer or core.
  4. Does the helper compute something only a 2D editor view needs? (Floorplan transforms, measurement offsets, SVG path builders, marquee bounds scoped to floorplan.) Editor. Generic 2D geometry that any view could use (polygon math, rotation, clamping, line thickening) can live in core as long as its names are generic — no Floorplan prefix.
  5. Does a new store field have a setter that no part of the target layer ever calls? (e.g. setMaterialPreview in useViewer that only the editor would ever invoke.) That's a layering smell — the state belongs in the caller's layer.
  6. Does the new file mention a specific kind by name? (door-…, wall-…, item-…, etc.) Then it belongs in packages/nodes/src/<kind>/, not under packages/viewer/src/components/renderers/<kind>/, packages/viewer/src/systems/<kind>.ts, packages/editor/src/components/tools/<kind>/, or packages/editor/src/components/ui/panels/<kind>-panel.tsx. Those legacy locations were deleted at Phase 6 cleanup — reintroducing one is a regression to the dispatch model.
  7. Does an import line read from '@pascal-app/nodes' inside core/, viewer/, or editor/? Blocker. The Biome noRestrictedImports rule already bans this; if it slipped through, the framework is reaching down into the plugin.

Write the classification down before writing findings. If core gains "Floorplan" types, the viewer gains paint-mode vocabulary, a renderer grows editor awareness, or a kind-specific file appears outside packages/nodes/src/<kind>/ — those are the blockers to lead with, not downstream symptoms.

4. Review checklist

A. Package boundaries

  • packages/viewer/** does not import from @pascal-app/editor, apps/editor, or @pascal-app/nodes, and does not reference useEditor, tool state, phase, or mode.
  • packages/core/** does not import Three.js, react-three-fiber, @pascal-app/viewer, @pascal-app/editor, or @pascal-app/nodes.
  • packages/editor/** does not import from @pascal-app/nodes.
  • packages/core/** does not introduce types or helpers named after an editor view (Floorplan*, Paint*, Draft*). Generic plan-geometry helpers are fine; view-specific vocabulary is not.
  • No new case '<kind>': clauses (or equivalent kind-specific branching keyed on node.type) inside packages/viewer/** or packages/editor/**. Phase 6 deleted these; the dispatch happens via nodeRegistry. The exceptions left in tree are treeNodeByType (a lookup map, not a switch) and unit-formatting switches (centimeters / feet / inches). Any new case 'door'|'wall'|'item'… in a framework package is a blocker — the behavior belongs on the kind's NodeDefinition.
  • Tools mutate useScene (committed state) and useLiveTransforms (ephemeral drag state); direct sceneRegistry mesh transforms are allowed only under the live-drag exception in wiki/architecture/tools.md. No business logic, no imports from packages/viewer.

B. Node registry & composition (packages/nodes)

If the PR adds or modifies a node kind, check against wiki/architecture/node-definitions.md and wiki/architecture/plugin-authoring.md:

  • Three independent fields: def.geometry?: (node, ctx) => Object3D, def.renderer?: () => Promise<{ default }>, def.system?: () => Promise<{ default }>. There is no discriminator — presence is participation. Setting all three is fine if the kind genuinely needs them; setting a def.system whose only job is to rebuild geometry on dirty is a smell — collapse to def.geometry and let <GeometrySystem> do the work.
  • Builders must be pure. A def.geometry function must not import useScene, must not mutate the store, and must not depend on React context. Read other nodes via GeometryContext (ctx.resolve / ctx.children / ctx.siblings / ctx.parent).
  • Builders emit local-space children. <ParametricNodeRenderer> binds <group position={liveTransform?.position ?? node.position}> in JSX. A builder that bakes world position into vertex coords, or a system that imperatively writes group.position / group.rotation, will desync R3F's prop binding — the node will snap to (0,0,0) after rebuild. Flag any imperative group.position.set(...) inside def.geometry or a registered system. (Tool-driven sceneRegistry.nodes.get(id).position.set(...) during a live drag is fine and is the documented pattern — see hook hygiene below.)
  • Tag geometry-built children. <GeometrySystem> only disposes children carrying userData.__fromGeometry = true. Custom systems that imperatively add children to a registered group must follow the same convention if the group can host React-mounted children (e.g. shelf surfaces hosting items).
  • One registered mesh per node ID. If a custom renderer mounts multiple objects, register the parent group (or whichever object the system needs to address via sceneRegistry.nodes.get(id)).
  • Previews must clone cached materials. If def.preview calls the geometry builder and then sets material.opacity = 0.5, but the builder caches materials at module scope (most do, keyed on material / `mate

Truncated for display — read the full file on GitHub.

Related Skills

View on GitHub
GitHub Stars24.3k
CategoryDevelopment
Updated4d ago
Forks3.0k

Languages

TypeScript

Trust signals

100/100

From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.

No cautions