@codyswann/lisa 4.73.9 → 4.74.1

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 (119) hide show
  1. package/README.md +52 -3
  2. package/all/create-only/.github/workflows/continuous-gates.yml +2 -2
  3. package/all/create-only/.github/workflows/workflow-load-failure-sweep.yml +1 -1
  4. package/cdk/create-only/.github/workflows/ci.yml +2 -2
  5. package/cdk/create-only/.github/workflows/deploy.yml +3 -3
  6. package/cdk/package-lisa/package.lisa.json +1 -1
  7. package/dist/core/lisa-owned-hash-ledger.d.ts.map +1 -1
  8. package/dist/core/lisa-owned-hash-ledger.js +60 -0
  9. package/dist/core/lisa-owned-hash-ledger.js.map +1 -1
  10. package/dist/core/lisa-owned-templates.d.ts +9 -2
  11. package/dist/core/lisa-owned-templates.d.ts.map +1 -1
  12. package/dist/core/lisa-owned-templates.js +13 -3
  13. package/dist/core/lisa-owned-templates.js.map +1 -1
  14. package/dist/core/nightly-e2e-guard-behavior-certificate.js +2 -2
  15. package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
  16. package/dist/core/upstream-evidence-manifest.js +87 -33
  17. package/dist/core/upstream-evidence-manifest.js.map +1 -1
  18. package/expo/copy-overwrite/jest.setup.pre.js +15 -1
  19. package/expo/copy-overwrite/scripts/bdd/ci-summary.mjs +37 -0
  20. package/expo/copy-overwrite/scripts/bdd/projection-model.mjs +157 -0
  21. package/expo/copy-overwrite/scripts/bdd/projection-ownership.mjs +300 -0
  22. package/expo/copy-overwrite/scripts/bdd/projection-paths.mjs +152 -0
  23. package/expo/copy-overwrite/scripts/bdd/projection-render.mjs +303 -0
  24. package/expo/copy-overwrite/scripts/bdd/projection-write.mjs +84 -0
  25. package/expo/copy-overwrite/scripts/bdd/projection.mjs +30 -0
  26. package/expo/copy-overwrite/scripts/bdd-matrix.mjs +54 -18
  27. package/expo/copy-overwrite/scripts/check-bdd-coverage.mjs +36 -27
  28. package/expo/create-only/.github/workflows/ci.yml +3 -3
  29. package/expo/create-only/.github/workflows/deploy.yml +4 -4
  30. package/expo/create-only/.github/workflows/nightly-e2e-bypass-reaper.yml +1 -1
  31. package/expo/create-only/.github/workflows/playwright-e2e.yml +1 -1
  32. package/expo/create-only/eas.json +1 -1
  33. package/harper-fabric/copy-overwrite/.github/workflows/ci.yml +1 -1
  34. package/harper-fabric/create-only/.github/workflows/deploy.yml +3 -3
  35. package/harper-fabric/create-only/.github/workflows/zap-baseline.yml +1 -1
  36. package/harper-fabric/package-lisa/package.lisa.json +2 -2
  37. package/nestjs/create-only/.github/workflows/ci.yml +2 -2
  38. package/nestjs/create-only/.github/workflows/deploy.yml +5 -5
  39. package/package.json +6 -6
  40. package/phaser/copy-overwrite/.github/workflows/ci.yml +1 -1
  41. package/phaser/package-lisa/package.lisa.json +2 -2
  42. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  43. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  44. package/plugins/lisa/.codex-plugin/skills/lisa-parity-sentry-sdk-setup/SKILL.md +104 -0
  45. package/plugins/lisa/.codex-plugin/skills/lisa-setup-workstation/scripts/workstation.mjs +3 -1
  46. package/plugins/lisa/rules/reference/bdd-e2e-coverage.md +9 -7
  47. package/plugins/lisa/skills/lisa-parity-sentry-sdk-setup/SKILL.md +104 -0
  48. package/plugins/lisa/skills/lisa-setup-workstation/scripts/workstation.mjs +3 -1
  49. package/plugins/lisa-agy/plugin.json +1 -1
  50. package/plugins/lisa-agy/skills/lisa-parity-sentry-sdk-setup/SKILL.md +104 -0
  51. package/plugins/lisa-agy/skills/lisa-setup-workstation/scripts/workstation.mjs +3 -1
  52. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  53. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  54. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  55. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  56. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  57. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  58. package/plugins/lisa-copilot/rules/reference/bdd-e2e-coverage.md +9 -7
  59. package/plugins/lisa-copilot/skills/lisa-parity-sentry-sdk-setup/SKILL.md +104 -0
  60. package/plugins/lisa-copilot/skills/lisa-setup-workstation/scripts/workstation.mjs +3 -1
  61. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  62. package/plugins/lisa-cursor/rules/bdd-e2e-coverage-reference.mdc +9 -7
  63. package/plugins/lisa-cursor/skills/lisa-parity-sentry-sdk-setup/SKILL.md +104 -0
  64. package/plugins/lisa-cursor/skills/lisa-setup-workstation/scripts/workstation.mjs +3 -1
  65. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  66. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  67. package/plugins/lisa-expo-agy/plugin.json +1 -1
  68. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  69. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  70. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  71. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  72. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  73. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  74. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  75. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  76. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  77. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  78. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  79. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  80. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  81. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  82. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  83. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  84. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  85. package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
  86. package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
  87. package/plugins/lisa-phaser-agy/plugin.json +1 -1
  88. package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
  89. package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
  90. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  91. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  92. package/plugins/lisa-rails-agy/plugin.json +1 -1
  93. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  94. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  95. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  96. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  97. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  98. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  99. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  100. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  101. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  102. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  103. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  104. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  105. package/plugins/src/base/rules/reference/bdd-e2e-coverage.md +9 -7
  106. package/plugins/src/base/skills/lisa-parity-sentry-sdk-setup/SKILL.md +104 -0
  107. package/plugins/src/base/skills/lisa-setup-workstation/scripts/workstation.mjs +3 -1
  108. package/scripts/check-shell-guard-refusal-coverage.mjs +65 -7
  109. package/scripts/generate-lisa-owned-hash-ledger.mjs +3 -0
  110. package/scripts/lib/shell-guard-shard-runner.mjs +381 -0
  111. package/scripts/lib/shell-guard-shards.mjs +383 -0
  112. package/scripts/lib/shell-guard-terminal-reporter.mjs +89 -0
  113. package/scripts/two-channel-couplings.json +2 -2
  114. package/scripts/update-node-version.ts +52 -6
  115. package/typescript/copy-overwrite/.nvmrc +1 -1
  116. package/typescript/create-only/.github/workflows/ci.yml +1 -1
  117. package/typescript/create-only/.github/workflows/review-evidence.yml +1 -1
  118. package/typescript/create-only/.github/workflows/third-party-review-evidence.yml +1 -1
  119. package/typescript/package-lisa/package.lisa.json +1 -1
@@ -84,6 +84,8 @@ Inspect the project before choosing an SDK. Read `package.json`
84
84
  - `pyproject.toml` / `requirements.txt`; `django`/`flask`/`fastapi` →
85
85
  **Python** (and which web framework)
86
86
  - A plain Node library/CLI → **Node**
87
+ - AWS Lambda handlers or a Serverless/SAM/CDK function runtime → inspect the
88
+ function's actual runtime and wrapper before choosing **Node/Lambda**.
87
89
 
88
90
  If the runtime is genuinely ambiguous, ask which app to instrument rather than
89
91
  guessing. Respect the project's package manager (bun/npm/pnpm/yarn — match the
@@ -98,6 +100,7 @@ Use the project's package manager. Examples (swap `bun add` for your manager):
98
100
  | React (browser) | `@sentry/react` |
99
101
  | Next.js | `@sentry/nextjs` |
100
102
  | Node / Express / Fastify | `@sentry/node` (+ `@sentry/profiling-node` for profiling) |
103
+ | AWS Lambda | `@sentry/aws-serverless` for a compatible Lambda wrapper, or `@sentry/node` for an unwrapped async handler |
101
104
  | NestJS | `@sentry/nestjs` (+ `@sentry/node`) |
102
105
  | React Native / Expo | `@sentry/react-native` |
103
106
  | Vue | `@sentry/vue` |
@@ -148,6 +151,107 @@ Sentry.init({
148
151
 
149
152
  Then, after routes are defined: `Sentry.setupExpressErrorHandler(app);`
150
153
 
154
+ ### Node24 Lambda completion
155
+
156
+ Review the actual function runtime and installed SDK before migrating. Node24
157
+ LTS is Lisa's default for new TypeScript hosts; an existing host's explicit
158
+ engine and create-only workflows remain host-owned. On AWS Lambda `nodejs24.x`,
159
+ callback-style handlers and legacy context completion APIs, including
160
+ `callbackWaitsForEmptyEventLoop`, are removed. Do not assign those properties,
161
+ including to frozen/non-extensible context objects. Supported async handlers,
162
+ synchronous returns and response streaming are distinct forms; follow the
163
+ [AWS handler contract](https://docs.aws.amazon.com/lambda/latest/dg/nodejs-handler.html).
164
+
165
+ Earlier non-streaming async handlers already returned without waiting for
166
+ unresolved background promises. Node24 aligns streaming completion with that
167
+ behavior; await work that must finish before returning or ending the stream.
168
+ Do not claim all Node20/22 async handlers drained arbitrary background work.
169
+ For streaming, flush at the appropriate point before `responseStream.end()` or
170
+ inside the awaited streaming pipeline, rather than after the stream is ended.
171
+ [AWS's Node24 migration explanation](https://aws.amazon.com/blogs/compute/node-js-24-runtime-now-available-in-aws-lambda/)
172
+ is the runtime authority; ordinary local Node process behavior is not deployed
173
+ Lambda evidence.
174
+
175
+ For an **unwrapped async** scheduled, queue or Cognito handler, initialize Sentry
176
+ once at module startup with the DSN from the environment. Await a finite positive
177
+ flush budget on both success and original-error paths. A false flush result or
178
+ rejection must not turn successful queue work into a retry or replace its real
179
+ error. Keep diagnostics local and non-throwing, and preserve the client for warm
180
+ invocations: `close()` disables it. The following helper wraps the host's existing
181
+ business operation; it neither mutates context nor adds a Lambda callback.
182
+
183
+ <!-- lisa-node24-unwrapped-example:start -->
184
+ ```ts
185
+ import * as Sentry from "@sentry/node";
186
+
187
+ // Initialize early, once outside the handler, with DSN from the environment.
188
+ function reportFlushProblem(message: string): void {
189
+ try {
190
+ console.warn(message);
191
+ } catch {
192
+ // Telemetry diagnostics must preserve the business outcome too.
193
+ }
194
+ }
195
+
196
+ export async function withSentryFlush<T>(
197
+ work: () => Promise<T>,
198
+ timeoutMs = 2000
199
+ ): Promise<T> {
200
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
201
+ throw new RangeError("Choose a finite positive Sentry flush budget");
202
+ }
203
+ try {
204
+ return await work();
205
+ } catch (originalError) {
206
+ try {
207
+ Sentry.captureException(originalError);
208
+ } catch {
209
+ // Preserve the original handler error even if capture fails.
210
+ }
211
+ throw originalError;
212
+ } finally {
213
+ try {
214
+ if (!(await Sentry.flush(timeoutMs))) {
215
+ reportFlushProblem("Sentry flush did not finish in time");
216
+ }
217
+ } catch {
218
+ reportFlushProblem("Sentry flush rejected");
219
+ }
220
+ }
221
+ }
222
+ ```
223
+ <!-- lisa-node24-unwrapped-example:end -->
224
+
225
+ In the existing async handler, return
226
+ `withSentryFlush(() => performBusinessWork(event, context))`; use the host's
227
+ actual business operation and preserve its return/error contract. Select a
228
+ positive budget that fits remaining invocation time with a safety margin.
229
+ Do not omit the timeout or use zero as a finite cap. The SDK's timeout argument
230
+ does not cancel every custom transport or guarantee completion before Lambda's
231
+ hard timeout, and a drained local queue does not prove tenant ingestion.
232
+ [Sentry API semantics](https://docs.sentry.io/platforms/javascript/guides/aws-lambda/configuration/apis.md)
233
+ describe `flush()` and `close()`.
234
+
235
+ For a **compatible `Sentry.wrapHandler`**, its documented default flush is up
236
+ to2000ms, configurable through `flushTimeout`; avoid a redundant manual flush
237
+ when that wrapper already handles completion. Check the installed version's
238
+ context behavior, too: `@sentry/aws-serverless`11.6.0 unconditionally assigns
239
+ `context.callbackWaitsForEmptyEventLoop` before invoking the business handler.
240
+ It throws on a non-extensible context lacking that removed property. Changing
241
+ the option does not remove the assignment. Use the unwrapped form when this
242
+ incompatibility applies; do not clone/unfreeze context or pre-add an obsolete
243
+ property to claim compatibility. See the [wrapper documentation](https://docs.sentry.io/platforms/javascript/guides/aws-lambda/configuration/lambda-wrapper.md)
244
+ and [versioned implementation](https://github.com/getsentry/sentry-javascript/blob/11.6.0/packages/aws-serverless/src/sdk.ts).
245
+
246
+ Treat Node types and optional native profiling as migration checks. Examples
247
+ using `Array.at` need an ES2022-or-later TypeScript `lib`; keep a host's business
248
+ compiler target deliberate. Confirm optional profiling prebuilds against the
249
+ actual Node ABI (Node24 uses137) only when profiling is in use; do not install an
250
+ unused profiling package. Verify the helper with the real installed SDK and
251
+ local transport, including success/error, timeout/false, rejected flush and a
252
+ second warm invocation. Label local observations honestly; actual Lambda
253
+ deployment and Sentry event ingestion require their own provider proof.
254
+
151
255
  **NestJS** — import `./instrument` first in `main.ts`, then add Sentry's module:
152
256
 
153
257
  ```ts
@@ -63,7 +63,9 @@ import {
63
63
  export function locate(name, exec = boundedChildOutput) {
64
64
  try {
65
65
  return String(
66
- exec("command", ["-v", name], { encoding: "utf8", shell: true })
66
+ exec("sh", ["-c", 'command -v -- "$1"', "lisa-locate", name], {
67
+ encoding: "utf8",
68
+ })
67
69
  ).trim();
68
70
  } catch {
69
71
  // probe-direction: fail-closed — null means "not proven present", and the
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-cdk",
3
- "version": "4.73.9",
3
+ "version": "4.74.1",
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": "4.73.9",
3
+ "version": "4.74.1",
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": "4.73.9",
3
+ "version": "4.74.1",
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": "4.73.9",
3
+ "version": "4.74.1",
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": "4.73.9",
3
+ "version": "4.74.1",
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": "4.73.9",
3
+ "version": "4.74.1",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -22,8 +22,9 @@ Default locations (a project that already has an equivalent contract keeps its o
22
22
  |---|---|---|
23
23
  | Scenarios | `bdd/features/*.feature` | Gherkin, the product-level behavior contract |
24
24
  | Coverage map | `bdd/coverage-map.json` | scenario → runner/platform/file/evidence mappings, plus waivers, per-runner test-discovery roots, and exclusions |
25
- | Generated matrix | `docs/bdd-scenario-matrix.md` | regenerated, never hand-edited |
26
- | Burndown | `docs/e2e-bdd-coverage.md` | current coverage per platform |
25
+ | Generated matrix | `docs/bdd-scenario-matrix/` | per-source-file leaves, regenerated, never hand-edited; static navigation at `docs/bdd-scenario-matrix.md` |
26
+ | Burndown | `docs/e2e-bdd-coverage/` | per-source-file mapping gaps and waivers; static navigation at `docs/e2e-bdd-coverage.md` |
27
+ | Feature JSON | `bdd/reports/v1/features/` | versioned local declarations/evidence; full aggregate remains in runtime `--report` and CI |
27
28
 
28
29
  ## Scenario shape
29
30
 
@@ -180,9 +181,10 @@ exclusion whose file is gone, whose title was renamed, or that no discovery root
180
181
 
181
182
  Two commands, wired into the project's script surface and into CI:
182
183
 
183
- 1. **Regenerate** — recompute coverage from features + map, rewrite the generated matrix
184
- (`docs/bdd-scenario-matrix.md`) and the burndown (`docs/e2e-bdd-coverage.md`), and refresh the
185
- machine-readable report. Low coverage is reported honestly and does **not** fail this command.
184
+ 1. **Regenerate** — recompute coverage from features + map and write the feature-local matrix,
185
+ burndown and JSON under `docs/bdd-scenario-matrix/`, `docs/e2e-bdd-coverage/` and
186
+ `bdd/reports/v1/features/`. Shared entry points contain static guidance. Reportable coverage
187
+ defects still produce paperwork; the coverage CLI keeps its original failing exit.
186
188
  2. **Check** — the CI gate. It fails on contract defects, not on ambition:
187
189
  - a duplicate or malformed scenario ID;
188
190
  - a scenario declaring a platform with no configured runner;
@@ -197,7 +199,7 @@ Two commands, wired into the project's script surface and into CI:
197
199
  - coverage given back: an obligation mapped at the base revision that nothing maps here;
198
200
  - new behavior nobody mapped or waived.
199
201
 
200
- Regeneration is never blocked by the check: `--write` rewrites the report and burndown whenever a
202
+ Regeneration is never blocked by a reportable coverage defect: `--write` rewrites feature reports whenever a
201
203
  report can be built at all, so a stale evidence string can never hold hostage the paperwork that
202
204
  documents it.
203
205
 
@@ -277,7 +279,7 @@ A repo with no contract yet, taking its first frontend work item:
277
279
  Pre-existing tests that align to no product behavior are recorded as `exclusions` with reasons
278
280
  during this step, never left undisclosed.
279
281
  3. **Write only this item's scenarios.** The first item is not a backfill project. Pre-existing
280
- uncovered behavior becomes burndown in `docs/e2e-bdd-coverage.md`, and the floor starts where the
282
+ uncovered behavior becomes feature-local burndown under `docs/e2e-bdd-coverage/`, and the floor starts where the
281
283
  repo actually is. That is a one-time act, not a recurring one: from here on the floor stays put
282
284
  and what protects each new obligation is the per-obligation check, not the number.
283
285
  4. **Seal this item's obligations** and commit the regenerated matrix and burndown with the change.
@@ -84,6 +84,8 @@ Inspect the project before choosing an SDK. Read `package.json`
84
84
  - `pyproject.toml` / `requirements.txt`; `django`/`flask`/`fastapi` →
85
85
  **Python** (and which web framework)
86
86
  - A plain Node library/CLI → **Node**
87
+ - AWS Lambda handlers or a Serverless/SAM/CDK function runtime → inspect the
88
+ function's actual runtime and wrapper before choosing **Node/Lambda**.
87
89
 
88
90
  If the runtime is genuinely ambiguous, ask which app to instrument rather than
89
91
  guessing. Respect the project's package manager (bun/npm/pnpm/yarn — match the
@@ -98,6 +100,7 @@ Use the project's package manager. Examples (swap `bun add` for your manager):
98
100
  | React (browser) | `@sentry/react` |
99
101
  | Next.js | `@sentry/nextjs` |
100
102
  | Node / Express / Fastify | `@sentry/node` (+ `@sentry/profiling-node` for profiling) |
103
+ | AWS Lambda | `@sentry/aws-serverless` for a compatible Lambda wrapper, or `@sentry/node` for an unwrapped async handler |
101
104
  | NestJS | `@sentry/nestjs` (+ `@sentry/node`) |
102
105
  | React Native / Expo | `@sentry/react-native` |
103
106
  | Vue | `@sentry/vue` |
@@ -148,6 +151,107 @@ Sentry.init({
148
151
 
149
152
  Then, after routes are defined: `Sentry.setupExpressErrorHandler(app);`
150
153
 
154
+ ### Node24 Lambda completion
155
+
156
+ Review the actual function runtime and installed SDK before migrating. Node24
157
+ LTS is Lisa's default for new TypeScript hosts; an existing host's explicit
158
+ engine and create-only workflows remain host-owned. On AWS Lambda `nodejs24.x`,
159
+ callback-style handlers and legacy context completion APIs, including
160
+ `callbackWaitsForEmptyEventLoop`, are removed. Do not assign those properties,
161
+ including to frozen/non-extensible context objects. Supported async handlers,
162
+ synchronous returns and response streaming are distinct forms; follow the
163
+ [AWS handler contract](https://docs.aws.amazon.com/lambda/latest/dg/nodejs-handler.html).
164
+
165
+ Earlier non-streaming async handlers already returned without waiting for
166
+ unresolved background promises. Node24 aligns streaming completion with that
167
+ behavior; await work that must finish before returning or ending the stream.
168
+ Do not claim all Node20/22 async handlers drained arbitrary background work.
169
+ For streaming, flush at the appropriate point before `responseStream.end()` or
170
+ inside the awaited streaming pipeline, rather than after the stream is ended.
171
+ [AWS's Node24 migration explanation](https://aws.amazon.com/blogs/compute/node-js-24-runtime-now-available-in-aws-lambda/)
172
+ is the runtime authority; ordinary local Node process behavior is not deployed
173
+ Lambda evidence.
174
+
175
+ For an **unwrapped async** scheduled, queue or Cognito handler, initialize Sentry
176
+ once at module startup with the DSN from the environment. Await a finite positive
177
+ flush budget on both success and original-error paths. A false flush result or
178
+ rejection must not turn successful queue work into a retry or replace its real
179
+ error. Keep diagnostics local and non-throwing, and preserve the client for warm
180
+ invocations: `close()` disables it. The following helper wraps the host's existing
181
+ business operation; it neither mutates context nor adds a Lambda callback.
182
+
183
+ <!-- lisa-node24-unwrapped-example:start -->
184
+ ```ts
185
+ import * as Sentry from "@sentry/node";
186
+
187
+ // Initialize early, once outside the handler, with DSN from the environment.
188
+ function reportFlushProblem(message: string): void {
189
+ try {
190
+ console.warn(message);
191
+ } catch {
192
+ // Telemetry diagnostics must preserve the business outcome too.
193
+ }
194
+ }
195
+
196
+ export async function withSentryFlush<T>(
197
+ work: () => Promise<T>,
198
+ timeoutMs = 2000
199
+ ): Promise<T> {
200
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
201
+ throw new RangeError("Choose a finite positive Sentry flush budget");
202
+ }
203
+ try {
204
+ return await work();
205
+ } catch (originalError) {
206
+ try {
207
+ Sentry.captureException(originalError);
208
+ } catch {
209
+ // Preserve the original handler error even if capture fails.
210
+ }
211
+ throw originalError;
212
+ } finally {
213
+ try {
214
+ if (!(await Sentry.flush(timeoutMs))) {
215
+ reportFlushProblem("Sentry flush did not finish in time");
216
+ }
217
+ } catch {
218
+ reportFlushProblem("Sentry flush rejected");
219
+ }
220
+ }
221
+ }
222
+ ```
223
+ <!-- lisa-node24-unwrapped-example:end -->
224
+
225
+ In the existing async handler, return
226
+ `withSentryFlush(() => performBusinessWork(event, context))`; use the host's
227
+ actual business operation and preserve its return/error contract. Select a
228
+ positive budget that fits remaining invocation time with a safety margin.
229
+ Do not omit the timeout or use zero as a finite cap. The SDK's timeout argument
230
+ does not cancel every custom transport or guarantee completion before Lambda's
231
+ hard timeout, and a drained local queue does not prove tenant ingestion.
232
+ [Sentry API semantics](https://docs.sentry.io/platforms/javascript/guides/aws-lambda/configuration/apis.md)
233
+ describe `flush()` and `close()`.
234
+
235
+ For a **compatible `Sentry.wrapHandler`**, its documented default flush is up
236
+ to2000ms, configurable through `flushTimeout`; avoid a redundant manual flush
237
+ when that wrapper already handles completion. Check the installed version's
238
+ context behavior, too: `@sentry/aws-serverless`11.6.0 unconditionally assigns
239
+ `context.callbackWaitsForEmptyEventLoop` before invoking the business handler.
240
+ It throws on a non-extensible context lacking that removed property. Changing
241
+ the option does not remove the assignment. Use the unwrapped form when this
242
+ incompatibility applies; do not clone/unfreeze context or pre-add an obsolete
243
+ property to claim compatibility. See the [wrapper documentation](https://docs.sentry.io/platforms/javascript/guides/aws-lambda/configuration/lambda-wrapper.md)
244
+ and [versioned implementation](https://github.com/getsentry/sentry-javascript/blob/11.6.0/packages/aws-serverless/src/sdk.ts).
245
+
246
+ Treat Node types and optional native profiling as migration checks. Examples
247
+ using `Array.at` need an ES2022-or-later TypeScript `lib`; keep a host's business
248
+ compiler target deliberate. Confirm optional profiling prebuilds against the
249
+ actual Node ABI (Node24 uses137) only when profiling is in use; do not install an
250
+ unused profiling package. Verify the helper with the real installed SDK and
251
+ local transport, including success/error, timeout/false, rejected flush and a
252
+ second warm invocation. Label local observations honestly; actual Lambda
253
+ deployment and Sentry event ingestion require their own provider proof.
254
+
151
255
  **NestJS** — import `./instrument` first in `main.ts`, then add Sentry's module:
152
256
 
153
257
  ```ts
@@ -63,7 +63,9 @@ import {
63
63
  export function locate(name, exec = boundedChildOutput) {
64
64
  try {
65
65
  return String(
66
- exec("command", ["-v", name], { encoding: "utf8", shell: true })
66
+ exec("sh", ["-c", 'command -v -- "$1"', "lisa-locate", name], {
67
+ encoding: "utf8",
68
+ })
67
69
  ).trim();
68
70
  } catch {
69
71
  // probe-direction: fail-closed — null means "not proven present", and the
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa",
3
- "version": "4.73.9",
3
+ "version": "4.74.1",
4
4
  "description": "Universal governance — agents, skills, commands, hooks, and rules for all projects",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -27,8 +27,9 @@ Default locations (a project that already has an equivalent contract keeps its o
27
27
  |---|---|---|
28
28
  | Scenarios | `bdd/features/*.feature` | Gherkin, the product-level behavior contract |
29
29
  | Coverage map | `bdd/coverage-map.json` | scenario → runner/platform/file/evidence mappings, plus waivers, per-runner test-discovery roots, and exclusions |
30
- | Generated matrix | `docs/bdd-scenario-matrix.md` | regenerated, never hand-edited |
31
- | Burndown | `docs/e2e-bdd-coverage.md` | current coverage per platform |
30
+ | Generated matrix | `docs/bdd-scenario-matrix/` | per-source-file leaves, regenerated, never hand-edited; static navigation at `docs/bdd-scenario-matrix.md` |
31
+ | Burndown | `docs/e2e-bdd-coverage/` | per-source-file mapping gaps and waivers; static navigation at `docs/e2e-bdd-coverage.md` |
32
+ | Feature JSON | `bdd/reports/v1/features/` | versioned local declarations/evidence; full aggregate remains in runtime `--report` and CI |
32
33
 
33
34
  ## Scenario shape
34
35
 
@@ -185,9 +186,10 @@ exclusion whose file is gone, whose title was renamed, or that no discovery root
185
186
 
186
187
  Two commands, wired into the project's script surface and into CI:
187
188
 
188
- 1. **Regenerate** — recompute coverage from features + map, rewrite the generated matrix
189
- (`docs/bdd-scenario-matrix.md`) and the burndown (`docs/e2e-bdd-coverage.md`), and refresh the
190
- machine-readable report. Low coverage is reported honestly and does **not** fail this command.
189
+ 1. **Regenerate** — recompute coverage from features + map and write the feature-local matrix,
190
+ burndown and JSON under `docs/bdd-scenario-matrix/`, `docs/e2e-bdd-coverage/` and
191
+ `bdd/reports/v1/features/`. Shared entry points contain static guidance. Reportable coverage
192
+ defects still produce paperwork; the coverage CLI keeps its original failing exit.
191
193
  2. **Check** — the CI gate. It fails on contract defects, not on ambition:
192
194
  - a duplicate or malformed scenario ID;
193
195
  - a scenario declaring a platform with no configured runner;
@@ -202,7 +204,7 @@ Two commands, wired into the project's script surface and into CI:
202
204
  - coverage given back: an obligation mapped at the base revision that nothing maps here;
203
205
  - new behavior nobody mapped or waived.
204
206
 
205
- Regeneration is never blocked by the check: `--write` rewrites the report and burndown whenever a
207
+ Regeneration is never blocked by a reportable coverage defect: `--write` rewrites feature reports whenever a
206
208
  report can be built at all, so a stale evidence string can never hold hostage the paperwork that
207
209
  documents it.
208
210
 
@@ -282,7 +284,7 @@ A repo with no contract yet, taking its first frontend work item:
282
284
  Pre-existing tests that align to no product behavior are recorded as `exclusions` with reasons
283
285
  during this step, never left undisclosed.
284
286
  3. **Write only this item's scenarios.** The first item is not a backfill project. Pre-existing
285
- uncovered behavior becomes burndown in `docs/e2e-bdd-coverage.md`, and the floor starts where the
287
+ uncovered behavior becomes feature-local burndown under `docs/e2e-bdd-coverage/`, and the floor starts where the
286
288
  repo actually is. That is a one-time act, not a recurring one: from here on the floor stays put
287
289
  and what protects each new obligation is the per-obligation check, not the number.
288
290
  4. **Seal this item's obligations** and commit the regenerated matrix and burndown with the change.
@@ -84,6 +84,8 @@ Inspect the project before choosing an SDK. Read `package.json`
84
84
  - `pyproject.toml` / `requirements.txt`; `django`/`flask`/`fastapi` →
85
85
  **Python** (and which web framework)
86
86
  - A plain Node library/CLI → **Node**
87
+ - AWS Lambda handlers or a Serverless/SAM/CDK function runtime → inspect the
88
+ function's actual runtime and wrapper before choosing **Node/Lambda**.
87
89
 
88
90
  If the runtime is genuinely ambiguous, ask which app to instrument rather than
89
91
  guessing. Respect the project's package manager (bun/npm/pnpm/yarn — match the
@@ -98,6 +100,7 @@ Use the project's package manager. Examples (swap `bun add` for your manager):
98
100
  | React (browser) | `@sentry/react` |
99
101
  | Next.js | `@sentry/nextjs` |
100
102
  | Node / Express / Fastify | `@sentry/node` (+ `@sentry/profiling-node` for profiling) |
103
+ | AWS Lambda | `@sentry/aws-serverless` for a compatible Lambda wrapper, or `@sentry/node` for an unwrapped async handler |
101
104
  | NestJS | `@sentry/nestjs` (+ `@sentry/node`) |
102
105
  | React Native / Expo | `@sentry/react-native` |
103
106
  | Vue | `@sentry/vue` |
@@ -148,6 +151,107 @@ Sentry.init({
148
151
 
149
152
  Then, after routes are defined: `Sentry.setupExpressErrorHandler(app);`
150
153
 
154
+ ### Node24 Lambda completion
155
+
156
+ Review the actual function runtime and installed SDK before migrating. Node24
157
+ LTS is Lisa's default for new TypeScript hosts; an existing host's explicit
158
+ engine and create-only workflows remain host-owned. On AWS Lambda `nodejs24.x`,
159
+ callback-style handlers and legacy context completion APIs, including
160
+ `callbackWaitsForEmptyEventLoop`, are removed. Do not assign those properties,
161
+ including to frozen/non-extensible context objects. Supported async handlers,
162
+ synchronous returns and response streaming are distinct forms; follow the
163
+ [AWS handler contract](https://docs.aws.amazon.com/lambda/latest/dg/nodejs-handler.html).
164
+
165
+ Earlier non-streaming async handlers already returned without waiting for
166
+ unresolved background promises. Node24 aligns streaming completion with that
167
+ behavior; await work that must finish before returning or ending the stream.
168
+ Do not claim all Node20/22 async handlers drained arbitrary background work.
169
+ For streaming, flush at the appropriate point before `responseStream.end()` or
170
+ inside the awaited streaming pipeline, rather than after the stream is ended.
171
+ [AWS's Node24 migration explanation](https://aws.amazon.com/blogs/compute/node-js-24-runtime-now-available-in-aws-lambda/)
172
+ is the runtime authority; ordinary local Node process behavior is not deployed
173
+ Lambda evidence.
174
+
175
+ For an **unwrapped async** scheduled, queue or Cognito handler, initialize Sentry
176
+ once at module startup with the DSN from the environment. Await a finite positive
177
+ flush budget on both success and original-error paths. A false flush result or
178
+ rejection must not turn successful queue work into a retry or replace its real
179
+ error. Keep diagnostics local and non-throwing, and preserve the client for warm
180
+ invocations: `close()` disables it. The following helper wraps the host's existing
181
+ business operation; it neither mutates context nor adds a Lambda callback.
182
+
183
+ <!-- lisa-node24-unwrapped-example:start -->
184
+ ```ts
185
+ import * as Sentry from "@sentry/node";
186
+
187
+ // Initialize early, once outside the handler, with DSN from the environment.
188
+ function reportFlushProblem(message: string): void {
189
+ try {
190
+ console.warn(message);
191
+ } catch {
192
+ // Telemetry diagnostics must preserve the business outcome too.
193
+ }
194
+ }
195
+
196
+ export async function withSentryFlush<T>(
197
+ work: () => Promise<T>,
198
+ timeoutMs = 2000
199
+ ): Promise<T> {
200
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
201
+ throw new RangeError("Choose a finite positive Sentry flush budget");
202
+ }
203
+ try {
204
+ return await work();
205
+ } catch (originalError) {
206
+ try {
207
+ Sentry.captureException(originalError);
208
+ } catch {
209
+ // Preserve the original handler error even if capture fails.
210
+ }
211
+ throw originalError;
212
+ } finally {
213
+ try {
214
+ if (!(await Sentry.flush(timeoutMs))) {
215
+ reportFlushProblem("Sentry flush did not finish in time");
216
+ }
217
+ } catch {
218
+ reportFlushProblem("Sentry flush rejected");
219
+ }
220
+ }
221
+ }
222
+ ```
223
+ <!-- lisa-node24-unwrapped-example:end -->
224
+
225
+ In the existing async handler, return
226
+ `withSentryFlush(() => performBusinessWork(event, context))`; use the host's
227
+ actual business operation and preserve its return/error contract. Select a
228
+ positive budget that fits remaining invocation time with a safety margin.
229
+ Do not omit the timeout or use zero as a finite cap. The SDK's timeout argument
230
+ does not cancel every custom transport or guarantee completion before Lambda's
231
+ hard timeout, and a drained local queue does not prove tenant ingestion.
232
+ [Sentry API semantics](https://docs.sentry.io/platforms/javascript/guides/aws-lambda/configuration/apis.md)
233
+ describe `flush()` and `close()`.
234
+
235
+ For a **compatible `Sentry.wrapHandler`**, its documented default flush is up
236
+ to2000ms, configurable through `flushTimeout`; avoid a redundant manual flush
237
+ when that wrapper already handles completion. Check the installed version's
238
+ context behavior, too: `@sentry/aws-serverless`11.6.0 unconditionally assigns
239
+ `context.callbackWaitsForEmptyEventLoop` before invoking the business handler.
240
+ It throws on a non-extensible context lacking that removed property. Changing
241
+ the option does not remove the assignment. Use the unwrapped form when this
242
+ incompatibility applies; do not clone/unfreeze context or pre-add an obsolete
243
+ property to claim compatibility. See the [wrapper documentation](https://docs.sentry.io/platforms/javascript/guides/aws-lambda/configuration/lambda-wrapper.md)
244
+ and [versioned implementation](https://github.com/getsentry/sentry-javascript/blob/11.6.0/packages/aws-serverless/src/sdk.ts).
245
+
246
+ Treat Node types and optional native profiling as migration checks. Examples
247
+ using `Array.at` need an ES2022-or-later TypeScript `lib`; keep a host's business
248
+ compiler target deliberate. Confirm optional profiling prebuilds against the
249
+ actual Node ABI (Node24 uses137) only when profiling is in use; do not install an
250
+ unused profiling package. Verify the helper with the real installed SDK and
251
+ local transport, including success/error, timeout/false, rejected flush and a
252
+ second warm invocation. Label local observations honestly; actual Lambda
253
+ deployment and Sentry event ingestion require their own provider proof.
254
+
151
255
  **NestJS** — import `./instrument` first in `main.ts`, then add Sentry's module:
152
256
 
153
257
  ```ts
@@ -63,7 +63,9 @@ import {
63
63
  export function locate(name, exec = boundedChildOutput) {
64
64
  try {
65
65
  return String(
66
- exec("command", ["-v", name], { encoding: "utf8", shell: true })
66
+ exec("sh", ["-c", 'command -v -- "$1"', "lisa-locate", name], {
67
+ encoding: "utf8",
68
+ })
67
69
  ).trim();
68
70
  } catch {
69
71
  // probe-direction: fail-closed — null means "not proven present", and the
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "4.73.9",
3
+ "version": "4.74.1",
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": "4.73.9",
3
+ "version": "4.74.1",
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": "4.73.9",
3
+ "version": "4.74.1",
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": "4.73.9",
3
+ "version": "4.74.1",
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": "4.73.9",
3
+ "version": "4.74.1",
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": "4.73.9",
3
+ "version": "4.74.1",
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": "4.73.9",
3
+ "version": "4.74.1",
4
4
  "description": "Harper/Fabric-specific Lisa 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": "4.73.9",
3
+ "version": "4.74.1",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"