diff --git a/.github/workflows/agent-map-check.yml b/.github/workflows/agent-map-check.yml new file mode 100644 index 000000000..a1b40cd12 --- /dev/null +++ b/.github/workflows/agent-map-check.yml @@ -0,0 +1,29 @@ +name: agent-map-check + +# Verifies that links inside the agentic framework (AGENTS.md, CLAUDE.md, +# agentic/** ) still resolve. Catches drift when docs or repo structure +# move. Markdown-link based; cheap to run. + +on: + pull_request: + paths: + - "AGENTS.md" + - "CLAUDE.md" + - "agentic/**" + - "docs/architecture/**" + - "docs/capabilities/**" + - "docs/getting-started/**" + - "docs/principles/**" + - ".agents/SITEMAP.md" + - ".github/workflows/agent-map-check.yml" + - "scripts/check-agent-map.sh" + push: + branches: [main] + +jobs: + check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Verify agentic framework links + run: bash scripts/check-agent-map.sh \ No newline at end of file diff --git a/.github/workflows/license-headers-check.yml b/.github/workflows/license-headers-check.yml new file mode 100644 index 000000000..a1f7876a9 --- /dev/null +++ b/.github/workflows/license-headers-check.yml @@ -0,0 +1,26 @@ +name: license-headers-check + +# Verifies that .js/.ts/.tsx source files CHANGED in a PR carry the repo's +# Eclipse/MIT SPDX header. Checks only changed files so pre-existing header +# debt doesn't block PRs. + +on: + pull_request: + paths: + - "backend/**/*.js" + - "frontend/**/*.ts" + - "frontend/**/*.tsx" + - "scripts/check-license-headers.sh" + - ".github/workflows/license-headers-check.yml" + push: + branches: [main] + +jobs: + check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Verify changed source files carry the MIT SPDX header + run: bash scripts/check-license-headers.sh "${{ github.event.pull_request.base.sha || 'origin/main' }}" \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..f255fe3eb --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,75 @@ +# AGENTS.md — AutoWRX + +> Vendor-neutral entry point for any AI coding agent (Claude Code, opencode, openclaw, …). Read this first. + +AutoWRX is a cloud-based rapid-prototyping environment for software-defined vehicle (SDV) apps. Stack: **Node.js/Express + MongoDB** backend, **React + Vite + TypeScript** frontend, **Playwright** E2E, **Docker Compose** deploy. + +## Start here (always load) + +- **Rules (must/must-not):** [`agentic/RULES.md`](./agentic/RULES.md) +- **Conventions:** [`agentic/CONVENTIONS.md`](./agentic/CONVENTIONS.md) + +Key rules in one line: +- Commit with **your own ECA-signed identity** — every contributor uses their own GitHub/email account (the one they signed the ECA with). `git commit -s`. +- Never commit on `main`. PRs target `main`. Never commit secrets (`.env*`). +- Don't push/deploy unless explicitly asked. Run tests before declaring done. Self-review every diff. + +## Understand the repo (before real work) + +Don't re-scan the whole repo. Run the **`understand-the-repo`** skill: load [`agentic/map/INDEX.md`](./agentic/map/INDEX.md) + [`agentic/memory/MEMORY.md`](./agentic/memory/MEMORY.md), then deep-read only the module you'll touch. + +Existing knowledge to lean on (do not duplicate): +- Architecture deep-dive → [`docs/architecture/`](./docs/architecture/) +- Capability catalog (code-grounded spec) → [`docs/capabilities/`](./docs/capabilities/) +- Pages & feature coverage → [`.agents/SITEMAP.md`](./.agents/SITEMAP.md) +- Getting started / local dev / contributing → [`docs/getting-started/`](./docs/getting-started/) +- Design principles → [`docs/principles/principle.md`](./docs/principles/principle.md) + +## Skills (load on demand, by task) + +Indexed in [`agentic/skills/README.md`](./agentic/skills/README.md). The core flow: + +- [`understand-the-repo`](./agentic/skills/understand-the-repo.md) — orient cheaply (map + memory). +- [`implement-feature`](./agentic/skills/implement-feature.md) — branch → understand → implement → test → review → commit → PR. +- [`run-tests`](./agentic/skills/run-tests.md) — Jest (backend) + Playwright (`.agents/`). +- [`code-review`](./agentic/skills/code-review.md) — self-review before commit. +- [`security-review`](./agentic/skills/security-review.md) — for auth/data/runtime/plugin changes. +- [`license-check`](./agentic/skills/license-check.md) — Eclipse/MIT headers + no incompatible-license code (for new/changed `.js`/`.ts`/`.tsx` or deps). +- [`commit-and-pr`](./agentic/skills/commit-and-pr.md) — ECA, sign-off, PR template. +- [`deploy`](./agentic/skills/deploy.md) — `instance-setup/` Docker Compose. +- [`docs-update`](./agentic/skills/docs-update.md) — keep map/capabilities in sync with code. +- [`learn-and-update`](./agentic/skills/learn-and-update.md) — capture best practices/trends/lessons. + +**Also available** (load when the task fits) — full list in [`agentic/skills/README.md`](./agentic/skills/README.md): +[`debug`](./agentic/skills/debug.md), [`find-race-conditions`](./agentic/skills/find-race-conditions.md), [`add-endpoint`](./agentic/skills/add-endpoint.md), [`add-frontend-feature`](./agentic/skills/add-frontend-feature.md), [`db-schema-change`](./agentic/skills/db-schema-change.md), [`realtime-event`](./agentic/skills/realtime-event.md), [`add-test`](./agentic/skills/add-test.md), [`performance-review`](./agentic/skills/performance-review.md), [`dependency-upgrade`](./agentic/skills/dependency-upgrade.md), [`troubleshoot-deploy`](./agentic/skills/troubleshoot-deploy.md), [`coder-workspace`](./agentic/skills/coder-workspace.md), [`plugin-authoring`](./agentic/skills/plugin-authoring.md), [`secrets-incident`](./agentic/skills/secrets-incident.md). + +## Quick commands + +```bash +# Backend +cd backend && npm install && npm run dev # dev server +cd backend && npm test # Jest +cd backend && npm run lint && npm run prettier # lint/format + +# Frontend +cd frontend && npm install && npm run dev # Vite on :3210 +cd frontend && npm run build # tsc + vite build +cd frontend && npm run lint # ESLint --max-warnings 0 + +# E2E +cd .agents && npm install && npx playwright install chromium +cd .agents && npx playwright test # all specs + +# Deploy (instance) +cd instance-setup && ./up.sh # docker compose up -d (needs .env.prod) +``` + +## Memory & learning + +- Repo-resident facts: [`agentic/memory/`](./agentic/memory/) (with `MEMORY.md` index). +- Continuous learning: [`agentic/learning/`](./agentic/learning/). Propose updates via PR; never auto-apply to rules. + +## Adapters + +- **Claude Code:** [`CLAUDE.md`](./CLAUDE.md) imports this file via `@path` (e.g. `@AGENTS.md`). See [`agentic/SETUP.md`](./agentic/SETUP.md) to enable native skill invocation. +- **opencode / openclaw / others:** you're reading the canonical entry. Point your tool at `AGENTS.md`. \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000..608b39f33 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,19 @@ +# CLAUDE.md — AutoWRX (Claude Code adapter) + +This is a thin adapter. The canonical agent rules live in vendor-neutral files and are imported below (Claude Code `@path` syntax — they expand at launch). Do not duplicate rules here. + +@AGENTS.md +@agentic/RULES.md +@agentic/CONVENTIONS.md + +## Claude Code specifics + +- **Skills:** the repo's skill playbooks are markdown in [`agentic/skills/`](./agentic/skills/). To invoke them via Claude Code's Skill tool natively, symlink them into `.claude/skills/` (see [`agentic/SETUP.md`](./agentic/SETUP.md)). Otherwise, load the matching skill file directly when a task fits. +- **Memory:** Claude Code's default memory is user-local (`~/.claude/...`). For this repo, prefer the **repo-resident** memory in [`agentic/memory/`](./agentic/memory/) so knowledge is shared across tools/machines and reviewable in PRs. Use user-local memory only for personal preferences. +- **Git identity:** commit with **your own** ECA-signed identity — each contributor uses their own account (this user's personal identity lives in user-local memory, not in repo rules). Always `git commit -s`. ECA must be signed. +- **Plan mode:** for non-trivial implementations, enter plan mode and get sign-off before coding (per Claude Code defaults). +- **Don't push/deploy unless explicitly asked**; commit only when asked. Each is separate authorization. + +## Quick orientation + +Read [`AGENTS.md`](./AGENTS.md) → run `understand-the-repo` skill → load the task's skill → follow `implement-feature`. \ No newline at end of file diff --git a/agentic/CONVENTIONS.md b/agentic/CONVENTIONS.md new file mode 100644 index 000000000..ed15c0ac4 --- /dev/null +++ b/agentic/CONVENTIONS.md @@ -0,0 +1,56 @@ +# Conventions + +Style and structure conventions for this repo. Load always (imported by `AGENTS.md` / `CLAUDE.md`). These reflect what the codebase already does — match it. + +## Branches & commits + +- **Branch naming:** `/` or `/-`. Types: `feat`, `docs`, `fix`, `chore`, `refactor`. Examples: `feat/612-agentic-coding-framework`, `docs/capabilities-improvements`, `fix/project-editor-move-guard`. +- **Commit message:** imperative summary ≤ ~72 chars; body explains the *why*. End with `Signed-off-by:` (via `git commit -s`) and, for agent-made commits, an attribution trailer — `Co-Authored-By: Claude ` when running as Claude Code, or the tool's equivalent; omit if the tool has no such convention. +- **One logical change per commit** where practical; squashing is done at PR merge, not in commits. + +## PRs + +- PRs target **`main`**. +- Title: `(): `. +- Body: **What / Why / How verified**. Note if the change touches security, data, runtime, or plugins. Link the issue (`Closes #nnn` / `Ref #nnn`). +- The PR pipeline currently runs the **ECA check only**; CI doesn't run tests on PRs, so the agent/author must run tests locally and state how it was verified. + +## Backend (`backend/`, Node.js + Express + MongoDB) + +- **Layering:** routes → controllers (thin) → services (logic) → models (Mongoose). Keep controllers thin; business logic lives in `services/`. See [`docs/principles/principle.md`](../docs/principles/principle.md). +- **Routes:** versioned under `routes/v2/`. Match existing grouping (e.g. `routes/v2/user-management/`, `routes/v2/vehicle-data/`). +- **Auth:** `auth({ optional: (req) => req.authConfig.PUBLIC_VIEWING })` pattern for public-optional reads; writes require auth; resource checks via `checkPermission` (RBAC v1, owner bypass). +- **Tests:** Jest, colocated or under a tests dir. Run `npm test`. Match existing spec style. +- **Lint/format:** `npm run lint`, `npm run prettier` (ESLint + Prettier; Husky pre-commit). + +## Frontend (`frontend/`, React + Vite + TypeScript) + +- **Atomic design:** `components/{atoms,molecules,organisms}`, `pages/`, `layouts/`, `stores/`, `hooks/`. Don't put page logic in atoms. +- **State:** Zustand stores under `stores/` (`authStore.ts`, …). Permissions via `hooks/usePermissionHook.ts`. +- **Routing:** `configs/routes.tsx`. +- **Build/lint:** `npm run build` (`tsc && vite build`), `npm run lint` (ESLint, `--max-warnings 0`). Dev server on port **3210**. + +## E2E (`.agents/`, Playwright) + +- Specs in `.agents/tests/*.spec.ts`. Run `cd .agents && npx playwright test`. +- Keep `.agents/SITEMAP.md` coverage status in sync when adding/changing a page feature. +- Env via `.agents/.env` (gitignored; see `.agents/.env.example`). + +## Docs + +- All docs under `docs/`; index at [`docs/README.md`](../docs/README.md). +- **Capability catalog** (`docs/capabilities/`) is **code-grounded**: every endpoint/status/flag claim must match the code. Format per [`docs/capabilities/README.md`](../docs/capabilities/README.md). +- When code structure changes, update `agentic/map/` pointers and (if a capability changed) `docs/capabilities/`. + +## Agent config (this framework) + +- Canonical content in `agentic/`. Tool-specific adapters (e.g. `CLAUDE.md`) stay thin and import canonical files via `@path` (e.g. `@AGENTS.md`) — don't duplicate rules into adapters. +- Memory: one fact per file under `agentic/memory/` + a one-line index entry in `MEMORY.md`. +- Skills: one procedure per file; each has *When to use · Steps · Guardrails · Exit criteria*. Keep them concise. + +## License (Eclipse / MIT) + +- Repo license: **MIT**, copyright Eclipse Foundation. Every new `.js`/`.ts`/`.tsx` source file **must** start with the Eclipse/MIT header (`SPDX-License-Identifier: MIT`) — see [`skills/license-check.md`](./skills/license-check.md) for the exact block. `.sh`/`.yml`/`.md` files do not carry it (repo convention). +- Don't remove or alter existing `Copyright`/`SPDX-License-Identifier` headers. +- Don't introduce copyleft (GPL/AGPL/CDDL) or proprietary third-party code — MIT can't combine with it. Vendored code must be MIT-compatible and keep its original notice. +- CI: `scripts/check-license-headers.sh` + `.github/workflows/license-headers-check.yml` check changed source files for the header. \ No newline at end of file diff --git a/agentic/README.md b/agentic/README.md new file mode 100644 index 000000000..b795e9e55 --- /dev/null +++ b/agentic/README.md @@ -0,0 +1,68 @@ +# AutoWRX Agentic Coding Framework + +A **repo-resident, vendor-neutral** framework that lets any AI coding agent — Claude Code, opencode, openclaw, or the next tool — work the same way in this repo: load the same rules, memory, skills, and repo map; follow the same implement → test → review → commit → PR → deploy flow; and avoid re-scanning the whole repo each session. + +> Issue: #612 · Design: [`docs/agentic-framework/PROPOSAL.md`](../docs/agentic-framework/PROPOSAL.md) + +## Layout + +``` +AGENTS.md vendor-neutral entry point (read by every tool) +CLAUDE.md Claude Code adapter (imports AGENTS.md via `@path`) +agentic/ + README.md this file + RULES.md hard rules (must / must-not) + CONVENTIONS.md naming, structure, commit, PR style + SETUP.md how to wire this repo into each tool + skills/ skill playbooks (load-on-demand procedures) + README.md skill index + understand-the-repo.md + implement-feature.md + run-tests.md + code-review.md + security-review.md + commit-and-pr.md + deploy.md + docs-update.md + learn-and-update.md + memory/ repo-resident knowledge base (facts + index) + MEMORY.md index (one line per fact) + map/ repo map: pointers to the real maps + compact tree + INDEX.md + TREE.md + learning/ continuous-learning layer + README.md + best-practices.md + trends.md + lessons.md +``` + +## How an agent uses this (the contract) + +1. On start, read `AGENTS.md` (and the tool's adapter, e.g. `CLAUDE.md`). It imports `agentic/RULES.md` + `agentic/CONVENTIONS.md` — these are the **always-loaded** rules. +2. Before doing real work, run the **`understand-the-repo`** skill: load `agentic/map/INDEX.md` + `agentic/memory/MEMORY.md` instead of re-scanning the repo. Deep-read only the specific module you'll touch. +3. For a task, load the matching **skill** from `agentic/skills/` (skills are markdown; load on demand, not all at once). +4. Follow the canonical flow in `agentic/skills/implement-feature.md`. +5. When you learn something durable, propose it into `agentic/memory/` or `agentic/learning/` via a PR (see `learn-and-update` skill). + +## What is NOT duplicated here + +This framework **points to** existing repo knowledge rather than copying it: + +- **Architecture / deep-dive** → [`docs/architecture/`](../docs/architecture/) +- **Capability catalog** → [`docs/capabilities/`](../docs/capabilities/) (the spec/acceptance reference) +- **Pages & feature coverage** → [`.agents/SITEMAP.md`](../.agents/SITEMAP.md) +- **Getting started / local dev / contributing** → [`docs/getting-started/`](../docs/getting-started/) +- **Design principles** → [`docs/principles/principle.md`](../docs/principles/principle.md) +- **E2E tests** → [`.agents/`](../.agents/) (Playwright) + +`agentic/map/` is an **index of pointers** to the above, plus a compact `TREE.md`. Update pointers when docs move; don't copy their content. + +## Vendor neutrality + +Canonical content lives in `agentic/`. Tool-specific entry files are thin adapters: +- **Claude Code** → `CLAUDE.md` uses `@path` imports (e.g. `@AGENTS.md`, `@agentic/RULES.md`) to pull in the canonical files. +- **opencode / openclaw / others** → read `AGENTS.md` natively (agents.md spec). +- **Skills** are plain markdown loaded on demand — every tool can read them. To get native Skill-tool invocation in Claude Code, see `SETUP.md` (symlink `agentic/skills/*` into `.claude/skills/`). + +See [`SETUP.md`](./SETUP.md) for per-tool wiring. \ No newline at end of file diff --git a/agentic/RULES.md b/agentic/RULES.md new file mode 100644 index 000000000..3955010d5 --- /dev/null +++ b/agentic/RULES.md @@ -0,0 +1,41 @@ +# Rules (must / must-not) + +Hard rules for any agent working in this repo. Load always (imported by `AGENTS.md` / `CLAUDE.md`). Violating these is a defect, not a style choice. + +## Git & contributions + +- **ECA is mandatory.** Every commit author must have signed the [Eclipse Contributor Agreement](https://www.eclipse.org/legal/eca/) and commit with the **email they signed the ECA with**. Each contributor uses their own ECA-signed identity — do not assume a specific name/email repo-wide. +- **Sign off commits:** `git commit -s` (adds `Signed-off-by:`). +- **Never commit on `main`.** Branch off `main` first; PRs target `main`. +- **Never force-push to shared branches.** Rebase your own feature branch only. +- **Never commit secrets** (`.env`, `.env.prod`, tokens, keys, cookies). They are gitignored; keep them out. +- **Co-author / attribution:** when an agent makes commits, end the message with `Co-Authored-By: Claude ` (or the tool's equivalent). See `commit-and-pr` skill. + +## Code changes + +- **Do not push or deploy unless explicitly asked.** Commit only when asked; push/PR only when asked; deploy only when asked. Each is a separate authorization. +- **Never mark a task complete if tests fail or work is partial.** Report failures honestly with output. +- **Before deleting/overwriting a file, look at it.** If it contradicts how it was described or you didn't create it, surface that instead of proceeding. +- **Match surrounding code:** naming, comment density, idioms. No drive-by reformatting outside the change's scope. +- **Backend:** thin controllers, logic in services (see [`docs/principles/principle.md`](../docs/principles/principle.md)). +- **Frontend:** atomic design (components/molecules/organisms/pages). Do not bypass the existing layering. + +## Verification + +- **Run tests before declaring done:** `backend: npm test` (Jest) and/or `cd .agents && npx playwright test` for affected flows. If you can't run them, say so. +- **Lint where it exists:** `backend: npm run lint && npm run prettier`; `frontend: npm run lint`. Fix your own lint errors; don't disable rules silently. +- **Self-review your diff before commit** (see `code-review` skill). Security-sensitive changes (auth, tokens, file ops, runtime, plugins) also run `security-review`. + +## Agent context discipline (token efficiency) + +- **Load the map + memory first,** not the whole repo. Use the `understand-the-repo` skill. +- **Deep-read only the module you're touching.** Don't dump files into context you won't use. +- **Skills are load-on-demand.** Don't preload all skills; load the one matching the task. +- **When you learn a durable fact, write it to `agentic/memory/` or `agentic/learning/`** (propose via PR) so the next session doesn't re-learn it. + +## Must-not + +- Don't fabricate endpoints, statuses, flags, or file paths. If unsure, read the code. +- Don't edit `docs/capabilities/*` technical claims without verifying against the route/controller code (the catalog is code-grounded). +- Don't change the ECA/git identity rules. +- Don't run destructive commands (`rm -rf`, `git reset --hard` on shared refs, `down.sh` on a prod env) without explicit confirmation. \ No newline at end of file diff --git a/agentic/SETUP.md b/agentic/SETUP.md new file mode 100644 index 000000000..006826488 --- /dev/null +++ b/agentic/SETUP.md @@ -0,0 +1,41 @@ +# Setup — wiring this repo into each AI tool + +The framework is vendor-neutral; each tool just needs to find `AGENTS.md` (and optionally the skills). One-time setup per machine. + +## Claude Code + +`CLAUDE.md` already imports `AGENTS.md` + rules via Claude Code's `@path` syntax (e.g. `@AGENTS.md`), so rules load automatically when Claude Code opens this repo. + +### Native skill invocation (optional but recommended) + +Claude Code's Skill tool only sees skills in `.claude/skills/`. `.claude/` is gitignored (per-user), so symlink the canonical skills in: + +```bash +# from repo root +mkdir -p .claude/skills +for s in agentic/skills/*.md; do + name=$(basename "$s" .md) + [ "$name" = "README" ] && continue # index, not a skill + ln -sf "../../agentic/skills/$name.md" ".claude/skills/$name.md" +done +``` + +Now `/understand-the-repo`, `/run-tests`, etc. are invokable. (The skill files use the markdown-playbook format; Claude Code treats a `.md` skill as a set of instructions it loads when invoked.) + +> Re-run after pulling if skills are added/renamed. + +### Memory + +Prefer repo-resident [`agentic/memory/`](./memory/) for shared facts. Keep `~/.claude/.../memory/` for personal preferences only. + +## opencode + +opencode reads `AGENTS.md` natively. Point it at the repo root; no extra config. To expose skills, symlink per opencode's skill dir convention into `agentic/skills/` (or set opencode's skills path to `agentic/skills/`). + +## openclaw / other agents + +Point the tool at `AGENTS.md` at repo root (this is the [agents.md](https://agents.md) convention). Skills are plain markdown — instruct the tool to load `agentic/skills/.md` when a task matches, or symlink into the tool's skill dir. Memory/map are markdown under `agentic/`. + +## Verify it works + +After setup, ask the agent: *"Where does the repo keep its agent rules and skills?"* Correct answer: `AGENTS.md` + `agentic/`. Then: *"Orient me on the repo without scanning everything"* — it should load `agentic/map/INDEX.md` + `agentic/memory/MEMORY.md`, not re-index the whole tree. \ No newline at end of file diff --git a/agentic/learning/README.md b/agentic/learning/README.md new file mode 100644 index 000000000..cb06cf1c4 --- /dev/null +++ b/agentic/learning/README.md @@ -0,0 +1,19 @@ +# Learning Layer + +Continuous-learning notes for agents working in this repo. Three files, each with a different cadence: + +- [`best-practices.md`](best-practices.md) — dated, sourced practices for this stack. Reviewed periodically; mark `Last reviewed:` so staleness is visible. +- [`trends.md`](trends.md) — light watch-list of things to research next; explicitly a seed, not authoritative. +- [`lessons.md`](lessons.md) — append-only log of concrete lessons from real sessions, one line per entry. + +## The loop + +1. During a session, the [`learn-and-update`](../skills/learn-and-update.md) skill researches a topic (web/docs/code) and captures **dated + sourced** notes into `best-practices.md` or `trends.md`. +2. Concrete session lessons (a bug, a surprise, a correction) get appended to `lessons.md` as one line: `- YYYY-MM-DD — (source)`. +3. **Updates to `RULES.md` / `CONVENTIONS.md` / `agentic/memory/` are PROPOSALS via PR, never auto-applied.** The always-loaded rule set stays stable and reviewable; learning lives here until it earns a promotion. + +## When to update + +- You re-discovered something a previous session clearly already knew → it belongs in `memory/` (propose it). +- You hit a stack-specific gotcha → append to `lessons.md` and, if recurring, propose a `memory/gotchas.md` entry. +- A best practice may have shifted (new Node/Vite/Playwright release) → research via the skill, update `best-practices.md` with a new `Last reviewed:` date. \ No newline at end of file diff --git a/agentic/learning/best-practices.md b/agentic/learning/best-practices.md new file mode 100644 index 000000000..3ca72968a --- /dev/null +++ b/agentic/learning/best-practices.md @@ -0,0 +1,39 @@ +# Best Practices (seed) + +Starting points for this stack — refine as we learn. Each entry has a `Last reviewed:` date and a source; if you re-verify, bump the date. + +## AGENTS.md as vendor-neutral entry point + +- Last reviewed: 2026-08-07 +- Source: https://agents.md +- Keep `AGENTS.md` as the canonical always-loaded file; tool adapters (`CLAUDE.md`) import it via `@path` rather than duplicating rules. +- One procedure per skill file; skills are load-on-demand, not preloaded. + +## Express thin-controller / service layer + +- Last reviewed: 2026-08-07 +- Source: [`docs/principles/principle.md`](../../docs/principles/principle.md) +- Controllers stay thin: parse/validate request, call a service, shape the response. Business logic lives in `services/`. +- Models (Mongoose) only express persistence; no HTTP-shaped errors thrown from models. + +## React + Vite atomic structure + +- Last reviewed: 2026-08-07 +- Source: [`agentic/CONVENTIONS.md`](../CONVENTIONS.md), `frontend/src/components/` +- `atoms` → `molecules` → `organisms` → `pages`; don't put page-level data fetching inside an atom. +- State in Zustand stores (`stores/`); permissions via `hooks/usePermissionHook.ts`; routing in `configs/routes.tsx`. +- `npm run build` runs `tsc && vite build`, so type errors fail CI — treat the build as a typecheck gate. + +## Playwright flakiness hygiene + +- Last reviewed: 2026-08-07 +- Source: [`.agents/TESTING.md`](../../.agents/TESTING.md) +- Prefer role/label selectors over CSS paths; retry only at the test level, never swallow assertions. +- Keep `.agents/SITEMAP.md` coverage status (✅/⚠️/❌) in sync when a page feature changes — it is the coverage source of truth. + +## MongoDB indexes / TTL for token cleanup + +- Last reviewed: 2026-08-07 +- Source: general MongoDB best practice; confirm against `backend/src/models/` before applying. +- Add a TTL index on any timestamped cleanup collection (expired sessions, reset tokens) rather than relying on a cron sweep. +- Compound indexes should match actual query shapes seen in `services/` — don't index speculatively. \ No newline at end of file diff --git a/agentic/learning/lessons.md b/agentic/learning/lessons.md new file mode 100644 index 000000000..408f3293e --- /dev/null +++ b/agentic/learning/lessons.md @@ -0,0 +1,17 @@ +# Lessons + +Append-only log of concrete lessons from real sessions. One line per entry: + +``` +- YYYY-MM-DD — (source) +``` + +Keep it specific and sourced; if a lesson generalizes, propose it into `memory/` or `best-practices.md` via PR. + +## Example + +- 2026-08-07 — framework-setup — `authLimiter` is defined in `backend/src/middlewares/rateLimiter.js` but not applied to any route, so login is currently unthrottled. (source: grep over `backend/src`; recorded in `memory/gotchas.md`) + +## Log + + \ No newline at end of file diff --git a/agentic/learning/trends.md b/agentic/learning/trends.md new file mode 100644 index 000000000..55c77360a --- /dev/null +++ b/agentic/learning/trends.md @@ -0,0 +1,11 @@ +# Trends (seed) + +A light watch-list, not authoritative. Items here are **to research next** via the [`learn-and-update`](../skills/learn-and-update.md) skill. + +- Last reviewed: 2026-08-07 + +## To research next + +- **Agent-skills ecosystem maturation** — `agents.md` convention and tool-specific skill formats (Claude Code `SKILL.md`, opencode) are evolving; revisit how `agentic/skills/` is exposed across tools. (Source: https://agents.md — to re-check.) +- **Node 22+ / Express 5 adoption** — confirm which Node/Express line `backend/` targets and whether middleware patterns (e.g. async error handling) have changed under Express 5. (Source: `backend/package.json` — to read next.) +- **Playwright component + fixture patterns** — newer Playwright patterns for multi-tab / network-mock suites may reduce flakiness in `.agents/`. (Source: https://playwright.dev — to research.) \ No newline at end of file diff --git a/agentic/map/INDEX.md b/agentic/map/INDEX.md new file mode 100644 index 000000000..3c13a3b81 --- /dev/null +++ b/agentic/map/INDEX.md @@ -0,0 +1,25 @@ +# Map Index + +Pointers to the real repo maps. **Load this INDEX + the relevant target map; do NOT scan the whole repo.** This file indexes, it does not duplicate — for content, open the target. + +## Compact module tree + +- [`TREE.md`](TREE.md) — one-line purpose per top-level dir / key subdir. Load first to orient. + +## Where to find what + +| When you need… | Load | +| --- | --- | +| Subsystem deep-dive (backend/frontend/deploy internals) | [`docs/architecture/`](../../docs/architecture/) | +| Per-cluster endpoint / status / flag spec (code-grounded) | [`docs/capabilities/`](../../docs/capabilities/) — load the cluster matching the area you're touching | +| Page / feature coverage status (✅/⚠️/❌) | [`.agents/SITEMAP.md`](../../.agents/SITEMAP.md) | +| Onboarding: codebase tour, local dev | [`docs/getting-started/codebase-tour.md`](../../docs/getting-started/codebase-tour.md) + [`local-development.md`](../../docs/getting-started/local-development.md) | +| Design rules / layering principles | [`docs/principles/principle.md`](../../docs/principles/principle.md) | +| E2E test conventions | [`.agents/TESTING.md`](../../.agents/TESTING.md) | +| Deploy topology | [`instance-setup/instance-setup-guide.md`](../../instance-setup/instance-setup-guide.md) + `docker-compose.prod.yml` | + +## How to use + +1. Read `TREE.md` to find the module path. +2. Open the one target map above that matches the task area. +3. Deep-read only the specific module you'll change — not its neighbors. \ No newline at end of file diff --git a/agentic/map/TREE.md b/agentic/map/TREE.md new file mode 100644 index 000000000..8f2d2c4e3 --- /dev/null +++ b/agentic/map/TREE.md @@ -0,0 +1,59 @@ +# Compact Module Tree + +One-line purpose per top-level dir / key subdir. Scannable, not exhaustive — no leaf files unless load-bearing. Verified against the working tree. + +``` +backend/src/ Node/Express + MongoDB backend + index.js process bootstrap + app.js Express app: middleware + route mounting + config/ env/config loading + controllers/ thin request handlers (no business logic) + decorators/ route/metadata decorators + docs/ backend-local API docs + middlewares/ auth, rateLimiter, error handlers + models/ Mongoose models (persistence layer) + routes/v2/ versioned API entry, grouped by domain: + user-management/ auth, users, permissions, assets + vehicle-data/ models, prototypes, custom/extended APIs + content/ discussions, feedback + system/ files, plugins, search, genai, site mgmt, templates + services/ business logic (called by controllers) + scripts/ one-off / scheduled jobs + typedefs/ shared JSDoc @typedef definitions + utils/ helpers + validations/ request schema validators + +frontend/src/ React + Vite + TypeScript SPA (dev port 3210) + App.tsx, main.tsx app shell + bootstrap + components/{atoms,molecules,organisms}/ atomic-design components + pages/ route-level views + layouts/ page wrappers + stores/ Zustand stores (auth, …) + hooks/ reusable hooks (usePermissionHook, …) + services/ API client layer + configs/routes.tsx single route table + data/, providers/, lib/, utils/, types/ misc support + +.agents/ Playwright E2E suite + tests/ *.spec.ts + SITEMAP.md page/feature coverage (✅/⚠️/❌) + TESTING.md E2E conventions + +instance-setup/ single-host Docker Compose deploy + docker-compose.prod.yml services: autowrx, autowrx-db, autowrx-dbdata, autowrx-network + up.sh, down.sh thin compose wrappers + nginx-sample.conf reverse-proxy template + coder/ code-server / VS Code-in-browser integration + data/ persisted volumes + +docs/ all human docs (index: docs/README.md) + architecture/ subsystem deep-dives + capabilities/ code-grounded endpoint/status/flag catalog + getting-started/ README, concepts, local-development, codebase-tour, development-guide, contributing, internal/ + guides/ custom-api-system, deployment, plugin + principles/principle.md design rules + reference/, examples/ reference + examples + +scripts/ repo-level helper scripts +plans/ planning notes / roadmap artifacts +``` \ No newline at end of file diff --git a/agentic/memory/MEMORY.md b/agentic/memory/MEMORY.md new file mode 100644 index 000000000..a24e2d249 --- /dev/null +++ b/agentic/memory/MEMORY.md @@ -0,0 +1,10 @@ +# Memory Index + +Repo-resident knowledge base. Each entry is a short, durable, non-obvious fact — not something the code or git log already shows. Load this index + the relevant file; don't re-derive facts every session. + +- [Architecture](architecture.md) — durable structural facts that span layers and aren't obvious from one file. +- [Gotchas](gotchas.md) — repo-specific traps and known gaps that bite if you don't know them. +- [Verified facts](verified-facts.md) — non-obvious facts confirmed by reading the code, worth not re-discovering. +- [Decisions](decisions.md) — ADR-style record of key choices and their rationale. + +Update rule: propose changes via PR (see [`../skills/learn-and-update.md`](../skills/learn-and-update.md)). Never edit rules to "fix" a memory fact — fix the code, then update memory. \ No newline at end of file diff --git a/agentic/memory/architecture.md b/agentic/memory/architecture.md new file mode 100644 index 000000000..435718cd1 --- /dev/null +++ b/agentic/memory/architecture.md @@ -0,0 +1,9 @@ +# Architecture facts + +Durable structural facts that span layers and aren't obvious from a single file. For deep-dive narratives, load [`docs/architecture/`](../../docs/architecture/) instead. + +- **Two-process backend:** `backend/src/index.js` boots the Express app (`app.js`); `app.js` wires middleware + mounts `routes/v2` under a versioned prefix. There is no separate worker process — scheduled/cron-style work lives in `scripts/`. +- **Route grouping by domain, not by HTTP verb:** `routes/v2/{user-management,vehicle-data,content,system}/` each have an `index.js` that aggregates that domain's `*.route.js` files. Add a new endpoint to the matching domain, not a flat list. +- **Layering is enforced by convention, not by tooling:** routes → thin controllers → services (logic) → models (Mongoose). Nothing prevents a controller from importing a model directly; reviewers must hold the line. See [`docs/principles/principle.md`](../../docs/principles/principle.md). +- **Frontend state is Zustand, not Redux:** stores in `frontend/src/stores/` (`authStore.ts`, …). Permissions read via `hooks/usePermissionHook.ts`. Routing is a single file: `configs/routes.tsx`. +- **Deploy is a single Compose stack:** `instance-setup/docker-compose.prod.yml` defines `autowrx`, `autowrx-db`, `autowrx-dbdata`, `autowrx-network`. `up.sh` / `down.sh` are thin wrappers around `docker compose`. No k8s, no separate CDN. \ No newline at end of file diff --git a/agentic/memory/decisions.md b/agentic/memory/decisions.md new file mode 100644 index 000000000..ceea2d8aa --- /dev/null +++ b/agentic/memory/decisions.md @@ -0,0 +1,23 @@ +# Decisions (ADR-style) + +Key choices and their rationale, kept short. Date each entry; supersede, don't silently rewrite. + +## 2026-08-07 — Agentic framework is repo-resident and vendor-neutral + +- **Context:** multiple AI coding tools (Claude Code, opencode, openclaw) work in this repo. +- **Decision:** canonical rules/memory/skills/map live in `agentic/`; tool-specific entry files (`CLAUDE.md`, `AGENTS.md`) are thin adapters that import canonical content (Claude Code via `@path`). +- **Rationale:** avoids drift between tools; one place to update rules. +- **Consequences:** never duplicate rules into an adapter; update `agentic/*` and let adapters pull through. + +## 2026-08-07 — Map is pointers, not copies + +- **Context:** `docs/architecture/`, `docs/capabilities/`, `.agents/SITEMAP.md` already describe the repo. +- **Decision:** `agentic/map/` is an index of pointers + a compact `TREE.md`; it does not re-narrate those docs. +- **Rationale:** duplication rots; the source docs are code-grounded and maintained. +- **Consequences:** when docs move, update pointers; when code structure changes, update `TREE.md` and (if a capability changed) `docs/capabilities/`. + +## 2026-08-07 — Learning updates are proposals via PR + +- **Context:** agents learn things every session; auto-editing rules is dangerous. +- **Decision:** new best-practices/trends/lessons land in `agentic/learning/`; changes to `RULES.md` / `CONVENTIONS.md` / `memory/` are PR proposals, never auto-applied. +- **Rationale:** keeps the always-loaded rule set stable and reviewable. \ No newline at end of file diff --git a/agentic/memory/gotchas.md b/agentic/memory/gotchas.md new file mode 100644 index 000000000..f5bba014d --- /dev/null +++ b/agentic/memory/gotchas.md @@ -0,0 +1,9 @@ +# Gotchas + +Repo-specific traps and known gaps. Verify before acting; if a gap is closed, move it to `verified-facts.md` or delete it. + +- **Login is unthrottled.** `authLimiter` is defined and exported in `backend/src/middlewares/rateLimiter.js` but is **not** applied to any route (grep finds only the definition + export, no import sites). Treat login/credential endpoints as unprotected against brute force until this is wired in. +- **No tests run on PRs.** PR CI runs the Eclipse `eclipsefdn/eca` check (an Eclipse bot, not a workflow file) plus `agent-map-check.yml` (only for `agentic/`+docs changes); there is **no Jest/Playwright job on PRs** (`build-docker.yml` and `deploy-dev-stage.yml` run on push/merge, not PR open). Agents/authors must run `npm test` (backend) and Playwright (`.agents/`) locally and state how it was verified in the PR body. +- **Plugins execute unsandboxed in the browser.** Plugin code runs with page-level privileges, not in an iframe/Web Worker sandbox. Treat plugin input as trusted-but-audited, not untrusted. +- **`.env*` is gitignored but easy to leak.** Don't paste values into PRs, logs, or commit messages. `.agents/.env` and `instance-setup/.env.prod` are both gitignored. +- **`down.sh` is destructive on prod.** It tears down the Compose stack; never run it against a production instance without explicit confirmation (see `RULES.md`). \ No newline at end of file diff --git a/agentic/memory/verified-facts.md b/agentic/memory/verified-facts.md new file mode 100644 index 000000000..a8da13242 --- /dev/null +++ b/agentic/memory/verified-facts.md @@ -0,0 +1,9 @@ +# Verified facts + +Non-obvious facts confirmed by reading the code. Each has a one-line source pointer. If you re-verify and a fact has changed, update the line + date. + +- **Route domains:** `routes/v2/` has exactly four groups — `user-management/`, `vehicle-data/`, `content/`, `system/` — each with its own `index.js`. (Source: `backend/src/routes/v2/`.) +- **Frontend dev port is 3210**, set by the `dev` script (`vite --port 3210`); not 3000/5173. (Source: `frontend/package.json`.) +- **Frontend build is `tsc && vite build`** — type errors fail the build, so `npm run build` is a typecheck gate, not just a bundler. (Source: `frontend/package.json`.) +- **ECA check is email-bound:** commits must be signed off (`git commit -s`) with the same email the author used to sign the Eclipse Contributor Agreement; the `eclipsefdn/eca` PR check fails otherwise. Identity is per-contributor, not repo-wide. (Source: `docs/getting-started/contributing.md` + `.github/workflows/` ECA check.) +- **`authLimiter` exists but is unused** — see `gotchas.md`; confirmed by grep showing only the definition site in `middlewares/rateLimiter.js`. (Last verified: 2026-08-07.) \ No newline at end of file diff --git a/agentic/skills/README.md b/agentic/skills/README.md new file mode 100644 index 000000000..a11d0cd53 --- /dev/null +++ b/agentic/skills/README.md @@ -0,0 +1,77 @@ +# Skills + +Repo-specific procedures an agent loads **on demand** when a task matches. Each skill is a markdown file with *When to use · Steps · Guardrails · Exit criteria*. Don't preload all skills — load the one that fits. + +## Index + +### Orient & flow +| Skill | When to use | File | +|---|---|---| +| **Understand the repo** | Before any real work — orient cheaply via map + memory instead of scanning the whole repo. | [understand-the-repo.md](./understand-the-repo.md) | +| **Implement feature** | The canonical flow: branch → understand → implement → test → review → commit → PR. Start here for any change. | [implement-feature.md](./implement-feature.md) | +| **Run tests** | Before declaring done; after code changes. Jest (backend) + Playwright (`.agents/`). | [run-tests.md](./run-tests.md) | +| **Code review** | Self-review the diff before commit (correctness, reuse, simplification, altitude, style). | [code-review.md](./code-review.md) | +| **Security review** | When the diff touches auth, tokens, permissions, file ops, runtime/exec, plugins, secrets, CORS/CSP, uploads, or user data. | [security-review.md](./security-review.md) | +| **License check** | When the diff adds/modifies `.js`/`.ts`/`.tsx` or dependencies — verify Eclipse/MIT headers + no incompatible-license code. | [license-check.md](./license-check.md) | +| **Commit & PR** | When asked to commit / open a PR. ECA, sign-off, PR template. | [commit-and-pr.md](./commit-and-pr.md) | +| **Docs update** | After structural/endpoint changes — keep `docs/capabilities/`, `.agents/SITEMAP.md`, and `agentic/map/` in sync. | [docs-update.md](./docs-update.md) | +| **Learn & update** | Periodically — research best practices/trends, capture lessons, propose framework updates via PR. | [learn-and-update.md](./learn-and-update.md) | + +### Debug & correctness +| Skill | When to use | File | +|---|---|---| +| **Debug** | Something is broken and you need to find where — symptom→where-to-look decision tree (winston/morgan, Docker/pm2 logs, browser console, Socket.IO frames, Playwright trace). | [debug.md](./debug.md) | +| **Find race conditions** | Suspected concurrency bug — no Mongo transactions, so atomicity is doc-level; check read-modify-write, counters, token single-flight, Socket.IO ordering, seed-vs-save races. | [find-race-conditions.md](./find-race-conditions.md) | + +### Build (add / change) +| Skill | When to use | File | +|---|---|---| +| **Add endpoint** | Adding a new v2 API endpoint — route → controller → service → model → auth gating → validation → capability doc → SITEMAP. | [add-endpoint.md](./add-endpoint.md) | +| **Add frontend feature** | Adding a page/component — atomic-design placement, route table, store/hook, API client, permission gate, E2E spec. | [add-frontend-feature.md](./add-frontend-feature.md) | +| **DB schema change** | Evolving a Mongoose model — additive fields, indexes/TTL, backfill scripts (no migration tool; no transactions). | [db-schema-change.md](./db-schema-change.md) | +| **Realtime event** | Adding a Socket.IO event — contract, `config/socket.js`, kit-server relay, subscribe→run→stop lifecycle, frontend listener. | [realtime-event.md](./realtime-event.md) | +| **Add test** | Adding a Jest spec (backend) or Playwright spec (`.agents/`) — fixtures, helpers, snapshot policy. | [add-test.md](./add-test.md) | + +### Review & health +| Skill | When to use | File | +|---|---|---| +| **Performance review** | Perf review of a diff/area — Mongo N+1/`populate`/indexes, external `CACHE_URL`/`LOG_URL` calls, frontend bundle, Socket.IO fan-out. | [performance-review.md](./performance-review.md) | +| **Dependency upgrade** | Upgrading an npm dep / clearing a Dependabot alert — audit, breaking-change check, tests, license compatibility. | [dependency-upgrade.md](./dependency-upgrade.md) | + +### Deploy & ops +| Skill | When to use | File | +|---|---|---| +| **Deploy** | When asked to deploy an instance — `instance-setup/` Docker Compose happy path. | [deploy.md](./deploy.md) | +| **Troubleshoot deploy** | When the stack won't come up — symptom→cause→fix (env, ports, Mongo, prototypes bind-mount, Coder reachability). | [troubleshoot-deploy.md](./troubleshoot-deploy.md) | +| **Coder workspace** | Debugging/extending the VS Code-in-browser integration — `instance-setup/coder/` + `plans/`, workspace lifecycle, `CODER_URL`. | [coder-workspace.md](./coder-workspace.md) | + +### Specialized +| Skill | When to use | File | +|---|---|---| +| **Plugin authoring** | Writing a plugin — `window.DAPlugins`/`PluginAPI`, unsandboxed model, `e2e-simple-plugin` fixture, upload. | [plugin-authoring.md](./plugin-authoring.md) | +| **Secrets incident** | A secret may have leaked — identify, blast radius, rotate-at-source, scrub logs/PRs, incident note. | [secrets-incident.md](./secrets-incident.md) | + +## The core flow + +``` +implement-feature + ├─ understand-the-repo (orient) + ├─ implement (per CONVENTIONS) + │ ├─ add-endpoint / add-frontend-feature / db-schema-change / realtime-event (by task type) + │ └─ add-test (add coverage as you go) + ├─ run-tests + ├─ code-review + │ ├─ security-review (if auth/data/runtime/plugins) + │ ├─ license-check (if new/changed .js/.ts/.tsx or deps) + │ └─ performance-review (if perf-sensitive area) + └─ commit-and-pr +broken? → debug → find-race-conditions +after merge → docs-update (if structure/endpoint changed) +on schedule → learn-and-update · dependency-upgrade +deploy broken? → troubleshoot-deploy · coder-workspace +secret leaked? → secrets-incident +``` + +## Wiring into Claude Code + +Skills are plain markdown. To invoke them via Claude Code's Skill tool natively, symlink each into `.claude/skills/` (see [`../SETUP.md`](../SETUP.md)). Otherwise just load the file when the task matches. \ No newline at end of file diff --git a/agentic/skills/add-endpoint.md b/agentic/skills/add-endpoint.md new file mode 100644 index 000000000..79a4456dd --- /dev/null +++ b/agentic/skills/add-endpoint.md @@ -0,0 +1,35 @@ +# Skill: add-endpoint +> The canonical procedure for adding a new v2 API endpoint end-to-end, keeping routes/controllers/services/models layering. + +## When to use +- When the task is "add an endpoint", "add an API route", "expose X over HTTP", or a feature requires new backend read/write surface. +- When extending an existing domain with a new verb/path under `routes/v2/`. + +## Steps +1. **Pick the domain.** Match existing grouping under `backend/src/routes/v2/{user-management,vehicle-data,content,system}/`. Each domain has an `index.js` that aggregates `*.route.js`. Add a new `*.route.js` only if the resource doesn't fit an existing file; otherwise extend the existing one. Read `routes/v2/index.js` to confirm aggregation. +2. **Add the service logic** in `backend/src/services/.service.js` (create the function, keep it pure-ish, throw `ApiError` for failures). Business logic lives here — not in routes/controllers. +3. **Add a thin controller** in `backend/src/controllers/.controller.js` that parses the request and delegates to the service. No business logic, no direct Mongoose calls. +4. **Touch the Mongoose model** in `backend/src/models/.model.js` only if a schema change is required — if so, run [`./db-schema-change.md`](./db-schema-change.md) in parallel (backfill script, index, validations). +5. **Choose auth gating.** Public-optional reads: `auth({ optional: (req) => req.authConfig.PUBLIC_VIEWING })`. Writes and non-public reads: `auth(...)` + `checkPermission('')` (RBAC v1, owner bypass; roles: readModel/writeModel/manageUsers/readAsset/writeAsset/generativeAI/deployHardware). Errors flow through `middlewares/error.js` via `ApiError`. +6. **Add Joi validation** in `backend/src/validations/.validation.js` (and export from `validations/index.js` if used) when the body/query/params shape matters. Wire it via `middlewares/validate.js`. +7. **Register the route.** In the domain `index.js` (or a new `*.route.js` imported there), mount the router. Confirm the path appears under `routes/v2/index.js` aggregation so it's live. +8. **Add a Jest test.** Per [`./add-test.md`](./add-test.md) — cover the happy path, the auth-denied path, and one validation failure. Run `cd backend && npm test`. +9. **Update the capability doc.** Per [`./docs-update.md`](./docs-update.md), edit `docs/capabilities/.md` (code-grounded): add the endpoint with method/path, who uses it, value, acceptance criteria, security + **Risks:**, data protection + **Risks:**, and a mermaid diagram if the flow is non-trivial. Verify every claim against the code you just wrote. +10. **Update `.agents/SITEMAP.md`** only if the endpoint backs a user-facing page/feature. +11. **Lint/format:** `cd backend && npm run lint && npm run prettier`. +12. **Self-review.** Run [`./code-review.md`](./code-review.md); because this touches auth/data, also run [`./security-review.md`](./security-review.md). Add the Eclipse/MIT SPDX header to any new `.js` file ([`./license-check.md`](./license-check.md)). + +## Guardrails +- Controllers stay thin. No business logic in routes or controllers. No Mongoose calls in controllers. +- Don't fabricate permission names or statuses — read `middlewares/permission.js` / the role model. +- Don't edit `docs/capabilities/*` claims without verifying against the new route/controller code. +- If the endpoint touches auth, tokens, file ops, or runtime, `security-review` is mandatory. +- New `.js` files must carry the SPDX header. +- Don't register a route outside its domain `index.js` — it won't be mounted. + +## Exit criteria +- Route is live under `routes/v2//`, controller delegates to service, model touched only if needed. +- Auth + validation chosen deliberately and verified against existing patterns. +- Jest test added and green; lint + prettier clean. +- Capability doc updated with code-grounded claims (incl. Risks); SITEMAP updated if page-facing. +- Self-review (+ security-review) done; SPDX headers present on new files. \ No newline at end of file diff --git a/agentic/skills/add-frontend-feature.md b/agentic/skills/add-frontend-feature.md new file mode 100644 index 000000000..9a4d93962 --- /dev/null +++ b/agentic/skills/add-frontend-feature.md @@ -0,0 +1,40 @@ +# Skill: add-frontend-feature +> Placing a frontend feature correctly in atomic design and wiring routes/state/permissions without bypassing the layering. + +## When to use +- When the task adds a UI feature: a new page, a reusable component, a UI-gated action, or a new screen flow. +- When you need to call a backend endpoint from the frontend and expose it to users. + +## Steps +1. **Choose the layer by scope.** + - **Atom** (`components/atoms/`): single-purpose primitive (button, input, badge). No page logic, no API calls. + - **Molecule** (`components/molecules/`): a small composition of atoms (form field, card). No API calls; receives props/callbacks. + - **Organism** (`components/organisms/`): a self-contained section that may fetch data via `services/` and hold local state. + - **Page** (`pages/`): route-level screen composing organisms/molecules. Page-level effects and data orchestration live here. + - **Layout** (`layouts/`): shell shared by pages (nav, chrome). + Match the existing component style/props pattern in the chosen folder — read 1-2 neighbors first. +2. **Register the route** (if page-level) in `frontend/src/configs/routes.tsx` — the single route table. Don't invent a parallel router. Add the lazy import and the `` entry with its permission guard if applicable. +3. **Add a Zustand store** in `frontend/src/stores/` **only** if state must persist across unrelated components/pages. For local or component-tree state, use React state/props. Match `authStore.ts` style. +4. **Add a hook** in `frontend/src/hooks/` for reusable logic (data fetching wrapper, derived flag, etc.). Gate UI permissions through `hooks/usePermissionHook.ts` — don't scatter raw role checks. +5. **Call the API via `services/`.** Add/extend a client in `frontend/src/services/` that hits the backend endpoint (see [`./add-endpoint.md`](./add-endpoint.md)). Never call `fetch`/`axios` directly from a molecule or atom; organisms/pages call service functions, atoms/molecules receive data via props. +6. **Type everything.** TS types for props, store shape, API responses. No `any` unless the surrounding code uses it. +7. **Build + lint:** `cd frontend && npm run build` (runs `tsc && vite build` — the typecheck gate) and `npm run lint` (ESLint, `--max-warnings 0`). Fix your own errors; don't silence rules. +8. **Add a Playwright spec** in `.agents/tests/*.spec.ts` per [`./add-test.md`](./add-test.md) for the user-facing flow. Run `cd .agents && npx playwright test`. +9. **Update `.agents/SITEMAP.md`** — flip the page/feature from ❌/⚠️ to ✅ (or add a row) to track coverage. +10. **Update docs.** If the feature exposes a new capability or changes a user-facing flow, run [`./docs-update.md`](./docs-update.md) against `docs/capabilities/.md` (code-grounded; verify claims against the new component/route). +11. **Self-review.** [`./code-review.md`](./code-review.md); add the Eclipse/MIT SPDX header to any new `.ts`/`.tsx` file ([`./license-check.md`](./license-check.md)). + +## Guardrails +- No page logic or API calls in atoms or molecules. Atoms/molecules receive data + callbacks as props. +- Don't bypass `configs/routes.tsx` — no ad-hoc routers or hardcoded nav. +- Don't add a Zustand store for one-component state; use React state. +- Don't bypass `usePermissionHook.ts` for role/permission gating. +- Don't ignore `tsc` errors — `npm run build` is the gate; lint must be `--max-warnings 0`. +- New `.ts`/`.tsx` files must carry the SPDX header. +- Don't fabricate component paths — read the folder before adding. + +## Exit criteria +- Component placed at the correct atomic layer; route registered in the table (if page-level). +- State in a store only if cross-component; permissions via the hook; API calls via `services/`. +- `npm run build` + `npm run lint` green; Playwright spec added and passing. +- `.agents/SITEMAP.md` and capability doc updated; SPDX headers present; self-review done. \ No newline at end of file diff --git a/agentic/skills/add-test.md b/agentic/skills/add-test.md new file mode 100644 index 000000000..70d156aa5 --- /dev/null +++ b/agentic/skills/add-test.md @@ -0,0 +1,64 @@ +# Skill: add-test +> Add a new test to the repo by kind — backend Jest unit/integration, or `.agents/` Playwright E2E. + +## When to use +- After implementing/fixing a feature and needing coverage for it (RULES.md: run tests before declaring done). +- When closing a coverage gap surfaced by `run-tests` or `code-review`. +- When a Playwright spec is missing for a page/flow you changed (check `.agents/SITEMAP.md` coverage status). + +## Steps + +### 1. Pick the kind +- Backend logic (services, controllers, models, utils) → Jest in `backend/`. +- Frontend page/flow or full request→response behavior → Playwright in `.agents/`. +- Frontend pure logic has no unit runner wired — prefer Playwright or refactor logic into a testable module; do not invent a Vitest/Jest setup. + +### 2. Backend Jest (`backend/`) +- Colocate the spec next to the code, or place it under the existing tests dir. Only ~8 Jest files exist — read one first and **match the existing spec style** (describe/it layout, setup/teardown, naming). +- File name: `.test.js` (or match the neighbor's convention). +- Mock external calls so tests don't depend on live services: + - `CACHE_URL` (`/get-recent-activities/:userId`) and `LOG_URL` calls go through `backend/config/axios.js` — mock that module rather than hitting the network. + - Mock Mongoose models or use a real Mongo instance (see next bullet) per existing specs. +- If the spec needs MongoDB and none is running, start the local container: + ```bash + docker run -d --name autowrx-mongo-test -p 27017:27017 mongo:4.4.6-bionic + ``` +- Run the file, then the whole suite to confirm no regressions: + ```bash + cd backend && npx jest path/to/file.test.js + cd backend && npm test + cd backend && npm run lint && npm run prettier + ``` + +### 3. Playwright E2E (`.agents/`) +- Add `tests/.spec.ts`. Read 1-2 existing specs first and mirror their structure (`test.describe`, `test.beforeEach` login, selectors from `helpers.ts`). +- Reuse `tests/helpers.ts` rather than re-implementing: + - `ADMIN` (from `ADMIN_EMAIL`/`ADMIN_PASSWORD` env), `TEST_USER` (`testuser@autowrx.test` / `TestPass123!`). + - `API_URL` (defaults from `BASE_URL` :3210 → :3200), `RUNTIME_SERVER_URL` (default `http://localhost:3090`), `RUNTIME_SERVER_CONFIG`. + - `loginAs`/`loginAsAdmin`/`logout`, `getAuthToken`, `createTestModelViaApi`, `createTestPrototype`, `setPrototypeStateViaApi`. + - Selectors: `LIBRARY_SEARCH_SELECTOR`, `[data-id="..."]` attributes used across specs. +- For plugin tests, use the `e2e-simple-plugin` fixture: `E2E_PLUGIN_FIXTURE_DIR` (`tests/fixtures/e2e-simple-plugin/`), `E2E_PLUGIN_ZIP_PATH`, `routeExternalPluginScript`, `createInternalPluginViaAdminZip`, `expectPluginDetailLoaded` with `E2E_PLUGIN_MARKER`. +- Follow the snapshot policy in `.agents/TESTING.md`: screenshots to `tests/screenshots/`, baseline updates via `--update-snapshots`, `--screenshot=only-on-failure` for runs. +- Run: + ```bash + cd .agents && npx playwright test tests/.spec.ts + cd .agents && npx playwright test # full sweep + cd .agents && npx playwright show-report # on failure + ``` +- After the spec is green, update `.agents/SITEMAP.md` coverage status to ✅ for the page/flow now covered. + +### 4. License header +- New `.js`/`.ts`/`.tsx` source files (including test files) must start with the Eclipse/MIT `SPDX-License-Identifier: MIT` header — see `license-check` skill. `.md`/`.sh`/`.yml` do not carry it. + +## Guardrails +- Don't commit `.env` (`.agents/.env`, `backend/.env`) — gitignored. Copy from `.env.example` locally only. +- Don't make tests depend on execution order or shared mutable state between specs. Keep specs atomic; clean up created entities (or use uniquely-named ones per run). +- Don't disable lint/test rules silently to make green — fix the code or surface the conflict. +- Don't assert on brittle selectors/text that flake; prefer `[data-id="..."]` attributes and `getByRole` over CSS classes. +- Don't invent a frontend unit-test framework. If you believe one is needed, propose it first. + +## Exit criteria +- The new test passes locally with the exact command(s) cited, and the surrounding suite is still green. +- Lint/format pass on the touched files. +- `.agents/SITEMAP.md` updated (for E2E) and any new source file carries the MIT header. +- Cross-link: hand off to `run-tests` for full runs, `code-review` for diff review, `docs-update` if a capability/coverage doc changed. \ No newline at end of file diff --git a/agentic/skills/code-review.md b/agentic/skills/code-review.md new file mode 100644 index 000000000..ba09d8aed --- /dev/null +++ b/agentic/skills/code-review.md @@ -0,0 +1,43 @@ +# Skill: code-review +> Self-review your own diff before commit — correctness, reuse, simplicity, altitude, style, and secrets. + +## When to use +- Before every commit (RULES.md: self-review your diff before commit). +- As the final check in [`./implement-feature.md`](./implement-feature.md), before [`./commit-and-pr.md`](./commit-and-pr.md). + +## Steps +1. **Produce the diff to review:** + ```bash + git diff main...HEAD # everything on this branch + git diff # unstaged + git diff --staged # staged + ``` +2. **Walk this checklist against the diff:** + - **Correctness:** Does it do what the task asked? Edge cases handled? Error/empty states covered? + - **Reuse:** Did you duplicate an existing util/service/hook/component? Search before adding new. Prefer extending `services/` logic over re-implementing in a controller. + - **Simplification:** Anything dead, overly clever, or copy-pasted that could be simpler? Consider the `simplify` skill. + - **Efficiency:** N+1 queries, unnecessary re-renders, blocking I/O on hot paths, repeated work in loops. + - **Altitude (right layer):** Backend — is the controller thin and logic in `services/`? Frontend — is logic in the right atomic level (no page logic in atoms)? See `docs/principles/principle.md`. + - **Matches surrounding style:** naming, comment density, idioms, export style. No drive-by reformatting outside the change's scope. + - **No secrets:** `.env*`, tokens, keys, cookies, internal URLs not in the diff. + - **No fabricated claims:** new endpoint/status/flag in `docs/capabilities/` matches the actual route/controller code. +3. **Run verification:** + ```bash + cd backend && npm run lint && npm run prettier + cd frontend && npm run lint && npm run tsc + ``` + Then [`./run-tests.md`](./run-tests.md) for affected suites. Fix your own lint errors; don't disable rules silently. +4. **Sensitive change?** If the diff touches auth, tokens, file operations, runtime execution, or plugins, also run [`./security-review.md`](./security-review.md) before commit. If it adds/modifies `.js`/`.ts`/`.tsx` or dependencies, also run [`./license-check.md`](./license-check.md) (Eclipse/MIT header + no incompatible-license code). +5. **Docs in sync?** If structure/capabilities changed, run [`./docs-update.md`](./docs-update.md) so `agentic/map/` and `docs/capabilities/` stay code-grounded. + +## Guardrails +- This is self-review on your own diff — don't skip it because "it's small." Review every diff. +- No drive-by reformatting outside the change's scope; match surrounding code. +- Don't mark "reviewed" if lint or tests fail. Report honestly. +- Don't weaken tests/lint to pass; fix the code or surface the conflict. + +## Exit criteria +- Every checklist item answered (mentally or in notes) with no open correctness/reuse/altitude/style/secrets issues. +- Lint + prettier + tsc + affected tests are green (or honestly reported as unrun). +- Security-review completed where applicable. +- The diff is ready for [`./commit-and-pr.md`](./commit-and-pr.md). \ No newline at end of file diff --git a/agentic/skills/coder-workspace.md b/agentic/skills/coder-workspace.md new file mode 100644 index 000000000..b1750f9bb --- /dev/null +++ b/agentic/skills/coder-workspace.md @@ -0,0 +1,36 @@ +# Skill: coder-workspace +> Debug or extend the Coder (VS Code in browser) integration: workspaces, templates, and the backend↔Coder link. + +## When to use +- A change to the Coder integration: workspace templates, the runner image, entrypoint, or the backend↔Coder wiring. +- A workspace won't start, can't see the prototypes tree, or the Coder tab in the app is broken. +- You need to add/adjust a Terraform template (docker / k8s / AKS). + +## Steps +1. **Locate the moving parts.** + - `instance-setup/coder/` — `autowrx-runner` (runner image), `coder-docker-compose.yml` (Coder control plane on `:7080`), `coder-entrypoint.sh` (workspace entrypoint), `terraform-provider-mirror`. + - `plans/` — Terraform templates: `docker-template.tf`, `docker-template.zip`, `k8s-template.tf`; `setup_coder_aks.sh`, `prepare-templates.sh`, `integration-plan.md`, `guide.md`, `cursor_webapp_and_coder_workspace_integ.md`. + - Backend side: the app reaches Coder at `host.docker.internal:7080` via the `CODER_URL` site config (set in the admin panel / DB siteconfig). +2. **Understand the lifecycle.** Template (uploaded to Coder) → Workspace (created from template by a user) → workspace container bind-mounts the prototypes path so the editor sees the same tree the backend serves. The backend only talks to Coder's API; it does not manage workspace containers directly. +3. **Reproduce the symptom.** + - Coder control plane down? `docker compose -f instance-setup/coder/coder-docker-compose.yml ps` and open `http://localhost:7080`. + - Workspace won't create? Check Coder dashboard logs and the template's Terraform (`plans/*.tf`). + - Workspace opens but prototypes tree is empty/wrong → the workspace bind-mount and the backend bind-mount **must be the same `${PROTOTYPES_PATH}`** (commits d6807b4, 6bd6ccb). Compare `docker compose -f docker-compose.prod.yml config | grep -A3 prototypes` with the workspace template's mount block. + - App's Coder tab / actions fail → backend can't reach Coder: confirm `extra_hosts: ["host.docker.internal:host-gateway"]` on the `autowrx` service and that `CODER_URL` siteconfig points at `http://host.docker.internal:7080`. See `troubleshoot-deploy.md`. +4. **Make the change.** Edit the template/runner/entrypoint. If changing a Terraform template, re-zip with `prepare-templates.sh` (or `zip docker-template.zip docker-template.tf`) and re-upload via the Coder dashboard (Templates → Create → Upload). If changing the runner image, rebuild it. +5. **Test workspace create + teardown.** Create a workspace from the updated template, confirm the editor loads and the prototypes tree matches the backend's view, then delete the workspace. Don't leave orphaned workspaces. +6. **Update docs.** If the wiring or a template changed, update `plans/guide.md` / `plans/integration-plan.md` and `docs/` pointers (see `docs-update.md`). + +## Guardrails +- Don't restart the `autowrx` (app) service for a Coder-only change if the backend is healthy — touch only the Coder control plane / templates / workspaces. +- Keep the prototypes bind-mount identical between Coder workspaces and the `autowrx` backend; divergence silently breaks the tree view. +- Never commit secrets (Coder admin password, tokens). `.env*` is gitignored. +- Test workspace create **and** teardown — a broken teardown leaks containers/volumes. +- Terraform template edits must be re-zipped and re-uploaded to Coder; an unzipped `.tf` alone does nothing. + +## Exit criteria +- Workspace starts from the updated template, sees the correct prototypes tree, and tears down cleanly. +- Backend↔Coder link verified (Coder tab/actions work). Docs updated if wiring changed. + +## Cross-links +- `deploy.md`, `troubleshoot-deploy.md`, `docs-update.md`. \ No newline at end of file diff --git a/agentic/skills/commit-and-pr.md b/agentic/skills/commit-and-pr.md new file mode 100644 index 000000000..d85405f84 --- /dev/null +++ b/agentic/skills/commit-and-pr.md @@ -0,0 +1,31 @@ +# Skill: Commit & PR +> Stage, sign off, push, and open a PR against `main` for the finished change. + +## When to use +When the work is verified (tests pass per `./run-tests.md`, self-reviewed per `./code-review.md`, and security-sensitive changes cleared per `./security-review.md`) and the user has asked to commit and/or push and/or open a PR. Each of commit / push / PR is a **separate authorization** — do none unless asked (see `RULES.md`). + +## Steps +1. **Verify identity first.** `git config user.name` / `git config user.email` must read **your own** ECA-signed identity — the email you signed the ECA with. Each contributor uses their own account; there is no repo-wide identity. Ensure `user.email` matches your ECA sign-up email, or the `eclipsefdn/eca` check will fail. +2. **Confirm you're not on `main`.** `git branch --show-current` — if it's `main`, branch off first: `git switch -c /` (types: `feat`, `docs`, `fix`, `chore`, `refactor`; see `CONVENTIONS.md`). Branch naming: `/-` or `/`. +3. **Stage only intended files.** `git add `. Never `git add -A`/`.` blindly. **Never stage `.env*`**, tokens, keys, or cookies — confirm via `git diff --cached --name-only` before committing. If a secret slipped in, unstage it; if already committed, that's a separate incident (rotate the secret). +4. **Commit with sign-off + attribution.** `git commit -s -m "" -m "..."` and an attribution trailer when the tool uses one — Claude Code: `-m "Co-Authored-By: Claude "`; other tools: their equivalent, or omit. The `-s` adds the `Signed-off-by:` line required by the Eclipse ECA. One logical change per commit where practical. +5. **Re-read the commit before pushing.** `git show --stat HEAD` and skim the message. Confirm summary is imperative, body explains the why, sign-off + co-author trailers are present, and the staged file list matches intent. +6. **Push the branch** (only if asked). `git push -u origin `. Never force-push shared refs; force-push only your own unshared feature branch and only when necessary. +7. **Open the PR against `main`** (only if asked) via `gh pr create --base main`. Title: `(): `. Body sections: + - **What:** what changed (1-3 lines). + - **Why:** the motivation / issue context. + - **How verified:** the exact commands you ran (`backend: npm test`, `cd .agents && npx playwright test ...`, `npm run lint`, manual steps) — the PR pipeline runs the **ECA check only**, so CI won't run tests; state how you verified it. If security-sensitive, note `./security-review.md` result. + - Issue link: `Closes #nnn` or `Ref #nnn`. +8. **Note the ECA requirement** in the PR body or comment if the author/committers might not be signed: every commit author must have signed the ECA (https://accounts.eclipse.org/) with the commit email, or the ECA check fails. Don't commit under an unsigned identity. +9. **Return the PR URL** to the caller. If you only committed (no PR asked), return the short SHA + branch name. + +## Guardrails +- **Commit only when asked; push only when asked; PR only when asked.** Each is separate (RULES.md). +- **Never commit on `main`.** Never force-push `main` or any shared branch. +- **Never commit secrets** (`.env*`, tokens, keys, cookies) — they're gitignored; keep them out. +- Don't rebase/rewrite history that's already pushed to a shared branch. +- If pre-commit hooks (Husky) fail on lint/format, fix your own errors; don't disable rules or `--no-verify` past them silently. +- Don't bundle unrelated changes into one PR to ship faster — split per `CONVENTIONS.md`. + +## Exit criteria +- PR opened against `main`: return the **PR URL** and confirm ECA check is required/pending. Or, if only a commit was authorized: return the **SHA + branch** and state that push/PR still needs explicit ask. Verify `git log -1 --format='%an <%ae>%n%(trailers:key=Signed-off-by)'` shows the correct identity and a `Signed-off-by:` trailer (and the tool's attribution trailer if you added one). \ No newline at end of file diff --git a/agentic/skills/db-schema-change.md b/agentic/skills/db-schema-change.md new file mode 100644 index 000000000..d0c19a2d6 --- /dev/null +++ b/agentic/skills/db-schema-change.md @@ -0,0 +1,36 @@ +# Skill: db-schema-change +> Evolving Mongoose models safely when there is no migration tool (schema-on-read, no Mongo transactions). + +## When to use +- When adding, renaming, removing, or re-typing a field on a Mongoose model in `backend/src/models/`. +- When adding an index (including TTL) or changing a default/validator. +- When a schema change requires backfilling existing documents. + +## Steps +1. **Read the model first.** Open `backend/src/models/.model.js` and the surrounding `services/.service.js` to see how the field is queried/updated. Check `agentic/memory/gotchas.md` for known issues (e.g. the `Token` collection has **no TTL index** — revoked/abandoned refresh tokens accumulate; adding a TTL on an expiry/revoked-at field is a good candidate here). +2. **Prefer additive, optional, defaulted changes.** Add new fields as `{ type, default }` (or `required: false`). Schema-on-read means old docs simply lack the field — Mongoose returns the default for `lean` only with `defaults` set; for full docs the default applies on access. Avoid renaming or removing fields; if you must, plan a backfill (step 5) before dropping the old name. +3. **Edit the schema** in `models/.model.js`. Add the field, `default`, any `enum`/`validate`/`ref`. Match the file's existing style (schema definition pattern, timestamps usage). +4. **Add an index if needed.** Define indexes on the schema (`: 1`, unique compounds, TTL via `index({ : 1 }, { expireAfterSeconds })`). Note: Mongoose creates the index on next app boot for a new field; for an existing field, ensure the index won't conflict with existing data (unique). Cite the Token TTL gap explicitly if you're adding a TTL there. +5. **Write a backfill script** in `backend/src/scripts/` when a default/transform is needed for old docs (e.g. set `newField = defaultValue` for all docs missing it, or compute `newField` from `oldField`). Make it idempotent (filter on `{ newField: { $exists: false } }` or `$or` checks) and dry-run-safe (log counts before/after; support a `--dry-run` flag). Run it against the target env explicitly — never auto-run in a migration hook. +6. **Update validations.** In `backend/src/validations/.validation.js`, add the field to the relevant Joi schema (body/query) with the right type, optional/required, and `enum` if the model constrains it. Export from `validations/index.js` if introduced there. +7. **Update the service + controllers** that read/write the field. Don't leak the old name if renaming; keep a read shim during transition if needed. +8. **Update the capability doc.** Per [`./docs-update.md`](./docs-update.md), edit `docs/capabilities/.md` — document the field, its default for old docs, the index, and any **Risks:** (e.g. "old docs read as default until backfill runs"). Verify the claim against the schema + script. +9. **Add a test.** Per [`./add-test.md`](./add-test.md) — unit test the model default, the backfill script's idempotency, and any service branch that depends on the field. Run `cd backend && npm test`. +10. **Lint/format:** `cd backend && npm run lint && npm run prettier`. +11. **Self-review.** [`./code-review.md`](./code-review.md); if the change affects query performance or large collections, also run [`./performance-review.md`](./performance-review.md). Add the Eclipse/MIT SPDX header to any new `.js` file ([`./license-check.md`](./license-check.md)). + +## Guardrails +- **No migration tool.** Don't invent one. Backfills are one-off scripts in `backend/src/scripts/`, run by a human against a named env. +- **Don't remove or rename a field without a backfill** — old documents will break readers that expect the old name, and writers that set it. +- **Prefer additive changes**: optional field + default. Avoid `required: true` on a new field unless every old doc is backfilled first. +- **No `withTransaction` / Mongo transactions** — the deployment is not guaranteed to be a replica set. +- **Never drop a collection or index in a script** without explicit user confirmation. Adding indexes is fine; dropping is destructive. +- **Index cost:** adding an index on a large collection has a runtime + storage cost — call it out and prefer `performance-review` for hot paths. +- New `.js` files must carry the SPDX header. + +## Exit criteria +- Schema change is additive (or a documented, idempotent backfill ships alongside a rename/remove). +- Index/TTL added intentionally (or explicitly skipped with a reason); Token TTL gap cited if relevant. +- Validations, service, controller, and capability doc updated and verified against code. +- Backfill script (if needed) is idempotent and dry-run-safe; Jest test added and green; lint clean. +- Self-review (+ performance-review where applicable) done; SPDX headers present. \ No newline at end of file diff --git a/agentic/skills/debug.md b/agentic/skills/debug.md new file mode 100644 index 000000000..575d1053f --- /dev/null +++ b/agentic/skills/debug.md @@ -0,0 +1,56 @@ +# Skill: Debug +> Symptom → where-to-look decision tree for this repo (backend, frontend, realtime, E2E). + +## When to use +Run this when diagnosing any unexpected behavior, error, or flake in the app or its tests. Pick the lane that matches the symptom and follow its branches. Cross-link `./find-race-conditions.md` for concurrency-shaped bugs, `./run-tests.md` for reproducing, `./troubleshoot-deploy.md` for deployed-env issues. + +## Steps + +### 0. Reproduce first +Get a minimal repro before touching code. Note the exact request/event/user/environment. For flaky behavior, run it 5–10×; if it only fails under load or parallel clicks, switch to `./find-race-conditions.md`. + +### 1. Backend lane +- **Logs (winston):** `backend/src/config/logger.js` is the source. Dev: `cd backend && npm run dev` (nodemon) → stdout. PM2: `pm2 logs`. Docker: `docker logs autowrx` / `docker logs -f autowrx`. External aggregation: backend proxies to `LOG_URL` (`config/config.js`, `config/axios.js`) — if a log line never reaches the external UI, check that proxy + `LOG_URL` reachability. +- **HTTP layer:** morgan logs requests + status (`app.js:37` morgan.errorHandler). A 500 here means an exception escaped the route handler. +- **Centralized error path:** `middlewares/error.js` (ApiError, errorConverter, errorHandler) wired at `app.js:292`. If an error returns the wrong status or shape, verify it reaches `errorHandler` (throw `ApiError` / pass `next(err)`, don't swallow). If a route returns raw `Error`, it bypassed conversion. +- **Node inspector:** `node --inspect` / `--inspect-brk` on the backend process; chrome://inspect. Step through the suspect service. With nodemon, set `NODE_OPTIONS=--inspect`. +- **Mongo query inspection:** enable Mongoose debug (`mongoose.set('debug', true)`) or log in the service to see the actual query/filter/update. Confirm indexes used (`explain`). Many bugs here are a missing filter or a stale field after a schema change (see `./db-schema-change.md`). + +### 2. Frontend lane +- **No ErrorBoundary:** `frontend/src/main.tsx` wraps in `React.StrictMode` only. Unhandled render errors surface in the **browser console** — that is the primary signal. In StrictMode, effects run twice in dev; don't chase a "double call" that only happens in dev. +- **Dev tools:** Vite dev server on port **3210** (`cd frontend && npm run dev`). Use React DevTools (components tree, hooks state) + Vite/Chrome DevTools. +- **Network tab:** inspect failing API calls (status, payload, `Set-Cookie`). For auth issues, check the refresh-token 401 replay path (see table below) and whether the httpOnly refresh cookie is present. +- **Socket.IO frames:** Network → WS filter; inspect frames for event names + payload ordering. `subscribe_apis` must precede `run_*` events (see Realtime lane). +- **Type errors:** `cd frontend && npm run build` runs `tsc && vite build` — surface silent type drift that dev HMR hides. + +### 3. Realtime lane (Socket.IO) +- Server: `backend/src/config/socket.js` (Socket.IO server; JWT auth via `handshake.query.access_token`). Events: `subscribe_apis`, `run_python_app`, `run_rust_app`, `stop_python_app`, `run_until_complete`, `fetchSignalMapping`, `replaceSignalMapping`, `fetchVss`, `replaceVss`, `replaceApi`. +- Runtime exec is **REMOTE** via `RUNTIME_SERVER_URL` (external kit/runtime server), NOT local `child_process`. The only local spawn is `spawn('unzip', …)` in `controllers/plugin.controller.js`. If "run app" fails, check the kit server reachability + event ordering, not `child_process`. +- Trace ordering: log on both emit and receive. A missing `subscribe_apis` before `run_*` is a common silent failure. Concurrent `run`/`stop` and `replaceSignalMapping`/`replaceVss` racing → `./find-race-conditions.md`. +- Reconnect: check `RUNTIME_SERVER_CONFIG` reconnectionAttempts/backoff on the kit-client side. + +### 4. E2E lane (Playwright) +- `cd .agents && npx playwright test`. On failure: `npx playwright show-report`, `--headed`, `--trace=on`, `--screenshot=only-on-failure`. Trace > screenshot > video for pinning the cause. Keep `.agents/SITEMAP.md` coverage in sync if the failure reflects a real page change. +- Env via `.agents/.env` (gitignored; see `.agents/.env.example`) — a missing var produces confusing auth/nav failures. + +## Common symptoms → root cause +| Symptom | Likely cause | First look | +|---|---|---| +| 401 loop on the frontend | refresh-token single-flight broken / refresh failure → `logOut` | `stores/authStore.ts`, queued-request replay on 401 | +| Empty workspace / file tree | prototypes bind-mount / `CODER_URL` / orchestrator not prepared | `services/orchestrator.service.js`, prototype seed (commit `6bd6ccb`) | +| 503 / health-check degraded | a dependent service (kit/runtime, `CACHE_URL`, `LOG_URL`, Mongo) down | `troubleshoot-deploy.md`, `config/axios.js`, health route | +| Recent prototypes missing in UI but exist in DB | `CACHE_URL` eventual consistency — list comes from `${CACHE_URL}/get-recent-activities/:userId`, not DB | `services/prototype.service.js` ~line 260; wait/cache-bust | +| New prototype has no README/main.* templates | seed-vs-save race (fixed by `6bd6ccb`); regression if seed moved out of `createPrototype` | `services/prototype.service.js` createPrototype | +| 500 with wrong status/shape | error bypassed `middlewares/error.js` | route handler: use `next(err)` / throw `ApiError` | +| "double API call" in dev only | `React.StrictMode` double-render | not a bug; verify in `npm run build` preview | +| Playwright flake | timing / async wait missing | `--trace=on`, re-run 5× | +| `run_*` event silently does nothing | missing `subscribe_apis` first, or kit server unreachable | WS frames tab, `RUNTIME_SERVER_URL` | + +## Guardrails +- Reproduce before fixing; never "fix" a symptom you haven't seen. +- Don't silence an error (empty catch, swallow `next`) to make it disappear — that hides it from `middlewares/error.js` and from future debugging. If you must handle, log it. +- Don't edit `docs/capabilities/*` claims during a debug pass unless the code now contradicts the doc (then do it via `./docs-update.md`). +- No secrets in logs/screenshots/traces you share. + +## Exit criteria +Return: **repro steps**, the **root cause** with `file:line`, the **fix** (or a pointer to the skill that should implement it, e.g. `./find-race-conditions.md`), and how it was **verified** (test run / manual repro cleared). If you cannot pin the cause, say so and list the remaining hypotheses ranked by likelihood. \ No newline at end of file diff --git a/agentic/skills/dependency-upgrade.md b/agentic/skills/dependency-upgrade.md new file mode 100644 index 000000000..81bee3e1b --- /dev/null +++ b/agentic/skills/dependency-upgrade.md @@ -0,0 +1,48 @@ +# Skill: dependency-upgrade +> Safely upgrade an npm dependency in `backend/` or `frontend/` and verify it without breaking tests, license, or lint. + +## When to use +- A Dependabot alert or `npm audit` flags a vulnerability to fix. +- A dep is blocking a Node/React/Vite feature or has a required security patch. +- A maintainer explicitly asks to bump a dep. + +## Steps + +### 1. Identify the target +- Get the alert: `cd backend && npm audit` (and `cd frontend && npm audit`), or open the Dependabot alert. Note the CVE/advisory ID and severity. +- Determine the **right** `package.json` — `backend/` and `frontend/` have separate manifests. Don't edit the wrong one. +- Check current vs target version and read the dependency's changelog/CHANGELOG for breaking changes between them. Note whether it's a patch/minor/major bump. + +### 2. Upgrade +- Prefer the smallest bump that resolves the issue. For a major bump, check the migration guide and decide whether it belongs in its own PR. +- Edit the correct `package.json` (or use `npm install @`), then `npm install` to refresh the lockfile. +- Check **transitive** deps: if the vulnerable package is a sub-dependency, use `npm ls ` to find the parent and upgrade the parent, not the leaf. + +### 3. Verify +- **Backend:** `cd backend && npm test` (Jest; start `autowrx-mongo-test` if a spec needs Mongo — see `run-tests`). Then `npm run lint && npm run prettier`. +- **Frontend:** `cd frontend && npm run tsc && npm run lint && npm run build` (tsc && vite build; ESLint `--max-warnings 0`). Inspect `rollup-plugin-visualizer` output if the dep affects bundle size. +- **E2E (if the dep affects runtime or UI):** `cd .agents && npx playwright test` for the affected flows. +- If tests can't be run (no DB/browser/env), say so explicitly and report what you did run (RULES.md). + +### 4. License check +- Run the `license-check` skill for the new/changed dependency's license. Repo is **MIT** (Eclipse Foundation) — only MIT-compatible licenses allowed (MIT/ISC/Apache-2.0/BSD). Copyleft (GPL/AGPL/CDDL) or proprietary is **blocking**. +- Check transitive deps' licenses too if a major bump pulled in new sub-deps. + +### 5. Commit & PR (only when asked) +- One dep per commit/PR when the bump is major or touches shared APIs; patch/minor bumps may be batched if low-risk. +- Branch off `main` (never commit on `main`), `git commit -s` with your ECA-signed identity, add the `Co-Authored-By` trailer for agent-made commits. +- PR targets `main`. Title: `chore(deps): bump from X to Y` (or `fix(deps): ...` for a CVE). Body: **What / Why** (CVE ID + advisory link) / **How verified** (exact test + lint commands run) / note if it touches security or runtime. See `commit-and-pr`. + +## Guardrails +- Don't `npm audit --fix --force` for major bumps blindly — it can break the app. Review each major upgrade individually. +- Never introduce copyleft or proprietary code (GPL/AGPL/CDDL/proprietary) — blocking; MIT can't combine with it. +- Don't upgrade a dep and skip verification because "it's just a patch" — still run the relevant suite + lint. +- Don't edit `package.json` in the wrong workspace (backend vs frontend). +- Don't commit lockfile drift unrelated to the upgrade. +- PR CI runs the **ECA check only** (no test CI on PRs) — local verification is mandatory and must be stated in the PR body. + +## Exit criteria +- The dep is bumped in the correct manifest, lockfile updated, and the affected suites (backend Jest / frontend build+lint / Playwright if relevant) are green with commands cited. +- License verified MIT-compatible (transitive too for majors). +- CVE/advisory resolved (re-run `npm audit` to confirm) — or the unresolved remainder documented. +- Cross-link: `license-check`, `run-tests`, `commit-and-pr`. \ No newline at end of file diff --git a/agentic/skills/deploy.md b/agentic/skills/deploy.md new file mode 100644 index 000000000..757b61136 --- /dev/null +++ b/agentic/skills/deploy.md @@ -0,0 +1,38 @@ +# Skill: deploy +> Stand up (or restart) a local/instance AutoWRX deployment via Docker Compose. + +## When to use +- When the user explicitly asks to deploy, restart, or bring up the instance. +- After a change that must be verified on a running stack (when local dev isn't enough). +- When asked to stop the instance (use `down.sh`). + +## Steps +1. **Confirm the target env.** Ask if unclear. Default target is a local/instance env via `instance-setup/`. **Never** treat an env as prod without explicit confirmation from the user. Note that the staging/prod deploy workflows (`.github/workflows/deploy-dev-stage.yml`'s staging/prod stages) are `.disabled` — there is currently no active CD pipeline. +2. **Ensure `.env.prod` exists.** It is gitignored and required by `up.sh`. Check for `instance-setup/.env.prod`: + - If missing, do **not** create or commit secrets. Ask the user to copy `.env.prod.sample` and fill it in (`cp .env.prod.sample .env.prod`). Required keys include `JWT_SECRET`, `CORS_ORIGINS`, `ADMIN_EMAILS`, `ADMIN_PASSWORD`, `FRONTEND_PORT`, `NAME` (see `instance-setup-guide.md`). + - If present, proceed. +3. **Bring the stack up.** From `instance-setup/`: + ```bash + cd instance-setup && ./up.sh + # equivalent to: docker compose -f docker-compose.prod.yml --env-file .env.prod up -d + ``` + Services: `autowrx`, `autowrx-db`, `autowrx-dbdata`, `autowrx-network`. First build takes 5–10 min. To override builtin widgets from the host, add `-f docker-compose.widgets.yml` (see `instance-setup-guide.md`). +4. **Verify health.** + ```bash + docker compose -f instance-setup/docker-compose.prod.yml ps + docker logs autowrx --tail 50 + ``` + Confirm the app responds at `http://:${FRONTEND_PORT}`. If containers fail, check `.env.prod` syntax (no spaces around `=`), port conflicts (`lsof -i :${FRONTEND_PORT}`), and `docker compose ... logs autowrx-db` for Mongo readiness. +5. **To stop** (only when asked): `cd instance-setup && ./down.sh`. +6. **Coder / VS Code workspaces.** If the task involves the Coder integration, the workspaces live under `instance-setup/coder/` with plan files under `plans/` — handle those separately from the core stack and don't restart the `autowrx` service for a Coder-only change. + +## Guardrails +- Deploy ONLY when explicitly asked — separate authorization from commit/push (see `RULES.md`). +- Never run `down.sh` against a prod env without explicit confirmation. +- Never create, edit, or commit `.env.prod` or any secret. They are gitignored on purpose. +- Don't push images or trigger remote deploy workflows; the active CI (`.github/workflows/build-docker.yml`) builds only — staging/prod stages are disabled. +- Backend `npm run docker:prod` and pm2 (`npm start`) are alternative local runners; prefer `instance-setup/up.sh` for an instance deploy unless the user asked for a specific runner. + +## Exit criteria +- Services up and healthy (`docker compose ps` shows them running; app responds on `${FRONTEND_PORT}`), **or** a failure reported honestly with the relevant logs and the likely cause. +- No secrets committed or printed. \ No newline at end of file diff --git a/agentic/skills/docs-update.md b/agentic/skills/docs-update.md new file mode 100644 index 000000000..c2d14dbba --- /dev/null +++ b/agentic/skills/docs-update.md @@ -0,0 +1,32 @@ +# Skill: docs-update +> Keep docs, the capability catalog, and the agent map in sync with code changes. + +## When to use +- Right after a code change that alters a route/endpoint, response status, feature flag, page, or module structure. +- When closing a feature/fix PR — docs drift is a defect too. +- When `understand-the-repo` surfaces a mismatch between the map and the code. + +## Steps +1. **Classify the change** and update only the affected surfaces: + - **Route / endpoint / status / flag changed** → update `docs/capabilities/.md`. Open the matching route/controller/service in `backend/src/routes/v2/` + `backend/src/controllers/` + `backend/src/services/` and verify every technical claim against the code. Preserve the format from `docs/capabilities/README.md`: per-capability **Description / Who uses it / value / Acceptance criteria / Quality control / Security + Risks: / Data protection + Risks:**, with mermaid diagrams where they already exist. + - **Page or feature changed** → update `.agents/SITEMAP.md` coverage status (✅ / ⚠️ / ❌) for the affected row. + - **Module structure changed** (file moved, layer added, new service) → update `agentic/map/TREE.md` (compact module tree) and `agentic/map/INDEX.md` pointers. Don't copy content — point to the real doc. + - **Durable fact learned** (non-obvious layering rule, gotcha, convention) → propose into `agentic/memory/` + a one-line index entry in `agentic/memory/MEMORY.md` (see `./learn-and-update.md`). +2. **Run the map-drift check** if present: + ```bash + scripts/check-agent-map.sh # only if it exists in the repo + ``` + If it doesn't exist, manually verify every pointer in `agentic/map/INDEX.md` resolves to a real file path. +3. **Cross-link, don't duplicate.** If the content already lives in `docs/architecture/`, `docs/getting-started/`, or `docs/principles/`, link to it instead of restating. `agentic/map/` is an index of pointers, not a second copy. +4. **Commit docs with the code change** (when authorized) under a `docs/...` branch or folded into the feature commit; follow `./commit-and-pr.md`. + +## Guardrails +- Never change a capability's endpoint/status/flag claim without reading the route/controller code — the catalog is code-grounded (`RULES.md`). +- Never fabricate paths, statuses, or flags; if map and code disagree, read the code and fix the map. +- Don't duplicate content that lives elsewhere — link to it. +- Don't edit `agentic/RULES.md` here; durable rules go through `learn-and-update` as a proposal PR. + +## Exit criteria +- The changed capability/page/module is reflected in the matching doc (`docs/capabilities/`, `.agents/SITEMAP.md`, `agentic/map/`). +- All `agentic/map/INDEX.md` pointers resolve (verified by `check-agent-map.sh` if present, else by manual check). +- No duplicated content — only links to existing docs where they already cover it. \ No newline at end of file diff --git a/agentic/skills/find-race-conditions.md b/agentic/skills/find-race-conditions.md new file mode 100644 index 000000000..1e11a6db0 --- /dev/null +++ b/agentic/skills/find-race-conditions.md @@ -0,0 +1,48 @@ +# Skill: Find Race Conditions +> Hunt concurrency bugs in a codebase that has NO MongoDB transactions. + +## When to use +Run this when a bug is timing-sensitive: flaky under load, "works on second click", lost updates, duplicate counters, stale lists, or any symptom that disappears when you add a log/print (serialization). Also run proactively on diffs that touch counters, read-modify-write flows, token refresh, Socket.IO event ordering, or prototype/file seeding. This repo has **no** `withTransaction` / `session.startTransaction` anywhere — atomicity is document-level only (`findOneAndUpdate`, `$inc`, `$push`). Pair with `./run-tests.md` and `./add-test.md` to lock a repro. + +## Steps + +### 1. Find read-modify-write sequences +Grep the touched area for the unsafe pattern: a `find()`/`findById()` (or `findOne()`) followed by in-JS mutation and `.save()` (or a second update). +``` +backend/src/services: grep -nE "\.findById\(|\.findOne\(|\.find\(" *.service.js +backend/src/services: grep -nE "\.save\(\)|\.updateOne\(|\.updateMany\(" *.service.js +``` +Any doc read, mutated in JS, then `.save()` is a lost-update candidate. Convert to **atomic** `findOneAndUpdate` / `findByIdAndUpdate` with `$set`, `$inc`, `$push`, `$pull` so the read+write is one Mongo op. If you need read-then-write semantics that can't be a single operator, use an optimistic-concurrency guard (`__v` / version key or a `updatedAt` compare in the filter) — still document-level, no session. + +### 2. Counter increments +Any `count = doc.count; doc.count = count + 1; doc.save()` is wrong. Use `findOneAndUpdate({ _id }, { $inc: { count: 1 } })`. Check `models/*.model.js` for counter fields and audit their increment sites. + +### 3. Token-refresh single-flight (frontend) +`frontend/src/stores/authStore.ts` (and the 401-interceptor) implements single-flight refresh: concurrent 401s queue, the first triggers refresh, queued requests replay after success; on refresh failure, `logOut`. Bugs to look for: a second refresh firing before the first resolves (double `POST /auth/refresh` → rotated refresh token invalidated → cascade logout), queued requests replayed with the wrong token, or the queue not cleared on failure. Verify the inflight promise is shared, not re-created per caller. + +### 4. Socket.IO event ordering +Server: `backend/src/config/socket.js`. Events: `subscribe_apis`, `run_python_app`, `run_rust_app`, `stop_python_app`, `run_until_complete`, `fetchSignalMapping`, `replaceSignalMapping`, `fetchVss`, `replaceVss`, `replaceApi`. +- **subscribe must precede run:** a `run_*` without a prior `subscribe_apis` (or one that arrives after a reconnect) silently no-ops. Confirm subscribe is awaited/acked before run is emitted. +- **concurrent run/stop:** `stop_*` racing `run_*` can leave the runtime thinking an app is running while the UI thinks it's stopped, or vice versa. Serialize per-app (per-id in-flight guard) or use an explicit state machine. +- **replace* races:** `replaceSignalMapping` / `replaceVss` / `replaceApi` issued back-to-back can interleave at the kit server; if order matters, await each ack before emitting the next. + +### 5. Seed-vs-save race (canonical example) +Commit **6bd6ccb** fixed the prototype seed race: `seedPrototypeFiles` only ran at workspace-prepare time and bailed if the folder was non-empty; the frontend POSTed files via `/v2/prototypes/:id/files` before prepare, so the seed was always skipped and new prototypes got no README/main.* templates. The fix moved `seedPrototypeFiles` **into `createPrototype` synchronously before the response returns**, so no frontend save can race it. When you see any new "create X then async-init X then user writes X" flow, apply the same pattern: init synchronously inside the create handler, or guard the init against concurrent writes with an atomic flag/lock. Files: `backend/src/services/prototype.service.js`, `backend/src/services/orchestrator.service.js`. + +### 6. CACHE_URL eventual consistency +Recent/popular prototypes come from `${CACHE_URL}/get-recent-activities/:userId` (`services/prototype.service.js` ~line 260), **not** the DB. A create followed immediately by a "recent" list read may return stale data (the cache hasn't caught up). Don't "fix" this by reading the DB instead; either invalidate/bust the cache on write, or design the UI to tolerate eventual consistency. Note any new list endpoint backed by `CACHE_URL` so callers know it's not read-after-write consistent. + +### 7. Other concurrency surfaces +- Filesystem races in plugin unzip (`spawn('unzip', …)` in `controllers/plugin.controller.js`) — concurrent uploads to the same slug/dir. +- `Promise.all` over a shared mutable array where order matters. +- Async middleware that doesn't `await` before `next()`. + +## Guardrails +- **Do not introduce `withTransaction` / `session.startTransaction`** without confirming the Mongo deployment is a replica set and the team is OK with the operational cost. Prefer atomic single-doc ops. +- Prefer `findOneAndUpdate` with atomic operators over read-then-`.save()`. Only escalate to optimistic concurrency or a logical lock if a single operator can't express the update. +- **Add a test that reproduces the concurrency** (parallel requests / interleaved events) before fixing — see `./add-test.md`. A race "fix" without a repro test is not verified. +- Don't paper over a race with a `setTimeout`/`sleep` or by adding a log line that serializes the code. That hides it, not fixes it. +- When fixing frontend single-flight, don't rotate the refresh token twice — that invalidates every queued caller. + +## Exit criteria +Return: each race found with **`file:line`**, the **interleaving** that triggers it (concrete sequence of events/requests), the **fix** (atomic op / single-flight / serialize / synchronous-init), and the **repro test** added (path) or why one wasn't possible. If you reviewed a diff and found none, list the concurrency surfaces you checked (counters, RMW, refresh, socket ordering, seed, cache) so the caller knows the audit was real. \ No newline at end of file diff --git a/agentic/skills/implement-feature.md b/agentic/skills/implement-feature.md new file mode 100644 index 000000000..0d3b9956b --- /dev/null +++ b/agentic/skills/implement-feature.md @@ -0,0 +1,34 @@ +# Skill: implement-feature +> The canonical flow tying the other skills together: scope → branch → understand → implement → test → review → commit → PR. + +## When to use +- When asked to implement a feature, fix, or refactor that will land as one or more commits. +- When the task spans code in `backend/`, `frontend/`, and/or `.agents/`. + +## Steps +1. **Confirm scope.** Restate what's being built/changed and where it lives. If unclear, ask before coding. Note whether it touches security-sensitive areas (auth, tokens, file ops, runtime, plugins) — those need `security-review`. +2. **Branch off `main`.** Never commit on `main`. Branch naming per `CONVENTIONS.md`: `/-` or `/` (types: `feat`, `fix`, `refactor`, `docs`, `chore`). + ```bash + git switch main && git pull --ff-only && git switch -c feat/- + ``` +3. **Orient.** Run [`./understand-the-repo.md`](./understand-the-repo.md) — load `agentic/map/INDEX.md` + `agentic/memory/MEMORY.md`, deep-read only the module you'll touch. +4. **Implement per `CONVENTIONS.md`.** + - Backend: thin `controllers/` → logic in `services/` → Mongoose `models/`. Versioned routes under `routes/v2/`. Match existing auth pattern (`auth({ optional: ... })`, `checkPermission`). + - Frontend: atomic design (`components/{atoms,molecules,organisms}`, `pages/`, `layouts/`, `stores/`, `hooks/`). State in Zustand `stores/`; permissions via `hooks/usePermissionHook.ts`; routes in `configs/routes.tsx`. Don't put page logic in atoms. + - Match surrounding style; no drive-by reformatting outside the change's scope. +5. **Run tests.** Run [`./run-tests.md`](./run-tests.md) — backend Jest for affected code, Playwright for affected flows. Don't declare done if tests fail. +6. **Self-review.** Run [`./code-review.md`](./code-review.md) on your diff. If the change touches auth/data/runtime/plugins, also run [`./security-review.md`](./security-review.md). If it adds/modifies `.js`/`.ts`/`.tsx` or dependencies, also run [`./license-check.md`](./license-check.md). +7. **Keep docs in sync.** If code structure or a capability changed, run [`./docs-update.md`](./docs-update.md) (update `agentic/map/`, `docs/capabilities/`, `.agents/SITEMAP.md` as needed). +8. **Commit & PR (only when asked).** Run [`./commit-and-pr.md`](./commit-and-pr.md): `git commit -s` with your own ECA-signed identity, PR targets `main`, body = **What / Why / How verified**. CI runs only the ECA check, so state explicitly how tests were verified locally. + +## Guardrails +- Do not push, PR, or deploy unless explicitly asked — each is a separate authorization. +- Never commit on `main`. Never commit secrets (`.env*`, tokens, keys). +- Never mark the task complete if tests fail or work is partial — report honestly. +- Don't fabricate endpoints/flags/paths — verify against code. + +## Exit criteria +- Code implemented, lint + tests green (or honestly reported as unrun). +- Self-review (+ security-review where applicable) done. +- Docs/map/capabilities updated if structure changed. +- PR opened (when authorized) with What/Why/How-verified and the issue linked (`Closes #nnn`). \ No newline at end of file diff --git a/agentic/skills/learn-and-update.md b/agentic/skills/learn-and-update.md new file mode 100644 index 000000000..b8235903b --- /dev/null +++ b/agentic/skills/learn-and-update.md @@ -0,0 +1,36 @@ +# Skill: learn-and-update +> The continuous-learning loop: research, record dated+sourced notes, then propose rule/map/memory updates via PR. + +## When to use +- When a durable lesson, gotcha, or better pattern surfaces during a task. +- On manual trigger (or a future scheduled run) to refresh best-practices/trends for the stack. +- When `understand-the-repo` or `docs-update` reveals something worth keeping for the next session. + +## Steps +1. **Identify the trigger.** Either a session lesson (a specific failure/insight from this task) or a research refresh (broader best-practices/trends for the stack). +2. **Research (for a refresh).** Web-search current best-practices, trends, and well-known conventions for this stack: + - Express + MongoDB (Node backend), React + Vite + TypeScript (frontend), Playwright (E2E), Docker Compose (deploy). + - Agent-coding conventions: `agents.md`, `AGENTS.md`, repo-resident memory/skills patterns. + Record the search date and source URLs with each note — do not present web content as repo fact. +3. **Write notes to the right file** under `agentic/learning/`: + - `best-practices.md` — recommended patterns for the stack (dated + sourced). + - `trends.md` — emerging tools/shifts worth tracking (dated + sourced). + - `lessons.md` — concrete session lessons: what went wrong, what worked, the fix, and the rule it implies. + Each entry: a timestamp/date, a one-line summary, the source (URL or `code: path/to/file`), and the proposed implication. If `agentic/learning/` doesn't yet exist, create it (the layout in `agentic/README.md` expects these files). +4. **Open a proposal PR.** Translate the notes into concrete, reviewable changes: + - New/updated memory fact → `agentic/memory/.md` + one-line index entry in `MEMORY.md`. + - Map drift → `agentic/map/TREE.md` / `INDEX.md` pointer updates. + - Skill tweak → edit to `agentic/skills/.md`. + - **Never auto-apply to `agentic/RULES.md`.** Rules are human-approved via PR only; the PR description proposes the rule change and links the supporting lesson/source. +5. **Document the decision.** If the outcome is "no change needed", record that in `lessons.md` with the reason so the next session doesn't re-investigate. + +## Guardrails +- Learning notes are **proposals**, not applied rules — human-approved via PR. +- Cite sources + dates for every note; web content is never repo fact. +- Don't edit `RULES.md` directly; propose rule changes in the PR body. +- Don't dump raw web articles — distill to the actionable implication for this repo. +- One logical change per PR; follow `./commit-and-pr.md` for branch/commit/PR style. + +## Exit criteria +- `agentic/learning/{best-practices,trends,lessons}.md` updated with dated + sourced entries, **and** +- a proposal PR opened (with concrete memory/map/skill/rule updates) **or** a documented decision not to change anything recorded in `lessons.md`. \ No newline at end of file diff --git a/agentic/skills/license-check.md b/agentic/skills/license-check.md new file mode 100644 index 000000000..3fa90c796 --- /dev/null +++ b/agentic/skills/license-check.md @@ -0,0 +1,40 @@ +# Skill: license-check +> Verify licensing on a change: source files carry the repo's Eclipse/MIT header, no incompatible third-party code is introduced, and no existing headers are stripped. + +## When to use +- Before commit on any change that **adds or modifies** `.js`, `.ts`, `.tsx` source files, or touches `package.json` / dependencies. +- When vendoring or copy-pasting code from elsewhere (Stack Overflow, another repo, an AI-generated snippet that includes a license notice). +- When you suspect a dependency's license may be incompatible. + +## Repo license +This repo is **MIT** (Copyright Eclipse Foundation). Source files start with: + +``` +// Copyright (c) 2025 Eclipse Foundation. +// +// This program and the accompanying materials are made available under the +// terms of the MIT License which is available at +// https://opensource.org/licenses/MIT. +// +// SPDX-License-Identifier: MIT +``` + +`.sh`, `.yml`, and `.md` files do **not** carry this header (repo convention) — only `.js`/`.ts`/`.tsx` source. + +## Steps +1. **New/changed source headers.** For every `.js`/`.ts`/`.tsx` file in the diff, confirm the first ~10 lines contain `SPDX-License-Identifier: MIT`. Run `scripts/check-license-headers.sh` (checks changed files against `origin/main`) and fix any it reports. +2. **No header stripping.** Diff must not remove or alter an existing `Copyright`/`SPDX-License-Identifier` block unless replacing the whole file with a properly re-licensed version. +3. **No vendored incompatible code.** Any third-party code pasted in must be MIT-compatible (MIT, BSD-2/3, Apache-2.0, ISC) and keep its original copyright/SPDX notice. GPL/AGPL/CDDL/proprietary snippets are **blocking** — Eclipse/MIT cannot combine with copyleft. +4. **Dependencies.** If `package.json` changed, sanity-check the new dep's license is MIT-compatible (most npm packages are MIT/ISC/Apache-2.0/BSD). Flag anything copyleft/proprietary. +5. **AI-generated code.** Generated snippets are fine (no third-party copyright), but still need the repo header on a new source file. + +## Guardrails +- Don't bulk-add headers to pre-existing files outside your change's scope (that's separate debt cleanup — its own PR). +- Don't change the license itself (MIT) or the copyright holder (Eclipse Foundation) without explicit maintainer sign-off. +- A copyleft/proprietary license finding is **blocking** — do not commit; surface it. + +## Exit criteria +- `scripts/check-license-headers.sh` passes for the changed files. +- No existing header stripped/altered. +- Any vendored code carries a compatible license + its notice. +- A short statement: "license-clean" or a list of findings with severity. \ No newline at end of file diff --git a/agentic/skills/performance-review.md b/agentic/skills/performance-review.md new file mode 100644 index 000000000..4cad65de2 --- /dev/null +++ b/agentic/skills/performance-review.md @@ -0,0 +1,51 @@ +# Skill: performance-review +> Review a diff or area for performance regressions across backend (Mongo/external calls), frontend (bundle/re-renders), and Socket.IO fan-out. + +## When to use +- Before merging a change that touches list endpoints, DB queries, external HTTP, frontend bundles, or realtime broadcasts. +- When a user reports slowness or scaling issues in a specific area. +- Periodic audit of a hot path (auth, prototype list, runtime, plugin load). + +## Steps + +### 1. Scope the review +- Identify the diff/area: `git diff main...` for a PR, or a named module/route. Read the changed controllers/services/models, frontend components/stores, and socket handlers. +- Note the user-facing flow and expected scale (rows, concurrent users, subscribers). + +### 2. Backend — MongoDB +- **N+1 / over-population:** scan for loops that call `.populate()` per item, or `.find()` inside a `.map()`/`for`. Prefer a single query with `.populate()`/`aggregate` or batched lookups. +- **Pagination:** list endpoints must use the existing `page, limit, fields, include_stats` filters (see list controllers). Flag any new list route that returns unbounded results. +- **Indexes:** for any new query filter or `sort`, check the Mongoose model for a matching index. Missing indexes on hot filters → flag. Known gap: the **Token collection has NO TTL index** (see `agentic/memory/gotchas.md`) — don't add auth-token leaks that rely on cleanup; surface the gap if relevant. +- **Projection:** large docs (prototypes with code, assets) should use field projection / `fields` filter rather than returning full payloads. + +### 3. Backend — external calls +- Calls proxied to `CACHE_URL` (`/get-recent-activities/:userId`) and `LOG_URL` are configured in `backend/config/axios.js`. Check: + - Are independent external calls `await`ed sequentially when they could run in parallel (`Promise.all`)? + - Are repeated identical calls cached (in-memory or via the cache service) instead of re-fetched per request? + - Are timeouts/retries set so one slow downstream doesn't block the request? +- Flag any blocking CPU work on the event loop (large sync JSON parse, crypto on hot path). + +### 4. Frontend (`frontend/`) +- **Bundle size:** run `cd frontend && npm run build` and inspect the `rollup-plugin-visualizer` output (configured in `vite.config.ts`). Flag large new deps or chunks that regressed the main bundle. +- **Re-renders:** check heavy components are memoized (`React.memo`, `useMemo`, `useCallback`) when parents re-render often; flag context values recreated each render. +- **Zustand selectors:** ensure components subscribe to the minimal slice via scoped selectors (`useStore(s => s.x)`) rather than whole-store subscriptions that re-render on every change. +- **Lists:** virtualize long lists; avoid inline keys that force re-mounts. + +### 5. Socket.IO +- For `emit`/broadcast paths, check fan-out: does one event emit to all sockets when a room/channel would suffice? Flag O(sockets) loops that could be O(subscribers) via rooms. + +### 6. Rank and report +- Rank findings by impact (user-visible latency at scale > theoretical micro-opts). For each: location (file:line), why it's slow, proposed fix, and expected effect. +- Where feasible, **measure before/after** (e.g. query `explain()`, build size diff, Playwright trace timing) rather than asserting from intuition. + +## Guardrails +- Don't optimize blindly — measure and confirm the hot path before refactoring. +- Preserve correctness: pagination limits, auth/permission checks, and field projection must not bypass RBAC or leak private fields. +- Don't add an index without checking the existing model indexes (avoid duplicates); index additions are a schema change — cross-link `db-schema-change`. +- Don't trade readability for micro-gains; surface the trade-off if contested. +- Don't introduce a new dependency to shave bundle size without running `license-check` (MIT-compatible only). + +## Exit criteria +- A ranked findings list with file:line, evidence (measurement or code pattern), and a concrete fix per item. +- "No issue found" is valid only if each surface (Mongo, external, frontend, socket) was actually inspected — say what you checked. +- Cross-link: `debug` for reproducing a reported slowdown, `db-schema-change` if an index/migration is the fix. \ No newline at end of file diff --git a/agentic/skills/plugin-authoring.md b/agentic/skills/plugin-authoring.md new file mode 100644 index 000000000..e05d9d40a --- /dev/null +++ b/agentic/skills/plugin-authoring.md @@ -0,0 +1,41 @@ +# Skill: plugin-authoring +> Write, package, and upload an AutoWRX plugin (micro-frontend that runs same-origin and unsandboxed in the browser). + +## When to use +- Building a new plugin (tab/addon) for a model or prototype page. +- Extending or refactoring an existing plugin's `PluginAPI` usage. +- Reviewing a plugin PR for correctness against the loader contract. + +## Steps +1. **Study the contract.** Read `docs/architecture/plugin-system.md` (code-grounded) and `docs/guides/plugin/`. The loader (`frontend/src/components/organisms/PluginPageRender.tsx`) injects the plugin's `url` as a `