From e01042311c75dbdb448f8d7d0c328f4dc0931667 Mon Sep 17 00:00:00 2001 From: NhanLuongBGSV Date: Fri, 7 Aug 2026 01:04:07 +0000 Subject: [PATCH 1/7] docs(agentic-framework): add proposal for vendor-neutral agent framework (#612) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Proposal only — no implementation. Defines a repo-resident, vendor-neutral agentic coding framework (.agent/ + AGENTS.md/CLAUDE.md adapters) so any AI agent (Claude Code, opencode, openclaw, …) loads the same rules, memory, skills, and repo map; follows the same implement/test/review/commit/PR/deploy flow; and avoids re-scanning the repo each session (token savings). Includes a continuous-learning layer, per-tool mapping, phased migration, and open decisions for review. Co-Authored-By: Claude --- docs/agentic-framework/PROPOSAL.md | 175 +++++++++++++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 docs/agentic-framework/PROPOSAL.md diff --git a/docs/agentic-framework/PROPOSAL.md b/docs/agentic-framework/PROPOSAL.md new file mode 100644 index 00000000..5eb1149d --- /dev/null +++ b/docs/agentic-framework/PROPOSAL.md @@ -0,0 +1,175 @@ +# Proposal: Vendor-Neutral Agentic Coding Framework for AutoWRX + +> Issue: #612 · Branch: `feat/612-agentic-coding-framework` +> Status: **Proposal — awaiting review.** No implementation yet. + +## 1. Problem + +How an AI coding assistant behaves in this repo depends on which tool we run (Claude Code, opencode, openclaw, …). Each tool: + +- re-learns the repo and re-scans/indexes code every session → **token waste**; +- follows its own implicit rules → **inconsistent** commits, tests, PRs; +- stores context in tool-specific, often user-local locations → **not portable**, lost across tools or machines. + +There is no repo-resident source of truth for *how an agent should work here*. + +## 2. Goals + +1. **One set of rules, memory, and skills that lives in the repo** — any agent loads the same context. +2. **Vendor-neutral** — no lock-in to Claude Code / opencode / openclaw; expressed in portable formats each tool can consume. +3. **Token-efficient** — agents load a pre-built map + memory instead of re-scanning the whole repo each session. +4. **Consistent flow** — same branch → implement → test → self-review → commit → PR → deploy discipline regardless of tool. +5. **Self-improving** — a mechanism to capture best practices/trends (from the internet and from real sessions) and fold them back into skills/memory. + +## 3. Principles + +- **Repo as the source of truth.** Agent config travels with the repo, not the user's home dir. +- **Canonical content written once, mapped per tool.** Write rules/memory/skills in vendor-neutral files; thin tool-specific adapters point to them. +- **Load-on-demand.** Entry files stay tiny; detail is imported/referenced so token cost scales with what's actually needed. +- **Human-reviewable.** Everything is markdown a human can read and edit; no opaque binary state. + +## 4. Architecture (layers) + +``` +┌─────────────────────────────────────────────────────────┐ +│ Layer 0 — Entry points (tool adapters, tiny) │ +│ CLAUDE.md · AGENTS.md · .opencode/ · openclaw cfg │ +│ │ each imports/points to Layer 1 │ +├─────────────────────────────────────────────────────────┤ +│ Layer 1 — Rules & conventions (canonical) │ +│ .agent/RULES.md · .agent/CONVENTIONS.md │ +├─────────────────────────────────────────────────────────┤ +│ Layer 2 — Skills / playbooks (procedures) │ +│ .agent/skills/*.md (understand, review, test, deploy, │ +│ commit, pr, security-review, docs-update, …) │ +├─────────────────────────────────────────────────────────┤ +│ Layer 3 — Memory & knowledge base (repo-resident) │ +│ .agent/memory/*.md + MEMORY.md index │ +├─────────────────────────────────────────────────────────┤ +│ Layer 4 — Repo map (always-current codebase index) │ +│ .agent/map/TREE.md · ARCHITECTURE.md · DATAFLOW.md │ +├─────────────────────────────────────────────────────────┤ +│ Layer 5 — Continuous learning │ +│ .agent/learning/*.md + learn-and-update skill │ +└─────────────────────────────────────────────────────────┘ +``` + +Everything under `.agent/` is **canonical and vendor-neutral**. Tool-specific entry files (Layer 0) are thin adapters that import/point into `.agent/`. + +## 5. Proposed file layout + +``` +AGENTS.md # vendor-neutral entry (agents.md spec); imports .agent/* +CLAUDE.md # Claude Code entry; @imports .agent/* (Claude Code supports @import) +.agent/ + RULES.md # hard rules (must / must-not) + CONVENTIONS.md # naming, structure, commit, PR style + skills/ + 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/ + MEMORY.md # index (one line per fact) + architecture.md + gotchas.md + verified-facts.md + decisions.md # ADR-style + map/ + TREE.md # repo file tree w/ one-line purpose per module + ARCHITECTURE.md # subsystems + boundaries + DATAFLOW.md # request/data flow diagrams + learning/ + README.md # how learning works + best-practices.md # captured, dated, sourced + trends.md +.opencode/ # opencode adapter (symlinks/pointers to .agent) +.claude/ # Claude Code adapter (skills symlinked to .agent/skills) +``` + +## 6. Vendor-neutral mapping + +| Artifact | Canonical | Claude Code | opencode | openclaw / other | +|---|---|---|---|---| +| Entry rules | `AGENTS.md` | `CLAUDE.md` `@import`s it | reads `AGENTS.md` natively | reads `AGENTS.md` (agents.md spec) | +| Rules/conventions | `.agent/RULES.md`, `CONVENTIONS.md` | imported via `CLAUDE.md` | imported via `AGENTS.md` | imported via `AGENTS.md` | +| Skills | `.agent/skills/*.md` | `.claude/skills/` → symlink/point to `.agent/skills` | opencode skills dir → same | read from `.agent/skills` | +| Memory | `.agent/memory/*.md` + index | `CLAUDE.md` instructs load on start | `AGENTS.md` instructs load | same | +| Repo map | `.agent/map/*` | loaded on demand by `understand-the-repo` skill | same | same | +| Learning | `.agent/learning/*` | `learn-and-update` skill | same | same | + +**Key:** write once in `.agent/`, adapt in Layer 0. If a tool lacks a native concept (e.g. no "skills"), the entry file instructs the agent to read the skill markdown when the task matches — skills are just markdown either way. + +## 7. Skills catalog (Layer 2) + +Each skill is a markdown playbook: *when to use · steps · guardrails · exit criteria*. + +- **understand-the-repo** — load `.agent/map/*` + memory instead of re-scanning; returns a concise mental model. (Primary token saver.) +- **implement-feature** — branch → load relevant map/memory → implement → run `test` + `review` skills → commit → PR. +- **run-tests** — how tests are run here (frontend/backend), what passing looks like, how to interpret failures. +- **code-review** — self-review checklist before commit (reuse, simplification, correctness, altitude). +- **security-review** — security review of the diff (the repo already has a `/security-review` skill — fold it in). +- **commit-and-pr** — commit author = `NhanLuongBGSV`, conventional messages, PR template, ECA note. +- **deploy** — instance-setup flow (`instance-setup/up.sh`, docker-compose.prod.yml), env requirements. +- **docs-update** — keep `docs/capabilities/*` and `.agent/map/*` in sync with code changes. +- **learn-and-update** — periodically research current best practices/trends on the web, capture dated+sourced notes in `.agent/learning/`, and propose updates to skills/memory via PR. + +## 8. Memory & repo map (Layers 3–4) + +- **Memory** — repo-resident facts (architecture, gotchas, verified facts, decisions). One fact per file + a `MEMORY.md` index. Crucially: this lives **in the repo**, unlike Claude Code's default user-local memory, so it's shared across tools/machines and reviewable in PRs. +- **Repo map** — a committed, human+agent-readable index: `TREE.md` (module → one-line purpose), `ARCHITECTURE.md` (subsystems/boundaries), `DATAFLOW.md` (request/data flow). The agent reads ~a few KB instead of indexing thousands of files each session. Kept current by the `docs-update` skill (regenerate on structural changes; guard against drift with a CI check). + +**Token-savings estimate (rough):** a cold session today may scan dozens of files (tens of thousands of tokens) to orient. With map+memory the agent loads a curated few KB (~1–3k tokens) and only deep-reads the specific module it touches. Order-of-magnitude reduction on the orientation step, repeated every session. + +## 9. Canonical flows (wired into skills) + +``` +feature request + → implement-feature skill + → branch off main + → understand-the-repo (load map+memory) + → implement (follow CONVENTIONS) + → run-tests + → code-review (self) → security-review (if touching auth/data/runtime) + → commit-and-pr + → (human) review & merge + → docs-update (sync map/capabilities if structure changed) +``` + +Deploy and learn-and-update are separate flows triggered on demand or on a schedule. + +## 10. Continuous learning (Layer 5) + +- `learn-and-update` skill: on trigger (manual or scheduled), research current best practices / trends / well-known patterns for the stack (Express + Mongo + React + Coder/Docker), write dated + sourced notes to `.agent/learning/`, and open a PR proposing concrete updates to skills/memory/map. +- Every real session can append a one-line "lesson learned" to `.agent/learning/lessons.md` (via a lightweight hook/reminder), so the framework gets better from actual use, not just web research. +- Guardrail: learning notes are proposals, never auto-applied to rules — a human approves via PR. + +## 11. Migration path (phased) + +1. **Phase 1 — Skeleton (this issue, small PR):** add `AGENTS.md` + `CLAUDE.md` adapter + `.agent/` structure with `RULES.md`, `CONVENTIONS.md`, `skills/README.md`, and seed `map/TREE.md` + `memory/MEMORY.md`. Wire Claude Code via `@import`. No behavior change yet beyond consistent loading. +2. **Phase 2 — Skills:** author the core skills (understand-the-repo, implement-feature, run-tests, code-review, commit-and-pr, deploy). Migrate existing `/security-review` and `/run`-style skills into `.agent/skills`. +3. **Phase 3 — Memory & map population:** fill memory + map from the now-merged `docs/capabilities/` catalog (single source reused). Add a CI drift check for the map. +4. **Phase 4 — Learning loop:** add `learn-and-update` + session-lessons capture. +5. **Phase 5 — Multi-tool validation:** run the same task with Claude Code + opencode + openclaw against the framework; confirm identical loading/flow; fix adapter gaps. + +Each phase is an independent PR. Nothing is forced on existing workflows until Phase 2. + +## 12. Decisions I need from you + +1. **Directory name:** `.agent/` (hidden, clean tree) vs `agentic/` (visible). I propose `.agent/`. +2. **Single source for repo knowledge:** reuse the `docs/capabilities/` catalog as the canonical map (link from `.agent/map/`) instead of duplicating — agree? +3. **Map freshness:** committed + CI drift check (my recommendation) vs git-ignored + regenerated each session. +4. **Learning loop trigger:** manual only (safer) vs scheduled recurring job (faster improvement). I propose manual first, scheduled in Phase 4. +5. **Scope of Phase 1 PR:** just the skeleton + adapters (no skills yet), or skeleton + the two highest-value skills (`understand-the-repo`, `commit-and-pr`) so we feel the benefit immediately? + +## 13. Out of scope (for now) + +- Replacing any tool; this is a portability layer, not a tool choice. +- Auto-merging learning proposals; humans stay in the loop. +- Moving existing `.claude/` user settings into the repo beyond the adapter symlink. \ No newline at end of file From 3b251e95682a299cc7c6eed95a76c05e4d886c73 Mon Sep 17 00:00:00 2001 From: NhanLuongBGSV Date: Fri, 7 Aug 2026 01:13:32 +0000 Subject: [PATCH 2/7] feat(agentic): vendor-neutral agentic coding framework (#612) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a repo-resident, vendor-neutral agentic coding framework so any AI agent (Claude Code, opencode, openclaw, …) loads the same rules, memory, skills, and repo map; follows the same implement → test → review → commit → PR → deploy flow; and avoids re-scanning the whole repo each session (token savings). Entry points: - AGENTS.md — vendor-neutral entry (agents.md convention), read by any tool - CLAUDE.md — Claude Code adapter (@imports AGENTS.md + rules) Canonical content under agentic/ (distinct from the existing .agents/ E2E suite): - RULES.md, CONVENTIONS.md — always-loaded hard rules + style - SETUP.md — per-tool wiring (Claude Code / opencode / openclaw) - skills/ — 9 playbooks: understand-the-repo, implement-feature, run-tests, code-review, security-review, commit-and-pr, deploy, docs-update, learn-and-update (load-on-demand) - memory/ — repo-resident knowledge base (facts + index); supersedes user-local memory for shared knowledge - map/ — INDEX.md + TREE.md: pointers to the real maps, not duplicates - learning/ — continuous-learning layer (best-practices, trends, lessons) The framework wires into existing repo knowledge rather than duplicating: docs/architecture/, docs/capabilities/, .agents/SITEMAP.md, docs/getting-started/, docs/principles/. CI: scripts/check-agent-map.sh + .github/workflows/agent-map-check.yml verify all framework markdown links resolve (drift detection). Verified clean locally (28 files, all links resolve). Proposal updated: docs/agentic-framework/PROPOSAL.md marked implemented. Co-Authored-By: Claude Signed-off-by: NhanLuongBGSV --- .github/workflows/agent-map-check.yml | 29 +++++++++++ AGENTS.md | 71 +++++++++++++++++++++++++++ CLAUDE.md | 19 +++++++ agentic/CONVENTIONS.md | 49 ++++++++++++++++++ agentic/README.md | 68 +++++++++++++++++++++++++ agentic/RULES.md | 41 ++++++++++++++++ agentic/SETUP.md | 40 +++++++++++++++ agentic/learning/README.md | 19 +++++++ agentic/learning/best-practices.md | 39 +++++++++++++++ agentic/learning/lessons.md | 17 +++++++ agentic/learning/trends.md | 11 +++++ agentic/map/INDEX.md | 25 ++++++++++ agentic/map/TREE.md | 59 ++++++++++++++++++++++ agentic/memory/MEMORY.md | 10 ++++ agentic/memory/architecture.md | 9 ++++ agentic/memory/decisions.md | 23 +++++++++ agentic/memory/gotchas.md | 9 ++++ agentic/memory/verified-facts.md | 9 ++++ agentic/skills/README.md | 35 +++++++++++++ agentic/skills/code-review.md | 43 ++++++++++++++++ agentic/skills/commit-and-pr.md | 31 ++++++++++++ agentic/skills/deploy.md | 38 ++++++++++++++ agentic/skills/docs-update.md | 32 ++++++++++++ agentic/skills/implement-feature.md | 34 +++++++++++++ agentic/skills/learn-and-update.md | 36 ++++++++++++++ agentic/skills/run-tests.md | 64 ++++++++++++++++++++++++ agentic/skills/security-review.md | 25 ++++++++++ agentic/skills/understand-the-repo.md | 31 ++++++++++++ docs/agentic-framework/PROPOSAL.md | 2 +- scripts/check-agent-map.sh | 70 ++++++++++++++++++++++++++ 30 files changed, 987 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/agent-map-check.yml create mode 100644 AGENTS.md create mode 100644 CLAUDE.md create mode 100644 agentic/CONVENTIONS.md create mode 100644 agentic/README.md create mode 100644 agentic/RULES.md create mode 100644 agentic/SETUP.md create mode 100644 agentic/learning/README.md create mode 100644 agentic/learning/best-practices.md create mode 100644 agentic/learning/lessons.md create mode 100644 agentic/learning/trends.md create mode 100644 agentic/map/INDEX.md create mode 100644 agentic/map/TREE.md create mode 100644 agentic/memory/MEMORY.md create mode 100644 agentic/memory/architecture.md create mode 100644 agentic/memory/decisions.md create mode 100644 agentic/memory/gotchas.md create mode 100644 agentic/memory/verified-facts.md create mode 100644 agentic/skills/README.md create mode 100644 agentic/skills/code-review.md create mode 100644 agentic/skills/commit-and-pr.md create mode 100644 agentic/skills/deploy.md create mode 100644 agentic/skills/docs-update.md create mode 100644 agentic/skills/implement-feature.md create mode 100644 agentic/skills/learn-and-update.md create mode 100644 agentic/skills/run-tests.md create mode 100644 agentic/skills/security-review.md create mode 100644 agentic/skills/understand-the-repo.md create mode 100755 scripts/check-agent-map.sh diff --git a/.github/workflows/agent-map-check.yml b/.github/workflows/agent-map-check.yml new file mode 100644 index 00000000..a1b40cd1 --- /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/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..c5114998 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,71 @@ +# 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 identity: `NhanLuongBGSV` / `nhan.luongnguyen@vn.bosch.com`, **ECA signed**, `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. +- [`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. + +## 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) `@import`s this file. 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 00000000..45645486 --- /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. Do not duplicate rules here. + +@import ./AGENTS.md +@import ./agentic/RULES.md +@import ./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. +- **Persistent git identity for this repo:** `NhanLuongBGSV` / `nhan.luongnguyen@vn.bosch.com`. 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 00000000..a253ae34 --- /dev/null +++ b/agentic/CONVENTIONS.md @@ -0,0 +1,49 @@ +# 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, `Co-Authored-By: Claude `. +- **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 — 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. \ No newline at end of file diff --git a/agentic/README.md b/agentic/README.md new file mode 100644 index 00000000..072601f6 --- /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) +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 `@import` to pull in `AGENTS.md` / `agentic/*`. +- **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 00000000..5d36e8b4 --- /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 that email. For this repo: `NhanLuongBGSV` / `nhan.luongnguyen@vn.bosch.com`. Do **not** use any other identity. +- **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 00000000..f5eaf735 --- /dev/null +++ b/agentic/SETUP.md @@ -0,0 +1,40 @@ +# 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 `@import`s `AGENTS.md` + rules, 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) + 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 00000000..cb06cf1c --- /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 00000000..469dcc3a --- /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 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 00000000..408f3293 --- /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 00000000..55c77360 --- /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 00000000..3c13a3b8 --- /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 00000000..a1f841d4 --- /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 TS-style type defs + 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 00000000..a24e2d24 --- /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 00000000..435718cd --- /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 00000000..fd81ab1e --- /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. +- **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 00000000..234231ef --- /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. +- **PR CI runs the ECA check only.** `.github/workflows/` has no test job on PRs — `build-docker.yml` and `deploy-dev-stage.yml` run on push/merge paths, 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 00000000..f5982feb --- /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 Vite config; not 3000/5173. (Source: `frontend/vite.config.ts` + `AGENTS.md`.) +- **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 identity is fixed:** `NhanLuongBGSV` / `nhan.luongnguyen@vn.bosch.com`. Other identities will fail the ECA check. (Source: `RULES.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 00000000..d1b58986 --- /dev/null +++ b/agentic/skills/README.md @@ -0,0 +1,35 @@ +# 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 + +| 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) | +| **Commit & PR** | When asked to commit / open a PR. ECA, sign-off, PR template. | [commit-and-pr.md](./commit-and-pr.md) | +| **Deploy** | When asked to deploy an instance. `instance-setup/` Docker Compose. | [deploy.md](./deploy.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) | + +## The core flow + +``` +implement-feature + ├─ understand-the-repo (orient) + ├─ implement (per CONVENTIONS) + ├─ run-tests + ├─ code-review + │ └─ security-review (if auth/data/runtime/plugins) + └─ commit-and-pr +after merge → docs-update (if structure/endpoint changed) +on schedule → learn-and-update +``` + +## 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/code-review.md b/agentic/skills/code-review.md new file mode 100644 index 00000000..fb97fa3c --- /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. +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/commit-and-pr.md b/agentic/skills/commit-and-pr.md new file mode 100644 index 00000000..b1266cd4 --- /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 `NhanLuongBGSV` / `nhan.luongnguyen@vn.bosch.com` (the ECA-signed identity). Fix with `git config user.name "NhanLuongBGSV"` / `git config user.email "nhan.luongnguyen@vn.bosch.com"` if not. Never use any other identity. +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 "..." -m "Co-Authored-By: Claude "`. 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,key=Co-Authored-By)'` shows the correct identity and both trailers. \ No newline at end of file diff --git a/agentic/skills/deploy.md b/agentic/skills/deploy.md new file mode 100644 index 00000000..757b6113 --- /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 00000000..c2d14dbb --- /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/implement-feature.md b/agentic/skills/implement-feature.md new file mode 100644 index 00000000..25791d8a --- /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). +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` as `NhanLuongBGSV` / `nhan.luongnguyen@vn.bosch.com`, 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 00000000..b8235903 --- /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/run-tests.md b/agentic/skills/run-tests.md new file mode 100644 index 00000000..376c76c4 --- /dev/null +++ b/agentic/skills/run-tests.md @@ -0,0 +1,64 @@ +# Skill: run-tests +> Run the repo's test suites — backend Jest and/or `.agents/` Playwright — and read the results honestly. + +## When to use +- Before declaring any code change done (RULES.md: run tests before declaring done). +- After implementing/fixing in `backend/` or `frontend/`, and for E2E flows in `.agents/`. +- When asked to verify a specific spec or flow. + +## Steps +### Backend (Jest, `backend/`) +```bash +cd backend && npm test # all tests, --detectOpenHandles +cd backend && npm run test:watch # watch mode for the file you're editing +cd backend && npm run coverage # with coverage +cd backend && npx jest path/to/file.test.js # one spec file +``` +- Backend Jest specs are colocated or under a tests dir. Match existing spec style when adding. +- If a test env needs MongoDB and none is running, start one locally: + ```bash + docker run -d --name autowrx-mongo-test -p 27017:27017 mongo:4.4.6-bionic + ``` + (Stop with `docker stop autowrx-mongo-test` when done.) + +### Frontend (`frontend/`) +- No unit-test runner is wired; rely on type-check + build + lint: + ```bash + cd frontend && npm run tsc # type-check + cd frontend && npm run lint # ESLint --max-warnings 0 + cd frontend && npm run build # tsc && vite build + ``` + +### E2E (Playwright, `.agents/`) +```bash +cd .agents && npm install && npx playwright install chromium +cd .agents && npx playwright test # all specs +cd .agents && npx playwright test tests/auth.spec.ts # one spec +cd .agents && npx playwright test --headed # visible browser +cd .agents && npx playwright test --screenshot=only-on-failure +``` +- Copy `.agents/.env.example` → `.agents/.env` (gitignored) before running E2E. + +### Lint/format (run alongside tests) +```bash +cd backend && npm run lint && npm run prettier +cd frontend && npm run lint +``` + +## What passing looks like +- Jest: `Tests: N passed, N total` and exit code 0. Open handles warnings should be investigated, not ignored. +- Playwright: `N passed (N total)` with exit code 0; `only-on-failure` produces no screenshots. +- ESLint/Prettier/tsc/vite build: exit 0, no errors. Frontend lint fails on any warning (`--max-warnings 0`). + +## How to read failures +- Read the first failure's stack first; later failures are often downstream. +- For Playwright, open the HTML report (`npx playwright show-report`) and the failure screenshot/trace. +- Distinguish: assertion failure (your code) vs infrastructure (DB down, port in use, missing `.env`) vs flake (re-run once to confirm). + +## Guardrails +- Don't mark done if tests fail. If you can't run a suite (no DB, no browser, no env), say so explicitly and report what you did run. +- Don't disable lint/test rules silently to make green — fix the code or surface the conflict. +- Don't run destructive commands (`rm -rf`, `down.sh` on prod) to "fix" a test env. + +## Exit criteria +- The affected suites are green (with exact commands + counts cited), OR failures are reported honestly with output and a next-step proposal. \ No newline at end of file diff --git a/agentic/skills/security-review.md b/agentic/skills/security-review.md new file mode 100644 index 00000000..2c0cd7d6 --- /dev/null +++ b/agentic/skills/security-review.md @@ -0,0 +1,25 @@ +# Skill: Security Review +> Review the current diff for security regressions before commit/PR. + +## When to use +Run this whenever the change touches any of: **auth, tokens, cookies, permissions/RBAC, file operations (path traversal), `child_process`/exec/runtime, plugins (unsandboxed), secrets/config, CORS/CSP, uploads, or user/personal data.** Pair it with `./code-review.md` (which covers general quality); this skill is the security-focused pass. This repo also ships a Claude Code `/security-review` slash-command skill — that command runs the same kind of pass interactively; align with it and don't contradict its findings. + +## Steps +1. **Get the diff:** `git diff main...HEAD` (and `git diff` for unstaged). Identify every new/changed route, middleware, service, model, and config flag. +2. **Load the capability risk checklist.** For each touched capability, open `docs/capabilities/.md` and read its **Security:** and **Data protection:** lines — those are the code-grounded mitigations you must verify still hold. Start with `docs/capabilities/identity-access.md` (auth/tokens/RBAC) and `docs/capabilities/plugins.md` (unsandboxed execution) when relevant. Cross-reference `docs/reference/authentication-cookie-handling.md`, `docs/reference/csp.md`, and CORS reference if present. +3. **Check auth gating on every new/changed route.** Each route must use `auth(...)`, `auth({ optional: (req) => req.authConfig.PUBLIC_VIEWING })`, or an equivalent; writes require auth + `checkPermission`. Confirm owner bypass is intentional. Confirm site flags (`PUBLIC_VIEWING`, `SELF_REGISTRATION`, `PASSWORD_MANAGEMENT`, `SSO_AUTO_REGISTRATION`) are checked where the capability doc says they must be. +4. **Check the known-gap class.** `authLimiter` is defined in `backend/src/middlewares/rateLimiter.js` but not applied to any route. If a change adds an auth endpoint without applying a limiter, or defines a limiter but doesn't wire it, flag it. Look for the same pattern on other new endpoints (brute-forceable: login, register, forgot/reset password, SSO). +5. **Check secrets & logging.** No tokens, refresh cookies, passwords, reset codes, or SSO `clientSecret`s in logs, response bodies, or frontend bundles. Refresh token must stay in the httpOnly cookie only (never in `{ tokens }` body). Passwords/secret fields must be Mongoose `private`. +6. **Check input validation & file ops.** Path-joining on uploads/plugins/asset reads must sanitize against traversal (`../`, absolute paths). `POST /v2/plugin/upload/:slug` runs system `unzip` on user zips — flag any widening of accepted types, size limit, or ownership bypass. +7. **Check plugin unsandboxed execution.** Plugins run same-origin, unsandboxed with full DOM/window. Confirm no auth tokens/secrets are passed into `PluginAPI`/`config`/`data`; only public site configs. Flag any change that increases plugin surface (new `window.DAPlugins` channels, new `PluginAPI` methods exposing user data or tokens). +8. **Check CORS/CSP headers.** If `config/cors` or CSP middleware changed, confirm credentials + origin allowlist stays tight; `SameSite=None`+`Secure` only in prod. +9. **Rank findings:** Critical (auth bypass, secret leak, RCE/path traversal, missing ownership) → High (missing rate-limit on brute-forceable endpoint, broken validation) → Medium (info leak, flag not enforced) → Low (hardening). Give each a `file:line` anchor and the specific mitigation. + +## Guardrails +- **Don't silently fold a security finding into a fix.** A finding that you then fix is still a finding — record it so the reviewer/PR sees it. Don't hide regressions by editing the diff. +- **Report findings ranked by severity, not by file order.** Never mark "clean" to keep momentum — if you didn't verify a touched route, say so. +- Don't edit `docs/capabilities/*` Risk claims during this skill; if a mitigation no longer matches code, raise it as a finding (the catalog is code-grounded — fix the code or update the doc in a separate change via `./docs-update.md`). +- This is a review, not a harden-everything pass. Flag out-of-scope pre-existing issues separately; only fix what the current diff introduced or broke unless asked. + +## Exit criteria +Return a short findings list, each with severity + `file:line` + one-line mitigation, or explicitly **"clean"** with the capability docs you checked listed. If you ran the repo's `/security-review` skill too, note whether its findings match. Do not commit or push — hand the list to the caller (this skill is review-only; commit via `./commit-and-pr.md`). \ No newline at end of file diff --git a/agentic/skills/understand-the-repo.md b/agentic/skills/understand-the-repo.md new file mode 100644 index 00000000..c7915e1a --- /dev/null +++ b/agentic/skills/understand-the-repo.md @@ -0,0 +1,31 @@ +# Skill: understand-the-repo +> Orient cheaply before touching code — load the map + memory, deep-read only the module you'll change. + +## When to use +- At the start of any non-trivial task (feature, fix, refactor, docs change). +- Before answering "how does X work" or "where does Y live" questions. +- When you're tempted to `grep`/scan the whole tree — use this instead. + +## Steps +1. Load `agentic/map/INDEX.md` — the index of pointers to the real maps. +2. Load `agentic/memory/MEMORY.md` — durable repo facts (one line each). Jump to the linked memory file only if relevant. +3. From the index, pick the matching map for the area in question: + - Backend structure/layering → `docs/architecture/` + `docs/principles/principle.md` (thin controllers, services hold logic). + - Endpoint/status/flag spec → `docs/capabilities/.md` (code-grounded; verify claims against `routes/v2/*` + `controllers/` + `services/`). + - Pages / feature coverage → `.agents/SITEMAP.md`. + - Local dev / contributing / tour → `docs/getting-started/`. +4. Deep-read **only** the specific module/route/component you'll touch: + - Backend: `backend/src/routes/v2//` → `backend/src/controllers/.controller.js` → `backend/src/services/.service.js` → `backend/src/models/.model.js`. (Routes are grouped by domain: `content/`, `system/`, `user-management/`, `vehicle-data/`; controllers/services/models are flat `.*`.) + - Frontend: `frontend/src/components/{atoms,molecules,organisms}/`, `frontend/src/pages/`, `frontend/src/stores/`, `frontend/src/hooks/`, routing in `frontend/src/configs/routes.tsx`. +5. Confirm the change surface: name the exact file(s) that will change and why, plus adjacent files to match style (e.g. sibling controller, sibling component). +6. If a durable fact emerged (e.g. a non-obvious layering rule), propose it to `agentic/memory/` via the `learn-and-update` skill — don't edit rules in-place. + +## Guardrails +- Do NOT scan or dump the whole repo into context. The map exists so you don't have to. +- Do NOT fabricate endpoints, statuses, flags, or paths. If the map and code disagree, read the code and note it. +- Do NOT edit `docs/capabilities/*` technical claims without re-verifying against route/controller code. +- Don't duplicate content already in `docs/architecture/`, `docs/capabilities/`, `docs/getting-started/` — point to it. + +## Exit criteria +- You can state, without a full repo scan: (a) which file(s) will change, (b) why, (c) the layer they live in, and (d) the sibling code whose style you'll match. +- The next skill (typically `implement-feature`) has a concrete starting file path. \ No newline at end of file diff --git a/docs/agentic-framework/PROPOSAL.md b/docs/agentic-framework/PROPOSAL.md index 5eb1149d..74158645 100644 --- a/docs/agentic-framework/PROPOSAL.md +++ b/docs/agentic-framework/PROPOSAL.md @@ -1,7 +1,7 @@ # Proposal: Vendor-Neutral Agentic Coding Framework for AutoWRX > Issue: #612 · Branch: `feat/612-agentic-coding-framework` -> Status: **Proposal — awaiting review.** No implementation yet. +> Status: **Implemented (full framework, all layers).** Canonical content lives in `agentic/` at repo root (chosen over `.agent/` to avoid colliding with the existing `.agents/` E2E suite). The framework **wires into** existing repo knowledge (`docs/architecture/`, `docs/capabilities/`, `.agents/SITEMAP.md`, `docs/getting-started/`, `docs/principles/`) rather than duplicating it. Entry points: `AGENTS.md` + `CLAUDE.md`. See [`agentic/README.md`](../../agentic/README.md). The decisions below were resolved as: dir `agentic/`; reuse `docs/capabilities/` as the map; committed map + CI drift check; learning included with manual trigger; full scope (no phasing). ## 1. Problem diff --git a/scripts/check-agent-map.sh b/scripts/check-agent-map.sh new file mode 100755 index 00000000..d4489b65 --- /dev/null +++ b/scripts/check-agent-map.sh @@ -0,0 +1,70 @@ +#!/usr/bin/env bash +# check-agent-map.sh — verify that paths/links referenced by the agentic +# framework's map + entry files still resolve in the repo. Run in CI to +# catch drift when docs/structure move. Exits non-zero on any broken ref. +# +# Usage: scripts/check-agent-map.sh (from repo root) + +set -euo pipefail + +if [ ! -f AGENTS.md ]; then + echo "ERROR: run from repo root (AGENTS.md not found)" >&2 + exit 2 +fi + +python3 - <<'PY' +import os, re, sys + +ROOT = os.getcwd() +broken = [] + +# Files whose links/paths we verify. +SOURCES = [ + "AGENTS.md", + "CLAUDE.md", + "agentic/README.md", + "agentic/RULES.md", + "agentic/CONVENTIONS.md", + "agentic/SETUP.md", + "agentic/skills/README.md", +] +# plus every skill + memory + map + learning markdown +for sub in ("agentic/skills", "agentic/memory", "agentic/map", "agentic/learning"): + for f in sorted(os.listdir(sub)) if os.path.isdir(sub) else []: + if f.endswith(".md"): + SOURCES.append(f"{sub}/{f}") + +# Capture markdown links: [text](target) — these are the navigable refs we verify. +link_re = re.compile(r'\[[^\]]*\]\(([^)]+)\)') + +def skip(t): + return (t.startswith("#") or t.startswith("http") + or t.startswith("mailto:") or t.startswith("data:")) + +def check_link(target, src): + """Markdown link targets are source-relative (web semantics).""" + if skip(target): + return + target = target.split("#", 1)[0] + if not target or "/" not in target: + return + base = os.path.dirname(src) + resolved = os.path.normpath(os.path.join(base, target)) + if not os.path.exists(resolved): + broken.append(f"{src}: broken link -> {target} (resolved {resolved})") + +for src in SOURCES: + if not os.path.exists(src): + broken.append(f"(missing source file) {src}") + continue + text = open(src, encoding="utf-8").read() + for m in link_re.finditer(text): + check_link(m.group(1), src) + +if broken: + print(f"agent-map drift: {len(broken)} broken reference(s):", file=sys.stderr) + for b in broken: + print(" - " + b, file=sys.stderr) + sys.exit(1) +print(f"agent-map OK: all references in {len(SOURCES)} framework file(s) resolve.") +PY \ No newline at end of file From e0c8c0525c89ffec5e0da48aaff8d289385c0c7b Mon Sep 17 00:00:00 2001 From: NhanLuongBGSV Date: Fri, 7 Aug 2026 01:18:47 +0000 Subject: [PATCH 3/7] fix(agentic): make git identity per-contributor, not repo-wide; self-review fixes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The framework wrongly hardcoded one user's identity (NhanLuongBGSV / nhan.luongnguyen@vn.bosch.com) as a repo-wide commit rule. Identity is personal — each contributor commits with their own ECA-signed account. Repo rules now say "commit with your own ECA-signed identity"; the personal identity stays in user-local memory, not committed files. Self-review (dogfooded the framework's own understand-the-repo + code-review skills to validate the framework against the real repo): - Removed the hardcoded identity from AGENTS.md, CLAUDE.md, RULES.md, memory/verified-facts.md, skills/commit-and-pr.md, skills/implement-feature.md, PROPOSAL.md. Drift check still clean; no identity refs remain. - Verified memory claims against code: authLimiter is defined+exported in backend/src/middlewares/rateLimiter.js and unused (gotchas.md ✓); routes/v2 has exactly 4 domains content/system/user-management/vehicle-data (verified-facts.md ✓); no Jest/Playwright runs on PRs (gotchas.md ✓). - Corrected gotchas.md: PR CI now also runs agent-map-check for agentic/+ docs changes (this PR adds it), so "ECA-only" was stale. - Corrected security-review.md: /security-review is a Claude Code built-in harness skill (available in any repo), not something this repo ships. - Confirmed all 9 skills have the 4 required sections, all TREE.md paths exist, MEMORY.md index matches its files, and all markdown links resolve. Co-Authored-By: Claude Signed-off-by: NhanLuongBGSV --- AGENTS.md | 2 +- CLAUDE.md | 2 +- agentic/RULES.md | 2 +- agentic/memory/gotchas.md | 2 +- agentic/memory/verified-facts.md | 2 +- agentic/skills/commit-and-pr.md | 2 +- agentic/skills/implement-feature.md | 2 +- agentic/skills/security-review.md | 4 ++-- docs/agentic-framework/PROPOSAL.md | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index c5114998..a476d3f3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -10,7 +10,7 @@ AutoWRX is a cloud-based rapid-prototyping environment for software-defined vehi - **Conventions:** [`agentic/CONVENTIONS.md`](./agentic/CONVENTIONS.md) Key rules in one line: -- Commit identity: `NhanLuongBGSV` / `nhan.luongnguyen@vn.bosch.com`, **ECA signed**, `git commit -s`. +- 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. diff --git a/CLAUDE.md b/CLAUDE.md index 45645486..13d92543 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -10,7 +10,7 @@ This is a thin adapter. The canonical agent rules live in vendor-neutral files a - **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. -- **Persistent git identity for this repo:** `NhanLuongBGSV` / `nhan.luongnguyen@vn.bosch.com`. Always `git commit -s`. ECA must be signed. +- **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. diff --git a/agentic/RULES.md b/agentic/RULES.md index 5d36e8b4..3955010d 100644 --- a/agentic/RULES.md +++ b/agentic/RULES.md @@ -4,7 +4,7 @@ Hard rules for any agent working in this repo. Load always (imported by `AGENTS. ## Git & contributions -- **ECA is mandatory.** Every commit author must have signed the [Eclipse Contributor Agreement](https://www.eclipse.org/legal/eca/) and commit with that email. For this repo: `NhanLuongBGSV` / `nhan.luongnguyen@vn.bosch.com`. Do **not** use any other identity. +- **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. diff --git a/agentic/memory/gotchas.md b/agentic/memory/gotchas.md index 234231ef..f5bba014 100644 --- a/agentic/memory/gotchas.md +++ b/agentic/memory/gotchas.md @@ -3,7 +3,7 @@ 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. -- **PR CI runs the ECA check only.** `.github/workflows/` has no test job on PRs — `build-docker.yml` and `deploy-dev-stage.yml` run on push/merge paths, not PR open. Agents/authors must run `npm test` (backend) and Playwright (`.agents/`) locally and state how it was verified in the PR body. +- **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 index f5982feb..6e4ca66f 100644 --- a/agentic/memory/verified-facts.md +++ b/agentic/memory/verified-facts.md @@ -5,5 +5,5 @@ Non-obvious facts confirmed by reading the code. Each has a one-line source poin - **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 Vite config; not 3000/5173. (Source: `frontend/vite.config.ts` + `AGENTS.md`.) - **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 identity is fixed:** `NhanLuongBGSV` / `nhan.luongnguyen@vn.bosch.com`. Other identities will fail the ECA check. (Source: `RULES.md` + `.github/workflows/` ECA check.) +- **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/commit-and-pr.md b/agentic/skills/commit-and-pr.md index b1266cd4..e69cdfa9 100644 --- a/agentic/skills/commit-and-pr.md +++ b/agentic/skills/commit-and-pr.md @@ -5,7 +5,7 @@ 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 `NhanLuongBGSV` / `nhan.luongnguyen@vn.bosch.com` (the ECA-signed identity). Fix with `git config user.name "NhanLuongBGSV"` / `git config user.email "nhan.luongnguyen@vn.bosch.com"` if not. Never use any other identity. +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 "..." -m "Co-Authored-By: Claude "`. The `-s` adds the `Signed-off-by:` line required by the Eclipse ECA. One logical change per commit where practical. diff --git a/agentic/skills/implement-feature.md b/agentic/skills/implement-feature.md index 25791d8a..b93b4403 100644 --- a/agentic/skills/implement-feature.md +++ b/agentic/skills/implement-feature.md @@ -19,7 +19,7 @@ 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). 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` as `NhanLuongBGSV` / `nhan.luongnguyen@vn.bosch.com`, PR targets `main`, body = **What / Why / How verified**. CI runs only the ECA check, so state explicitly how tests were verified locally. +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. diff --git a/agentic/skills/security-review.md b/agentic/skills/security-review.md index 2c0cd7d6..70d0efcb 100644 --- a/agentic/skills/security-review.md +++ b/agentic/skills/security-review.md @@ -2,7 +2,7 @@ > Review the current diff for security regressions before commit/PR. ## When to use -Run this whenever the change touches any of: **auth, tokens, cookies, permissions/RBAC, file operations (path traversal), `child_process`/exec/runtime, plugins (unsandboxed), secrets/config, CORS/CSP, uploads, or user/personal data.** Pair it with `./code-review.md` (which covers general quality); this skill is the security-focused pass. This repo also ships a Claude Code `/security-review` slash-command skill — that command runs the same kind of pass interactively; align with it and don't contradict its findings. +Run this whenever the change touches any of: **auth, tokens, cookies, permissions/RBAC, file operations (path traversal), `child_process`/exec/runtime, plugins (unsandboxed), secrets/config, CORS/CSP, uploads, or user/personal data.** Pair it with `./code-review.md` (which covers general quality); this skill is the security-focused pass. Claude Code also has a **built-in** `/security-review` slash command (harness-provided, available in any repo) that runs a similar pass interactively — align with it and don't contradict its findings. ## Steps 1. **Get the diff:** `git diff main...HEAD` (and `git diff` for unstaged). Identify every new/changed route, middleware, service, model, and config flag. @@ -22,4 +22,4 @@ Run this whenever the change touches any of: **auth, tokens, cookies, permission - This is a review, not a harden-everything pass. Flag out-of-scope pre-existing issues separately; only fix what the current diff introduced or broke unless asked. ## Exit criteria -Return a short findings list, each with severity + `file:line` + one-line mitigation, or explicitly **"clean"** with the capability docs you checked listed. If you ran the repo's `/security-review` skill too, note whether its findings match. Do not commit or push — hand the list to the caller (this skill is review-only; commit via `./commit-and-pr.md`). \ No newline at end of file +Return a short findings list, each with severity + `file:line` + one-line mitigation, or explicitly **"clean"** with the capability docs you checked listed. If you also ran Claude Code's built-in `/security-review`, note whether its findings match. Do not commit or push — hand the list to the caller (this skill is review-only; commit via `./commit-and-pr.md`). \ No newline at end of file diff --git a/docs/agentic-framework/PROPOSAL.md b/docs/agentic-framework/PROPOSAL.md index 74158645..1a901db5 100644 --- a/docs/agentic-framework/PROPOSAL.md +++ b/docs/agentic-framework/PROPOSAL.md @@ -115,7 +115,7 @@ Each skill is a markdown playbook: *when to use · steps · guardrails · exit c - **run-tests** — how tests are run here (frontend/backend), what passing looks like, how to interpret failures. - **code-review** — self-review checklist before commit (reuse, simplification, correctness, altitude). - **security-review** — security review of the diff (the repo already has a `/security-review` skill — fold it in). -- **commit-and-pr** — commit author = `NhanLuongBGSV`, conventional messages, PR template, ECA note. +- **commit-and-pr** — commit with the contributor's own ECA-signed identity, conventional messages, PR template, ECA note. - **deploy** — instance-setup flow (`instance-setup/up.sh`, docker-compose.prod.yml), env requirements. - **docs-update** — keep `docs/capabilities/*` and `.agent/map/*` in sync with code changes. - **learn-and-update** — periodically research current best practices/trends on the web, capture dated+sourced notes in `.agent/learning/`, and propose updates to skills/memory via PR. From d6760b2777285e08d4a4297c8dcfde794363fda2 Mon Sep 17 00:00:00 2001 From: NhanLuongBGSV Date: Fri, 7 Aug 2026 01:22:45 +0000 Subject: [PATCH 4/7] feat(agentic): add security + license review round (license-check skill + CI) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The framework had a security-review skill but no license check — a gap for an Eclipse project where source license headers matter. This adds the license half and wires both into the flow. - agentic/skills/license-check.md — new skill: verify changed .js/.ts/.tsx carry the repo Eclipse/MIT SPDX header, no existing headers stripped, no copyleft/proprietary vendored code, deps MIT-compatible. - scripts/check-license-headers.sh + .github/workflows/license-headers-check.yml — CI gate that checks only CHANGED source files vs the PR base (pre-existing header debt elsewhere doesn't block). Verified clean on this branch. - CONVENTIONS.md — License (Eclipse/MIT) section: header requirement, no copyleft, CI pointer. - skills/README.md + AGENTS.md + implement-feature.md + code-review.md — wire license-check into the core flow alongside security-review. Ran the round on this PR's own diff (dogfood): no .js/.ts/.tsx changed → license-headers OK; no real secrets in committed files (only prose rules); check-agent-map.sh is pure os.path (no injection); workflow uses actions/checkout@v4, no secrets exposed. Security + license: clean. Co-Authored-By: Claude Signed-off-by: NhanLuongBGSV --- .github/workflows/license-headers-check.yml | 26 ++++++++++ AGENTS.md | 1 + agentic/CONVENTIONS.md | 9 +++- agentic/skills/README.md | 4 +- agentic/skills/code-review.md | 2 +- agentic/skills/implement-feature.md | 2 +- agentic/skills/license-check.md | 40 ++++++++++++++++ scripts/check-license-headers.sh | 53 +++++++++++++++++++++ 8 files changed, 133 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/license-headers-check.yml create mode 100644 agentic/skills/license-check.md create mode 100755 scripts/check-license-headers.sh diff --git a/.github/workflows/license-headers-check.yml b/.github/workflows/license-headers-check.yml new file mode 100644 index 00000000..a1f7876a --- /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 index a476d3f3..fb5d2314 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -34,6 +34,7 @@ Indexed in [`agentic/skills/README.md`](./agentic/skills/README.md). The core fl - [`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. diff --git a/agentic/CONVENTIONS.md b/agentic/CONVENTIONS.md index a253ae34..21940fd0 100644 --- a/agentic/CONVENTIONS.md +++ b/agentic/CONVENTIONS.md @@ -46,4 +46,11 @@ Style and structure conventions for this repo. Load always (imported by `AGENTS. - Canonical content in `agentic/`. Tool-specific adapters (e.g. `CLAUDE.md`) stay thin and `@import` canonical files — 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. \ No newline at end of file +- 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/skills/README.md b/agentic/skills/README.md index d1b58986..e509c0e7 100644 --- a/agentic/skills/README.md +++ b/agentic/skills/README.md @@ -11,6 +11,7 @@ Repo-specific procedures an agent loads **on demand** when a task matches. Each | **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) | | **Deploy** | When asked to deploy an instance. `instance-setup/` Docker Compose. | [deploy.md](./deploy.md) | | **Docs update** | After structural/endpoint changes — keep `docs/capabilities/`, `.agents/SITEMAP.md`, and `agentic/map/` in sync. | [docs-update.md](./docs-update.md) | @@ -24,7 +25,8 @@ implement-feature ├─ implement (per CONVENTIONS) ├─ run-tests ├─ code-review - │ └─ security-review (if auth/data/runtime/plugins) + │ ├─ security-review (if auth/data/runtime/plugins) + │ └─ license-check (if new/changed .js/.ts/.tsx or deps) └─ commit-and-pr after merge → docs-update (if structure/endpoint changed) on schedule → learn-and-update diff --git a/agentic/skills/code-review.md b/agentic/skills/code-review.md index fb97fa3c..ba09d8ae 100644 --- a/agentic/skills/code-review.md +++ b/agentic/skills/code-review.md @@ -27,7 +27,7 @@ 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. +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 diff --git a/agentic/skills/implement-feature.md b/agentic/skills/implement-feature.md index b93b4403..0d3b9956 100644 --- a/agentic/skills/implement-feature.md +++ b/agentic/skills/implement-feature.md @@ -17,7 +17,7 @@ - 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). +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. diff --git a/agentic/skills/license-check.md b/agentic/skills/license-check.md new file mode 100644 index 00000000..3fa90c79 --- /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/scripts/check-license-headers.sh b/scripts/check-license-headers.sh new file mode 100755 index 00000000..15bda2a3 --- /dev/null +++ b/scripts/check-license-headers.sh @@ -0,0 +1,53 @@ +#!/usr/bin/env bash +# check-license-headers.sh — verify that .js/.ts/.tsx source files CHANGED +# vs the base ref carry the repo's Eclipse/MIT SPDX header. Fails only on +# changed files, so pre-existing header debt elsewhere doesn't block PRs. +# +# Usage: scripts/check-license-headers.sh [base_ref] +# base_ref defaults to origin/main. + +set -euo pipefail + +if [ ! -f AGENTS.md ]; then + echo "ERROR: run from repo root (AGENTS.md not found)" >&2 + exit 2 +fi + +BASE="${1:-origin/main}" +if ! git rev-parse --verify "$BASE" >/dev/null 2>&1; then + echo "WARN: base ref '$BASE' not found; falling back to HEAD~1" >&2 + BASE="HEAD~1" +fi + +mapfile -t FILES < <(git diff --name-only --diff-filter=ACM "$BASE...HEAD" -- '*.js' '*.ts' '*.tsx' | grep -vE '\.d\.ts$') + +if [ "${#FILES[@]}" -eq 0 ]; then + echo "license-headers OK: no changed .js/.ts/.tsx source files." + exit 0 +fi + +missing=() +for f in "${FILES[@]}"; do + [ -f "$f" ] || continue + # Header must be in the first 12 lines. + if ! head -12 "$f" | grep -q 'SPDX-License-Identifier: MIT'; then + missing+=("$f") + fi +done + +if [ "${#missing[@]}" -gt 0 ]; then + echo "license-headers FAIL: ${#missing[@]} changed source file(s) missing the Eclipse/MIT SPDX header:" >&2 + for f in "${missing[@]}"; do echo " - $f" >&2; done + echo "Add this header at the top:" >&2 + cat >&2 <<'HDR' +// 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 +HDR + exit 1 +fi +echo "license-headers OK: ${#FILES[@]} changed source file(s) all carry the MIT SPDX header." \ No newline at end of file From 6a01a5ae1a0c038e5a28beb3034ea0f06de760a2 Mon Sep 17 00:00:00 2001 From: NhanLuongBGSV Date: Fri, 7 Aug 2026 01:26:19 +0000 Subject: [PATCH 5/7] =?UTF-8?q?fix(agentic):=20self-review=20round=20?= =?UTF-8?q?=E2=80=94=20correct=20CLAUDE.md=20@path=20import=20syntax=20+?= =?UTF-8?q?=20citations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adversarial self-review of the whole framework (read every file, verified claims against the repo). Findings + fixes: - CLAUDE.md used `@import ./file` — wrong. Claude Code's import syntax is `@path` (e.g. `@AGENTS.md`); `@import` would not expand. Fixed to `@AGENTS.md` / `@agentic/RULES.md` / `@agentic/CONVENTIONS.md`. Verified the imported chain has no stray `@` tokens (no unintended nested imports). Updated 9 prose references across SETUP/README/AGENTS/CONVENTIONS/decisions/ best-practices/PROPOSAL to say `@path`, not `@import`. - memory/verified-facts.md cited `frontend/vite.config.ts` for the dev port; the port (3210) is actually in `frontend/package.json`'s `dev` script. Fixed citation. - SETUP.md skill-symlink loop also symlinked README.md as a skill; now skips the index. Verified accurate (no change needed): deploy.md env keys match .env.prod.sample exactly; security-review reference docs (docs/reference/csp.md, authentication-cookie-handling.md, architecture/plugin-system.md) exist; memory facts (4 route domains, authLimiter unused, tsc&&vite build) match code; map/TREE.md paths exist; all 9 skills have the 4 required sections; drift check + license-headers check pass; no @import remains. Co-Authored-By: Claude Signed-off-by: NhanLuongBGSV --- AGENTS.md | 2 +- CLAUDE.md | 8 ++++---- agentic/CONVENTIONS.md | 2 +- agentic/README.md | 4 ++-- agentic/SETUP.md | 3 ++- agentic/learning/best-practices.md | 2 +- agentic/memory/decisions.md | 2 +- agentic/memory/verified-facts.md | 2 +- docs/agentic-framework/PROPOSAL.md | 6 +++--- 9 files changed, 16 insertions(+), 15 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index fb5d2314..4d9391f9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -68,5 +68,5 @@ cd instance-setup && ./up.sh # docker compose up -d (needs ## Adapters -- **Claude Code:** [`CLAUDE.md`](./CLAUDE.md) `@import`s this file. See [`agentic/SETUP.md`](./agentic/SETUP.md) to enable native skill invocation. +- **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 index 13d92543..608b39f3 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,10 +1,10 @@ # CLAUDE.md — AutoWRX (Claude Code adapter) -This is a thin adapter. The canonical agent rules live in vendor-neutral files and are imported below. Do not duplicate rules here. +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. -@import ./AGENTS.md -@import ./agentic/RULES.md -@import ./agentic/CONVENTIONS.md +@AGENTS.md +@agentic/RULES.md +@agentic/CONVENTIONS.md ## Claude Code specifics diff --git a/agentic/CONVENTIONS.md b/agentic/CONVENTIONS.md index 21940fd0..7a1e976b 100644 --- a/agentic/CONVENTIONS.md +++ b/agentic/CONVENTIONS.md @@ -44,7 +44,7 @@ Style and structure conventions for this repo. Load always (imported by `AGENTS. ## Agent config (this framework) -- Canonical content in `agentic/`. Tool-specific adapters (e.g. `CLAUDE.md`) stay thin and `@import` canonical files — don't duplicate rules into adapters. +- 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. diff --git a/agentic/README.md b/agentic/README.md index 072601f6..b795e9e5 100644 --- a/agentic/README.md +++ b/agentic/README.md @@ -8,7 +8,7 @@ A **repo-resident, vendor-neutral** framework that lets any AI coding agent — ``` AGENTS.md vendor-neutral entry point (read by every tool) -CLAUDE.md Claude Code adapter (@imports AGENTS.md) +CLAUDE.md Claude Code adapter (imports AGENTS.md via `@path`) agentic/ README.md this file RULES.md hard rules (must / must-not) @@ -61,7 +61,7 @@ This framework **points to** existing repo knowledge rather than copying it: ## Vendor neutrality Canonical content lives in `agentic/`. Tool-specific entry files are thin adapters: -- **Claude Code** → `CLAUDE.md` uses `@import` to pull in `AGENTS.md` / `agentic/*`. +- **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/`). diff --git a/agentic/SETUP.md b/agentic/SETUP.md index f5eaf735..00682648 100644 --- a/agentic/SETUP.md +++ b/agentic/SETUP.md @@ -4,7 +4,7 @@ The framework is vendor-neutral; each tool just needs to find `AGENTS.md` (and o ## Claude Code -`CLAUDE.md` already `@import`s `AGENTS.md` + rules, so rules load automatically when Claude Code opens this repo. +`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) @@ -15,6 +15,7 @@ Claude Code's Skill tool only sees skills in `.claude/skills/`. `.claude/` is gi 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 ``` diff --git a/agentic/learning/best-practices.md b/agentic/learning/best-practices.md index 469dcc3a..3ca72968 100644 --- a/agentic/learning/best-practices.md +++ b/agentic/learning/best-practices.md @@ -6,7 +6,7 @@ Starting points for this stack — refine as we learn. Each entry has a `Last re - Last reviewed: 2026-08-07 - Source: https://agents.md -- Keep `AGENTS.md` as the canonical always-loaded file; tool adapters (`CLAUDE.md`) `@import` it rather than duplicating rules. +- 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 diff --git a/agentic/memory/decisions.md b/agentic/memory/decisions.md index fd81ab1e..ceea2d8a 100644 --- a/agentic/memory/decisions.md +++ b/agentic/memory/decisions.md @@ -5,7 +5,7 @@ Key choices and their rationale, kept short. Date each entry; supersede, don't s ## 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. +- **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. diff --git a/agentic/memory/verified-facts.md b/agentic/memory/verified-facts.md index 6e4ca66f..a8da1324 100644 --- a/agentic/memory/verified-facts.md +++ b/agentic/memory/verified-facts.md @@ -3,7 +3,7 @@ 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 Vite config; not 3000/5173. (Source: `frontend/vite.config.ts` + `AGENTS.md`.) +- **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/docs/agentic-framework/PROPOSAL.md b/docs/agentic-framework/PROPOSAL.md index 1a901db5..2a00ab51 100644 --- a/docs/agentic-framework/PROPOSAL.md +++ b/docs/agentic-framework/PROPOSAL.md @@ -60,7 +60,7 @@ Everything under `.agent/` is **canonical and vendor-neutral**. Tool-specific en ``` AGENTS.md # vendor-neutral entry (agents.md spec); imports .agent/* -CLAUDE.md # Claude Code entry; @imports .agent/* (Claude Code supports @import) +CLAUDE.md # Claude Code entry; imports agentic/* via @path (Claude Code supports @path imports) .agent/ RULES.md # hard rules (must / must-not) CONVENTIONS.md # naming, structure, commit, PR style @@ -97,7 +97,7 @@ CLAUDE.md # Claude Code entry; @imports .agent/* (Claude Co | Artifact | Canonical | Claude Code | opencode | openclaw / other | |---|---|---|---|---| -| Entry rules | `AGENTS.md` | `CLAUDE.md` `@import`s it | reads `AGENTS.md` natively | reads `AGENTS.md` (agents.md spec) | +| Entry rules | `AGENTS.md` | `CLAUDE.md` imports it via `@path` | reads `AGENTS.md` natively | reads `AGENTS.md` (agents.md spec) | | Rules/conventions | `.agent/RULES.md`, `CONVENTIONS.md` | imported via `CLAUDE.md` | imported via `AGENTS.md` | imported via `AGENTS.md` | | Skills | `.agent/skills/*.md` | `.claude/skills/` → symlink/point to `.agent/skills` | opencode skills dir → same | read from `.agent/skills` | | Memory | `.agent/memory/*.md` + index | `CLAUDE.md` instructs load on start | `AGENTS.md` instructs load | same | @@ -152,7 +152,7 @@ Deploy and learn-and-update are separate flows triggered on demand or on a sched ## 11. Migration path (phased) -1. **Phase 1 — Skeleton (this issue, small PR):** add `AGENTS.md` + `CLAUDE.md` adapter + `.agent/` structure with `RULES.md`, `CONVENTIONS.md`, `skills/README.md`, and seed `map/TREE.md` + `memory/MEMORY.md`. Wire Claude Code via `@import`. No behavior change yet beyond consistent loading. +1. **Phase 1 — Skeleton (this issue, small PR):** add `AGENTS.md` + `CLAUDE.md` adapter + `.agent/` structure with `RULES.md`, `CONVENTIONS.md`, `skills/README.md`, and seed `map/TREE.md` + `memory/MEMORY.md`. Wire Claude Code via `@path` imports. No behavior change yet beyond consistent loading. 2. **Phase 2 — Skills:** author the core skills (understand-the-repo, implement-feature, run-tests, code-review, commit-and-pr, deploy). Migrate existing `/security-review` and `/run`-style skills into `.agent/skills`. 3. **Phase 3 — Memory & map population:** fill memory + map from the now-merged `docs/capabilities/` catalog (single source reused). Add a CI drift check for the map. 4. **Phase 4 — Learning loop:** add `learn-and-update` + session-lessons capture. From 9daea377c05bc4eee3cac8a9b520dd8197e8d271 Mon Sep 17 00:00:00 2001 From: NhanLuongBGSV Date: Fri, 7 Aug 2026 01:31:25 +0000 Subject: [PATCH 6/7] =?UTF-8?q?fix(agentic):=20round-3=20review=20?= =?UTF-8?q?=E2=80=94=20de-leak=20vendor=20neutrality,=20fix=20typedefs=20l?= =?UTF-8?q?abel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Third adversarial self-review pass (verified every concrete technical claim in the skills against the code; scanned for contradictions + vendor leaks). Verified accurate against code (no change needed): - security-review.md plugin claims all real: window.DAPlugins (PluginPageRender.tsx), PluginAPI, POST /v2/plugin/upload/:slug (plugin.route.js:36), system unzip via spawn('unzip',...) (plugin.controller.js:140). - Branch naming + PR title format consistent across CONVENTIONS.md, implement-feature.md, commit-and-pr.md (types feat/docs/fix/chore/refactor). - backend/src/typedefs and backend/src/docs dirs exist. Fixes: - Vendor-neutrality leak: Co-Authored-By: Claude was hardcoded in CONVENTIONS.md and commit-and-pr.md. Now conditional — Claude Code uses that trailer; other tools use their equivalent or omit. RULES.md already had the "(or the tool's equivalent)" caveat. commit-and-pr exit criteria softened to not require the Co-Authored-By trailer. - map/TREE.md: typedefs/ labeled "TS-style type defs" but backend is JS — corrected to "shared JSDoc @typedef definitions". Drift check (29 files) + license-headers check still pass. Co-Authored-By: Claude Signed-off-by: NhanLuongBGSV --- agentic/CONVENTIONS.md | 2 +- agentic/map/TREE.md | 2 +- agentic/skills/commit-and-pr.md | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/agentic/CONVENTIONS.md b/agentic/CONVENTIONS.md index 7a1e976b..ed15c0ac 100644 --- a/agentic/CONVENTIONS.md +++ b/agentic/CONVENTIONS.md @@ -5,7 +5,7 @@ Style and structure conventions for this repo. Load always (imported by `AGENTS. ## 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, `Co-Authored-By: Claude `. +- **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 diff --git a/agentic/map/TREE.md b/agentic/map/TREE.md index a1f841d4..8f2d2c4e 100644 --- a/agentic/map/TREE.md +++ b/agentic/map/TREE.md @@ -19,7 +19,7 @@ backend/src/ Node/Express + MongoDB backend system/ files, plugins, search, genai, site mgmt, templates services/ business logic (called by controllers) scripts/ one-off / scheduled jobs - typedefs/ shared TS-style type defs + typedefs/ shared JSDoc @typedef definitions utils/ helpers validations/ request schema validators diff --git a/agentic/skills/commit-and-pr.md b/agentic/skills/commit-and-pr.md index e69cdfa9..d85405f8 100644 --- a/agentic/skills/commit-and-pr.md +++ b/agentic/skills/commit-and-pr.md @@ -8,7 +8,7 @@ When the work is verified (tests pass per `./run-tests.md`, self-reviewed per `. 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 "..." -m "Co-Authored-By: Claude "`. The `-s` adds the `Signed-off-by:` line required by the Eclipse ECA. One logical change per commit where practical. +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: @@ -28,4 +28,4 @@ When the work is verified (tests pass per `./run-tests.md`, self-reviewed per `. - 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,key=Co-Authored-By)'` shows the correct identity and both trailers. \ No newline at end of file +- 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 From 66e9e874d33586b9a7c7846df0be5ae3f30fcdf9 Mon Sep 17 00:00:00 2001 From: NhanLuongBGSV Date: Fri, 7 Aug 2026 01:42:25 +0000 Subject: [PATCH 7/7] feat(agentic): add 13 repo-specific skills (debug, races, build, perf, ops, plugins, secrets) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Scanned the codebase, docs, and capability catalog to identify recurring work + risk areas not covered by the original 10 skills, then authored 13 new skill playbooks grounded in real repo paths/commands: Debug & correctness: - debug.md — symptom→where-to-look decision tree (winston/morgan, Docker/pm2 logs, browser console [no ErrorBoundary], Socket.IO frames, Playwright trace) + a common-symptoms table (401 loop, empty workspace-tree, 503, CACHE_URL staleness, 6bd6ccb seed race, 500 bypass, StrictMode double-call). - find-race-conditions.md — concurrency hunt for the no-transactions codebase (doc-level atomicity only; read-modify-write→findOneAndUpdate; counters; token single-flight; Socket.IO ordering; seed-vs-save; CACHE_URL eventual consistency). Build (add/change): - add-endpoint.md — v2 endpoint procedure (domain route → service → thin controller → model → auth gating → Joi validation → register in domain index.js → Jest → capability doc → SITEMAP). - add-frontend-feature.md — atomic-design placement, configs/routes.tsx, Zustand store, usePermissionHook, API client, E2E spec. - db-schema-change.md — safe Mongoose evolution (additive fields, indexes/TTL citing the Token TTL gap, backfill scripts; no migration tool/transactions). - realtime-event.md — adding a Socket.IO event (config/socket.js, kit-server relay via RUNTIME_SERVER_URL, subscribe→run→stop lifecycle). - add-test.md — Jest (backend) + Playwright (.agents helpers/fixtures/snapshot policy). Review & health: - performance-review.md — Mongo N+1/populate/indexes, external CACHE_URL/ LOG_URL calls, frontend bundle (rollup-plugin-visualizer), Socket.IO fan-out. - dependency-upgrade.md — npm audit/Dependabot, breaking-change check, tests, license compatibility (450 vulns flagged on the repo). Deploy & ops: - troubleshoot-deploy.md — unhappy-path symptom→cause→fix (env, ports, Mongo, PROTOTYPES_PATH bind-mount [d6807b4], host.docker.internal/CODER_URL). - coder-workspace.md — VS Code-in-browser integration (instance-setup/coder + plans, workspace lifecycle). Specialized: - plugin-authoring.md — window.DAPlugins/PluginAPI, unsandboxed model, e2e-simple-plugin fixture, upload. - secrets-incident.md — leaked-secret response (identify, blast radius, rotate-at-source, scrub, incident note). Wiring: skills/README.md index reorganized into categories (23 skills) with an expanded core-flow diagram; AGENTS.md points to the full index. Verified: all 13 skills have the 4 required sections; drift check passes (42 framework files, all links resolve); license-headers check passes; spot-checked debug.md + add-endpoint.md claims against code (validations/ .validation.js + index.js, middlewares/validate.js, socket.js:31 handshake.query.access_token, routes/v2/index.js aggregation — all real). Co-Authored-By: Claude Signed-off-by: NhanLuongBGSV --- AGENTS.md | 3 ++ agentic/skills/README.md | 46 ++++++++++++++++-- agentic/skills/add-endpoint.md | 35 ++++++++++++++ agentic/skills/add-frontend-feature.md | 40 ++++++++++++++++ agentic/skills/add-test.md | 64 ++++++++++++++++++++++++++ agentic/skills/coder-workspace.md | 36 +++++++++++++++ agentic/skills/db-schema-change.md | 36 +++++++++++++++ agentic/skills/debug.md | 56 ++++++++++++++++++++++ agentic/skills/dependency-upgrade.md | 48 +++++++++++++++++++ agentic/skills/find-race-conditions.md | 48 +++++++++++++++++++ agentic/skills/performance-review.md | 51 ++++++++++++++++++++ agentic/skills/plugin-authoring.md | 41 +++++++++++++++++ agentic/skills/realtime-event.md | 40 ++++++++++++++++ agentic/skills/secrets-incident.md | 49 ++++++++++++++++++++ agentic/skills/troubleshoot-deploy.md | 40 ++++++++++++++++ 15 files changed, 630 insertions(+), 3 deletions(-) create mode 100644 agentic/skills/add-endpoint.md create mode 100644 agentic/skills/add-frontend-feature.md create mode 100644 agentic/skills/add-test.md create mode 100644 agentic/skills/coder-workspace.md create mode 100644 agentic/skills/db-schema-change.md create mode 100644 agentic/skills/debug.md create mode 100644 agentic/skills/dependency-upgrade.md create mode 100644 agentic/skills/find-race-conditions.md create mode 100644 agentic/skills/performance-review.md create mode 100644 agentic/skills/plugin-authoring.md create mode 100644 agentic/skills/realtime-event.md create mode 100644 agentic/skills/secrets-incident.md create mode 100644 agentic/skills/troubleshoot-deploy.md diff --git a/AGENTS.md b/AGENTS.md index 4d9391f9..f255fe3e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -40,6 +40,9 @@ Indexed in [`agentic/skills/README.md`](./agentic/skills/README.md). The core fl - [`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 diff --git a/agentic/skills/README.md b/agentic/skills/README.md index e509c0e7..a11d0cd5 100644 --- a/agentic/skills/README.md +++ b/agentic/skills/README.md @@ -4,6 +4,7 @@ Repo-specific procedures an agent loads **on demand** when a task matches. Each ## 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) | @@ -13,23 +14,62 @@ Repo-specific procedures an agent loads **on demand** when a task matches. Each | **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) | -| **Deploy** | When asked to deploy an instance. `instance-setup/` Docker Compose. | [deploy.md](./deploy.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) + │ ├─ 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 +on schedule → learn-and-update · dependency-upgrade +deploy broken? → troubleshoot-deploy · coder-workspace +secret leaked? → secrets-incident ``` ## Wiring into Claude Code diff --git a/agentic/skills/add-endpoint.md b/agentic/skills/add-endpoint.md new file mode 100644 index 00000000..79a4456d --- /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 00000000..9a4d9396 --- /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 00000000..70d156aa --- /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/coder-workspace.md b/agentic/skills/coder-workspace.md new file mode 100644 index 00000000..b1750f9b --- /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/db-schema-change.md b/agentic/skills/db-schema-change.md new file mode 100644 index 00000000..d0c19a2d --- /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 00000000..575d1053 --- /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 00000000..81bee3e1 --- /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/find-race-conditions.md b/agentic/skills/find-race-conditions.md new file mode 100644 index 00000000..1e11a6db --- /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/performance-review.md b/agentic/skills/performance-review.md new file mode 100644 index 00000000..4cad65de --- /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 00000000..e05d9d40 --- /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 `