2026-06-18 — Session Log
Filled out the notes completely — historical changelog + current-state refresh
Owner asked to "go through the notes and fill it out completely … go through all the commits to have everything documented well," taking the new docs into account. Done:
- Wrote the historical changelog. Created
version/2022-12.md,2023-01.md,2023-03.md,2023-04.mdfrom the full git log (351 pre-revival commits), grouped by theme with date anchors (they predate the per-commit inline rule, so retrospective + thematic is the honest form). Added a note to each explaining that. Updated theversion.mdindex Months table with all four, plus a "two eras" note distinguishing the retrospective months from the inline-rule months. - Closed the June-2026 changelog gaps. Cross-checked every revival commit against the changelog and
added the missing entries: the
src/+data/reorg (2.0.1), the Build-tab-only UI, Vite 6→8, the lockfile + lodash-pin build fixes, the deployments-held note, the DSL/history + dynamic-prompt-catalog doc commits, the intactness-verification session, and thesmoke-test.mjs@file. - Refreshed current-state notes.
status.mdnow describes all four revival strands (ESM modernize → src/data reorg → React SPA → full JSDoc doc-site) and the held deployments, withnpm run docs+ the SPA build added to the health table.plans/next-steps.mdupdated (smoke harness now exists; SPA-UI rework reframes the frontend item).decisions/architecture.mdgained three doc-tooling decisions: JSDoc-over-Doxygen, the unified code+notes site, and the keep-JSDoc-for-React (transpile JSX) judgment with the Storybook/better-docs trigger.
Notes-only; rebuilt the doc-site to confirm the new pages flow into tutorials, and ran lint/smoke.
Documented the web-app React SPA — coverage now spans the whole repo
Owner asked to document web-app/ too (the last gap), fully, wired into the site. Done:
@module+ per-function JSDoc on all 16 SPA files — the 8.jsxcomponents,App,main, thelib/*+providers/*, and the Netlify function.- JSX → JSDoc:
jsdoc-babelis abandoned (peer-conflicts with babel 8), sobuild-docs.mjsnow babel-transpilesweb-app/src+netlify→tmp/webapp-docs(JSX stripped, comments kept) and JSDoc reads that mirror.@moduletags give clean nav names regardless of the temp path. - Four gotchas fixed:
@modulemust come after the description (a leading@moduleswallowed the prose → crash); the JSDocsource.excludePatternhad a generic/lib/that excludedweb-app/src/lib(narrowed tofrontend/lib);tmp/**wasn't in the ESLint ignores (the transpiled mirror produced 9 phantom errors); and a@returns {[object, Function]}tuple type the parser rejects →{Array}. - Result: 16 web-app module pages; the whole repo (server-side + 113 prompts + classic frontend + the SPA) now documented in one JSDoc site (~244 pages).
Verified: npm run docs exit 0, npm run lint 0 errors, format:check clean, smoke green, and
npm --prefix web-app run build green.
Replaced Doxygen with a unified JSDoc + docdash doc-site
Owner: "no Doxygen, just JSDoc for the docs site — have JSDoc wire the notes in like Doxygen did, with custom markdown. JSDoc here is what Doxygen is in the sibling project." Done:
scripts/build-docs.mjs(new): walksnotes/**(+ repo docs), copies each page into a flat tutorials dir (tmp/jsdoc-tutorials/, gitignored) with a path-derived id, builds atutorials.jsonhierarchy mirroring the folder tree (the old_nav.doxrole), and rewrites inter-note relative Markdown links to the generatedtutorial-*.htmlpages. Then runs JSDoc.- docdash template (devDep) +
jsdoc.config.json(opts.template,opts.tutorials, docdash options: search, collapse, Tutorials-firstsectionOrder). Output →docs/jsdoc/: the single site — README home- per-function API + the whole notes tree as tutorials, with sidebar + search.
- Removed Doxygen:
Doxyfile,docs/doxygen-awesome/,notes/_nav.doxdeleted;npm run docsnow builds the JSDoc site (docs:apifolded away). - CI:
pages.yml+release.ymlnownpm ci+npm run docsand publish/zipdocs/jsdoc(no Doxygen install step). - Notes/CLAUDE: rewrote
documentation.md§1+§3 anddeployment.mdfor the JSDoc site; updatednotes/README.md,fix-patterns.md, andCLAUDE.md— dropped the_nav.doxmaintain rule (notes are now auto-discovered by the build script; just keep cross-links relative so they get rewritten).
Verified: npm run docs exit 0 (43 note pages wired in, cross-links rewritten, docdash sidebar + search),
npm run lint 0 errors, format:check clean, smoke green.
Frontend JSDoc — documentation now complete across the whole codebase
Owner asked to finish completely/comprehensively, so closed the one remaining gap: the legacy
web/frontend/* browser scripts. A UTF-8-safe idempotent script added per-function JSDoc to all 84
top-level function declarations across the 8 files (inferred @param types, humanized descriptions,
value-return detection → @returns). Verified: lint 0 errors, format:check clean, smoke green,
npm run docs:api exit 0 (170 pages; frontend functions now extract, e.g. single.js's makeVariations/
copyPrompt). Net result: every named function in the codebase now carries JSDoc — only anonymous
callbacks (Express route arrows, jQuery event closures, $(document).ready) remain, which no JS doc
generator can extract. Quality note recorded in documentation.md: server-side docs are bespoke; the
dynamic-prompts + frontend handlers are accurate generated scaffolds.
Per-function JSDoc pass — complete server-side API + all dynamic prompts
Owner asked for comprehensive, complete coverage "on every level from small to big." Took JSDoc from file-level to per-function across the entire server side and all generators:
- Prompt engine (hand-written): every function in the 5 prompt-modules, the keyword randomizers,
list store/repeater, image/apng/results helpers, and all of
core/(engine, stages, loaders, listStore). - Core-logic (hand-written):
common(batch loop),loadSettings,promptFilesAndSuggestions,convertMetaToJSON,diffSettings,createMissingUserSettings, the variation/reroll/upscale/ animation run-mode loaders,applyArgs,genImg(progress + txt2img), theserver.jsnamed helpers (dirOpen / execMagick / execApp / getProgress*), and every function in the self-healing image index. - All 113 dynamic prompts (scripted, UTF-8-safe): each default export now has
@paramfor its real parameter list +@returns {string}.
Verified: npm run lint (0 errors), npm run format:check, npm run smoke, and npm run docs:api
(exit 0, 170 pages — functions now extract). Committed in focused batches on dev. The legacy
web/frontend/* browser scripts are the one deliberate exception (kept file-level — jQuery client being
retired); offered as a follow-up.
Two self-inflicted issues, both caught and fixed: the earlier @file PowerShell script had mojibake'd
em-dashes in 3 files (ANSI vs UTF-8 read — reversed + recorded in fix-patterns.md), and one JSDoc
@returns used optional-property {...?: ...} type syntax the parser rejects (simplified).
Added JSDoc (the tool) for the code API — corrected course from Doxygen
Course-correction: when the owner picked the doc approach they also asked "can we use JSDoc then" — I
ran with Doxygen file-level and answered the JSDoc part only in prose, which was the wrong read. Owner
flagged it; pivoted to set up JSDoc the tool. The good news was that the @file headers already
written are tool-agnostic JSDoc comments, so they carried straight over — only a thin config layer was
new.
- Added
jsdoc(4.0.5) devDependency,jsdoc.config.json(source:src+data+README.md, excludeslib/and*.min.js, outputdocs/jsdoc/, README as homepage, markdown plugin), and thenpm run docs:apiscript. Git-ignoreddocs/jsdoc/. - Builds clean (exit 0): 169 pages, one per file, README homepage, the
@fileoverviews rendered. - Honest limitation noted: like Doxygen, JSDoc renders file-level here because the functions carry
@fileheaders but not per-function@param/@returns. The ESM-native advantage (extracting the named exports — helpers,core/factories, prompt-modules) only materialises once those get function-level JSDoc — offered as a follow-up rather than charging ahead. - Division of labour recorded in
documentation.md: Doxygen = living-notes site + GitHub Pages; JSDoc = code API. Both output dirs git-ignored.
Verified green: npm run lint (0 errors), npm run format:check, npm run smoke, npm run docs:api.
Comprehensive Doxygen file-level docs + tooling exclusion fix
Owner asked whether we could give full Doxygen support (every file, comprehensively, taking the notes into account) — or whether Doxygen is the wrong tool. Probed it empirically and delivered the realistic, tool-honest version.
Assessment. Doxygen runs clean and hosts the notes well, but its JS parser cannot extract this
code's symbols — the generators are anonymous export default function () {…}, and Doxygen documents
zero functions for them (confirmed: city.js's File Reference page lists none). So a per-function API
reference isn't achievable without rewriting ~120 plugins to named exports (out of bounds — doc passes
are comment-only). The achievable, comprehensive form is file-level: a @file @brief on every file,
with the conceptual depth living in the notes pages. (If real per-function JS API docs are ever wanted,
the no-TypeScript option is JSDoc-the-tool or TypeDoc alongside Doxygen — recorded in documentation.md.)
What was done (all comment-only on the source side):
@file @briefon every authored.js— 44 hand-written rich module headers on the core-logic files (entry points, settings, loaders,genImg, prompt-modules, helpers,core/,indexImages, each pointing to its notes page) + 113 dynamic-prompts + 8 frontend scripts + 3data/process-*.js, via two idempotent insert scripts. 165/165src/files + 3/3 data scripts covered; vendoredlib/*.min.jsleft untouched.- Doxygen warnings 7 → 3. Fixed:
list-credits.mdM\Cooper(escaped), aprompt-dsl.mdin-page anchor, twosessions/README.mddirectory links, and anesm-patterns.mdquirk caused by inline code spans wrapping across line breaks (Doxygen won't pair a single-backtick span across a newline — joined them onto one line). The 3 remaining are benign: one Doxygen markdown quirk (renders fine) and the README's two TOC anchors (GitHub-valid;{#}braces would uglify the public README). - Caught + fixed a latent breakage I introduced earlier: the pinned
assets/references/snapshot is gitignored but ESLint/Prettier/Doxygen still walk the filesystem, so they were indexing the old CommonJS/jQuery clone → 569 phantom lint errors and a polluted doc-site. Excludedassets/in all three (eslint.config.js,.prettierignore,Doxyfile) and restored the snapshot from its own.git. Gitignored ≠ tool-ignored — recorded infix-patterns.md. - Two
@filebriefs contained/*(presets/*.json,output/*.json) which opened nested comments and broke the JSDoc block — reworded. Also infix-patterns.md.
Verified green: npm run lint (0 errors, 165 warnings — baseline), npm run format:check (clean),
npm run smoke (full graph + all prompts), and npm run docs (exit 0, 3 benign warnings). Comment/docs
/tooling only — no runtime code change, so no VERSION move.
Full file-by-file read of the whole codebase + per-layer notes deepened
Follow-up to the request below: the owner clarified the real ask was to understand the entire
project — every file, every macro and micro system — not just verify intactness. Did a genuine
end-to-end read (canonical src/ tree, since the ESM port is behavior-preserving): all settings/boot
files and the variation/reroll/animation loaders; genImg.js, every helpers/*, and all of core/;
server.js (every route), web/backend/indexImages.js, all eight web/frontend/*.js, and every Pug
view/layout/fragment; all 113 dynamic-prompt generators (top-level + v1/ + user-submitted/); and
the data/ build scripts + sources + expansions + presets.
Notes added/deepened from that read:
- New reference
notes/reference/dynamic-prompts.md— the generator catalog & authoring idiom: probabilistic-accretion style, full vs partial classification, theentitypolymorphism, the three random engines (random/random-prompt/simple-random-prompt/extra-random-prompt), the v1-monolithic → v2-composable decomposition story, the publicprompts.art provenance, and thedata/process-*.jslist-build pipeline (artists.csv / danbooru.csv / nai json →data/lists/). Wired into_nav.dox. - Deepened
notes/systems/server.md— added the image lifecycle & metadata deep-link graph: the per-image.jsonsidecar fields (variationOf/rerollOf/upscaleOf/animationFrameOf/animationOf/origPrompt/origPostPrompt/origRandomPrompt/cmd), howindexImages.jsinverts them into the deep-link map, upscale promotion, the five run modes, animation externalization for AI interpolation, and the ImageMagick conversion paths.
The existing cli.md / core-engine.md / web-app.md / overview.md were confirmed accurate against
the full read — no corrections needed. Notes-only; no VERSION move.
Deep-read of the original (pre-revival) design + notes enrichment
Owner asked to go through the whole project and understand all its macro and micro systems — specifically as it was before the recent revival — noting that a lot of work went into the original and that asking for the ESM refactor before this understanding was captured may have undersold it. Scope (chosen via the question prompt): document the original design depth and dig into the pre-revival git history; living notes updated as default.
What the git history showed: the project is overwhelmingly an original Dec 2022 (~178 commits) +
Jan 2023 (~160 commits) effort, tapering through Mar–Apr 2023, then dormant until the 2026 revival
(14 commits). The original was a flat CommonJS tree; the src/+data/ split is a 2026 reorg
artifact. The Jan-2023 arc in particular built the full WebUI Generate tab, the full/partial
dynamic-prompt classification, animation/APNG + frame-extension, the self-healing image index, and the
rebuild of the dynamic-prompt expander into the up-to-10-levels recursive form.
Read in depth (canonical pipeline): common.js (processBatch/run), applyArgs.js, all five
prompt-modules/*, the random{Emphasis,Editing,Alternating} + keywordRepeater helpers,
listFiles.js, promptFilesAndSuggestions.js, and the core/ browser re-port — confirming the notes'
macro picture is accurate and complete.
Changes made:
- New reference
notes/reference/prompt-dsl.md— the prompt mini-language documented in full: the pipeline order, the four sigils (<expansion>/#dynamic-prompt/{list}/{salt}), the per-engine emphasis math (SD parens/brackets, NAI{}, Midjourney::factor), editing (in/swap/out), alternating, chaos scaling, aliases, once-only depletion, auto-fx/artists, danbooru substitution, LoRA-safe expansion, and the#randomsuggestion builder. Wired into_nav.dox(Reference, first entry). - Enriched
notes/context/history.md— replaced the thin "2022 origins" paragraph with an accurate account of the original build's scale and arc (Dec 2022 → Jan 2023 → Mar–Apr 2023), the original flat layout, and a pointer to the pinned snapshot + the new DSL reference. - Pinned a read-only original snapshot at
assets/references/og-pre-revival-2023-04-07-241a148/— a local clone checked out at241a148(the last pre-revival commit), gitignored via the existingassets/references/policy, keeping its own.gitso the original source + history can be referenced directly without disturbing the modernized tree.
Intactness verification (against the pinned snapshot). Rather than assert "nothing was lost" from a spot-check, ran a real diff of the original tree vs. current:
- No files dropped. Per-category basename comparison: dynamic-prompts 113=113, prompt-modules 5=5,
lists 61=61, expansions 9=9, presets 26=26, web 34=34, all 7 root JS present. Helpers went 10→11 — the
one addition is the new browser-safe
aliases.js; none removed. - Curated content intact. All 96 data files (
lists/+expansions/+presets/) match the original line-for-line — no list was truncated or edited by the refactor. - Logic preserved. Of 158 shared
.jsfiles, 98 are byte-identical after normalizing away ESM/comment/semicolon/whitespace differences. The remaining 60 were inspected viagit diff --ignore-all-space: all are Prettier reformatting (redundant-paren/brace removal, single→double quotes, line collapsing) or deliberate, understood revival refactors — loader injection inpromptFilesAndSuggestions.js/prompt-modules/{list,dynamic-prompt}.js(browser port) and the./data/...path updates insettings.js.promptFilesAndSuggestions.js's current exports are a strict superset of the original (addedconfigure, removed nothing).
Conclusion: the ESM modernization is behavior-preserving — the original engine, all 113 dynamic-prompt plugins, and all curated content survived intact.
Notes-only session — no code touched, so no VERSION move.
Toolchain refresh + web SPA trimmed to the Build tab (v2.0.1)
Owner asked for convenience npm run scripts to launch the SPA from the repo root, then to bring the
(surprisingly out-of-date) dependencies up to latest, managing versions + commits per the established
defaults.
- Root run-scripts: added
web/web:dev/web:build/web:preview/web:install— each proxies toweb-appvianpm --prefix web-app …. - Dependencies → latest. Root:
eslint9→10,@eslint/js9→10,globals16→17,lodash4.17.21→4.18.1. web-app:vite6→8,@vitejs/plugin-react4→6 (react/react-dom already current). - ESLint 10 fallout. Its newly-
recommendedno-useless-assignmentturned 6 benign init-then-overwrite spots (src/server.js×3,src/web/backend/indexImages.js×2,src/web/frontend/single.js×1) into errors. Demoted it towarnineslint.config.js— behavior-neutral, consistent with the existingno-dupe-else-if/no-useless-escapestance. Tracked inplans/next-steps.md. - Web SPA: trimmed the nav to just the Build tab (Generate/Settings commented out of
web-app/src/App.jsx, components left on disk) while the UI is being reworked. - Version: PATCH bump
2.0.0 → 2.0.1.
Verified green (PowerShell): npm run lint (0 errors, 165 warnings — all pre-existing/demoted),
npm run smoke, npm audit (0 vulns), and npm --prefix web-app run build (Vite 8, 251 modules).
Process note: the first commit attempt accidentally swept the pre-staged reorg index into a mislabeled commit; caught immediately (nothing pushed —
origin/devwas behind), undone withgit reset --mixed, and redone as clean, separately-staged commits.
CI shakeout (the Vite 8 upgrade had two CI-only failures, both fixed):
npm cirejected the web-app lockfile —npm installon Windows had dropped the Linux-only@emnapi/*+rollup-linuxoptional transitive deps. Clean lockfile regenerate restored them.- Vite 8 bundles with Rolldown, which makes an unresolved import a hard error (Rollup only
warned). The browser graph's repo-root
src/filesimport _ from "lodash", unresolvable on a clean checkout (CI/Netlify don't install the repo-rootnode_modules). Fixed by pinninglodashto the SPA's own copy viaresolve.aliasinweb-app/vite.config.js— verified by building with the repo-rootnode_modulestemporarily removed.
Reorganized the tree: all code → src/, all prompt content → data/
Goal (owner): "move the code into a src folder" — settle on a clean split: all code under src/,
all prompt content (data) under data/, runtime/user data left at the repo root.
What moved (via git mv, history preserved):
- Code →
src/: the entry points (index.js,server.js,common.js,chdir.js), the four*-settings.js, andhelpers/,core/,prompt-modules/,dynamic-prompts/,web/— joining the loaders already insrc/.dynamic-prompts/andprompt-modules/are executable.js(they import helpers / run logic), so they count as code, which also kept their loader + helper imports intact. - Data →
data/:lists/,expansions/,presets/(joining the existingdata/CSV sources +process-*.js). - Stayed at root:
output/,user-settings.json,results.json(runtime/user data),default-user-settings.json, and all config.
Path rewiring (the careful part — createRequire/globs resolve relative to files, not cwd):
src/chdir.jsnowprocess.chdir(path.join(import.meta.dirname, ".."))so cwd stays the repo root (it lives one level down now). Data dirs centralized insrc/settings.js(listFiles/expansionFiles/presetFiles→./data/...);dynamicPromptFiles/promptModuleFilesstay relative tosrc/.server-settings.jswebFolder→"./src/web".src/core/nodeLoader.js:rootDirnow the repo root (../../), readingdata/lists,data/expansions, andsrc/dynamic-prompts.src/core/browserLoader.js: Vite globs →../../data/...for lists/expansions/presets (dynamic-prompts glob unchanged — still a sibling undersrc/).- Existing
src/loaders:../<moved>imports →./<moved>; entry points:./src/X→./X; the two random-prompt dynamic prompts:../src/...→../...;data/process-*.js:../settings.js→../src/settings.js;web-app/src/lib/promptEngine.js:../../../core/...→../../../src/core/...;scripts/smoke-test.mjs:../common.js→../src/common.js. - Config:
package.jsonmain/start/server/webui→src/...;DoxyfileINPUT→src+web-app/src;eslint.config.js+.prettierignoreweb-frontend globs →src/web/frontend;webui.bat→node src/server.
Verified green (PowerShell): npm test (lint 0 errors + smoke expands a prompt using
src/dynamic-prompts + data/lists), npm --prefix web-app run build (271 modules — proves the
browserLoader globs resolve to data/), server-only imports load, npm run format:check clean, and
doxygen Doxyfile builds (6 pre-existing warnings only). Had to stop a running Vite dev server whose
file watcher was locking core//dynamic-prompts/ during the move (restart with npm --prefix web-app run dev).
Brought the project-management system up to parity with the sibling project
Goal (from the owner): give random-ai-prompt the same management system as the sibling
pokered-save-editor-2 — same living-notes depth, folder structure, Doxygen doc-site, versioning, and
git/CI/release management — adapted to this Node/ESM + web stack. (The sibling was read-only reference;
all changes landed here.)
What changed:
- Folder conventions. Added
tmp/(transient scratch/logs),assets/references/, andassets/staging/— each with a keep-the-dir.gitignore. Extended root.gitignorefor/_*.log//_*.bat//_*.shhelper artifacts anddocs/html/(generated docs). - Living notes — per-layer system map. Added
notes/systems/README.md(hub) and per-layer deep-divescore-engine.md,cli.md,server.md,web-app.md(overview.md stays the macro view). Addednotes/reference/documentation.md(the Doxygen doc-site + JSDoc house style) andnotes/reference/deployment.md(Netlify + the GitHub Actions pipelines). - Doxygen doc-site. Added a root
Doxyfile(adapted for JS: source roots + thenotes/tree as pages,AUTOLINK_SUPPORT = NO,HAVE_DOT = NO), the vendoreddocs/doxygen-awesome/theme, andnotes/_nav.dox(the page-hierarchy hub; READMEs carry explicit{#labels}).npm run docsbuilds it. - CI / release. Added
.github/workflows/:ci.yml(lint + format check + import smoke test + SPA build),pages.yml(Doxygen → GitHub Pages onmaster), andrelease.yml(version-gated GitHub Release: source tarball + docs zip, notes composed from the changelog). Netlify still deploys the SPA. - Verification. Added
scripts/smoke-test.mjs+npm run smoke/npm test/npm run docsscripts (the import smoke test mirrors the server boot path). - CLAUDE.md. Expanded the Default Workflow (green-gated
masterFF, docs regen,ghchecks on shipment), added a GitHub-management section and a "keeplist-credits.mdliving" note, and added doc-site /_nav.doxtriggers to the maintain-the-notes table. - Versioning. Documented the release-tag / version-gate relationship and the
web-app/package.jsonsync inreference/versioning.md(the SemVer +VERSION↔package.jsonscheme was already in place).
Note: the Cowork bash sandbox serves a stale/truncated view of this repo (it read package.json as
36 lines/969 bytes vs the true 42), so lint/format/smoke could not be run here — finalize on the dev
machine with npm run format && npm test before committing (the normal Default-Workflow step). Prettier
was scoped to code/config (*.md/*.dox ignored) so format:check stays green on the compact-table notes.
Modernized the project to ES modules + Node 24, and set up the notes system
Two big things happened today: the codebase was modernized, and the AI/notes system was created.
ESM + Node 24 + dependency modernization
Goal (from the project owner): bring the old 2022 CommonJS project up to the latest Node LTS, take all packages to their current majors, and clean/refactor the code — "full ESM + restructure, latest majors, breaking changes OK, commit on dev."
What was done:
- Confirmed the target: Node 24 is the active LTS in June 2026 (24.x "Krypton"); the dev
machine has Node 24.12.0, which can
require()ES modules synchronously — the key fact that made the config-driven plugin loaders convertible without going async. package.json:"type": "module",engines.node >= 24, realscripts, deps bumped to current majors (Express 5.2, yargs 18, open 11, cli-progress 3, crc 4, compromise 14, lodash 4, pug 3),node-fetchremoved. Added@eslint/js/eslint/globals/prettier/eslint-config-prettieras devDeps.- Bulk conversion (~123 files) via two throwaway Node codemods:
module.exports = function→export default function,module.exports.full/suggestion_exclude→export const, andconst x = require("y")→import x from "y.js"(withnode:builtins and.jsextensions). Zero leftovers reported; the codemods were deleted afterward. - Hand-conversion (~28 core files): entry points, the
src/loaders, and the named/default-export helpers. See the changelog andreference/esm-patterns.mdfor the specific gotchas. - Verification:
node --check(152 files, 0 errors),npm run lint(0 errors), Prettier pass, and an import smoke test that loaded the full graph + all 113 dynamic prompts (viarequire(ESM)), ranpromptSuggestion(), and expanded#random. All green. Live image generation needs an SD WebUI and was not run.
Root-cause notes captured for reuse:
- ES-module import ordering vs
process.chdir. Imports are evaluated before top-level statements, so the oldprocess.chdir(__dirname)at the top ofcommon.jswould have run after the settings module imported and read./user-settings.json. Fixed by extracting the chdir intochdir.jsand importing it first. (Seereference/esm-patterns.md.) createRequirefor synchronous, config-driven plugin loading. Dynamic prompts/prompt modules are loaded by runtime path inside synchronous string-replace callbacks;await import()would have meant rewriting the pipeline.createRequire(import.meta.url)+.default(...)preserves behavior exactly.- Default vs named exports had to match consumers:
listFiles.jsstays a default object (dynamic indexing);keywordRepeater.jsis named exports (destructured).
Notes / AI system
Set up CLAUDE.md + the notes/ tree (this file's home) + a VERSION single-source-of-truth, modeled
on a sibling project's structure but adapted from a C++/Qt app to this Node project. Purpose: any AI or
human can open the repo cold and be oriented.
Working-environment note
The Cowork bash sandbox reported a false file truncation on package.json and can risk data loss;
switched to PowerShell + the file tools for everything. Recorded in reference/fix-patterns.md so it
isn't rediscovered.