From b6687b6379d4327283b8d86abd19f3113df62546 Mon Sep 17 00:00:00 2001 From: Kam Date: Thu, 1 Oct 2026 02:23:29 +0300 Subject: [PATCH 1/2] chore: add issue skills, a glossary, weekly version checks and code owners Adds skills for fixing one issue, working through a batch and settling open decisions, a glossary of project terms, and a repository section in AGENTS.md with its commands and the rules that fail quietly. CLAUDE.md now imports AGENTS.md, and the generic Angular rules move to .claude/rules. Adds a publish check against a local registry, a weekly run of it on the newest versions our ranges allow, issue triage from the issue forms, an area prefix for issue titles, a shared setup action for the workflows, and both maintainers as code owners. Refs #100 --- .claude/rules/angular.md | 63 +++ .claude/skills/devtools-fix-issue/SKILL.md | 40 ++ .claude/skills/devtools-work-issues/SKILL.md | 51 +++ .claude/skills/grilling/SKILL.md | 28 ++ .github/CODEOWNERS | 2 +- .github/ISSUE_TEMPLATE/bug_report.yml | 5 + .github/ISSUE_TEMPLATE/feature_request.yml | 5 + .github/actions/setup/action.yml | 26 ++ .github/workflows/ci.yml | 18 +- .github/workflows/latest.yml | 63 +++ .github/workflows/triage.yml | 38 ++ AGENTS.md | 101 ++--- CLAUDE.md | 78 +--- CONTRIBUTING.md | 25 +- docs/CONTEXT.md | 89 ++++ package.json | 1 + scripts/verify-publish.mjs | 413 +++++++++++++++++++ 17 files changed, 885 insertions(+), 161 deletions(-) create mode 100644 .claude/rules/angular.md create mode 100644 .claude/skills/devtools-fix-issue/SKILL.md create mode 100644 .claude/skills/devtools-work-issues/SKILL.md create mode 100644 .claude/skills/grilling/SKILL.md create mode 100644 .github/actions/setup/action.yml create mode 100644 .github/workflows/latest.yml create mode 100644 .github/workflows/triage.yml create mode 100644 docs/CONTEXT.md create mode 100644 scripts/verify-publish.mjs diff --git a/.claude/rules/angular.md b/.claude/rules/angular.md new file mode 100644 index 0000000..095574c --- /dev/null +++ b/.claude/rules/angular.md @@ -0,0 +1,63 @@ +# Angular rules + +You are an expert in TypeScript, Angular, and scalable web application development. You write functional, maintainable, performant, and accessible code following Angular and TypeScript best practices. + +These apply to every Angular and TypeScript file in the repository: the panel (`app`), the package (`packages/ng-devtools`), the demo apps and the docs site. `AGENTS.md` points here so agents other than Claude Code find them too. + +## TypeScript Best Practices + +- Use strict type checking +- Prefer type inference when the type is obvious +- Avoid the `any` type; use `unknown` when type is uncertain + +## Angular Best Practices + +- Always use standalone components over NgModules +- Must NOT set `standalone: true` inside Angular decorators. It's the default in Angular v20+. +- Do NOT set `changeDetection: ChangeDetectionStrategy.OnPush` explicitly. `OnPush` is the default in Angular v22+. +- Use signals for state management +- Implement lazy loading for feature routes +- Do NOT use the `@HostBinding` and `@HostListener` decorators. Put host bindings inside the `host` object of the `@Component` or `@Directive` decorator instead +- Use `NgOptimizedImage` for all static images. + - `NgOptimizedImage` does not work for inline base64 images. + +## Accessibility Requirements + +- It MUST pass all AXE checks. +- It MUST follow all WCAG AA minimums, including focus management, color contrast, and ARIA attributes. + +### Components + +- Keep components small and focused on a single responsibility +- Use `input()` and `output()` functions instead of decorators +- Use `model()` for two-way bound properties with `[(prop)]` syntax instead of pairing `input()` with `output()` +- Use `computed()` for derived state +- Use `linkedSignal()` for state derived from multiple reactive sources that must stay synchronized +- Prefer inline templates for small components +- Prefer Signal Forms (`@angular/forms/signals`) for new forms. They are stable in Angular v22+ and provide signal-based state, type-safe field access, and schema-based validation +- When not using Signal Forms, prefer Reactive forms instead of Template-driven ones +- Do NOT use `ngClass`, use `class` bindings instead +- Do NOT use `ngStyle`, use `style` bindings instead +- Do NOT import `CommonModule`, import only the directives and pipes the template uses, such as `AsyncPipe` or `DatePipe` +- When using external templates/styles, use paths relative to the component TS file. + +## State Management + +- Use signals for local component state +- Use `computed()` for derived state +- Keep state transformations pure and predictable +- Do NOT use `mutate` on signals, use `update` or `set` instead + +## Templates + +- Keep templates simple and avoid complex logic +- Use native control flow (`@if`, `@for`, `@switch`) instead of `*ngIf`, `*ngFor`, `*ngSwitch` +- Use the async pipe to handle observables +- Do not assume globals like (`new Date()`) are available. + +## Services + +- Design services around a single responsibility +- Use the `providedIn: 'root'` option for singleton services +- Prefer the `@Service` decorator over `@Injectable({providedIn: 'root'})` for new singleton services (Angular v22+) +- Use the `inject()` function instead of constructor injection diff --git a/.claude/skills/devtools-fix-issue/SKILL.md b/.claude/skills/devtools-fix-issue/SKILL.md new file mode 100644 index 0000000..1a37c2c --- /dev/null +++ b/.claude/skills/devtools-fix-issue/SKILL.md @@ -0,0 +1,40 @@ +--- +name: devtools-fix-issue +description: Take one GitHub issue in this repository to a pull request, from checking the report against the code to answering review comments. Use when asked to fix, investigate or close a specific issue, or to address review comments on a fix. +--- + +# Fix one issue + +Treat the issue as a claim. The report, its evidence and its proposed fix can all be wrong or out of date. + +## 1. Check the report + +- Read it with `gh issue view --repo santoshyadavdev/angular-devtools`, then read the code it names on `main`. +- Check the claim against the reference the code follows: Angular's own source in `node_modules/@angular/*` for debug APIs and forms or router behaviour, the NgRx or Analog packages for their internals, devframe for transport and auth. +- If the report is wrong, already fixed, or needs a product or design decision, stop and say so with evidence. Don't guess a design. The `grilling` skill settles the decision with the maintainer. +- If it can only be confirmed by a manual test the maintainer has to do (the Chrome extension in real Chrome, for example), stop and say what the test is. + +## 2. Reproduce, then fix + +1. Write a test that fails for the reported reason, not for some side effect. Package code goes in `packages/ng-devtools/src/__tests__`, panel code in `app/src/__tests__` (`pnpm test:panel`). +2. Make the smallest fix that covers the cause. Follow `docs/contributing/coding-standards.md` and the `devtools-inspector` or `devtools-ui` skill for the area. +3. Undo the fix and run the test again. It must fail. Put the fix back. +4. Update the docs page for the area when behaviour, options, labels or tools change (`devtools-docs` skill). + +## 3. Check it + +Run the checks in the `devtools-verify` skill. When `app/` changed, run `pnpm extension:build` and commit `extension/ui`, or CI fails. + +Then review your own diff as a skeptic: data that now leaks without redaction, a new tool missing from the config lists in `packages/ng-devtools/src/config.ts`, a listener or wrapper that is never removed, a docs claim the code doesn't back. + +## 4. Open the pull request + +Follow the `devtools-commit` skill. Put `Fixes #` in the body. When only part of the issue is fixed, write `Refs #` and say what is left. + +Issue titles follow `area: what is wrong`, in lowercase, with a commit scope as the area: `router: a failed lazy navigation is only logged`. Use it for any follow-up issue you open, and use the issue's area as the scope of the fix's commit. + +## Review comments + +- Check each comment against the code before changing anything. Bots (CodeRabbit) are often right and sometimes wrong. +- Fix the valid ones with a test. For the rest, reply with the evidence: the file and line, a command and its output, or the case the reviewer missed. +- A CI failure your change caused reproduces locally. A flake passes on a rerun and fails on `main` too. Say which it was. diff --git a/.claude/skills/devtools-work-issues/SKILL.md b/.claude/skills/devtools-work-issues/SKILL.md new file mode 100644 index 0000000..562560a --- /dev/null +++ b/.claude/skills/devtools-work-issues/SKILL.md @@ -0,0 +1,51 @@ +--- +name: devtools-work-issues +description: Work through a batch of GitHub issues in this repository with parallel agents, then combine, verify and ship them as one pull request per batch. Use when asked to fix all issues of a priority or label, or several issues at once. +--- + +# Work a batch of issues + +Each issue still goes through the `devtools-fix-issue` skill. This skill is about running many of them at once without agents getting in each other's way. + +## 1. Plan the batch + +- List the issues: `gh issue list --repo santoshyadavdev/angular-devtools --label P2 --state open --limit 200`. +- Leave out issues that need a product or design decision, or a manual test the maintainer has to do. List them in the report as "for later", and settle the decisions afterwards with the `grilling` skill. If only part of an issue is clear, do that part and use `Refs #` for it. +- Titles follow `area: what is wrong` (`router: a failed lazy navigation is only logged`), and the area is a commit scope, so it usually names the group. Title any follow-up issue the same way. +- Group the rest by the files they touch (inspector or area: forms, router, http, analog, signals, overlay and popup, cli and config, extension), so no two groups edit the same code. Aim for three to eight issues per group. + +## 2. One worktree per group + +- Create a detached worktree per group, plus one for combining, in a folder git ignores: + `git worktree add --detach `, then `pnpm install --frozen-lockfile --prefer-offline` in each. +- Agents only edit files in their own worktree. They don't commit, stage, branch, stash or push. A reviewer can read each group's work with `git diff`. +- Each agent returns, per issue: fixed, partly fixed or skipped, the cause and fix in a line, the test it added, and its check results. +- With many worktrees inside the repository folder, Nx finds duplicate projects. Run it as `NX_WORKSPACE_ROOT_PATH=$PWD NX_DAEMON=false pnpm exec nx test angular-devtools`. + +## 3. Combine + +- Copy each group's changed and new files into the combine worktree. For a file that another group changed too, use `git merge-file` against the base version (`git show :`) and keep every fix. +- Run the full `devtools-verify` checks there once, and fix breakage between groups. +- Run `pnpm extension:build` once at the end, not in every group, and commit `extension/ui` in its own commit. + +## 4. Verify before the pull request + +Run read-only agents against the combined branch, each in its own worktree and port range: + +- a code review per pull request (`devtools-reviewer` role); +- the panel in a real browser, every inspector tab, with axe (`a11y-reviewer` role); +- every agent tool through a real MCP client; +- every setup: Express hub, Vite plugin, CLI, static report, the Analog example; +- regressions: tests deleted or weakened since `main`, and removed tools, config keys or flags. + +Then have a second agent try to refute each finding, and fix only what survives. + +## 5. Ship + +- One pull request per batch, with `Closes #` per fixed issue, a "Left open" section, and the checks. +- Stacked batches (P2 built on P1, and so on): after the first is squash merged, merge `main` into the next one. Its conflicts are the same changes on both sides, so keep the branch's side, then check that the diff against the old branch head only adds what landed on `main` since. Watch for paragraphs the merge duplicates in docs. +- Conflicts in `extension/ui/assets` are build output. Drop both sides and run `pnpm extension:build` again. + +## 6. Clean up + +Remove the worktrees (`git worktree remove -f -f `, then `git worktree prune`) and delete the merged local branches. diff --git a/.claude/skills/grilling/SKILL.md b/.claude/skills/grilling/SKILL.md new file mode 100644 index 0000000..1b544e9 --- /dev/null +++ b/.claude/skills/grilling/SKILL.md @@ -0,0 +1,28 @@ +--- +name: grilling +description: Stress-test a plan, design or open decision by asking the user one question at a time, each with a recommended answer, until both sides agree, and only then act. Use before a non-trivial design, for issues left open as "needs a decision", or whenever the user asks to be grilled or to have their thinking challenged. +--- + +# Grilling + +Interview the user about every part of the plan until you reach a shared understanding. Walk down each branch of the decision tree and settle the decisions one by one, in the order they depend on each other. + +## How to ask + +- Ask one question at a time, and wait for the answer before the next. Several questions at once are hard to answer well. +- Give your recommended answer with every question, and say why in a sentence or two. Name the alternatives you considered and what each would cost. +- Keep a running list of what is decided. Restate it when a later answer changes an earlier one. + +## Facts versus decisions + +- Look up facts yourself instead of asking. Read the code, the docs, the issue and its comments (`gh issue view --repo santoshyadavdev/angular-devtools --comments`), `git log`, and Angular's own source in `node_modules/@angular/*`. Quote what you found when it shapes a question. +- Put every decision to the user and wait. A decision is anything about behaviour, scope, naming, defaults, security or what the project supports. Don't settle one because it looks obvious. +- Use the words in `docs/CONTEXT.md`. If a question needs a word that isn't there, say so; the answer may belong in the glossary. + +## Don't act yet + +Don't edit files, open pull requests, or comment on issues until the user confirms you have reached a shared understanding. Then summarise the decisions, and hand the work to the matching skill: `devtools-fix-issue` for one issue, `devtools-work-issues` for a batch. + +## Issues that need a decision + +This is the tool for issues that `devtools-fix-issue` and `devtools-work-issues` leave open as "needs a decision" or "for later", such as #69, #100, #128, #157, #166 and #181. Read the issue and the code it names first, then grill the user on the open choice. Once it is settled, the issue can go through `devtools-fix-issue` like any other. If the user wants the decision recorded on the issue, draft the comment and let them post it. diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 5a3bbe3..699102f 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -* @santoshyadavdev +* @santoshyadavdev @erkamyaman diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 53c6744..78a9c06 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -1,7 +1,12 @@ name: Bug report description: Something in the devtools shows wrong data, breaks, or looks wrong +title: ': ' labels: [bug, needs triage] body: + - type: markdown + attributes: + value: | + Title the issue `area: what is wrong`, in lowercase, for example `router: a failed lazy navigation is only logged`. The area is one of the [commit scopes](https://github.com/santoshyadavdev/angular-devtools/blob/main/docs/contributing/commit-message-guidelines.md#scope), such as `components`, `router`, `forms`, `http`, `mcp`, `extension` or `docs`. - type: dropdown id: area attributes: diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index 0282442..f7a4e8f 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -1,7 +1,12 @@ name: Feature request description: Suggest an inspector, a view or an agent tool +title: ': ' labels: [feature, needs triage] body: + - type: markdown + attributes: + value: | + Title the issue `area: what is missing`, in lowercase, for example `signals: the detail panel can't jump to a dependency or consumer`. The area is one of the [commit scopes](https://github.com/santoshyadavdev/angular-devtools/blob/main/docs/contributing/commit-message-guidelines.md#scope), such as `components`, `router`, `forms`, `http`, `mcp`, `extension` or `docs`. - type: textarea id: problem attributes: diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml new file mode 100644 index 0000000..3314e8a --- /dev/null +++ b/.github/actions/setup/action.yml @@ -0,0 +1,26 @@ +name: Set up the workspace +description: pnpm, Node and a frozen install. Shared by every workflow so they resolve the same tree. + +inputs: + registry-url: + description: Passed to setup-node, which writes an .npmrc for it. Only the release sets it. + required: false + default: '' + +runs: + using: composite + steps: + # Reads the version from the root `packageManager` field, so CI and a laptop resolve the + # same tree. + - uses: pnpm/action-setup@v5 + + - uses: actions/setup-node@v7 + with: + node-version-file: .nvmrc + cache: pnpm + registry-url: ${{ inputs.registry-url }} + + # Frozen: a lockfile that does not match the manifests fails the run rather than quietly + # resolving something newer. + - run: pnpm install --frozen-lockfile + shell: bash diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2fe2add..9fa1e11 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,14 +25,7 @@ jobs: fetch-depth: 0 persist-credentials: false - - uses: pnpm/action-setup@v5 - - - uses: actions/setup-node@v7 - with: - node-version-file: .nvmrc - cache: pnpm - - - run: pnpm install --frozen-lockfile + - uses: ./.github/actions/setup - uses: nrwl/nx-set-shas@v4 @@ -77,14 +70,7 @@ jobs: with: persist-credentials: false - - uses: pnpm/action-setup@v5 - - - uses: actions/setup-node@v7 - with: - node-version-file: .nvmrc - cache: pnpm - - - run: pnpm install --frozen-lockfile + - uses: ./.github/actions/setup - name: Install Chromium run: pnpm exec playwright install --with-deps chromium diff --git a/.github/workflows/latest.yml b/.github/workflows/latest.yml new file mode 100644 index 0000000..4ea98c1 --- /dev/null +++ b/.github/workflows/latest.yml @@ -0,0 +1,63 @@ +name: Latest versions + +# The package declares `@angular/core >=20` and `vite >=5`, and this repository pins the versions +# it tests on, so a new Angular, Analog or Vite release can break users between our releases +# without CI noticing (#100). Each week this makes fresh apps the way users do, on whatever those +# ranges resolve to that day, installs the package from a local registry, wires the documented +# setup, builds it and checks the hub answers. See apps/docs/src/content/contributing/publishing.md. +on: + schedule: + # Mondays at 06:00 UTC. + - cron: '0 6 * * 1' + workflow_dispatch: + +permissions: + contents: read + # A failing scheduled run opens, or comments on, one issue per scenario. + issues: write + +concurrency: + group: ${{ github.workflow }} + cancel-in-progress: false + +jobs: + scenario: + name: ${{ matrix.scenario }} + runs-on: ubuntu-latest + timeout-minutes: 30 + strategy: + # Every scenario reports, so one week's failures are all visible at once. + fail-fast: false + matrix: + scenario: + - angular-cli + - analog + steps: + - uses: actions/checkout@v7 + with: + persist-credentials: false + + - uses: ./.github/actions/setup + + # Starts its own Verdaccio, publishes the package there, and writes the Angular, Analog, + # Vite and devframe versions it resolved to the job summary, pass or fail. + - run: pnpm verify:publish --scenario=${{ matrix.scenario }} + + # One open issue per scenario, found by its title: a new one the first week it fails, and a + # comment on that one every week after until someone closes it. + - name: Report the failure + if: failure() && github.event_name == 'schedule' + env: + GH_TOKEN: ${{ github.token }} + SCENARIO: ${{ matrix.scenario }} + RUN: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} + run: | + title="ci: the $SCENARIO setup fails on the latest versions" + body="The $SCENARIO scenario of \`pnpm verify:publish\` failed on the newest versions the peer ranges allow: $RUN. The run's summary lists the versions it resolved. See #100." + number=$(gh issue list --state open --search "\"$title\" in:title" --json number,title \ + | jq -r --arg title "$title" 'map(select(.title == $title)) | .[0].number // empty') + if [ -n "$number" ]; then + gh issue comment "$number" --body "Still failing: $RUN" + else + gh issue create --title "$title" --body "$body" --label bug --label 'area: ci' + fi diff --git a/.github/workflows/triage.yml b/.github/workflows/triage.yml new file mode 100644 index 0000000..fe8089a --- /dev/null +++ b/.github/workflows/triage.yml @@ -0,0 +1,38 @@ +name: Triage + +# Labels a new issue from what its form says. The bug report's Area dropdown maps to an `area:` +# label where the choice names one part of the repository. The inspector choices (Components, +# Router, Forms and so on) can be a panel or a package bug, so a maintainer labels those. +on: + issues: + types: [opened] + +permissions: + issues: write + +jobs: + label: + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - env: + GH_TOKEN: ${{ github.token }} + # Through the environment, never interpolated into the script: the body is anyone's text. + BODY: ${{ github.event.issue.body }} + NUMBER: ${{ github.event.issue.number }} + REPO: ${{ github.repository }} + run: | + # An issue form renders each answer as `###