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
81 changes: 81 additions & 0 deletions .agent/knowledge/api-cheatsheet.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# `openmct.*` Cheat Sheet

## Bootstrapping

```js
openmct.install(plugin);
openmct.start(elOrSelector);
```

## Types

```js
openmct.types.addType(key, {
name, description, cssClass, creatable, initialize
});
openmct.types.get(key);
```

## Objects

```js
openmct.objects.addRoot(idOrFn, priority);
openmct.objects.addProvider(namespace, { get(identifier) });
openmct.objects.get(identifier);
openmct.objects.mutate(obj, path, value);
```

## Composition

```js
openmct.composition.addProvider({ appliesTo(obj), load(obj) });
openmct.composition.get(obj); // returns CompositionCollection
```

## Telemetry

```js
openmct.telemetry.addProvider({
supportsRequest(o, opts), request(o, opts),
supportsSubscribe(o), subscribe(o, cb, opts),
supportsMetadata(o), getMetadata(o),
supportsLimits(o), getLimitEvaluator(o)
});
openmct.telemetry.addFormat({ key, format, parse, validate });
openmct.telemetry.request(obj, opts);
openmct.telemetry.subscribe(obj, cb, opts);
```

## Time

```js
openmct.time.addTimeSystem(sys);
openmct.time.setTimeSystem(key, bounds);
openmct.time.getTimeSystem();

openmct.time.addClock(clk);
openmct.time.setClock(clk, offsets);
openmct.time.getClock();

openmct.time.setBounds(b); openmct.time.getBounds();
openmct.time.setClockOffsets(o); openmct.time.getClockOffsets();
openmct.time.setMode('realtime' | 'fixed');
openmct.time.getMode();
openmct.time.isRealTime();
openmct.time.isFixed();
```

Events: `boundsChanged`, `timeSystemChanged`, `clockChanged`,
`clockOffsetsChanged`, `modeChanged`.

## Indicators

```js
const ind = openmct.indicators.simpleIndicator();
ind.text('…').iconClass('icon-info');
openmct.indicators.add(ind); // or add({ element })
```

## Priority

`openmct.priority.HIGHEST | HIGH | DEFAULT | LOW | LOWEST`
32 changes: 32 additions & 0 deletions .agent/knowledge/architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Architecture — Mental Model

Open MCT is a **framework core** + **plugin registry**.

Core (`src/MCT.js` → `src/api/*`) owns:

- object registry & providers
- composition graph
- telemetry pipeline
- time system + clocks
- view / action / indicator / form / menu / notification registries
- priority scheme

Plugins add:

- types (kinds of objects)
- object providers (how to fetch models by identifier)
- composition providers (what children an object has)
- telemetry providers (historical + realtime data)
- view providers (how to render an object)
- action providers (context-menu / toolbar operations)
- indicators, formatters, time systems, clocks

Data flow for a plot:

1. Time bounds change → view calls `openmct.telemetry.request(obj, opts)`.
2. Matching provider returns `Datum[]` → view renders history.
3. Provider is also subscribed → new datums pushed → view appends live.

Domain-object identity:
`{ namespace, key }` — namespace usually maps 1:1 to a persistence store
or a plugin's synthetic root.
18 changes: 18 additions & 0 deletions .agent/knowledge/glossary.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Glossary

- **domain object** — anything shown in the tree; `{ namespace, key }` identity.
- **model** — JSON-serializable state of a domain object.
- **composition** — array of child identifiers.
- **namespace** — persistence / provider partition.
- **type** — registered kind of domain object.
- **provider** — plugin implementation of an extension point.
- **datum** — one telemetry sample; a plain JS object keyed by value-metadata
keys.
- **time system** — defines how numeric time values are interpreted and
formatted.
- **clock** — ticking source of "now" values in a time system.
- **bounds** — `{ start, end }` window in the active time system.
- **offsets** — relative `{ start<0, end>=0 }` used with clocks in realtime
mode.
- **view provider** — object with `{ key, canView, view(o, path) }`.
- **action provider** — context-menu / toolbar operation registration.
40 changes: 40 additions & 0 deletions .agent/knowledge/plugin-anatomy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Plugin Anatomy

## Minimum

```js
export default function MyPlugin(options) {
return function install(openmct) {
/* register types, providers, views, actions */
};
}
```

## Recommended layout (feature-first)

```txt
src/plugins/myPlugin/
plugin.js
pluginSpec.js
README.md
MyProvider.js
MyProviderSpec.js
components/
MyView.vue
myPlugin.scss
```

## Registration

In `src/plugins/plugins.js`:

```js
import MyPlugin from './myPlugin/plugin.js';
plugins.MyPlugin = MyPlugin;
```

## Install (host page or test)

```js
openmct.install(openmct.plugins.MyPlugin(optionalConfig));
```
15 changes: 15 additions & 0 deletions .agent/knowledge/reference-plugins.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Reference Plugins (Guided Tours)

- `src/plugins/conjunctionSSA/` — full example: types, root, object provider,
composition tree, telemetry (subscribe + request), condition set, layout.
Read its `README.md` for the walkthrough.
- `src/plugins/telemetryTable/` — view-heavy plugin backed by a telemetry
source. Good template for tabular views.
- `src/plugins/gauge/` — smaller view provider example with a composition
policy and a substantial spec file (`GaugePluginSpec.js`).
- `src/plugins/plot/` — largest view plugin; look here for time-series
rendering patterns and `minmax` strategy handling.
- `src/plugins/condition/` — rule-engine style; useful for derived state.
- `src/plugins/utcTimeSystem/` — the canonical time-system + clock plugin.
- `example/generator/` — synthetic telemetry source; ideal for scaffolding
new telemetry providers.
43 changes: 43 additions & 0 deletions .agent/knowledge/telemetry-datum-shapes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Telemetry Metadata & Datums

## Telemetry object

```js
{
identifier: { namespace, key },
name,
type,
telemetry: {
values: [
{ key: 'utc', source: 'timestamp', format: 'utc', hints: { domain: 1 } },
{
key: 'value',
name: 'Value',
unit: 'kg',
format: 'float',
min: 0,
max: 100,
hints: { range: 1 }
}
]
}
}
```

## Datum shape

Keys match `telemetry.values[].source` (or `key` if no `source`):

```js
{ timestamp: 1712345678000, value: 42 }
```

## Rules

- Exactly one value MUST have `hints.domain` and must correspond to the active
time system's key (map with `source` if the raw field name differs).
- `request()` returns `Promise<Datum[]>`, sorted ascending by domain.
- `subscribe()` returns an unsubscribe function; each callback receives
exactly one datum.
- For enums: `format: 'enum'` + `enumerations: [{ value, string }]`.
- For arrays: `format: 'number[]'` or `format: 'string[]'`.
41 changes: 41 additions & 0 deletions .agent/knowledge/time-api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Time API Notes

Modes: `'realtime'` | `'fixed'`.

- Realtime uses a clock + offsets.
- Fixed uses absolute bounds.

Offsets: `{ start: <negative>, end: >= 0 }` — relative to
`clock.currentValue()`.

## Custom clock

```js
{
key, name, cssClass, description,
on(event, cb), // event === 'tick'
off(event, cb),
currentValue()
}
```

Register: `openmct.time.addClock(clk)`.

## Custom time system

```js
{
key,
name,
cssClass,
timeFormat, // key of a registered format
durationFormat, // key of a registered format
isUTCBased
}
```

## Deprecated — do not use in new code

- Methods: `timeSystem()`, `bounds()`, `clock()`, `clockOffsets()`,
`stopClock()`
- Events: `'bounds'`, `'timeSystem'`, `'clock'`, `'clockOffsets'`
13 changes: 13 additions & 0 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,19 @@
"version": "0.2",
"language": "en,en-us",
"words": [
"alfano",
"envisat",
"gmst",
"keplerian",
"luni",
"myorg",
"perifocal",
"raan",
"starlink",
"tesserals",
"tles",
"zarya",
"zonals",
"gress",
"doctoc",
"minmax",
Expand Down
22 changes: 22 additions & 0 deletions .devin/rules/00-project-overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
trigger: always_on
---

# Open MCT — Project Overview

- Framework for time-series / telemetry dashboards. Entry: `openmct.js` → `src/MCT.js`.
- Composed of ~66 built-in plugins under `src/plugins/`, aggregated in `src/plugins/plugins.js`.
- Extension points live in `src/api/` (objects, composition, telemetry, time,
types, actions, forms, indicators, priority, user, menu, notifications,
tooltips, overlays, annotation, status).
- Demo host: `index.html` (served by `npm start`).
- Build: webpack configs in `.webpack/`. Types generated by `tsc` from JSDoc.
- Unit tests: Karma + Jasmine, `*Spec.js` colocated. E2E: Playwright under `e2e/`.

Vocabulary (see `.agent/knowledge/glossary.md`):

- **Domain object**: any item in the tree. Identified by `{namespace, key}`.
- **Model**: JSON-serializable state of a domain object.
- **Composition**: parent→children relation.
- **Type**: registered kind of domain object.
- **Provider**: plugin-supplied implementation (object/composition/telemetry/etc.).
38 changes: 38 additions & 0 deletions .devin/rules/10-code-style.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
trigger: always_on
---

# Code Style (enforced by ESLint + Prettier)

Formatting (Prettier config: `.prettierrc`):

- Single quotes, no trailing commas, `printWidth: 100`, `endOfLine: auto`.

Language:

- ES modules only. `import` at top of file. No `require` in `src/`.
- `const`/`let` only, never `var`. Prefer `const`.
- `===` / `!==` only. `curly` always. No nested ternaries. No bitwise ops.
- Prefer named function declarations over arrow-assigned functions
(`func-style: declaration`).
- One class per file (`max-classes-per-file: 1`).
- Prefer ES6 classes over prototypal patterns.
- Avoid magic numbers — hoist to named `const`s in `UPPER_SNAKE_CASE`.
- No lodash/underscore where a builtin exists (plugin
`you-dont-need-lodash-underscore`).
- No unsanitized DOM writes (`no-unsanitized/DOM`).
- Imports must be sortable (`simple-import-sort/imports`).

Filenames (`unicorn/filename-case`):

- JS: camelCase for utility modules; PascalCase for files exporting a class or
Vue component.
- `.vue` and files exporting classes → PascalCase (`MyThing.vue`, `MyThing.js`).

Organization: **by feature, not by type** (see CONTRIBUTING.md example).

Do NOT:

- Add or remove comments/JSDoc unless asked.
- Modify eslint/prettier config to make code pass.
- Introduce Angular, RxJS, or other frameworks. Vue 3 only.
Loading
Loading