@codyswann/lisa 2.164.0 → 2.165.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/dist/codex/scripts/lint-on-edit.sh +7 -9
  2. package/dist/opencode/plugin-templates/lisa-lint-on-edit.ts +8 -9
  3. package/package.json +1 -1
  4. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  5. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  6. package/plugins/lisa-agy/plugin.json +1 -1
  7. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  8. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  9. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  10. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  11. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  12. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  13. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  14. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  15. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  16. package/plugins/lisa-expo-agy/plugin.json +1 -1
  17. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  18. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  19. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  20. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  21. package/plugins/lisa-harper-fabric/skills/harper-config-yaml/SKILL.md +6 -1
  22. package/plugins/lisa-harper-fabric/skills/harper-realtime/SKILL.md +187 -0
  23. package/plugins/lisa-harper-fabric/skills/harper-realtime/agents/openai.yaml +4 -0
  24. package/plugins/lisa-harper-fabric/skills/harper-resources/SKILL.md +3 -2
  25. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  26. package/plugins/lisa-harper-fabric-agy/skills/harper-config-yaml/SKILL.md +6 -1
  27. package/plugins/lisa-harper-fabric-agy/skills/harper-realtime/SKILL.md +187 -0
  28. package/plugins/lisa-harper-fabric-agy/skills/harper-resources/SKILL.md +3 -2
  29. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  30. package/plugins/lisa-harper-fabric-copilot/skills/harper-config-yaml/SKILL.md +6 -1
  31. package/plugins/lisa-harper-fabric-copilot/skills/harper-realtime/SKILL.md +187 -0
  32. package/plugins/lisa-harper-fabric-copilot/skills/harper-resources/SKILL.md +3 -2
  33. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  34. package/plugins/lisa-harper-fabric-cursor/skills/harper-config-yaml/SKILL.md +6 -1
  35. package/plugins/lisa-harper-fabric-cursor/skills/harper-realtime/SKILL.md +187 -0
  36. package/plugins/lisa-harper-fabric-cursor/skills/harper-resources/SKILL.md +3 -2
  37. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  38. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  39. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  40. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  41. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  42. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  43. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  44. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  45. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  46. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  47. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  48. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  49. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  50. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  51. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  52. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  53. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  54. package/plugins/lisa-rails-agy/plugin.json +1 -1
  55. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  56. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  57. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  58. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  59. package/plugins/lisa-typescript/hooks/lint-on-edit.sh +15 -61
  60. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  61. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  62. package/plugins/lisa-typescript-copilot/hooks/lint-on-edit.sh +15 -61
  63. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  64. package/plugins/lisa-typescript-cursor/hooks/lint-on-edit.sh +15 -61
  65. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  66. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  67. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  68. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  69. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  70. package/plugins/src/harper-fabric/skills/harper-config-yaml/SKILL.md +6 -1
  71. package/plugins/src/harper-fabric/skills/harper-realtime/SKILL.md +187 -0
  72. package/plugins/src/harper-fabric/skills/harper-resources/SKILL.md +3 -2
  73. package/plugins/src/typescript/hooks/lint-on-edit.sh +15 -61
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env bash
2
2
  # Lisa-managed Codex hook script (PostToolUse Edit|Write|apply_patch).
3
- # Runs ESLint --fix on every just-edited file. If unfixable errors remain on
4
- # any file, exits non-zero so Codex sees the failure and the agent self-corrects.
3
+ # Runs oxlint on every just-edited JS/TS file. Full ESLint remains enforced at
4
+ # the commit/CI chokepoint via the project lint scripts.
5
5
  # Resolves target file(s) via the shared extractor (Edit/Write + apply_patch).
6
6
  set -uo pipefail
7
7
 
@@ -15,10 +15,10 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
15
15
  # shellcheck source=/dev/null
16
16
  . "${SCRIPT_DIR}/_extract-edit-paths.sh"
17
17
 
18
- if [ -x "./node_modules/.bin/eslint" ]; then
19
- ESLINT="./node_modules/.bin/eslint"
20
- elif command -v eslint >/dev/null 2>&1; then
21
- ESLINT="eslint"
18
+ if [ -x "./node_modules/.bin/oxlint" ]; then
19
+ OXLINT="./node_modules/.bin/oxlint"
20
+ elif command -v oxlint >/dev/null 2>&1; then
21
+ OXLINT="oxlint"
22
22
  else
23
23
  exit 0
24
24
  fi
@@ -31,9 +31,7 @@ while IFS= read -r FILE_PATH; do
31
31
  ts | tsx | js | jsx | mjs | cjs) ;;
32
32
  *) continue ;;
33
33
  esac
34
- # Auto-fix what we can; surface anything left so the agent fixes it itself.
35
- "$ESLINT" --fix "${FILE_PATH}" >/dev/null 2>&1 || true
36
- "$ESLINT" --quiet "${FILE_PATH}" || STATUS=1
34
+ "$OXLINT" --quiet "${FILE_PATH}" || STATUS=1
37
35
  done <<EOF
38
36
  $(lisa_extract_edit_paths "$JSON_INPUT")
39
37
  EOF
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * Lisa-managed OpenCode plugin (tool.execute.after).
3
3
  *
4
- * Runs ESLint --fix on every just-edited JS/TS file, then re-checks. If
5
- * unfixable problems remain, throws so OpenCode marks the tool call failed and
6
- * the agent self-corrects (the equivalent of the Codex hook's non-zero exit).
7
- * Fails open when ESLint isn't installed.
4
+ * Runs oxlint on every just-edited JS/TS file. If problems remain, throws so
5
+ * OpenCode marks the tool call failed and the agent self-corrects (the
6
+ * equivalent of the Codex hook's non-zero exit). Fails open when oxlint isn't
7
+ * installed. Full ESLint remains enforced at the commit/CI chokepoint.
8
8
  *
9
9
  * Port of Lisa's Codex hook `lint-on-edit.sh`. OpenCode passes the edited file
10
10
  * via `input.args.filePath`; `tool.execute.after` runs after a successful
@@ -38,15 +38,14 @@ export const LisaLintOnEdit = async ({
38
38
  if (input.tool !== "edit" && input.tool !== "write") return;
39
39
  const filePath = String(input.args?.filePath ?? "");
40
40
  if (!filePath || !EXTS.has(extOf(filePath))) return;
41
- const eslint = resolveBin("eslint");
42
- if (!eslint) return; // fail open no ESLint installed
43
- await $`${eslint} --fix ${filePath}`.quiet().nothrow();
44
- const res = await $`${eslint} --quiet ${filePath}`.quiet().nothrow();
41
+ const oxlint = resolveBin("oxlint");
42
+ if (!oxlint) return; // fail open - no oxlint installed
43
+ const res = await $`${oxlint} --quiet ${filePath}`.quiet().nothrow();
45
44
  if (res.exitCode === 0) return;
46
45
  const out =
47
46
  `${res.stdout?.toString() ?? ""}${res.stderr?.toString() ?? ""}`.trim();
48
47
  throw new Error(
49
- `lint-on-edit: ESLint reported unfixable problems in ${filePath}:\n${out}`
48
+ `lint-on-edit: oxlint reported problems in ${filePath}:\n${out}`
50
49
  );
51
50
  },
52
51
  };
package/package.json CHANGED
@@ -85,7 +85,7 @@
85
85
  "lodash": ">=4.18.1"
86
86
  },
87
87
  "name": "@codyswann/lisa",
88
- "version": "2.164.0",
88
+ "version": "2.165.0",
89
89
  "description": "Claude Code governance framework that applies guardrails, guidance, and automated enforcement to projects",
90
90
  "main": "dist/index.js",
91
91
  "exports": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.164.0",
3
+ "version": "2.165.0",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.164.0",
3
+ "version": "2.165.0",
4
4
  "description": "Universal governance: agents, skills, commands, hooks, and rules for all projects.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.164.0",
3
+ "version": "2.165.0",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.164.0",
3
+ "version": "2.165.0",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.164.0",
3
+ "version": "2.165.0",
4
4
  "description": "AWS CDK-specific Lisa plugin.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.164.0",
3
+ "version": "2.165.0",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.164.0",
3
+ "version": "2.165.0",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "2.164.0",
3
+ "version": "2.165.0",
4
4
  "description": "AWS CDK-specific plugin",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.164.0",
3
+ "version": "2.165.0",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "2.164.0",
3
+ "version": "2.165.0",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.164.0",
3
+ "version": "2.165.0",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.164.0",
3
+ "version": "2.165.0",
4
4
  "description": "Expo and React Native-specific skills, agents, rules, and MCP servers.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.164.0",
3
+ "version": "2.165.0",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.164.0",
3
+ "version": "2.165.0",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.164.0",
3
+ "version": "2.165.0",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.164.0",
3
+ "version": "2.165.0",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.164.0",
3
+ "version": "2.165.0",
4
4
  "description": "Harper/Fabric-specific Lisa rules for TypeScript component apps.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -52,7 +52,7 @@ unmentioned extensions stay on.
52
52
 
53
53
  | Key | Purpose | Common options |
54
54
  | --- | --- | --- |
55
- | `rest` | Auto REST endpoints for exported resources/tables | `true`, or an object with options |
55
+ | `rest` | Auto REST endpoints and resource WebSocket subscriptions | `true`, or an object with options such as `webSocket` |
56
56
  | `graphqlSchema` | Define tables/types from GraphQL files | `files: '*.graphql'` — see [[harper-schema-graphql]] |
57
57
  | `jsResource` | Load custom JS resources | `files: 'resources.js'` — see [[harper-resources]] |
58
58
  | `static` | Serve static files over HTTP | `files: 'web/**'`, `urlPath` |
@@ -61,6 +61,11 @@ unmentioned extensions stay on.
61
61
  | `dataLoader` | Seed tables from JSON/YAML | `files` |
62
62
  | `fastifyRoutes` | Custom Fastify routes | `files: 'routes/*.js'`, `urlPath` |
63
63
 
64
+ For real-time work, component `config.yaml` keeps `rest`, `graphqlSchema`, and
65
+ `jsResource` enabled so exported resources can be addressed by HTTP/WebSocket and
66
+ MQTT topic paths. Broker ports and MQTT authentication live in the root
67
+ `harper-config.yaml`, not the component file. See [[harper-realtime]].
68
+
64
69
  ## External components and custom plugins
65
70
 
66
71
  A component you depend on from npm needs a `package:` directive matching a
@@ -0,0 +1,187 @@
1
+ ---
2
+ name: harper-realtime
3
+ description: This skill should be used when adding or troubleshooting Harper (HarperDB/Fabric) real-time behavior: MQTT topics, WebSocket resource subscriptions, resource publish/subscribe handlers, SSE-style streaming routes, and local subscriber verification. Pairs with harper-resources, harper-config-yaml, harper-schema-graphql, and harper-build-and-deploy.
4
+ ---
5
+
6
+ # Harper Realtime
7
+
8
+ ## Overview
9
+
10
+ Harper exposes live data through the same Resource model used for REST and
11
+ GraphQL. Exported tables/resources can be addressed as MQTT topics and WebSocket
12
+ paths, while custom resources can override the messaging handlers when the default
13
+ table behavior is not enough.
14
+
15
+ Use real-time primitives when the product needs pushed state: live feeds, activity
16
+ streams, collaborative views, device telemetry, or status updates. Do not replace
17
+ these with client polling unless the issue explicitly asks for polling.
18
+
19
+ ## Resource and topic model
20
+
21
+ - A GraphQL type marked `@table @export` creates a default exported table resource.
22
+ - An exported JavaScript Resource class from `resources.js` creates a resource
23
+ endpoint with the class name as the path/topic root.
24
+ - Resource paths map naturally to subscription targets: collection-level
25
+ subscriptions use the resource name, and record-level subscriptions append the
26
+ record id or path segment.
27
+ - MQTT supports multi-level topics and wildcards. Use `resource/#` for a resource
28
+ subtree and `resource/+/status` for one path segment.
29
+ - WebSocket subscriptions target the REST resource URL. For example,
30
+ `ws://localhost:9926/Activity/123` subscribes to the `Activity` resource record
31
+ with id `123`.
32
+
33
+ Keep the URL/topic names stable. If a UI depends on `Activity/123`, changing the
34
+ resource export name is an API break.
35
+
36
+ ## Resource methods
37
+
38
+ The MQTT plugin routes broker messages through Resource methods:
39
+
40
+ | Method | Use |
41
+ | --- | --- |
42
+ | `subscribe(target, context)` | Authorize and shape subscription reads for a resource or record. |
43
+ | `publish(target, message, context)` | Accept or transform messages written to a topic/resource. |
44
+ | `connect(incomingMessages)` | Customize WebSocket connection behavior for a resource. |
45
+
46
+ For table-backed resources, prefer default behavior until the product needs a
47
+ custom message shape, authorization check, fan-out, or derived event. When
48
+ overriding, preserve built-in table behavior with `super.subscribe(...)` or
49
+ `super.publish(...)` where that behavior is still wanted.
50
+
51
+ ```javascript
52
+ export class Activity extends tables.Activity {
53
+ static async publish(target, message, context) {
54
+ const payload = await message;
55
+ await super.publish(target, payload, context);
56
+ return { ...payload, acceptedAt: Date.now() };
57
+ }
58
+ }
59
+ ```
60
+
61
+ For WebSocket-only behavior, implement `connect(incomingMessages)` and return an
62
+ async iterable. Use the default `super.connect()` stream when you only need to
63
+ push extra server messages or clean up on disconnect.
64
+
65
+ ## Transport choices
66
+
67
+ | Transport | Best fit | Notes |
68
+ | --- | --- | --- |
69
+ | MQTT | Device streams, backend subscribers, wildcard topics, durable clients. | Plain MQTT defaults to port `1883`; MQTTS defaults to `8883`. |
70
+ | MQTT over WebSocket | Browser or edge clients using MQTT semantics. | Uses the HTTP port, default `9926`, with the `mqtt` WebSocket subprotocol. |
71
+ | Resource WebSocket | Browser live views tied to one REST resource path. | Enabled with the `rest` plugin unless `rest.webSocket: false` is set. |
72
+ | SSE/custom streaming route | One-way browser updates when WebSocket is not appropriate. | Implement as a project route; do not assume SSE automatically subscribes to Resource changes. |
73
+
74
+ Authentication is usually required for MQTT. When `mqtt.requireAuthentication` is
75
+ `false`, authorization still applies at the resource/table level, so public
76
+ connections must be explicitly allowed by roles or resource logic.
77
+
78
+ ## config.yaml wiring
79
+
80
+ Component-level `config.yaml` enables the app surface:
81
+
82
+ ```yaml
83
+ rest: true
84
+ graphqlSchema:
85
+ files: schema.graphql
86
+ jsResource:
87
+ files: resources.js
88
+ ```
89
+
90
+ The root Harper `harper-config.yaml`, not the component `config.yaml`, owns broker
91
+ ports and MQTT authentication:
92
+
93
+ ```yaml
94
+ mqtt:
95
+ network:
96
+ port: 1883
97
+ securePort: 8883
98
+ webSocket: true
99
+ requireAuthentication: true
100
+ ```
101
+
102
+ Keep the `rest`, `graphqlSchema`, and `jsResource` declarations together when a
103
+ project has a custom component `config.yaml`. Harper does not merge custom
104
+ component config with defaults. See [[harper-config-yaml]].
105
+
106
+ ## Filtering and message shape
107
+
108
+ - Prefer record-level subscriptions (`Resource/<id>`) when the UI watches one
109
+ entity; use collection or wildcard subscriptions only when the product needs a
110
+ feed.
111
+ - Keep published messages typed and small. Send the changed record or a compact
112
+ event envelope, not a full page payload.
113
+ - Include stable identifiers in custom events: resource name, id, operation, and
114
+ timestamp are usually enough.
115
+ - Treat inaccessible or unauthenticated subscribe attempts as authorization
116
+ failures, not empty streams.
117
+ - Do not disable the audit log for tables that need real-time messages or
118
+ replication; Harper uses it for live subscriptions.
119
+
120
+ ## Fabric and replication
121
+
122
+ For clustered/Fabric deployments, real-time behavior must match the deploy target:
123
+
124
+ - Verify against the same environment that users connect to, not only a local
125
+ single-node process.
126
+ - Use `replicated=true` when deploying a component that needs to run across Fabric
127
+ nodes. See [[harper-build-and-deploy]].
128
+ - Keep event handlers idempotent. A subscriber may reconnect and replay from the
129
+ latest known state.
130
+ - If a bug appears only across nodes, capture the target URL, topic/path, node
131
+ count when known, and the exact publish/subscribe commands in the evidence.
132
+
133
+ ## Local verification
134
+
135
+ 1. Build generated Harper assets from source:
136
+
137
+ ```bash
138
+ bun run build
139
+ ```
140
+
141
+ 2. Start the component:
142
+
143
+ ```bash
144
+ harper dev harper-app
145
+ ```
146
+
147
+ 3. In another shell, subscribe to a topic or WebSocket path:
148
+
149
+ ```bash
150
+ npx mqtt sub -h localhost -p 1883 -u HDB_ADMIN -P "$HARPER_PASSWORD" -t 'Activity/#' -v
151
+ ```
152
+
153
+ ```bash
154
+ npx wscat -c ws://localhost:9926/Activity/123
155
+ ```
156
+
157
+ 4. Publish or mutate the watched record:
158
+
159
+ ```bash
160
+ npx mqtt pub -h localhost -p 1883 -u HDB_ADMIN -P "$HARPER_PASSWORD" -t 'Activity/123' -m '{"status":"live"}'
161
+ ```
162
+
163
+ 5. Confirm the subscriber receives the expected message shape and that a normal
164
+ REST/GraphQL read returns the same resulting state.
165
+
166
+ Record the command, topic/path, payload, and observed message in PR evidence. If a
167
+ local Harper binary or credentials are unavailable, report that blocker instead of
168
+ claiming the subscription was verified.
169
+
170
+ ## Project conventions
171
+
172
+ - Write resource code in TypeScript under `src/`; `harper-app/resources.js` is a
173
+ generated artifact. See [[harper-resources]].
174
+ - If real-time work changes `config.yaml`, update the project Fabric runbook and
175
+ re-run the smoke path. See [[harper-config-yaml]].
176
+ - Prefer a pushed update over a polling workaround when the issue asks for live
177
+ behavior.
178
+ - For Lisa plugin edits, change `plugins/src/harper-fabric`, run
179
+ `bun run build:plugins`, and commit both source and generated plugin copies.
180
+
181
+ ## Sources
182
+
183
+ - [Resources overview](https://docs.harperdb.io/reference/v5/resources/overview)
184
+ - [Resource API](https://docs.harperdb.io/reference/v5/resources/resource-api)
185
+ - [WebSockets](https://docs.harperdb.io/reference/v5/rest/websockets)
186
+ - [MQTT configuration](https://docs.harperdb.io/reference/v4/mqtt/configuration)
187
+ - [Transaction logging](https://docs.harperdb.io/reference/v5/database/transaction)
@@ -0,0 +1,4 @@
1
+ display_name: "Harper Realtime"
2
+ short_description: "adding or troubleshooting Harper (HarperDB/Fabric) real-time behavior: MQTT topics, WebSocket resource subscriptions, resource…"
3
+ default_prompt:
4
+ - "Use $harper-realtime: adding or troubleshooting Harper (HarperDB/Fabric) real-time behavior: MQTT topics, WebSocket resource subscriptions, resource…."
@@ -70,8 +70,9 @@ jsResource:
70
70
  ```
71
71
 
72
72
  Resources can also be registered programmatically with `server.resources.set()`.
73
- See [[harper-config-yaml]] for the extension wiring and [[harper-schema-graphql]]
74
- for how the schema defines the tables resources extend.
73
+ See [[harper-config-yaml]] for the extension wiring, [[harper-schema-graphql]] for
74
+ how the schema defines the tables resources extend, and [[harper-realtime]] when
75
+ `subscribe`, `publish`, or WebSocket behavior is part of the feature.
75
76
 
76
77
  ## Project conventions (TS is source)
77
78
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.164.0",
3
+ "version": "2.165.0",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -52,7 +52,7 @@ unmentioned extensions stay on.
52
52
 
53
53
  | Key | Purpose | Common options |
54
54
  | --- | --- | --- |
55
- | `rest` | Auto REST endpoints for exported resources/tables | `true`, or an object with options |
55
+ | `rest` | Auto REST endpoints and resource WebSocket subscriptions | `true`, or an object with options such as `webSocket` |
56
56
  | `graphqlSchema` | Define tables/types from GraphQL files | `files: '*.graphql'` — see [[harper-schema-graphql]] |
57
57
  | `jsResource` | Load custom JS resources | `files: 'resources.js'` — see [[harper-resources]] |
58
58
  | `static` | Serve static files over HTTP | `files: 'web/**'`, `urlPath` |
@@ -61,6 +61,11 @@ unmentioned extensions stay on.
61
61
  | `dataLoader` | Seed tables from JSON/YAML | `files` |
62
62
  | `fastifyRoutes` | Custom Fastify routes | `files: 'routes/*.js'`, `urlPath` |
63
63
 
64
+ For real-time work, component `config.yaml` keeps `rest`, `graphqlSchema`, and
65
+ `jsResource` enabled so exported resources can be addressed by HTTP/WebSocket and
66
+ MQTT topic paths. Broker ports and MQTT authentication live in the root
67
+ `harper-config.yaml`, not the component file. See [[harper-realtime]].
68
+
64
69
  ## External components and custom plugins
65
70
 
66
71
  A component you depend on from npm needs a `package:` directive matching a