Skip to content
Merged
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
188 changes: 188 additions & 0 deletions .coderabbit.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
# yaml-language-server: $schema=https://storage.googleapis.com/coderabbit_public_assets/schema.v2.json
language: en-US

# Under 250 characters — the schema's limit.
tone_instructions: >-
Name the trigger, the code path, and the user-visible consequence for every
finding. If you cannot name one, do not raise it. No praise, no preamble, no
restating the diff. Silence beats a nitpick.

reviews:
profile: assertive
poem: false
in_progress_fortune: false

auto_review:
enabled: true
drafts: false

high_level_summary_instructions: |
Write in present tense: "adds", not "added".
Lead with what changes for a user of the app, not with the file list.
Do not restate the PR description back to the author.

pre_merge_checks:
title:
mode: warning
requirements: |
A reader who sees only the title should understand what the PR does.
Conventional-commit form: <type>(<scope>): <subject>, imperative mood.
Do not require a specific length; this repo's history runs 50-75 chars
and the cap is not enforced.
# Quoted: bare `off` is a YAML 1.1 boolean, and this field takes a string.
description:
mode: "off"

# CI runs `npm run ci` (lint + snc + tests + mcp-schema) and takes minutes;
# the 90s default expires before the result exists.
tools:
github-checks:
timeout_ms: 600000
# `npm run lint` already gates every PR — a second opinion is duplicate noise.
eslint:
enabled: false
# Docs here are deliberate prose, not linted text.
markdownlint:
enabled: false
languagetool:
enabled: false

path_filters:
- '!public/**' # Angular build output
- '!package-lock.json'
- '!src/assets/steelseries-min.js' # vendored, minified
- '!src/assets/tween-min.js' # vendored, minified
- '!src/assets/skip-dashboard-schema.json' # generated by `npm run gen:mcp-schema`
- '!perf-harness/results/**' # committed measurement baselines
- '!src/assets/**/*.{png,jpg,jpeg,svg,mp3,ico,webmanifest}'

path_instructions:
- path: '**/*'
instructions: |
## Evidence, not impressions
Every finding states the trigger, the code path it runs through, and what
the user sees. A finding you cannot express that way is not one. Say
plainly when you are unsure rather than hedging an assertion.

## Comments
A comment explains why the code is the way it is, never what changed or
why it changed. Write for a reader who never saw the diff: no narrating
the change, no "fixes bug X", no "we used to do Y", no restating what the
code already says. Flag comments that violate this. Prefer no comment to
one that earns no keep.

## Do not ask for these
- **A CHANGELOG entry.** `CHANGELOG.md` was deliberately removed (#586).
Release notes come from `git log` via
`.github/scripts/generate-release-notes.sh` and are edited by hand on
the draft release. Do not suggest reinstating the file.
- **A VERSION bump.** The rule is subtle (a bump opens a release cycle;
later PRs in the same cycle do not re-bump unless they are a higher
semver level) and `version-bump-check` already enforces it in CI.
- **Syncing with mxtommy/kip.** Skip originated as a fork but is an
independent project. KIP is not an upstream to track or mirror.
- **A bundled Signal K server plugin.** The package is webapp-only by
design; the Freeboard-SK integration lives in the separate
`@halos-org/skip-freeboard-panel` package.

## Scope
One logical change per PR. Flag substantial unrelated work and suggest a
separate PR; a called-out trivial fly-by fix is fine. Do not ask for
refactoring of code the PR merely touches.

- path: '**/*.spec.ts'
instructions: |
## Specs run against the REAL app services, by design
Read the "Testing reality" section of CLAUDE.md before commenting on test
setup. Under this runner, `src/test.ts`'s classes are different module
instances than the app bundle's, so **any** `{ provide: AppClass, ... }`
placed there is DI-inert — a stub and the real class behave identically.
Never suggest adding a shared or global app-service stub. A spec that
needs a fake declares it locally; a local `SignalKConnectionService` fake
must still expose `serverServiceEndpoint$` and `serverVersion$`, because
services subscribe to them at construction.

Never suggest a per-file `vi.mock()` for a library that `vitest.config.ts`
aliases to a shim (chart.js and its plugins, gridstack, canvas-gauges).
That is the defect #544 was: a per-file mock wins only when its spec loads
the module first, so the real library gets cached instead and silently
drops everything fed to it.

## Judge whether a test can fail
Value a test that fails when the production change is reverted. Flag
assertions on source text, on a stub's logged intent rather than recorded
state, and on internals that an equivalent implementation would change.

## Tolerances are physical, not library-exact
Unit-conversion assertions use a tolerance that separates neighbouring
units, not one that pins the conversion library's exact double. Do not
ask for tighter `toBeCloseTo` precision; that makes the suite fail on a
library rounding change no user could observe.

## Running them
`ng test --include='<path>'` runs one spec. Plain `npx vitest run <file>`
does not work here — it bypasses the Angular builder.

- path: 'src/app/widgets/**'
instructions: |
Widgets are standalone components composed with three host directives:
`WidgetRuntimeDirective` (config merge), `WidgetStreamsDirective`
(diff-based path subscriptions), `WidgetMetadataDirective` (zones/meta).

A widget holding stream-derived presentation state owns clearing it. The
streams directive rebuilds the subscription on a re-point, but
`suppressBootstrapNull: true` filters the replayed leading null, so
against a path that reports nothing the callback never runs and the
previous path's reading stays on screen as a live reading of the new one.
Compare `widgetPathSignature()` across effect runs and clear on a change.

Angular 21, zoneless, signals. Effects read signals and do their writes
inside `untracked()`; check that placement rather than assuming.

- path: 'src/app/core/services/**'
instructions: |
The DI graph is deliberately acyclic — `connection <- auth <- storage <-
settings`, `data <- delta <- connection`. Flag a new edge that closes a
cycle, and check CLAUDE.md's architecture section still matches.

`DataService.updatePathData` runs per delta value. Skip targets Pi-class
hardware; treat that path as allocation-sensitive, and say so when a
change adds work to it. `perf-harness/` measures it — ask for numbers
rather than asserting a regression.

All applicationData writes go through a sequential JSON-Patch queue
because the server cannot handle concurrent writes. A patch's slot name
is baked in at enqueue time.

`units.service.ts` diverges from the Signal K server's imperial fuel-flow
formulas by a factor of 3600 on purpose — the server converts to gallons
per second rather than per hour (upstream signalk-server#2951). Do not
suggest reconciling Skip's values with the server's.

- path: '{package.json,angular.json,src/manifest.json}'
instructions: |
The package name is the serving path. `angular.json` `baseHref`, the
`dev` serve-path, and `src/manifest.json` `id`/`scope`/`start_url` must
all stay `/@halos-org/skip/`. It is also a cross-package contract: the
companion `@halos-org/skip-freeboard-panel` hardcodes it along with
Skip's widget-type ids and `#/widget/:type` embed routes. Flag any change
to it that does not also account for that package.

- path: '**/*.md'
instructions: |
Documentation describes the current state, not development history. Flag
implementation-status language ("Step 3", "TODO", "currently implemented
as"), build narratives, and unchecked checklist items.

There is no `docs/` tree: planning records live in git history, and
anything documenting current behaviour belongs in `README.md` (for users)
or `CLAUDE.md` (for contributors). Do not suggest adding one — a separate
document describing how the code works is how it drifts out of sync.
`src/assets/help-docs/**` is the in-app help content and is user-facing
prose, not developer documentation.

knowledge_base:
code_guidelines:
enabled: true
filePatterns:
- CLAUDE.md
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ Skip is one part of a Signal K stack, and it's easy to extend in two directions:

**Signal K Plugins** — domain-specific enrichment (polars, performance calculations, derived environmental data, routing aids) published into the Signal K data model, which Skip can then display.

**Skip Widgets** — visual components that read Signal K path data and API v2 features. Scaffolding a new one takes only a few moments: run `npm run generate:widget`, or ask your AI to build one from the Skip project instructions. See `CLAUDE.md` and `docs/widget-schematic.md` for details.
**Skip Widgets** — visual components that read Signal K path data and API v2 features. Scaffolding a new one takes only a few moments: run `npm run generate:widget`, or ask your AI to build one from the Skip project instructions. See `CLAUDE.md` for details.

## Getting Started

Expand Down Expand Up @@ -249,11 +249,11 @@ For comprehensive development guidance, start with `CLAUDE.md`:

### Widget Creation Workflow
1. Scaffold with `npm run generate:widget` (Host2 schematic-first path).
2. Use `docs/widget-schematic.md` for CLI flags, prompting behavior, and troubleshooting.
2. See `tools/schematics/create-host2-widget/schema.json` for the available options and their prompts.
3. Follow the Host2 runtime/stream patterns documented in `CLAUDE.md`.

### Key Priorities
- **Widget Development**: Use Host2 patterns and scaffold with the `create-host2-widget` schematic (see `docs/widget-schematic.md`).
- **Widget Development**: Use Host2 patterns and scaffold with the `create-host2-widget` schematic.
- **Angular Patterns**: Use signals, standalone components, and modern control flow.
- **Theming**: Follow Skip's theme system for consistent UI.
- **Code Quality**: Run `npm run lint` before commits.
Expand Down
Loading
Loading