Repository navigation
Harness in both subprojects, module docs aligned with the code, Markdown gate - #29
Merged
Merged
Conversation
- Add scripts/ to the directories the error-code scan skips: it walks the disk, not what git tracks, so the git-ignored scripts/update-fixture-expected.ts made it fail locally with its shift codes (PI, IT, FO) read as error codes - No tracked script sends error codes; they are CLI tools, not API responses, so the scan loses nothing
- Add backend/.nvmrc (22) and frontend/.nvmrc (24): fnm only reads the version file in the current directory, so both projects fell back to the open engines range and picked the newest installed Node (24) locally - Set engines.node to 22.x in backend and 24.x in frontend: Render builds the backend on 22.23.3 and Vercel builds the frontend on 24.x; the open >=22.16.0 range let Vercel auto-upgrade to the next major - Read each CI job's Node version from its project's .nvmrc: CI tested the frontend on 22 while production builds it on 24
- Add backend/pnpm-workspace.yaml with minimumReleaseAge: 10080, so a dependency version published less than 7 days ago is never resolved: most compromised releases are pulled from the registry well within that window - Bump packageManager from pnpm 10.13.1 to 10.28.0, the same as the frontend: minimumReleaseAge exists since pnpm 10.16 and an older pnpm ignores it without any warning - The lockfile is unchanged: a frozen install accepts it as is
- Add a verify script to the backend (lint with --max-warnings=0, format check, typecheck, tests): one command that runs the same gate locally and in CI, and eslint no longer passes with warnings - Make the backend CI job call pnpm run verify instead of four separate steps, so CI and the local check cannot drift apart - Use pnpm run <script> in the frontend CI job and in the backend README command table: the short form runs a pnpm built-in instead when a script name collides with one - Point the README's 'What CI runs' row at verify
- Add *.ps1 text eol=crlf to .gitattributes: Windows PowerShell 5.1 can misread scripts saved with LF only, and backend/db-mysql/backup/backup.ps1 is one - The repository copy stays LF, so no renormalization is needed; only the working copy on checkout changes
- Stop ignoring skills-lock.json: skills are rebuilt from it on every machine, while .claude/ and .agents/ stay ignored like node_modules - Add backend/skills-lock.json with the seven backend skills and their source and hash, so the three machines rebuild the same set
… from CLAUDE.md - Add backend/AGENTS.md with the harness layer 1, a declared exception (state and decisions stay in the root docs/, since backend/docs/ is git-ignored), its Security section (L3 plus the backend areas) and the owner's note on where the model goes wrong: backend is treated as its own project inside the repo - Add @AGENTS.md to the root CLAUDE.md and a one-line CLAUDE.md importing it next to backend/AGENTS.md and the 16 module AGENTS.md files: a CLAUDE.md in or above a directory turns off Claude Code's own reading of AGENTS.md, and a module AGENTS.md without a pointer was verified not to load - Root AGENTS.md: say that Claude Code reads it through the import instead of keeping CLAUDE.md in sync, note that the security level line is repeated in backend/AGENTS.md, and drop a duplicated Spanish fragment in the Security areas
- Add ADR-042, accepted: the harness is adopted per subproject starting with backend, with CLAUDE.md pointers next to each AGENTS.md; ADR-017 is marked as revised by it, since it had deferred the harness until the generator supported repos without a root package.json - TODO: remove 'check which Node Render uses' (its build log shows 22.23.3 via .nvmrc, and engines is now pinned) and 'check that Claude Code loads module AGENTS.md' (verified and fixed with the pointers) - TODO: narrow the harness item to adopting it in frontend and splitting the root AGENTS.md, and add moving the backend to Node 24 through preview
- Wrap rows in useMemo in DailyRevenueTab: data?.rows ?? [] built a new array on every render while there was no data, so lookupDate's useCallback was rebuilt each time and eslint reported it under react-hooks/exhaustive-deps; it is the only lint warning in the frontend and blocks a gate that fails on warnings
- Add frontend/pnpm-workspace.yaml with minimumReleaseAge: 10080, as in the backend, so a dependency version published less than 7 days ago is never resolved: most compromised releases are pulled from the registry well within that window - The frontend already pins pnpm 10.28.0, which supports the setting; the lockfile is unchanged and a frozen install accepts it as is
- Add a verify script to the frontend (lint with --max-warnings=0, format check, typecheck): one command that runs the same gate locally and in CI, and eslint no longer passes with warnings - Make the frontend CI job call pnpm run verify instead of three separate steps, as the backend job does, so CI and the local check cannot drift apart - Use pnpm run <script> in the frontend README command table and point its CI row at verify: the short form runs a pnpm built-in instead when a script name collides with one
- Add frontend/skills-lock.json with the fifteen frontend skills and their source and hash, so the three machines rebuild the same set; .claude/ and .agents/ stay ignored like node_modules
- Add frontend/AGENTS.md with the harness layer 1, the same as in backend/AGENTS.md, and frontend/CLAUDE.md importing it: frontend is treated as its own project inside the repo, as ADR-042 set for backend - Declare the exception to rules 12 and 13 (state and decisions stay in the root docs/, since frontend/docs/ is git-ignored), so no frontend/docs/ is created - Add a Security section with the L3 line shared with the root and backend AGENTS.md and the frontend areas (auth and route protection, UI-only role gating, API clients, client-side uploads, personal data, CSP and markdown rendering, configuration), so the security agent reviews the frontend against its own paths - Add the owner's note on where the model goes wrong: several tasks in one prompt are worked one at a time
- Keep in the root only what both subprojects share: Context7 policy, Markdown formatting, commits and hooks, the security level, a new frontend-backend contract section and the module map, so each side's details load where they apply - Move each side's stack, installed versions, commands, architecture, auth and messaging paths into backend/AGENTS.md and frontend/AGENTS.md, each with its list of module docs, so the subproject links down to them - Drop the root scheduling section: all of it was already in the three scheduling module docs - Point the root Security areas at the lists both subprojects already carry, so there is a single list per side - Explain how the levels load: OpenCode reads only the first AGENTS.md walking up from where it starts, so the files link to each other; drop Codex, which is not used - Fix what had gone stale while moving it, checked against the code and the lockfiles: the demo-admin role and disabled demo user (ADR-038), the pool in config/config.ts (it is config/db.ts), a Vercel preview pattern in CORS that does not exist, mysql2 in the frontend, the debug-*.js scheduling helpers that do not exist, and the full script lists (verify, typecheck, setup:local)
- Open every module AGENTS.md with an Up line to its subproject AGENTS.md (both, when the doc covers both sides) and to the root, because OpenCode only loads the first AGENTS.md it finds and a module doc otherwise has no way back to the shared rules - Point cross references at AGENTS.md instead of the one-line CLAUDE.md that imports it, which tells a non-Claude client nothing - Scheduling solver: refer to backend/services/scheduling/AGENTS.md for the end-to-end view and the cross-language constraint guide, which no longer live in the root - Reflow the touched files with Prettier, as the repo rule asks for Markdown edited on purpose
…O item - Add ADR-043: the root keeps what is shared, each subproject its own context, and the three levels link explicitly, because OpenCode reads a single AGENTS.md - TODO: remove the frontend harness item; both halves are done - SESSION: decisions up to ADR-043 and the current harness state
- Root, backend and frontend AGENTS.md: OpenCode 1.18.12 loads every AGENTS.md from where it starts up to the repo root, plus a module one when it reads a file there; the earlier text said it loaded only the first, read from its docs instead of its source - State what neither client does: load the other side's AGENTS.md, which is what the cross links are for - ADR-043: fix the motive accordingly and reject declaring instructions in opencode.json, since OpenCode already loads the root - Add revert to the root commit types, as the harness layer 1 lists it - Drop the PowerShell code search section, which agents do not need
- Layout: the frozen baseline ends at 20_checklist.sql, and scripts/ also holds the local helpers and scheduling-seed.sql sits next to the mock, so the tree matches the folder - Reconstruct from scratch: point at pnpm setup:local and say what it runs, since MASTER_INSTALL.sql by hand fails on the two baseline bugs the script patches in memory - Flag recreate-local.sh as older and narrower than setup:local - Aiven: the credentials come from backend/.env; aiven-conexion.md no longer exists - Table count: 67 declared plus 3 views, not about 50
- Constraint signatures: only the cross-month constraints take virtual_days_by_emp, and locked_cells takes emp_idx_by_id, so the doc no longer promises one shared signature - Node client: the daemon has idle, starting and ready phases; the semaphore, not a busy phase, serializes requests - day_blocks: the minimum block is the MIN_SHIFT_BLOCK constant, not a config value - H4/H5 debt: say where the TS validator actually drifts (H4 counts the previous streak without the exemption, H5 checks no cross-month window) - Local setup: install from requirements.txt, which pins what Render installs through pnpm build; the TODO section the doc pointed to no longer exists
- Validator: validate() registers only the coverage and employee-rules classes; H2, H4, H5 and the libre counts run inline in runFinalValidation (H4 and H5 inside the month only, H5 and the libre limits as warnings), and the other four classes are only used by the unit tests. The doc presented those classes as the live rules - Solver doc: correct the H4/H5 drift written in the previous commit, which described the unused class instead of the live validator - Access: the router is admin only; a published month answers 409 to edits, it is not a read-only view for staff - Generation: name the 404/409/422 checks, and say that approved requests and fixed days are inserted without source_constraint_id, so they are editable afterwards, and that libre numbers are recalculated - Deleting an approved constraint unlocks its cells (ON DELETE SET NULL) instead of removing them - setSchedulableEmployees no longer loses dates: drop the known-bug note - Endpoints: PUT for assignments and approvals, /rules and /employees, and the real middlewares; one repository function name - Daemon phases: no busy phase, the semaphore serializes - Flag soft-weight @emitter tags that point at the unused classes
- Access is admin only in the layout too, not admin and group-admin - PDF export uses pdf-lib, not jsPDF with autotable - PresenciasTab converts a schedule pasted from Excel; it is not an editor for P employees. shift-stats and presencias have no tab button and are reached by URL only - Drop lib/scheduling/server.ts from the tree (removed on 2026-10-02), the DashboardLayout that never existed, and the setSchedulableEmployees bug, which is fixed - Names: getMonthById, downloadSchedulePdf(monthData), formatLocalDate in config/utils/date.ts, dictionaries in messages/<locale>/ - An infeasible result opens a modal, not the warnings banner; cells a generation fills from requests or fixed days stay editable - The iOS DayPicker workaround is a suggestion, not applied in the code - Fix the parking reference path
- services/parking/ holds target-spot.ts, and parking.repository.ts handles availability, not invoice metadata - parking_availability is also extended by a cron job at startup and daily at 03:00, not only by the triggers - Only booking status and payment method are duplicated in the frontend constants; flag that SpotType in models/parking does not match the spot_type ENUM - GET /bookings: document quickFilter and the date-range mode, and page + limit pagination instead of limit + offset
- The frontend constants copy only booking status and payment method, not source, spot type or level - React Query is used by useParkingStatus and the dashboard, with local keys; the bookings list keeps its data in state and calls parkingApi directly. Use the real method names (getAllSpots, getAllBookings) - Pagination is page + limit (50), and the list is server-rendered for the requested page, not page 0 - No trend charts and no invoicing on either side: drop "coming soon" and the backend PDF toggle that no longer exists - Mantenimiento sees the nav link; the backend answers 403
- The list of days and a shift's history need canViewReports (admin), not just any role - Add the eight endpoints the doc missed (vouchers active, stats and detail, payment summary, update and delete of single payments and denominations) and drop POST /vouchers, which does not exist - A shift is deleted unless closed, not only when open; vouchers are justified, cancelled or deleted only from pending - can_close also requires the day to be open; the totals path is recalculateTotals then updateDailyTotals - Replace the shifted roleCheck line numbers with the middleware names and roles
- Routes: /dashboard/cashier is an overview page, not a redirect; the layout belongs to hotel/, and there is an error boundary - PDF: exportDailyToPdf(daily, selectedDate, labels, shiftType) exports the active shift plus a day summary and downloads it itself; only DaySummarySidebar calls it, and ExportLabels lives in that file - Use the real hook and selector names (useUpdateDenominations, useUpdatePayments, useLogsFilters, useReportsDate...) and add the ones the doc missed; drop the HistoryStats component, which does not exist - The overview, reports and logs read admin-only endpoints and the UI does not gate them; the demo-admin role no longer exists - Dictionaries live in messages/<locale>/
- Drop the email service: email-service.ts and nodemailer were removed on 2026-10-02, and manual notifications are in-app only - Document payment-rules.ts (payment coherence, 2026-10-11) and that the recalculation runs from PUT /:id in group-controller - Contacts: /contacts and /contacts/primary need canViewGroupContacts, and the history hides contact entries from mantenimiento (2026-10-12). Flag that GET /:id still returns contacts to every viewing role - Deleting a group keeps its history since the 2026-10-11 migration - Status sync happens in the repositories, both ways - Route order: the global payment routes come after GET /:id and only work because /:id matches one segment - Replace the shifted roleCheck line numbers with names and roles
- Hooks: list the ones that exist; the list, group create/edit/delete, the status cards and the history call groupsApi directly. Six hooks the doc named (useGroups, useCreateGroup...) do not exist - Cache keys come from groupsKeys; the server action lives in groups/actions/, not under [id] - NotificationModal creates an in-app notification, now or scheduled; there is no email preview or SMTP - Contacts are gated in the UI since 2026-10-12 (tab hidden, URL falls back to the summary); flag that the detail still carries them - Store fields, component sizes, cards/ and StatusTimeline; dictionaries in messages/<locale>/
- Images are private (authenticated) since 2026-10-04 and served by the backend through GET /:id/images/:imageId/file; document the route (16 routes, not 14) and private-files.ts - Uploads go through requireStorage and the shared imageUpload middleware, not a multer config in the routes file - The history action is an ENUM column, not a CHECK constraint - useMaintenanceList takes one options object; the keys factory lives in its hook file - canAccessMaintenance no longer lists demo-admin - Update the file sizes
- Photos are private since 2026-10-04: the entry stores API paths (/api/blacklist/images/<file>), upload returns that path, and GET /images/:file signs and sends the file on the server. The doc still described Cloudinary URLs in the row - Upload checks the file bytes and the 5 MB limit; list services/uploads - CloudinaryService is shared by auth, backoffice, maintenance and checklist, not only backoffice - Frontend: add the server actions folder, Highlight.tsx and the current file sizes
- Invoice transitions are enforced: every UPDATE carries the status it starts from, and editing needs pending. The doc still warned that any status could move to any other. Add unpay (paid -> validated) - isRealAdmin does not exist; the routes use isAdmin - PDFs, stamps and signatures are private files: uploads go through requireStorage and backofficeUpload.ts (10 MB, real PDF bytes), downloads through fetchStoredFile, assets through /assets/:id/file, and backoffice-files.ts swaps the signed URLs for API paths - Frontend: the tabs use React Query after the server render; add the lazy tabs, the modals and PdfEditorModal, which stamps the PDF in the browser; the fourth tab is settings - AssetType is stamp | signature; CloudinaryService has five importers
- Attachments are private files: the client gets an API path from
attachment-response.ts and reads the file through
GET /attachments/:attachmentId/file; add both to the doc
- Uploads go through requireStorage and singleImage('file')
- Say what the optimistic toggle does, and update the file sizes
- useLogbooks takes one options object and also returns useReaders and the priority mappers; the mapping is defined twice (LogbooksList and useLogbooks) - The day is read from /day/:day, not ?day=; document the /all filters, include_trashed among them - Flag the open TODO item: trash, history and comments of deleted entries reach any role with access - Read/solve history is written by logbookReads-repository; add logbook-errors.ts and the current file sizes
- The parser now checks the PDF bytes, reads at most 20 pages and gives up after 15 s; failures throw FnbPdfError - A PDF with no tracked code also answers 422, and the upload has no requireStorage because the PDF is not stored - Update the file sizes; the import script does exist
- High: the group detail still returns contacts to maintenance, which the 2026-10-12 decision meant to keep from it - Medium: the scheduling rules H2, H4, H5 and libres exist twice and disagree; cells filled from approved requests and fixed days stay editable after a generation, pending a decision - Low: SpotType does not match the DB ENUM; the local solver venv runs another Python than production and has no pytest Found while checking the module AGENTS.md files against the code.
- Import pdf-parse/lib/pdf-parse.js instead of the package entry: v1's index.js runs a debug block when imported from ESM, which reads ./test/data/05-versions-space.pdf from the working directory, rewrites a .txt next to it on every boot, and crashes with ENOENT without it - Remove backend/test/, which only existed to feed that block; its PDF was a byte-for-byte copy of tests/fnb/fixtures/opera-revenue-sample.pdf - Add types/pdf-parse.d.ts, since @types/pdf-parse only types the entry - Explain both in the F&B AGENTS.md, where the folder was undocumented Checked: importing the old entry from a directory without test/ throws ENOENT; the lib import parses the fixture with no test/ present.
- Split the tests by what they need: 4 auth files need SECRET_JWT_KEY and 7 need the database (NEEDS_DATABASE in vitest.config.ts). The old "8 files" line named whole folders and mixed both groups - The database tests run against the one DB_ENVIRONMENT selects, local by default, not always the shared Aiven database - Say to run from backend/, describe frontend/, scheduling-corpus/ and the F&B fixture, and note that backend/test/ is gone Measured by running the suite without .env, with and without the key.
…ects The root AGENTS.md says Prettier must not reformat code inside Markdown code blocks, and the root config sets embeddedLanguageFormatting off. The *.md overrides in backend/ and frontend/ did not repeat it, so any Markdown under them had its embedded JSON and code reformatted.
18 tracked Markdown files failed prettier --check: hand-wrapped prose, unaligned tables and blockquotes without continuation markers. Only whitespace, table padding and quote markers change; the text is the same. The checklist guides stay as they are, excluded on purpose by frontend/.prettierignore.
Each project's format:check only covers code, so the root AGENTS.md, docs/ and the module docs had no gate and had drifted. The step runs in the frontend job with its Prettier, the one Markdown binary: the backend ships a different version that wraps some lines differently. AGENTS.md now documents the same check to run before committing.
Reflowing joined inline code that had been split across lines and kept the continuation indent inside the span, so `handicapped | electric` and three more rendered with a run of spaces.
- Declare an exception to layer-1 rule 9 in backend/ and frontend/ AGENTS.md: the session starts at the repo root and every Node or pnpm command first runs fnm use, which reads the subproject's .nvmrc - Remove the root .nvmrc: Render and CI read each subproject's file since f934b4d, and its 22 only made a root session run frontend/ commands on the wrong major, which pnpm merely warns about - Record the decision as ADR-044 and update SESSION and TODO The two sides run Node 22 and 24, and tasks that cross the contract between them need both in view, so one session per side does not fit.
- Bump prettier from 3.6.2 to 3.9.9 and reformat the 9 frontend files and 2 module AGENTS.md the new version wraps differently, so lint, format:check and the Markdown step in CI stay green in this commit - Point the root AGENTS.md at keeping both versions together The two projects shipped different Prettier versions that disagree on some Markdown lines, and CI checks every Markdown file with the frontend's binary. The code changes are layout only: union types on one line without the leading pipe, and one call rewrapped.
pnpm format runs prettier --write over the whole frontend, and the lockfile was not ignored, so it rewrote pnpm-lock.yaml in a layout pnpm does not produce. The backend already ignores its own lockfile.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Changes
backend/andfrontend/, each with its ownAGENTS.md; the rootAGENTS.mdkeeps what both share, and every module doc links up to its subproject and the root. A session runs from the repo root and switches Node per side withfnm use; the root.nvmrcis gone.backend/22,frontend/24) in.nvmrcandengines; pnpm 10.28.0 with a 7-day hold on new releases; a singleverifyscript per side in CI; Prettier 3.9.9 on both sides..mdreformatted to the repo rules, code blocks left untouched in both projects, and a CI step that checks them all.pdf-parse/lib/pdf-parse.js: the package entry ran a debug block on import that neededbackend/test/, now removed.Why
The harness rules and the module docs had drifted from the code, and nothing gated the Markdown. The fixes clear what blocked the new gates.
Checked
No database migrations.