Imported from srm985/reflecta-mono (
AGENTS.md). Install upstream withnpx skills add srm985/reflecta-mono. Copyright stays with the author.
AGENTS.md
Repository operating model
Reflecta is an npm workspace monorepo for a web application.
Workspace paths:
packages/reflecta-backendpackages/reflecta-uipackages/reflecta-components
Top-level intent:
packages/reflecta-backendis the Node.js / TypeScript / Express backend.packages/reflecta-uiis the React / TypeScript web UI.packages/reflecta-componentsis the shared Storybook component package consumed by the UI through Module Federation.
Concrete repo details:
- This repo uses npm workspaces from the root
package.json; there is no pnpm/yarn workspace file. - Root scripts include
npm run develop,npm run lint,npm run lint:fix,npm run storybook,npm run pre-commit, andnpm run pre-push. - Package scripts are workspace-scoped, for example
npm run lint -w reflecta-ui,npm run build -w reflecta-components, andnpm run build -w reflecta-backend. - There are no test files or test scripts currently visible; use package lint/build plus targeted manual validation unless tests are added later.
- The devcontainer runs a workspace service plus MySQL 8.4, forwards
3000and3100, and the components dev server commonly uses3003while Storybook uses6006. .envfiles exist in each package and can contain real secrets. Inspect variable names only unless the user explicitly asks for values.
Generated and runtime-sensitive paths:
packages/reflecta-components/declarationsis generated by the component package build.packages/reflecta-ui/src/components/remotesis generated by the UI webpack build from component declarations.packages/*/distcontains build output.packages/reflecta-backend/static/ecosystem.config.jsis PM2/deployment-adjacent and points at/var/www/api/src/app.js.
Important package coupling:
reflecta-componentsexposes non-_internalcomponent directories through Module Federation asremoteEntry.jsusing container namereflecta_components.reflecta-uiconsumes the component remote using thereflecta-components-module-federationkey andFEDERATED_COMPONENTS_URL.- Component props are a public compatibility boundary; changes often require updates in
reflecta-uiand Storybook stories. - Backend API responses are manually mapped from snake_case database rows to camelCase UI-facing objects. Keep UI slices/views aligned with backend route changes.
- Authentication uses a split JWT: backend stores header+payload in a cookie and the UI sends the token signature as a bearer token.
Treat the codebase as one connected web application. Even when a requested change appears local, consider package boundaries, shared contracts, module-federated component behavior, build output, and deployment impact.
Default behavior
- Cross-package changes are allowed when needed to keep the application consistent.
- Prefer the best solution you can confidently implement, not blindly the smallest diff.
- If a minimal diff is clean and sufficient, use it.
- If the quickest implementation would introduce noticeable tech debt, either refactor or clearly call out the tradeoff.
- Suggest follow-up cleanup when it would materially improve maintainability.
Reasoning guidance
- Default to medium reasoning for routine implementation and local changes.
- Use high reasoning for changes that affect multiple packages, API contracts, Module Federation boundaries, authentication, data loss risk, build behavior, PM2 process management, or deployment behavior.
- Prefer medium or low reasoning for mechanical cleanup once the intended change is clear.
- Keep response verbosity medium by default; be concise for routine status updates and thorough when summarizing risks, contracts, validation, or follow-up work.
Change boundaries
- Avoid creating new files if an existing file or established pattern can absorb the change cleanly.
- Avoid renaming or moving files unless explicitly approved.
- Avoid adding dependencies unless explicitly approved.
- Avoid changing root tooling, workspace configuration, build configuration, or deployment configuration unless truly required, and discuss the impact first.
- Prefer modifying existing code over introducing new abstractions unless a new abstraction clearly improves the design.
Architecture and type system rules
Strongly prefer a single source of truth for types.
- Prefer imported, shared, derived, or indexed-access types over creating new parallel local types.
- Prefer
typealiases overinterfacefor new TypeScript shapes. Useinterfaceonly when declaration merging, extending an existing interface, or an established local pattern makes it the clearer choice. - Derive types with
Pick,Omit, extension, composition, indexed access, and existing package exports before creating a new type. - If a new type is truly required, define it robustly and reuse it consistently.
- If a shared contract changes, update affected producers and consumers together when appropriate.
- Avoid duplicating request, response, model, or DTO shapes across packages when a shared type is appropriate.
- Keep backend API contracts, UI API clients, and component props aligned.
Function, component, and type declaration rules
- Functions and components should have types.
- Do not create ad hoc inline types directly in function signatures.
- For React components, prefer colocated
types.tsfiles when that is already the local pattern. - Otherwise, keep types in the same file or move them to a shared/local
types.tswhen reuse justifies it. - If a local type is introduced, use it consistently rather than recreating equivalent shapes elsewhere.
- Prefer named
typedeclarations instead of inline object/function signature types.
Code style preferences
Optimize first for readability and self-documenting code.
- Prefer early returns and guard clauses over nested conditionals.
- Avoid nested ternary operators.
- One-line ternaries are fine when they remain easy to read.
- Chained expressions are good when readable. Keep short chains on one line and break longer ones cleanly.
- Avoid needless helpers. Do not extract tiny helpers unless they clearly improve reuse or readability.
- Avoid spaghetti code and deep chains of functions that primarily call other single-use functions. Prefer a direct, readable flow unless abstraction materially improves reuse, testability, or understanding.
- If a utility is needed, keep it focused to a single responsibility.
- Prefer clear, descriptive names over abbreviations.
- Do not destructure values in function parameters. Destructure inside the function body.
- Prefer
export defaultwhere it aligns with the existing pattern. - Avoid inline single-line conditional statements that reduce readability.
- Prefer pure functions where practical.
Formatting preferences
Follow existing repo formatter, ESLint rules, and local file patterns.
Current formatting/tooling facts:
- ESLint is Airbnb-based with TypeScript support.
- Indentation is 4 spaces, trailing commas are disallowed, object keys and imports are sorted, and object/array newline rules are strict.
- Root TypeScript config is strict; backend overrides to CommonJS/Node resolution while UI and components use ESNext modules and webpack aliases.
In addition:
- Avoid unrelated reformatting.
- Preserve explicit import ordering rules.
- Keep formatting changes scoped to the work being done.
- Avoid introducing stylistic churn that breaks from the existing code style unless there is a strong reason, and call it out when you do.
- If a clearly better local pattern exists, you may propose it, but do not silently impose repo-wide style changes.
Comments and documentation
- Comments are welcome when they improve clarity.
- Write comments from one developer to another.
- Prefer “we” phrasing when appropriate.
- Preserve existing comments and TODOs unless they are clearly obsolete.
- Do not add noise comments that simply restate the code.
Competing patterns
If you find competing patterns in the repo:
- follow the existing local pattern for the area you are changing,
- identify the inconsistency,
- propose a more consolidated direction if it would help,
- do not perform broad unrequested standardization unless explicitly asked.
Backend rules
For packages/reflecta-backend:
- Preserve Express, routing, middleware, controller, service, and validation patterns already present in the package.
- Keep request and response boundaries explicit and typed.
- Keep handlers and route flows direct unless abstraction materially improves reuse, testability, or understanding.
- Prefer shared or exported contract types over backend-local copies when the UI or component package also depends on the shape.
- Reuse existing logging, error handling, configuration, and response helpers where they exist.
- Be conservative with environment-variable contracts, authentication/session behavior, process lifecycle behavior, and deployment-adjacent code.
UI rules
For packages/reflecta-ui:
- Preserve React, routing, state management, form, fetching, and styling patterns already present in the package.
- Keep components small and presentational where practical.
- Keep API interaction out of presentational components when an existing client, hook, or state-management pattern is available.
- Prefer shared contract types when UI behavior depends on backend data shapes.
- Do not hard-code Module Federation remote URLs, backend URLs, or deployment-specific hostnames when existing configuration or environment wiring should be used.
- Keep federated imports from
reflecta-componentsaligned with the exposed public API of that package.
Component package rules
For packages/reflecta-components:
- Treat this package as a reusable UI compatibility boundary.
- Keep exported component APIs intentional, stable, and documented through Storybook where appropriate.
- Avoid app-specific backend calls or product workflow logic inside shared components.
- Prefer public exports over deep internal imports.
- If a component prop contract changes, update affected UI consumers in the same task when appropriate.
- Be careful with Module Federation exposes, shared dependency settings, and build output because changes can affect runtime integration.
Module Federation rules
- Treat Module Federation configuration as runtime-sensitive.
- Keep shared React dependencies singleton-compatible when that is the established configuration.
- Do not rename exposed modules, remotes, or public component exports unless explicitly requested or required by the task.
- When changing a federated component, validate both the component package build and the UI consumer integration when scripts are available.
- Call out any change that requires coordinated deployment of
reflecta-uiandreflecta-components.
Deployment and runtime caution
Reflecta runs as a web app on a Lightsail instance with PM2.
- Do not run live Lightsail, AWS, SSH, database, or production-changing commands unless explicitly approved.
- Be conservative around PM2 ecosystem files, startup scripts, ports, environment variables, reverse proxy assumptions, and build output paths.
- If a change affects runtime process names, startup commands, health checks, environment-variable contracts, or deployment behavior, explain the impact clearly.
- Never print secrets.
- Avoid printing raw logs or stack traces that may contain secrets or credentials.
Safety and approvals
- Do not install or update packages unless explicitly approved.
- Do not use destructive git commands.
- Do not create commits or branches automatically.
- Call out when a git checkpoint would be wise before a risky change.
- Do not read home-directory credentials such as
~/.aws,~/.ssh, or similar secret stores unless explicitly instructed. - Never print secrets.
Verification rules
Use best judgment, but follow these principles:
Useful commands by area:
-
Root:
npm run lint,npm run storybook,npm run develop. -
UI:
npm run lint -w reflecta-ui,npm run lint:js -w reflecta-ui,npm run lint:scss -w reflecta-ui,npm run build -w reflecta-ui. -
Components:
npm run lint -w reflecta-components,npm run build -w reflecta-components,npm run storybook -w reflecta-components. -
Backend:
npm run lint -w reflecta-backend,npm run build -w reflecta-backend. -
Prefer targeted validation over broad expensive validation when possible.
-
Run lint and typecheck automatically when appropriate and scripts are available.
-
Prefer lint fix when it is safe and clearly supported by the repo.
-
For backend changes, prefer backend lint, typecheck, and targeted tests.
-
For UI changes, prefer UI lint, typecheck, tests, and build validation when relevant.
-
For component changes, prefer component lint, typecheck, tests, Storybook validation, and build validation when relevant.
-
When shared contracts or federated components change, validate affected consumers in all impacted packages.
-
If a required script or command does not exist, say so clearly and stop rather than inventing a replacement.
-
Do not claim verification you did not perform.
Completion and summaries
In the final summary:
- clearly state what changed,
- mention whether you followed an existing local pattern or introduced a new one,
- call out assumptions,
- call out any contract, migration, deployment, or operational risk,
- list commands run,
- list commands not run when they were relevant,
- note any follow-up cleanup worth considering,
- mention when browser or deployment validation is still needed.
When the change touches multiple packages, summarize with cross-package impact in mind rather than treating each package in isolation.