Repository navigation
feat(render): resourceDirs callback - #236
Conversation
Render hooks get context.callbacks.resourceDirs(kind): each config root's resource folder of that kind, then each plugin's, tagged with the plugin's short name. A plugin's resource folder follows the convention schemas already use (package.json sctx.<kind>, else <pluginDir>/<kind>), now in pluginResourceDir. spacePluginNames is extracted from resolveSpacePluginSchemas so both share one list. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019XphpeFwEYm8K11SoT9ewz
Code reviewNo issues found. Checked for bugs and CLAUDE.md compliance. |
| ) => Promise<ValidationIssue[]>; | ||
| /** Render only: the graph being rendered, in the space graph format. */ | ||
| exportGraph?: () => SpaceGraphData; | ||
| /** Render only: every folder of one kind of resource (such as `map-views`), with the plugin providing it if any. */ |
There was a problem hiding this comment.
Why render only? Run doc-review skill on this PR
There was a problem hiding this comment.
And check against definition of done
There was a problem hiding this comment.
You're right that resourceDirs didn't need to be render-only. In 76fe6b8, parse and template sync get it too (read-space.ts, commands/template-sync.ts). The api.md sentence now sits under Resources, beside resourceDir, rather than under render hooks.
validate and exportGraph stay render-only:
validatereads the space through the parse hook, so offering it during parse would recurse.exportGraphexports the graph being rendered, which only exists in render.
doc-review: I tightened the new api.md line, and the comments and the config.md sentence passed. Definition of done: no CLI, config key or term changes, so there was nothing else to update. The prose gate is marked.
Generated by Claude Code
Parse and template sync get callbacks.resourceDirs too; validate and exportGraph stay render-only. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019XphpeFwEYm8K11SoT9ewz
Code reviewNo issues found. Checked for bugs and CLAUDE.md compliance. |
Revert resourceDirs for parse and template sync. Remove the "Render only" notes from the callback types, since where callbacks are passed is decided by their callers. doc-review gains a check for comments that state a fact another module decides. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019XphpeFwEYm8K11SoT9ewz
|
This is about the "Why render only?" comment. A pending review of yours on this PR blocks thread replies, so I'm replying here. I misread the comment at first. f6f8d17 corrects that:
Generated by Claude Code |
mindsocket
left a comment
There was a problem hiding this comment.
I'm pretty frustrated that this is not opus-level code quality. What on earth is going on?
| there is none. It follows the [resources folder](config.md#resources-folder) layout, so a tool that adds its | ||
| own kind of resource finds it the same way. | ||
|
|
||
| A plugin hook finds these folders for its space, including other plugins' folders, with `context.callbacks.resourceDirs(kind)`. |
There was a problem hiding this comment.
This doesn't make sense here.
|
|
||
| 11. Flag comments that restate code or explain history, and library errors that mention CLI flags. | ||
| 12. Flag comments that state a fact another module decides, such as where a type is used ("render only") or a | ||
| rule enforced elsewhere. Name the owner, or leave it out. |
There was a problem hiding this comment.
No, just "leave it out", no leniency. The amount of comment noise being added from Claude models is a shit-show and is creating massive review overheads and maintenance burden
| ``` | ||
|
|
||
| A render hook can validate the space and export the rendered graph through `context.callbacks.validate()` and `exportGraph()`. Pass `semantic` to `validate` only when the render run asks for it, never from plugin config. | ||
| A render hook can validate the space, export the rendered graph and find resource folders (including other plugins') through `context.callbacks.validate()`, `exportGraph()` and `resourceDirs()`. Pass `semantic` to `validate` only when the render run asks for it, never from plugin config. |
There was a problem hiding this comment.
Drop this whole sentence. It's not needed in api docs at all. Trim anything from this doc that is already mentioned in code comments, that is intuitively inferred from the API shape, or that is a minor implementation detail or logic.
| | Installed package (`sctx-*`) | Spaces that name it in `plugins` | Spaces that name it in `plugins` | | ||
|
|
||
| Plugins can also contribute schemas and partials via a `<pluginRoot>/schemas/` directory (or `"sctx": { "schemas": "..." }` in `package.json`). If a space specifies a plugin-prefixed schema (e.g. `"sctx-wardley-mapping/wardley_map.json"`), schemas are resolved statically without executing plugin code, and the plugin's code hooks are loaded when parsing or rendering. | ||
| Plugins can also contribute schemas and partials via a `<pluginRoot>/schemas/` directory (or `"sctx": { "schemas": "..." }` in `package.json`). Other resources follow the same pattern. For example, map view definitions go in `<pluginRoot>/map-views/`, or the folder named by `"sctx": { "map-views": "..." }`. If a space specifies a plugin-prefixed schema (e.g. `"sctx-wardley-mapping/wardley_map.json"`), schemas are resolved statically without executing plugin code, and the plugin's code hooks are loaded when parsing or rendering. |
There was a problem hiding this comment.
What does this have to do with config?
There was a problem hiding this comment.
Treat the codebase as if you own it and don't just avoid making things worse, also clean up docs related to your change that don't meet the style guides and definition of done
| return [...named, ...builtinPlugins]; | ||
| } | ||
|
|
||
| /** The roots of the loaded config files (the main config and the configs it includes), after `configDir` if given. */ |
There was a problem hiding this comment.
Is this appropriate design? Does it belong here? What is "loaded"?
There was a problem hiding this comment.
Whole file needs deeper consideration of function names, separation of concerns, module deaign, sequencing
| try { | ||
| const declared = JSON.parse(readFileSync(pkgJsonPath, 'utf8')).sctx?.[kind]; | ||
| if (typeof declared === 'string' && isDir(resolve(pluginDir, declared))) return resolve(pluginDir, declared); | ||
| } catch {} |
There was a problem hiding this comment.
Blind catch?! At least explain why
|
|
||
| return pluginSources; | ||
| /** Synchronously collect all plugin schema sources available to a space. */ | ||
| export function resolveSpacePluginSchemas( |
There was a problem hiding this comment.
Are all of these new functions getting used?
Loader reads top-down: loadPlugins, discoverPlugins, validatePluginConfig, then private helpers. resourceDirs moves to plugins/util beside the other plugin-location helpers and uses the space's config root only. pluginResourceDir and spacePluginNames are private. No blind catches: a malformed plugin package.json throws. Docs: api.md drops what code comments and types already say; config.md keeps only config; concepts.md Plugin says what a plugin is and links to config. doc-review check 12 has no exception. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019XphpeFwEYm8K11SoT9ewz
|
Your review is addressed in e51c30f. Here's what changed, by comment. loader.ts ("what is loaded", "whole file needs deeper consideration")
util.ts ("blind catch", "are all of these new functions used")
Docs ("what does this have to do with config", "doesn't make sense here", "drop this whole sentence", "clean up related docs")
Tests, typecheck and lint pass, and doc-review has been run. Generated by Claude Code |
Code reviewNo issues found. Checked for bugs and CLAUDE.md compliance. |
Requested by Rog · project thread
What
This is the third render callback, agreed alongside
validateandexportGraph(#232). A render plugin uses it to find resource folders such asmap-viewswithout importing core.context.callbacks.resourceDirs(kind)returns, in order:resourceDir), andA plugin's resource folder follows the convention schemas already use:
"sctx": { "<kind>": "…" }in its package.json, otherwise<pluginDir>/<kind>.pluginResourceDir(pluginDir, kind)(inplugins/util.ts) now holds that rule, andresolvePluginSchemasDiruses it too.spacePluginNames(space, config)is extracted fromresolveSpacePluginSchemas, so schemas andresourceDirswork from the same list of plugin names (schema prefix, space plugins, global plugins).discoverPluginsandresourceDirsnow share smallconfigRootsandpluginsFolderEntrieshelpers in the loader.Review notes
PluginContext.callbacks.resourceDirs.pluginResourceDirandspacePluginNamesare internal and not exported fromapi.ts.loadMapViewDefinitionsreads"sctx": { "mapViews": … }today. Under the shared convention that key becomes"sctx": { "map-views": … }. Thesctx-map-viewsplugin slice will switch to it.Tests
tests/render/render-plugins.test.tsnow coversresourceDirs('map-views'), which returns the config root's.sctx/map-viewsand a plugin'smap-viewsfolder.bun run test,typecheckandlintpass, and doc-review has been run on the two doc lines (docs/api.md,docs/config.md).Generated by Claude Code