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
68 changes: 68 additions & 0 deletions .agents/skills/cpn-commit/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
---
name: cpn-commit
description:
"Use when committing in this repo: conventional commit shape enforced by
commitlint."
version: 1.0.0
license: Apache-2.0
---

# Console commits

The `commit-msg` Husky hook runs commitlint (`commitlint.config.cjs`, extends
`@commitlint/config-conventional` with `'body-leading-blank': [2, 'always']`).
Release Please derives version bumps from the type.

## Prerequisites

- Feature branch off `origin/main`, `git branch --show-current` to confirm —
never commit on `main`.
- Husky hooks active via `pnpm install`; commitlint rejects a malformed
message at `commit-msg`.

An unmet requirement is a reported blocker, never a silent scope change.
Never bypass hooks with `--no-verify`.

## Commit shape

| Rule | Value |
| -------- | ----------------------------------------------------------------------------------------- |
| Types | `feat`, `fix`, `chore`, `docs`, `refactor`, `revert`, `build`, `feature` |
| Scope | optional, `type(scope):` |
| Breaking | `type!:` / `type(scope)!:` |
| Subject | imperative, lowercase start, no trailing period |
| Body | optional, separated from the subject by exactly one blank line |
| Footer | `Refs #N`; never `Closes #N` — issues close deliberately after verification |

Reference safety: a bare `#N` resolves to a console issue/PR. Cross-repo
references use a full URL or `owner/repo#N`.

## Procedure

Single-line message:

```bash
git commit -m "fix: prevent null group lookup in keycloak sync"
```

With a body, use a heredoc; repeated `-m` flags are fragile under shell
quoting. The blank line after the subject satisfies `body-leading-blank`:

```bash
git commit -m "$(cat <<'EOF'
feat(plugins): add vault secret rotation

Supports monthly rotation via the hook post step.

Refs #123
EOF
)"
```

Fold work into the last commit with `git commit --amend` — never amend a
commit that is already pushed and under review.

## Verify

`git log -1 --format=%B` — shape matches the table; footer `Refs #N` present
when an issue stands behind the commit.
73 changes: 73 additions & 0 deletions .agents/skills/cpn-dev-workflow/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
---
name: cpn-dev-workflow
description:
"Use when contributing to this repo: issue-first lifecycle, workspace
isolation, quality gates, and the PR workflow."
version: 1.0.0
license: Apache-2.0
---

# Console dev workflow

## Stack

- pnpm monorepo, Node >= 26, pnpm >= 11.8
- Backend target: `apps/server-nestjs`. `apps/server` is frozen (read-only
reference) — never modify it.
- Git-backed repository: work on feature branches off `origin/main`;
`main` is protected.

## Prerequisites

```bash
gh api user --jq .login # authenticated
gh api repos/cloud-pi-native/console --jq .viewerPermission # need write
node --version && pnpm --version # Node >= 26, pnpm >= 11.8
git status --porcelain # clean checkout
```

An unmet requirement is a reported blocker, never a silent scope change.

## Lifecycle

Lifecycle: discussion → issue → issue comments → PR. No PR without an issue
behind it; no bare-request implementation.

1. **One issue per item.** Bug `🐛 [BUG] - <summary>` / feature
`💡 [REQUEST] - <summary>`, via `.github/ISSUE_TEMPLATE/`. Body = problem
statement plus a `- [ ]` acceptance tasklist, Définition du fini — never
the solution; analysis goes in comments. Search existing issues before
creating.
2. **Triage before work**: set each empty, determinable field — labels
from `gh label list`, never invented; assignee; milestone: bug → highest
open patch of the current minor line, feature → next minor/major.
3. **Branch from `origin/main`**, implement, commit.
4. **Draft PR** linked to the issue.
5. **Human approving review is the merge gate** — do not self-merge.
6. **Close deliberately**: verify every acceptance box, then close the issue
with an evidence comment. Never rely on PR-merge auto-close.

Details live in the `cpn-issue`, `cpn-commit`, `cpn-pr`, and `cpn-review`
skills.

## Isolation

- One logical change per branch and PR; out-of-scope fixes become follow-up
issues.
- When the current checkout holds unrelated work in progress, isolate in a
fresh git worktree instead of mixing:

```bash
git worktree add ../console.<topic> -b <branch> origin/main
```

## Verify

Before opening the PR:

```bash
pnpm format
pnpm lint
pnpm test # targeted specs at minimum
pnpm playwright:test # only if a user journey is affected
```
84 changes: 84 additions & 0 deletions .agents/skills/cpn-issue/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
---
name: cpn-issue
description:
"Use when opening, triaging, or closing an issue in this repo: French
templates, acceptance ledger, additive triage."
version: 1.0.0
license: Apache-2.0
---

# Console issues

Issue-first repo norm: no PR without an issue behind it (lifecycle in the
`cpn-dev-workflow` skill, link-up in `cpn-pr`).

## Prerequisites

- Issues live on `cloud-pi-native/console`.
- `gh` authenticated with write access, verified:

```bash
gh api user --jq .login # authenticated
gh api repos/cloud-pi-native/console --jq .viewerPermission # write to triage
```

An unmet requirement is a reported blocker, never a silent scope change.

## Open

1. Search before creating — reuse a matching open issue instead of a
duplicate: `gh issue list --repo cloud-pi-native/console --state open
--search "<keywords>"`.
2. Title `🐛 [BUG] - <summary>` or `💡 [REQUEST] - <summary>`, via
`.github/ISSUE_TEMPLATE/`; label `bug` / `enhancement`.
3. Body in **French**, from the template: problem statement (need, scope,
impact) plus a `- [ ]` **Définition du fini** acceptance tasklist as the
work ledger — never the solution; findings and analysis go in comments.
4. Free-text rules: natural paragraphs, no hard wrapping, never run a
formatter over a body; a literal `@` in prose triggers a user/team mention
— wrap it in a code span.

```bash
gh issue create --repo cloud-pi-native/console \
--title "💡 [REQUEST] - <summary>" --label enhancement --body-file <file>
```

## Triage

Fill each empty, determinable field, additively (`--add-label` /
`--add-assignee`, never `--label`); never invent a value the repo doesn't
have — filter labels against `gh label list`:

```bash
gh issue edit <N> --repo cloud-pi-native/console \
--add-label <label> --add-assignee "$(gh api user --jq .login)" \
--milestone "<milestone>"
```

- **labels** — from `gh label list`, seeded by the title marker.
- **assignee** — the author, if empty.
- **milestone** — bug → highest open patch of the current minor line;
enhancement → next minor/major.
- **project** — `--add-project <n>` only when one board is the obvious home;
skip when ambiguous.

The issue clearly belongs to another `cloud-pi-native/*` repo? Transfer
instead of re-triaging: `gh issue transfer <N> <OWNER/REPO>` — do not edit or
close the source first.

## Iterate & close

- The body stays the stable problem statement; decisions go to the comment
thread via `gh issue comment <N> --body-file <file>`, one line per decision;
lasting references are appended to the body's Références section.
- Closure is deliberate: verify every `- [ ]` box against evidence, then
`gh issue close <N> --comment "<evidence>"`. Never rely on PR-merge
auto-close, never close silently — state why (duplicate → link the
canonical issue).

## Verify

```bash
gh issue view <N> --repo cloud-pi-native/console \
--json number,title,labels,state
```
84 changes: 84 additions & 0 deletions .agents/skills/cpn-pr/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
---
name: cpn-pr
description:
"Use when opening or triaging a PR in this repo: French body from the
template, draft-first, origin-only, review-gated."
version: 1.0.0
license: Apache-2.0
---

# Console pull requests

## Prerequisites

```bash
gh api user --jq .login # authenticated
gh api repos/cloud-pi-native/console --jq .viewerPermission # write, origin-only
git fetch origin && git rebase origin/main # current, no conflicts
```

- An issue stands behind the change — issue-first norm, no orphan PRs.
- Quality gates green — see the `cpn-dev-workflow` skill; the `pre-push`
Husky hook already runs unit tests.

An unmet requirement is a reported blocker, never a silent scope change.

## Before opening

- Duplicate/stack check — list open PRs; if one already delivers the change,
push there instead of opening a second. If your change depends on an open
PR, base your branch on its branch.

```bash
gh pr list --state open --json number,title,headRefName \
--jq '.[] | "\(.number)\t\(.title)\t\(.headRefName)"'
```

- Rebase onto `main` first: `git fetch origin && git rebase origin/main`.
Never push a conflicted branch.
- Duplicate work is ruled out and the branch is conflict-free.

## Opening

- Branches live on the org repo itself; origin-only, no forks. `main` is
protected; only `hotfix/*` may bypass the feature-branch rule, and the
branch prefix matches the commit type: `feat/`, `fix/`, `docs/`, ...
- Open as **draft**, title = conventional commit subject, body =
`.github/PULL_REQUEST_TEMPLATE.md` verbatim, in French, linking the issue
under `Issues liées`:

```bash
gh pr create --repo cloud-pi-native/console --draft --base main \
--head <branch> \
--title "<type>: <subject>" \
--body-file <body>
```

- The body is free text: natural prose, no hard wrapping, never run a
formatter over it.
- A literal `@` in prose triggers a user/team mention — wrap it in a code
span.

## Triage after creation

Set each empty, determinable field, additively (`--add-label` /
`--add-assignee`, never `--label`):

- **labels** — from `gh label list`, never from memory. Conventional type →
matching label; doc changes → `docs` (this repo's real label;
`documentation` does not exist).
- **assignee** — the author, if empty.
- **milestone** — bug → highest open patch of the current minor line;
feature → next minor/major.
- **reviewers** — one collaborator if none requested; otherwise skip.

## After opening

- Keep it draft until review passes; a human approving review from another
collaborator is required — never self-merge.
- CI includes the SonarQube Quality Gate. When all checks are green but
`mergeStateStatus` is `BLOCKED`, enqueue:

```bash
gh workflow run 243523481 --repo cloud-pi-native/console -f PR_NUMBER=<N>
```
79 changes: 79 additions & 0 deletions .agents/skills/cpn-review/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
---
name: cpn-review
description:
"Use when reviewing a PR or reconciling its review threads in this repo:
severity-tagged French inline findings, DoD ledger, never merge."
version: 1.0.0
license: Apache-2.0
---

# Console PR review & reconciliation

Review = read + verdict. Reconciliation = threads + DoD ledger + CI report.
Neither merges — merge follows human approval; see `cpn-pr`.

## Prerequisites

```bash
gh api user --jq .login # authenticated
gh pr view <N> --repo cloud-pi-native/console # PR exists
```

- Review covers others' work — never review or approve your own PR.

An unmet requirement is a reported blocker, never a silent scope change.

## Review

1. **Context** — `gh pr view <N> --repo cloud-pi-native/console`: title, body,
linked issue; confirm the branch is rebased on `main` and the diff matches
the stated scope: `gh pr diff <N> --name-only`.
2. **High-level** — architecture fit: `apps/server-nestjs` is the only
modifiable backend target, `apps/server` frozen; API contracts in
`packages/shared`; hook lifecycle `pre → main → post` with `revert` on
failure; permission checks at the router via BigInt bitmasks.
3. **Line-by-line** — YAGNI first: anything deletable or replaceable by the
stdlib is a finding. A deliberate corner-cut carries a `ponytail:` comment
naming the ceiling and the upgrade path.
4. **Verdict** — findings posted **inline, in French**, one comment per
finding, severity-prefixed: 🔴 `blocking`, 🟠 `important`, 🟡 `nit`,
⚪ `suggestion`, ✨ `praise`. Review body = 2-3 sentence verdict.

```bash
gh pr review <N> --repo cloud-pi-native/console \
--request-changes --body "…" # only on blocking/important findings
gh pr review <N> --repo cloud-pi-native/console --approve --body "…" # otherwise
```

Commitlint violations → suggest the corrected conventional message; the
author amends.

## Reconcile

1. **Ledger DoD** — criteria = the linked issue's `- [ ]` tasklist; verify
each against the diff/CI. Tick a box only with evidence posted first; an
unmet criterion is reported, never silently ticked. No linked issue →
link one or state "sans ledger".
2. **Threads** — an unresolved inline thread is an unfinished review:
pertinent → address it or add it to the issue ledger; irrelevant → reject
with a stated rationale, then resolve. Resolution is the GraphQL mutation —
a reply alone does not close the thread:

```bash
gh api graphql -f query='mutation($id: ID!) {
resolveReviewThread(input: {threadId: $id}) { thread { isResolved } }
}' -f id=<threadId>
```

3. **Approval + CI** — a human approving review from another collaborator on
the current head, re-reviewed after new commits; `gh pr checks <N>`. The
SonarQube Quality Gate requires 0 new issues; when every check is green
but `mergeStateStatus` is `BLOCKED`, enqueue:

```bash
gh workflow run 243523481 --repo cloud-pi-native/console -f PR_NUMBER=<N>
```

4. **Report only** — verdict: ledger N/N · approval state ·
threads resolved or pending with rationale · CI green/pending/failing.
Never merge from here.