Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 108 additions & 0 deletions .agents/skills/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# Euro-Office task pipeline — skills

Assisted, portable AI-agent skills covering the full lifecycle of a task —
**fetch/define → plan → implement → audit → prepare a PR** — for the Euro-Office DocumentServer
meta-repo. The skills **propose and show** commands; a **human** runs builds, commits, and PRs. They
work across **Claude Code, Codex, and Cursor**.

The canonical source lives here in `.agents/skills/`. The skills **do not duplicate** the
environment docs (`AGENTS.md`, `CONTRIBUTING.md`, per-repo `AGENTS.md`/`CLAUDE.md`) — they **link**
them.

## The skills

| Skill | Invoke | What it does | Output |
|---|---|---|---|
| `blueprint` | `/blueprint [<ref>]` | Onboard `gh`/Jira (first run) + fetch + investigate + define a task (GitHub / Jira / manual) | `.ai/tasks/<task-id>/plan.md` |
| `breakdown` | `/breakdown [<task-id>]` | plan.md → atomic ~5-min steps; propose a branch per affected repo | `.ai/tasks/<task-id>/tasks.md` |
| `apply` | `/apply` | Ensure the task branch (interactive — propose/create, you can rename it), apply the next step, show the build/test command; stop | (branch + code edit + `- [x]`) |
| `audit` | `/audit` · `/audit <owner>/<repo>#<n>` · `/audit <PR-URL>` | Security + code review + emulated quality gate + proposed PR comments — task diff **or** any open PR | task: `.ai/tasks/<task-id>/review.md` · PR: `.ai/reviews/<repo>-<n>/review.md` |
| `prepare-pr` | `/prepare-pr` | Prepare (never publish) the PR(s): body + `gh pr create` | `.ai/tasks/<task-id>/pr-<repo>.md` |

Artifacts are gitignored and cross-tool, split by concept:
- **Task workspace** — `.ai/tasks/<task-id>/` holds everything for a task you drive (`plan.md`,
`tasks.md`, `review.md`, `pr-<repo>.md`), co-located so each stage feeds the next. `<task-id>` is a
slug of the ref (`web-apps #54` → `web-apps-54`, `EUOFFICE-5` → `euoffice-5`, manual → slug of the
title); skills infer it from the current branch `feature/<task-id>`, or ask.
- **Standalone PR reviews** — `.ai/reviews/<repo>-<n>/` holds `audit`'s output when reviewing an open
PR. A PR review is **not** a task, so it never lives under `.ai/tasks/`.

## The flow

```
/blueprint <ref> -> plan.md (onboards gh/Jira on first run; else manual paste)
|
/breakdown -> tasks.md (+ propose feature/<task-id> branches)
|
/apply (repeat) -> ensure branch (interactive) + one step; you run build/test; you commit
|
/audit -> review.md (security / code / quality gate)
|
/prepare-pr -> PR body + `gh pr create` for you to run
```

Assisted mode throughout: the agent never runs builds/commits/PRs and never opens issues/PRs — it
proposes and you execute (the one exception: `apply` may create/switch the task branch after you
confirm). Contribution policy lives in `AGENTS.md` (§Commits, §Contribution policy) and
`CONTRIBUTING.md` (§AI-assisted contributions): Conventional Commits + `Assisted-by: AGENT:MODEL`,
**never** `Signed-off-by` (human DCO), AI-use disclosure in the PR, focused PRs, AGPL-3.0.

## Smart execution (mode / model / effort)

When a skill starts it **announces a recommended execution profile** — plan mode for planning stages,
a suggested model, and a suggested reasoning effort — plus how to switch (`/plan` or Shift+Tab ·
`/model` · `/effort`). You apply it: skills **recommend and remind, they don't enforce** (SKILL.md
frontmatter can't set model/effort/mode, and these are Claude-Code-specific). Skills also remind you
to **lower effort** if you'd raised it. Full table + how-to: `_shared/execution-profiles.md`.

## Onboarding (once per person)

The first `/blueprint` run offers to set up the integrations it needs. You can also run the helper
directly at any time:
- Linux / macOS / WSL / Git Bash: `bash scripts/setup-integrations.sh`
- Windows PowerShell: `powershell -File scripts/setup-integrations.ps1`

It detects your OS, installs `gh`, runs the interactive `gh auth login`, helps set the Jira env vars,
and self-checks. Everything is **per-person** and **never committed** (OSS). The only unavoidable
manual step is the interactive `gh auth login`. Without any of this, the skills still work via
**manual paste**. Per-platform matrix: `_shared/integrations.md`.

## Portability — how each tool discovers the skills

| Tool | Mechanism |
|---|---|
| **Codex / generic** | reads `.agents/skills/<name>/SKILL.md` directly (canonical) |
| **Claude Code** | `.claude/skills/<name>/SKILL.md` — a **real thin adapter** that points here |
| **Cursor** | `.cursor/rules/<name>.mdc` — a thin rule that points here |

> Why real adapters for Claude Code, not a symlink? Claude Code on Windows over `\\wsl.localhost`
> cannot follow WSL symlinks, and skill discovery does not resolve symlinks anyway (regression
> anthropics/claude-code #38051). So each `.claude/skills/<name>/SKILL.md` is a real file that
> redirects to the canonical playbook — a single source of truth is preserved.

## `_shared/` references (read, don't duplicate)

- `repo-matrix.md` — what lives in each submodule/repo + code anchors + build/lint per repo
- `task-ref-parsing.md` — GitHub / Jira / manual detection + task-id slug rules
- `integrations.md` — `gh` + Jira setup, cross-platform (Linux/macOS/Windows/WSL)
- `build-commands.md` — pointer to `AGENTS.md` + per-repo lint/test
- `sonar-quality-gate.md` — emulated quality-gate rubric (A–E, PASS/FAIL)
- `agpl-checklist.md` — AGPL-3.0 checks
- `memory-leak-checklist.md` — web-apps memory-leak sweep
- `execution-profiles.md` — recommended mode / model / effort per skill

Onboarding helper scripts live in `scripts/setup-integrations.{sh,ps1}`.

## Maintenance — editing or adding a skill

- **Edit** a skill's behavior: change only `.agents/skills/<name>/SKILL.md` (canonical). The Claude
Code adapter and Cursor rule redirect here, so behavior updates with no re-sync. (If you change the
`description`, also update it in the adapter/rule, since that one line is duplicated there.)
- **Add** a skill: create `.agents/skills/<name>/SKILL.md`, plus a real adapter at
`.claude/skills/<name>/SKILL.md` (frontmatter + pointer) and a Cursor rule at
`.cursor/rules/<name>.mdc`.
- **Frontmatter**: `name`, `description` (trigger-oriented), `user-invokable` (spelled with a **k**),
and `metadata` (e.g. `version`). There is no top-level `version` key, and no `model`/`effort`/
`permission-mode` key (those are recommendations in the body — see `_shared/execution-profiles.md`).
- Skills load at session start; a **new** Claude Code session is needed to pick up new/renamed skills.
Use `/skills` to list discovered skills and `/doctor` to validate config.
24 changes: 24 additions & 0 deletions .agents/skills/_shared/agpl-checklist.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# AGPL-3.0 checklist (licensing)

DocumentServer and its components are **AGPL-3.0**. Every AI-assisted contribution must comply.
Sources: `LICENSE` (root), `CONTRIBUTING.md` §"AI-assisted contributions" (Licensing) and the
[AI Contribution Policy](https://github.com/Euro-Office/.github/blob/main/AI_POLICY.md).

## Checks

- [ ] **License header** on every NEW source file, in the format used by neighboring files in the same
repo (copy the existing header; do not invent one).
- [ ] **No incompatible material**: no snippet copied from sources whose license is incompatible with
AGPL-3.0 (proprietary, GPL-incompatible, code with unclear licensing).
- [ ] **Third-party dependencies**: license **compatible** with AGPL-3.0 and **verified against the
real registry** (npm/PyPI/…); no invented or unverified packages (Euro-Office policy).
- [ ] **Copyright/attribution** preserved when adapting permitted third-party code.
- [ ] **Network use (AGPL §13)**: if a network-accessible feature is added, the obligation to make the
corresponding source available is not broken.
- [ ] **No secrets or proprietary data** embedded in the code.

## Notes

- The **human** certifies the DCO (`Signed-off-by`); the agent **never** adds it.
- If in doubt about the license of an AI-generated snippet → **flag it in `review.md`** for human
review; do not silence it.
54 changes: 54 additions & 0 deletions .agents/skills/_shared/build-commands.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Build / lint / test commands (per repo)

> **POINTER, not duplication.** The server's start/build/verify workflow is authoritative in
> **`AGENTS.md`** (root), §"Build & run a test server (Docker)". **Always derive from there**; this
> sheet only adds what `AGENTS.md` does not cover (per-repo lint/test) and a quick target index.

## Server: start, in-container build, and verification

See `AGENTS.md` §"Build & run a test server (Docker)":
- **Start** → "Start the server" subsection (docker under `develop/`; healthcheck at `/healthcheck`).
- **Build** → "Build changes" subsection (in-container targets via `docker compose exec -T eo make <target>`).
- **Verify in a browser** → "Verify in a browser (Playwright MCP)" subsection.

`AGENTS.md` is the reference; follow whatever it says (e.g. do not use interactive `make`/`make local`
under `develop/`). This sheet **does not** contradict `AGENTS.md`.

### Quick index of in-container targets (source: `AGENTS.md` + `develop/setup/Makefile`)

| You change… | Target |
|---|---|
| web-apps (first time / deps) | `make web-apps` |
| web-apps (fast rebuild) | `make web-apps-dev` |
| sdkjs | `make sdkjs` |
| core (all) | `make core` |
| core (x2t only) | `make core/x2t` |
| server docservice | `make server/docservice` (or `server/converter`, `server/metrics`, `server/adminp`) |

⚠️ The `web-apps*` targets rewrite locale JSON (`translation/merge_and_check.py`). **Do not commit**
that churn unless intended (`audit` and `prepare-pr` watch for it).

## Lint / test per repo (what `AGENTS.md` does not cover)

**server** (in the `server/` repo, see `server/package.json`):
```sh
npm run lint:check # eslint .
npm run format:check # prettier . --check
npm run code:check # both (lint + format)
npm run "unit tests" # jest — the name has a space → it must be quoted!
```
Auto-fix: `lint:fix` / `format:fix` / `code:fix`. Integration: `"integration tests with server instance"`,
`"integration database tests"`.

**sdkjs**:
```sh
cd sdkjs && python tests/code-style/check.py # code-style
```
QUnit: HTML tests under `sdkjs/tests/{word,cell,slide,pdf,common,oform,visio}/` (open in a browser).

**web-apps**: repo eslint/prettier; prioritize the *memory-leak sweep*
(`.agents/skills/_shared/memory-leak-checklist.md`).

**core**: C++/CMake build via `make core*` (above); see `core/AGENTS.md` for tests.

> Rule: if a repo's `AGENTS.md`/`CLAUDE.md` defines commands, **those win** over this sheet.
25 changes: 25 additions & 0 deletions .agents/skills/_shared/execution-profiles.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Execution profiles (mode / model / effort per skill)

Each skill runs best in a certain **mode**, **model**, and reasoning **effort**. These are
**recommendations, not enforcement**: Claude Code's `SKILL.md` frontmatter cannot set model/effort/
mode (verified — those keys are rejected), and the concepts are Claude-Code-specific (Codex/Cursor
ignore them). So each skill **announces** its recommended profile when it starts and **you apply it**:

- **Mode** — plan mode via `/plan` or Shift+Tab (cycles modes); leave plan mode to run edits.
- **Model** — `/model <opus|sonnet|haiku>`. **If you only have one model available, ignore this.**
- **Effort** — `/effort <low|medium|high|xhigh|max>`. If you raised effort earlier and a skill wants
less, **lower it now** (e.g. `/effort medium`) — skills remind you so you don't stay on max by accident.

## Recommended profiles

| Skill | Mode | Model | Effort | Why |
|---|---|---|---|---|
| `blueprint` | plan mode | Opus | high | investigate + define; deep reasoning, no code changes |
| `breakdown` | plan mode | Sonnet (Opus if complex) | medium | decompose the plan into atomic steps |
| `apply` | normal | Sonnet | low–medium | apply one small, well-scoped step |
| `audit` | normal (read-only review) | Opus | high (max if security-critical) | catch bugs / security / quality |
| `prepare-pr` | normal | Sonnet (or Haiku) | low | draft the PR body from plan.md |

Notes:
- Starting points — scale **up** for unusually complex tasks, **down** for trivial ones.
- Only the human switches model/effort/mode; skills recommend and remind, never enforce.
118 changes: 118 additions & 0 deletions .agents/skills/_shared/integrations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
# Integrations (personal) — NEVER committed (this is OSS)

## Contents

- [Which shell actually runs the fetch?](#which-shell-actually-runs-the-fetch)
- [GitHub — `gh` CLI (primary path)](#github--gh-cli-primary-path): install · authenticate · fetch
- [Jira — direct REST (current solution)](#jira--direct-rest-current-solution): set env vars · fetch
- [Jira — MCP `mcp-atlassian` (professional upgrade, future)](#jira--mcp-mcp-atlassian-professional-upgrade-future)
- [Quick self-check](#quick-self-check)
- [Fallback](#fallback)

No credential, instance, or config containing secrets may be **committed**. Everything lives in the
**user's shell profile / OS keychain** or in **local** config (never `project` scope). If nothing is
available, fall back to **manual paste**.

These skills are used by an **international team on Linux, macOS, Windows, and WSL**. The fetch
**commands** below are identical on every platform — only the **install step** and **where you set
env vars / PATH** differ. Pick your platform from the tables.

**Fastest path (recommended):** run the onboarding helper once — `bash scripts/setup-integrations.sh`
(Linux/macOS/WSL/Git Bash) or `powershell -File scripts/setup-integrations.ps1` (Windows). `blueprint`
also offers this on its first run. It automates the install + auth + env + self-check described below.

## Which shell actually runs the fetch? (read this first)

The agent runs `gh`/`curl` in **the shell your AI tool uses**, and `gh` + env vars must be available
**there**:
- Native **Linux / macOS**: your login shell (bash/zsh).
- Native **Windows**: usually **Git Bash** (bundled with the AI tool). It inherits Windows PATH and
Windows user env vars.
- **Windows editing a repo inside WSL** (repo under `\\wsl.localhost\...`): the tool may run **Git
Bash on Windows** even though the code is in WSL. Then `gh` must be installed **for Windows**, not
only in WSL. If you prefer to keep everything in WSL, install `gh` in WSL and have the agent call
`wsl gh …` / `wsl curl …`.

**Rule of thumb:** run `gh --version` in the same shell the tool uses. If it says *command not
found*, install `gh` for **that** environment (see table). Same idea for `echo "$JIRA_URL"`.

## GitHub — `gh` CLI (primary path)

### 1) Install (pick your platform)

| Platform | Command |
|---|---|
| macOS | `brew install gh` |
| Debian / Ubuntu / **WSL** | `sudo apt install gh` (for the latest, add the official gh apt repo) |
| Fedora / RHEL | `sudo dnf install gh` |
| Arch | `sudo pacman -S github-cli` |
| **Windows** | `winget install --id GitHub.cli` (or `scoop install gh` / `choco install gh`) |

Official install matrix: <https://github.com/cli/cli#installation>. After a Windows install, **reopen**
the tool so Git Bash picks up the new PATH.

### 2) Authenticate (once, any platform)

```sh
gh auth login # GitHub.com · HTTPS · account with access to the Euro-Office org (incl. private repos like `internal`)
gh auth status # verify
```
Non-interactive / CI alternative: export a PAT (repo scope) as `GH_TOKEN` (or `GITHUB_TOKEN`) instead
of `gh auth login`.

### 3) Fetch (identical on every platform)

```sh
gh issue view <n> --repo <owner>/<repo> \
--json title,body,comments,labels,state,assignees,url
```
(`<owner>` defaults to `Euro-Office`.) For PRs: `gh pr view <n> --repo … --json …`.
No `gh` / not authed / no access to a private repo → **manual paste**.

## Jira — direct REST (current solution)

**Server/Data Center** instance → **PAT + `Bearer`**, REST **v2**, description in **wiki-markup**
(not ADF). The skill reads `$JIRA_URL` → **instance-agnostic**.

### 1) Set the env vars (per platform — never in the repo)

| Shell / platform | Where | How (reopen the shell afterwards) |
|---|---|---|
| bash — Linux / **WSL** | `~/.bashrc` | `export JIRA_URL="https://<instance>"` / `export JIRA_PERSONAL_TOKEN="<PAT>"` |
| zsh — macOS (default) | `~/.zshrc` | same `export …` lines |
| **Git Bash** — Windows | `~/.bashrc` (= `%USERPROFILE%\.bashrc`) | same `export …` lines |
| Windows (system-wide) | user env vars | `setx JIRA_URL "https://<instance>"` then `setx JIRA_PERSONAL_TOKEN "<PAT>"` (Git Bash inherits them; reopen) |

Check: `echo "$JIRA_URL"` prints a value (not empty).

### 2) Fetch (identical on every platform)

```sh
curl -sf -H "Authorization: Bearer $JIRA_PERSONAL_TOKEN" \
"$JIRA_URL/rest/api/2/issue/<KEY>?fields=summary,description,status,issuetype,comment,attachment,labels,priority"
```
Lightweight wiki-markup → markdown conversion (`h1.`→`#`, `*bold*`, `{code}`→fenced block, `#`/`*`
lists). Without the env vars → **manual paste**. (`curl` ships with macOS/Linux and Git Bash.)

## Jira — MCP `mcp-atlassian` (professional upgrade, future)

Only if you want JQL/boards. Docker + **local** registration with env pass-through (no secrets in config):
```sh
claude mcp add jira --scope local \
-e JIRA_URL -e JIRA_PERSONAL_TOKEN \
-- docker run -i --rm -e JIRA_URL -e JIRA_PERSONAL_TOKEN <mcp-atlassian-image>
```
(Verify the image against its real registry before using it — Euro-Office policy: nothing unverified.)
**Never** in `project` scope nor in a committed `.mcp.json` (it would expose/force config on the whole repo).

## Quick self-check (run in the tool's shell)

```sh
gh --version && gh auth status # GitHub ready?
echo "${JIRA_URL:-<unset>}" # Jira URL present?
```

## Fallback

Preference per source: integration available → if it fails / is absent → **manual paste** (title +
description + screenshots). **Never invent** the content of an issue.
27 changes: 27 additions & 0 deletions .agents/skills/_shared/memory-leak-checklist.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Memory-leak sweep (web-apps / front-end focus)

The editors are long-lived SPAs with canvas and real-time collaboration: leaks accumulate as
documents, panels, and views are opened/closed. Sweep the diff with this checklist. Anchors:
`web-apps/apps/*`, `sdkjs/common/` (e.g. `sdkjs/common/CollaborativeEditingBase.js`).

## Checks (everything created must be released in `destroy`/teardown)

- [ ] **Event listeners**: every `addEventListener` / `on(...)` / jQuery `.on(...)` has its matching
`removeEventListener` / `off(...)` on teardown. Watch `window`, `document`, `resize`, `scroll`,
`keydown`.
- [ ] **Timers**: every `setInterval`/`setTimeout`/`requestAnimationFrame` is cleared
(`clearInterval`/`clearTimeout`/`cancelAnimationFrame`).
- [ ] **Canvas / contexts**: 2D/WebGL contexts and large buffers released; no `ImageData`/canvas
retained out of use; render caches bounded or cleared.
- [ ] **Collaborative handlers**: subscriptions to co-editing events / websockets / engine callbacks
(`Asc`/sdkjs) unregistered when the document closes or the view changes.
- [ ] **DOM references**: detached nodes not retained by closures; refs set to `null` on destroy.
- [ ] **Observers / pub-sub**: `MutationObserver`/`ResizeObserver`/`IntersectionObserver` disconnected;
internal event buses have their `unsubscribe`.
- [ ] **Cycles**: no object↔DOM cycles that prevent GC; no globals growing without bound.

## How to verify

- Open/close the same document N times and watch the heap (DevTools → Memory → snapshots) with no
monotonic growth of detached nodes / listeners.
- Check that every component with `init`/`create` has a **symmetric** `destroy`/`dispose`.
Loading
Loading