@plumbus/core 0.6.4 → 0.6.6

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 (207) hide show
  1. package/CHANGELOG.md +400 -0
  2. package/README.md +23 -13
  3. package/dist/.tsbuildinfo +1 -1
  4. package/dist/ai/ai/security.d.ts +36 -0
  5. package/dist/ai/ai-service.d.ts.map +1 -1
  6. package/dist/ai/ai-service.js +36 -8
  7. package/dist/ai/ai-service.js.map +1 -1
  8. package/dist/ai/index.d.ts +1 -1
  9. package/dist/ai/index.d.ts.map +1 -1
  10. package/dist/ai/index.js +1 -1
  11. package/dist/ai/index.js.map +1 -1
  12. package/dist/ai/security.d.ts +9 -0
  13. package/dist/ai/security.d.ts.map +1 -1
  14. package/dist/ai/security.js +18 -1
  15. package/dist/ai/security.js.map +1 -1
  16. package/dist/ai/types/config.d.ts +11 -0
  17. package/dist/ai/types/entity.d.ts +15 -0
  18. package/dist/ai/types/fields.d.ts +51 -0
  19. package/dist/api/index.d.ts +2 -2
  20. package/dist/api/index.d.ts.map +1 -1
  21. package/dist/api/index.js +1 -1
  22. package/dist/api/index.js.map +1 -1
  23. package/dist/api/route-generator.d.ts +17 -0
  24. package/dist/api/route-generator.d.ts.map +1 -1
  25. package/dist/api/route-generator.js +55 -2
  26. package/dist/api/route-generator.js.map +1 -1
  27. package/dist/cli/commands/api.d.ts +9 -0
  28. package/dist/cli/commands/api.d.ts.map +1 -1
  29. package/dist/cli/commands/api.js +10 -1
  30. package/dist/cli/commands/api.js.map +1 -1
  31. package/dist/cli/commands/init.js +1 -1
  32. package/dist/cli/commands/translation.d.ts.map +1 -1
  33. package/dist/cli/commands/translation.js +13 -28
  34. package/dist/cli/commands/translation.js.map +1 -1
  35. package/dist/cli/commands/ui.d.ts +7 -4
  36. package/dist/cli/commands/ui.d.ts.map +1 -1
  37. package/dist/cli/commands/ui.js +28 -36
  38. package/dist/cli/commands/ui.js.map +1 -1
  39. package/dist/cli/mcp-serve-context.d.ts.map +1 -1
  40. package/dist/cli/mcp-serve-context.js +40 -35
  41. package/dist/cli/mcp-serve-context.js.map +1 -1
  42. package/dist/cli/scaffold-write.d.ts +1 -1
  43. package/dist/cli/scaffold-write.d.ts.map +1 -1
  44. package/dist/cli/scaffold-write.js +1 -1
  45. package/dist/cli/scaffold-write.js.map +1 -1
  46. package/dist/cli/templates/resources.d.ts.map +1 -1
  47. package/dist/cli/templates/resources.js +5 -6
  48. package/dist/cli/templates/resources.js.map +1 -1
  49. package/dist/config/loader.d.ts.map +1 -1
  50. package/dist/config/loader.js +37 -0
  51. package/dist/config/loader.js.map +1 -1
  52. package/dist/data/field-encryption.d.ts +17 -0
  53. package/dist/data/field-encryption.d.ts.map +1 -0
  54. package/dist/data/field-encryption.js +80 -0
  55. package/dist/data/field-encryption.js.map +1 -0
  56. package/dist/data/index.d.ts +2 -0
  57. package/dist/data/index.d.ts.map +1 -1
  58. package/dist/data/index.js +2 -0
  59. package/dist/data/index.js.map +1 -1
  60. package/dist/data/mask-fields.d.ts +17 -0
  61. package/dist/data/mask-fields.d.ts.map +1 -0
  62. package/dist/data/mask-fields.js +56 -0
  63. package/dist/data/mask-fields.js.map +1 -0
  64. package/dist/data/registry.d.ts +4 -0
  65. package/dist/data/registry.d.ts.map +1 -1
  66. package/dist/data/registry.js +6 -0
  67. package/dist/data/registry.js.map +1 -1
  68. package/dist/data/repository.d.ts +3 -0
  69. package/dist/data/repository.d.ts.map +1 -1
  70. package/dist/data/repository.js +123 -41
  71. package/dist/data/repository.js.map +1 -1
  72. package/dist/define/defineCapability.d.ts +2 -0
  73. package/dist/define/defineCapability.d.ts.map +1 -1
  74. package/dist/define/defineCapability.js.map +1 -1
  75. package/dist/errors/data-errors.d.ts +23 -0
  76. package/dist/errors/data-errors.d.ts.map +1 -0
  77. package/dist/errors/data-errors.js +45 -0
  78. package/dist/errors/data-errors.js.map +1 -0
  79. package/dist/errors/index.d.ts +3 -11
  80. package/dist/errors/index.d.ts.map +1 -1
  81. package/dist/errors/index.js +3 -16
  82. package/dist/errors/index.js.map +1 -1
  83. package/dist/errors/plumbus-error.d.ts +13 -0
  84. package/dist/errors/plumbus-error.d.ts.map +1 -0
  85. package/dist/errors/plumbus-error.js +15 -0
  86. package/dist/errors/plumbus-error.js.map +1 -0
  87. package/dist/execution/capability-executor.d.ts.map +1 -1
  88. package/dist/execution/capability-executor.js +142 -61
  89. package/dist/execution/capability-executor.js.map +1 -1
  90. package/dist/execution/capability-invocation.d.ts +3 -1
  91. package/dist/execution/capability-invocation.d.ts.map +1 -1
  92. package/dist/execution/capability-invocation.js +41 -2
  93. package/dist/execution/capability-invocation.js.map +1 -1
  94. package/dist/execution/context-deps.d.ts +23 -0
  95. package/dist/execution/context-deps.d.ts.map +1 -0
  96. package/dist/execution/context-deps.js +45 -0
  97. package/dist/execution/context-deps.js.map +1 -0
  98. package/dist/execution/context-factory.d.ts.map +1 -1
  99. package/dist/execution/context-factory.js +9 -1
  100. package/dist/execution/context-factory.js.map +1 -1
  101. package/dist/execution/deferred-flow-service.d.ts +9 -0
  102. package/dist/execution/deferred-flow-service.d.ts.map +1 -0
  103. package/dist/execution/deferred-flow-service.js +54 -0
  104. package/dist/execution/deferred-flow-service.js.map +1 -0
  105. package/dist/execution/index.d.ts +4 -0
  106. package/dist/execution/index.d.ts.map +1 -1
  107. package/dist/execution/index.js +2 -0
  108. package/dist/execution/index.js.map +1 -1
  109. package/dist/execution/transactional-outbox.d.ts +33 -0
  110. package/dist/execution/transactional-outbox.d.ts.map +1 -0
  111. package/dist/execution/transactional-outbox.js +84 -0
  112. package/dist/execution/transactional-outbox.js.map +1 -0
  113. package/dist/flows/engine.d.ts +1 -0
  114. package/dist/flows/engine.d.ts.map +1 -1
  115. package/dist/flows/engine.js +1 -1
  116. package/dist/flows/engine.js.map +1 -1
  117. package/dist/flows/flow-service.d.ts.map +1 -1
  118. package/dist/flows/flow-service.js +2 -2
  119. package/dist/flows/flow-service.js.map +1 -1
  120. package/dist/governance/index.d.ts +1 -1
  121. package/dist/governance/index.d.ts.map +1 -1
  122. package/dist/governance/index.js +1 -1
  123. package/dist/governance/index.js.map +1 -1
  124. package/dist/index.d.ts +12 -11
  125. package/dist/index.d.ts.map +1 -1
  126. package/dist/index.js +9 -10
  127. package/dist/index.js.map +1 -1
  128. package/dist/jobs/deferred-job-dispatch-service.d.ts +7 -0
  129. package/dist/jobs/deferred-job-dispatch-service.d.ts.map +1 -0
  130. package/dist/jobs/deferred-job-dispatch-service.js +16 -0
  131. package/dist/jobs/deferred-job-dispatch-service.js.map +1 -0
  132. package/dist/jobs/dispatch.d.ts.map +1 -1
  133. package/dist/jobs/dispatch.js +8 -2
  134. package/dist/jobs/dispatch.js.map +1 -1
  135. package/dist/jobs/index.d.ts +3 -0
  136. package/dist/jobs/index.d.ts.map +1 -1
  137. package/dist/jobs/index.js +2 -0
  138. package/dist/jobs/index.js.map +1 -1
  139. package/dist/jobs/job-dispatch-service.d.ts +24 -0
  140. package/dist/jobs/job-dispatch-service.d.ts.map +1 -0
  141. package/dist/jobs/job-dispatch-service.js +26 -0
  142. package/dist/jobs/job-dispatch-service.js.map +1 -0
  143. package/dist/observability/index.d.ts +1 -1
  144. package/dist/observability/index.d.ts.map +1 -1
  145. package/dist/observability/index.js +1 -1
  146. package/dist/observability/index.js.map +1 -1
  147. package/dist/observability/metrics.d.ts +4 -0
  148. package/dist/observability/metrics.d.ts.map +1 -1
  149. package/dist/observability/metrics.js +19 -1
  150. package/dist/observability/metrics.js.map +1 -1
  151. package/dist/runtime/bootstrap.d.ts +2 -0
  152. package/dist/runtime/bootstrap.d.ts.map +1 -1
  153. package/dist/runtime/bootstrap.js +3 -1
  154. package/dist/runtime/bootstrap.js.map +1 -1
  155. package/dist/runtime/register-consumers.d.ts.map +1 -1
  156. package/dist/runtime/register-consumers.js +12 -16
  157. package/dist/runtime/register-consumers.js.map +1 -1
  158. package/dist/runtime/start-worker-pool.d.ts.map +1 -1
  159. package/dist/runtime/start-worker-pool.js +5 -1
  160. package/dist/runtime/start-worker-pool.js.map +1 -1
  161. package/dist/runtime/startup-warnings.d.ts +8 -0
  162. package/dist/runtime/startup-warnings.d.ts.map +1 -0
  163. package/dist/runtime/startup-warnings.js +26 -0
  164. package/dist/runtime/startup-warnings.js.map +1 -0
  165. package/dist/server/bootstrap.d.ts +1 -1
  166. package/dist/server/bootstrap.d.ts.map +1 -1
  167. package/dist/server/bootstrap.js +49 -23
  168. package/dist/server/bootstrap.js.map +1 -1
  169. package/dist/testing/e2e.d.ts.map +1 -1
  170. package/dist/testing/e2e.js +4 -1
  171. package/dist/testing/e2e.js.map +1 -1
  172. package/dist/translations/index.d.ts +4 -0
  173. package/dist/translations/index.d.ts.map +1 -1
  174. package/dist/translations/index.js +12 -1
  175. package/dist/translations/index.js.map +1 -1
  176. package/dist/translations/status.d.ts +24 -0
  177. package/dist/translations/status.d.ts.map +1 -0
  178. package/dist/translations/status.js +35 -0
  179. package/dist/translations/status.js.map +1 -0
  180. package/dist/types/capability.d.ts +5 -0
  181. package/dist/types/capability.d.ts.map +1 -1
  182. package/dist/types/config.d.ts +11 -0
  183. package/dist/types/config.d.ts.map +1 -1
  184. package/dist/types/context.d.ts +37 -1
  185. package/dist/types/context.d.ts.map +1 -1
  186. package/dist/worker/bootstrap.d.ts.map +1 -1
  187. package/dist/worker/bootstrap.js +25 -37
  188. package/dist/worker/bootstrap.js.map +1 -1
  189. package/dist/worker/index.d.ts +1 -1
  190. package/dist/worker/index.d.ts.map +1 -1
  191. package/dist/worker/index.js +1 -1
  192. package/dist/worker/index.js.map +1 -1
  193. package/instructions/README.md +38 -0
  194. package/instructions/ai.md +68 -20
  195. package/instructions/api.md +2 -0
  196. package/instructions/capabilities.md +19 -1
  197. package/instructions/cli.md +68 -2
  198. package/instructions/events.md +2 -0
  199. package/instructions/framework.md +5 -1
  200. package/instructions/governance.md +2 -0
  201. package/instructions/patterns.md +1 -1
  202. package/instructions/peer-dependencies.md +17 -5
  203. package/instructions/prompts.md +84 -0
  204. package/instructions/security.md +27 -15
  205. package/instructions/testing.md +45 -32
  206. package/instructions/translations.md +3 -3
  207. package/package.json +5 -4
package/CHANGELOG.md ADDED
@@ -0,0 +1,400 @@
1
+ # @plumbus/core changelog
2
+
3
+ ## 0.6.6
4
+
5
+ ### Breaking behavior changes
6
+
7
+ - **`plumbus translation status` exit code** — exits non-zero when any locale is incomplete (including `--json`). Previously incomplete locales printed a warning but exited 0. Aligns with docs that already recommend wiring the command into CI; update scripts that assumed exit 0.
8
+
9
+ ### Added
10
+
11
+ - **`computeStatus` / `formatTranslationStatus`** — shared translation coverage util (exported from `@plumbus/core`); used by `plumbus translation status` and `plumbus ui generate`.
12
+ - **`plumbus ui generate --skip-locale-parity`** — by default, generate refuses incomplete locale coverage (`exit 1`); the flag warns and continues.
13
+
14
+ ### Changed
15
+
16
+ - **`plumbus ui generate` / `ui nextjs`** — no longer mirror modules into `.plumbus/generated/ui` when writing to a real frontend out-dir. That path remains only the last-resort default when no frontend directory is detected (or when `--out-dir` points there explicitly).
17
+
18
+ ## 0.6.5
19
+
20
+ ### Breaking behavior changes
21
+
22
+ Contract-first defaults — no framework-wide legacy mode. Escape hatches are per-app opt-outs; see [Migration stance](../../docs/upgrading-contract-alignment.md#migration-stance-locked).
23
+
24
+ - **Transactional outbox default ON (A1)** — `action` and `eventHandler` capabilities now run handler + output validation inside a single database transaction so entity writes and `ctx.events.emit()` outbox rows commit or roll back together. Auto-excluded: `kind: 'job'`, `effects.ai: true`, non-empty `effects.external`. Nested failures inside an active transaction re-throw to roll back the parent scope; `ctx.flows.start()` and `ctx.jobs.enqueue()` inside a transaction defer until commit (pre-allocated ids). Nested success capability audits defer until commit. Opt out globally with `execution.transactionalOutbox: false` (or `PLUMBUS_TRANSACTIONAL_OUTBOX=false`), or per capability with `transactional: false`. Migration: [Upgrading for contract alignment](../../docs/upgrading-contract-alignment.md#1-transactional-outbox-default-on-a1).
25
+
26
+ - **`plumbus api validate` governance signals are advisory** — the command exits 1 only on hard contract findings (manifest, policy, path params, fixtures). Governance rule signals are printed but no longer fail the command unless you pass `--fail-on-governance`. Aligns with the advisory-only governance model. Migration: [Upgrading for contract alignment](../../docs/upgrading-contract-alignment.md#2-plumbus-api-validate-and-governance-signals-a4).
27
+
28
+ - **AI security `mode: 'block'`** — when `aiProviders.security` or `AI_SECURITY_*` env is configured and `mode` is `block`, classified fields at the warn threshold abort the AI call instead of being redacted. Without explicit security config, classified fields are not scanned. Migration: [Upgrading for contract alignment](../../docs/upgrading-contract-alignment.md#12-ai-security-mode-block-vs-redact-a2).
29
+
30
+ ### Added
31
+
32
+ - **`aiProviders.security` (opt-in)** — `AISecurityConfig` on multi-provider AI config (`mode`, `warnThreshold`, `redactThreshold`, auto-populated `entities` from the entity registry when security is enabled). Wired through server, worker, and MCP bootstraps only when configured.
33
+
34
+ - **Structured log masking (A18)** — `maskKeys` on `StructuredLoggerConfig`, exported `getMaskedFields` / `collectMaskedFieldsFromEntities`, and `withLogMasking()` wrapper. Bootstraps derive mask keys from entity field metadata (`maskedInLogs` and sensitive classifications). Redacted values use `***MASKED***` (deep/nested key walk).
35
+
36
+ - **Consumer encryption key wiring** — API server, worker pool, flow-runner, and event/job consumer contexts pass `PLUMBUS_ENCRYPTION_KEY` into `wireContextDependencies` so `encrypted: true` fields decrypt in handlers.
37
+
38
+ - **`ctx.jobs.enqueue`** — when `jobQueue` is configured on `createServer`, handlers can enqueue job capabilities via `ctx.jobs.enqueue(name, input)`; calls inside a transactional outbox defer until commit (same as `ctx.flows.start`). Returns a pre-allocated job id immediately so handlers can `await` without deadlocking the transaction; the queue write runs after commit.
39
+
40
+ - **Structured data/AI errors** — repository tenant/RETURNING failures, encryption config/payload errors, job dispatch validation, and AI security/budget blocks now throw `PlumbusError` subclasses with stable `code` values.
41
+
42
+ - **ServerConfig.logger** — custom loggers passed to `createServer()` are now used for per-request `ctx.logger` (with masking), not only bootstrap messages.
43
+
44
+ - **Field encryption at rest (A3)** — AES-256-GCM via `PLUMBUS_ENCRYPTION_KEY`; repository encrypts/decrypts `encrypted: true` string fields with plaintext fallback for legacy rows.
45
+
46
+ - **Per-request locale resolution (A17)** — `resolveRequestLocale()` in the route generator reads `plumbus-ui-locale` cookie then `Accept-Language`; resolved locale is passed on `DependencyOptions` into `ctx.translations`.
47
+
48
+ ### Behavior fixes
49
+
50
+ - **Encrypted-field queries rejected** — when `PLUMBUS_ENCRYPTION_KEY` is set, `findMany`/`count` filters, `orderBy`, and `dateFilters` on `encrypted: true` fields throw `DataValidationError` instead of silently matching or sorting ciphertext.
51
+
52
+ - **Deferred post-commit isolation** — post-commit flow/job/audit callbacks catch and log failures individually so a throwing deferred start does not fail the already-committed capability or skip remaining deferred work.
53
+
54
+ - **Audit-record masking** — repository audit payloads use deep masking with token `***` (structured logs remain `***MASKED***`).
55
+
56
+ - **Nested capability audits** — failure audits record immediately inside nested transactions; success audits defer until parent commit.
57
+
58
+ - **Deferred flow ids** — `ctx.flows.start()` inside a transaction returns the same execution id created after commit.
59
+
60
+ - **LLM inside open transaction** — first nested invoke of an `effects.ai: true` capability inside an active transaction emits a one-time `ctx.logger.warn` that the parent transaction is held open for the LLM call.
61
+
62
+ - **HTTP event causation** — capability-triggered HTTP emits restore dynamic `causationId` from the executing capability.
63
+
64
+ - **`plumbus mcp serve` logs** — capability request logs are structured JSON at `info` minimum level (debug suppressed).
65
+
66
+ - **`maskedInLogs` in structured log metadata (A18)** — capability request loggers redact masked entity field names in metadata (token `***MASKED***`, nested objects included). Escape hatch: custom logger without `maskKeys`, or omit sensitive keys from metadata.
67
+
68
+ - **`encryptFieldValue('')` round-trip** — empty plaintext no longer produces an undecryptable ciphertext blob.
69
+
70
+ - **Invalid `AI_SECURITY_*_THRESHOLD` env values** — bogus thresholds are ignored with a startup warning instead of matching every classified field.
71
+
72
+ ## 0.6.4
73
+
74
+ ### Added
75
+
76
+ - **`defineTranslation()` typecheck key consistency** — for literal / `as const` message catalogs, TypeScript now rejects locales that do not share the same key set (native diagnostics on the locale attribute). Runtime import-time validation is unchanged. Apps with existing key drift may start failing `tsc` even though they still throw at import time today.
77
+
78
+ ## 0.6.3
79
+
80
+ ### Added
81
+
82
+ - **`QueryOptions.search`** — OR-of-ILIKE across named entity columns for free-text search (usable via `findMany`/`count`). LIKE metacharacters (`%`, `_`, `\`) in the term are escaped, so the term matches literally rather than as a wildcard pattern.
83
+ - **`QueryOptions.in`** — SQL `IN` filter (empty arrays ignored).
84
+ - **`QueryOptions.notEq`** — SQL `<>` filter. Under SQL three-valued logic, rows whose column is `NULL` are excluded (matching `<>` semantics); the in-memory test repository mirrors this.
85
+ - **Multi-column `QueryOptions.orderBy`** — now accepts a `string` (unchanged) or an array of `{ column, dir? }` sort specs. A spec that omits `dir` falls back to the top-level `orderDir` (then defaults to `desc`).
86
+ - **`count`** options widened to accept `search`/`in`/`notEq` so totals match filtered `findMany` queries.
87
+ - **`createInMemoryRepository` parity** — the in-memory test double applies `search` (literal, case-insensitive), `in`, `notEq` (NULL-excluding), and multi-column `orderBy` with the same semantics as the SQL repository.
88
+ - **`plumbus ui generate --server-locale-cookie`** — pass-through to `@plumbus/ui` for opt-in server-side locale resolution from the `plumbus-ui-locale` cookie.
89
+
90
+ Additive and backward-compatible: no methods were added to or removed from the public `Repository` interface, and existing `findMany`/`count` behavior is identical for callers that do not pass the new option keys.
91
+
92
+ ## 0.6.1
93
+
94
+ ### Added
95
+
96
+ - **`plumbus translation new --locale-folders`** — scaffold per-locale message files under `app/translations/en/` and `app/translations/he/` with a thin `defineTranslation()` assembler.
97
+ - **`plumbus ui generate --split-locale-bundles`** — pass-through to `@plumbus/ui` to emit per-locale i18n bundles under `i18n/locales/`.
98
+
99
+ ## 0.6.0
100
+
101
+ ### Breaking
102
+
103
+ - **`AICostRecord.operation` union widened** — the type now includes `transcribe`, `synthesize`, and `transport` in addition to `generate`, `extract`, `classify`, and `embed`. Update exhaustive `switch` statements, persisted filters, and dashboards that assume the previous four-value union.
104
+
105
+ ### Added
106
+
107
+ - **Voice/media cost operations** — `AICostRecord.operation` now also supports `transcribe`, `synthesize`, and `transport`, and cost rows can carry optional `mediaUsage` (`audioInputSeconds`, `audioOutputSeconds`, `characters`, `connectionMinutes`, `participantMinutes`).
108
+ - **`ctx.ai.recordProviderCost(entry, costContext?)`** — public AI service method for recording provider-side spend when a workload does not flow through `generate*`, `extract`, or `classify` (for example STT/TTS/realtime transport). It uses the same in-memory tracker and `onAICostRecorded` hook path as text AI calls.
109
+ - **`ctx.ai.checkProviderCostBudget({ estimatedTokens?, estimatedCostUsd? })`** — pre-check shared daily/per-request budgets before voice/media provider work.
110
+ - **Media-aware budget pre-checks** — `CostTracker.checkBudget()` now accepts `estimatedCostUsd` so voice/media layers can pre-check shared daily USD caps before opening a session or issuing a provider call.
111
+
112
+ ### Upgrading
113
+
114
+ - Voice/media integrations should call `ctx.ai.recordProviderCost(...)` instead of importing AI-service internals or maintaining a separate ledger path.
115
+ - See [`docs/ai/ai-integration.md`](../../docs/ai/ai-integration.md#upgrading-to-plumbuscore-060) for ledger and budget migration notes.
116
+
117
+ ## 0.5.0
118
+
119
+ ### Added
120
+
121
+ - **Workers and queues runtime** — unified bootstrap with `PLUMBUS_RUNTIME_ROLE` (`all`, `api`, `worker`), three logical queues (`events`, `flows`, `jobs`), and `plumbus worker start` for split deployments.
122
+ - **`job_executions` table** — durable job status, auth snapshot at dequeue, and `GET /api/jobs/:jobId` for polling completion.
123
+ - **`eventHandler` auto-registration** — optional `trigger: { event, versionConstraint? }` on `defineCapability`; worker pool wires consumers when set. Manual `ConsumerRegistry` registrations still take precedence for the same id.
124
+ - **Optional peer dependencies** — `redis` (durable queues) and `cron-parser` (scheduled flow triggers); in-memory fallbacks with startup warnings when missing.
125
+ - **CLI** — `plumbus worker` (health/ready/metrics), `plumbus events` ops (replay, dead-letter), `plumbus flow dead-letter`.
126
+ - **Runtime exports** — `resolveRuntimeQueues`, `registerCapabilityConsumers`, `dispatchQueuedJob`, `createJobService`, `registerJobStatusRoute`, `RuntimeRole`, and related helpers.
127
+ - **Governance** — advisory rules for split deploy without worker, missing `trigger.event`, and job payload compatibility.
128
+ - **`effects.capabilities` + `ctx.capabilities.invoke`** — sanctioned synchronous capability-to-capability composition with declared dependencies, cycle detection, and runtime `dependencyViolation` enforcement.
129
+ - **Flow auth snapshot** — `flow_executions.auth_snapshot_json` stores the caller's `AuthContext` at start; step execution restores roles/scopes from the snapshot (not worker `system` auth).
130
+ - **`dependencyViolation` error code** — undeclared invoke targets, cycles, missing capabilities, and synchronous job invoke attempts return structured `400` errors with actionable metadata.
131
+
132
+ ### Breaking
133
+
134
+ - **Canonical capability names only** — registry keys, flow `step.capability`, `effects.capabilities`, `ctx.capabilities.invoke`, generated `RegisteredCapabilityName`, `capability-graph.md`, and MCP manifest tool names use `<domain>.<capabilityName>` (e.g. `billing.approveRefund`). Short local names (`approveRefund`) are no longer valid references outside `defineCapability({ name })`.
135
+ - **Flow step auth** — user-triggered flows no longer auto-inject the `system` role on every step. Steps run under the stored auth snapshot; capabilities must list the caller's actual roles (or `public`) — not rely on implicit `system` elevation.
136
+ - **Job blocking in flows and invoke** — `kind: 'job'` capabilities cannot run synchronously inside flow steps or via `ctx.capabilities.invoke`; use job dispatch, events, or async consumers instead.
137
+ - **Handler `__runtime` invoker stripping** — `invokeCapability`, `resolveCapability`, and `invocationEmitScope` are no longer exposed on handler-visible `ctx.__runtime`; use `ctx.capabilities.invoke` only.
138
+
139
+ ### Changed
140
+
141
+ - **Worker pool gating** — `plumbus dev` / `plumbus start` start background workers when the app defines events, `eventHandler` or `job` capabilities, or scheduled flows (not only event-triggered flows).
142
+ - **HTTP `kind: 'job'`** — when the API wires `jobQueue` (any job capability on `plumbus dev` / `plumbus start`, including `PLUMBUS_RUNTIME_ROLE=api` without a worker), routes return **202** with `{ data: { jobId, status: "accepted" } }` and enqueue via the jobs queue (previously ran synchronously with **200** because `jobQueue` was not wired on the server).
143
+ - **Job dispatch** — jobs publish to the dedicated **jobs** queue with a `JobQueuePayload` envelope, not the events queue.
144
+ - **Event handler security** — dequeue uses tenant binding from `event_outbox` (fail-closed); trusted replay via `plumbus events` ops.
145
+
146
+ ### Upgrading
147
+
148
+ See `docs/upgrading-workers.md` in the Plumbus monorepo (not shipped in the npm `instructions/` bundle). Required steps for most apps:
149
+
150
+ ```bash
151
+ plumbus migrate generate && plumbus migrate apply
152
+ ```
153
+
154
+ Apps with `kind: 'job'` HTTP clients must poll `GET /api/jobs/:jobId` instead of expecting a synchronous **200** body. Split production deploys need Redis (`pnpm add redis`) and a `plumbus worker` process.
155
+
156
+ For canonical capability names, `effects.capabilities`, and invoke policy, see `docs/upgrading-capability-names.md` in the Plumbus monorepo (not shipped in the npm `instructions/` bundle). Consumer apps also ship `instructions/upgrading-0.5-capabilities.md` (agent-facing checklist). Summary:
157
+
158
+ 1. Update flow `step.capability`, `effects.capabilities`, and `ctx.capabilities.invoke` strings to `<domain>.<name>`.
159
+ 2. Run `plumbus generate` to refresh `RegisteredCapabilityName`, `mcp-manifest.json`, and `capability-graph.md`.
160
+ 3. Run `plumbus verify` — `architecture.non-canonical-capability-reference` and related dependency rules flag stale references.
161
+ 4. Run `plumbus migrate generate && plumbus migrate apply` if upgrading to the `auth_snapshot_json` column for flow executions.
162
+
163
+ ### Developer experience
164
+
165
+ - **Consumer AI guidance — 0.5 capability upgrade** — new `instructions/upgrading-0.5-capabilities.md` (canonical names, invoke policy, flow auth snapshot, migration checklist). `plumbus init` wires it into Copilot, Cursor, and AGENTS.md. `AGENT_WIRING_VERSION` bumped to **7**. Run `plumbus init --patch` on existing projects.
166
+
167
+ ### Non-breaking (default topology)
168
+
169
+ - `plumbus dev` and `plumbus start` default to **`PLUMBUS_RUNTIME_ROLE=all`** — API and workers remain colocated.
170
+ - In-memory queues remain the default when Redis is not configured.
171
+ - `eventHandler` capabilities without `trigger.event` behave as before (manual registration only).
172
+ - MCP job tasks without a durable Redis queue still execute in-process.
173
+
174
+ ## 0.4.2
175
+
176
+ ### Added
177
+
178
+ - **Partner API exposure** — optional `exposeAs: ['api']` and inline `api` metadata on `defineCapability` (operationId, method, path, stability, auth scopes, idempotency, test intent).
179
+ - **`@plumbus/api`** — optional peer dependency (version-locked `0.1.x`). Install with `pnpm add @plumbus/api` for manifest validation, OpenAPI/docs export, compatibility diff, test fixtures, and `registerApiRoutes()`.
180
+ - **CLI `plumbus api`** — `validate`, `generate openapi`, `generate docs`, `diff`, `test-fixtures validate`. Commands lazy-load `@plumbus/api` and print an install hint when the package is missing.
181
+ - **API governance** — advisory rules in `plumbus verify` for partner API surface (missing descriptions, public+test conflicts, etc.).
182
+ - **Consumer AI guidance includes partner API** — `plumbus init` wires `@plumbus/api/instructions/*` and `instructions/api.md`. `AGENT_WIRING_VERSION` bumped to **6**.
183
+ - **Flow docs** — convention for passing large payloads by reference through flow state (entity id, not inline blobs).
184
+ - **Ecosystem READMEs** — sibling packages (`@plumbus/mcp`, `@plumbus/ui`, `@plumbus/chat`, `@plumbus/chat-ui`, `@plumbus/knowledge-base`, `@plumbus/browser-extension`) patch-bumped so npm READMEs list `@plumbus/api`.
185
+
186
+ ### Upgrading existing projects
187
+
188
+ After `pnpm add @plumbus/api`, refresh agent wiring if your project predates the current template:
189
+
190
+ ```bash
191
+ plumbus init --patch --agent agents-md # or: plumbus init --patch
192
+ plumbus doctor
193
+ ```
194
+
195
+ ### Non-breaking
196
+
197
+ - Capabilities without `exposeAs: ['api']` behave identically on convention routes and in tests.
198
+ - Upgrading `@plumbus/core` does **not** install `@plumbus/api`; install it explicitly when you want a partner-facing API.
199
+
200
+ ## 0.4.0
201
+
202
+ ### Added
203
+
204
+ - **MCP exposure** — optional `exposeAs: ['mcp']` and `mcp?: { description?, dangerous?, agentTags? }` on capabilities; validation when MCP-exposed; `isMcpExposed()` helper.
205
+ - **`@plumbus/core/mcp`** — `buildMcpManifest`, `renderSkillFile`; `plumbus generate` writes `mcp-manifest.json` and `skills/<domain>/<kebab>.md`.
206
+ - **`zodInputToJsonSchema()`** — exported from `@plumbus/core` for MCP/OpenAPI-style JSON Schema from Zod inputs.
207
+ - **`@plumbus/mcp`** — separate, optional runtime package. Declared as an optional peer dependency of `@plumbus/core` (version-locked `0.4.x`). Install with `pnpm add @plumbus/mcp` when you want to serve capabilities to AI agents; `@plumbus/core` works without it.
208
+ - **CLI `plumbus mcp`** — `serve` (stdio / HTTP), `generate`, `list-tools`. `serve` lazy-loads `@plumbus/mcp` and prints a friendly install hint if the package is missing.
209
+ - **`PlumbusConfig.mcp.agents`** — static agent token map for MCP auth (see `docs/mcp/agent-authentication.md`).
210
+ - **Governance** — advisory rule for MCP-exposed capabilities missing agent-facing descriptions.
211
+ - **Consumer AI guidance includes MCP** — `plumbus init` now wires a new `instructions/mcp.md` reference into Copilot, Cursor, and AGENTS.md so coding agents in consumer projects discover `exposeAs: ['mcp']`, `plumbus mcp serve`, and agent auth. Scaffolded capabilities include a commented-out MCP block as a discoverable next step. `AGENT_WIRING_VERSION` bumped to 3.
212
+
213
+ ### Upgrading existing projects
214
+
215
+ If you ran `plumbus init` on an earlier version, your `.cursor/rules/`, `.github/copilot-instructions.md`, and `AGENTS.md` files were generated against `AGENT_WIRING_VERSION` 2 and do not reference the new MCP instruction. To pick up the MCP guidance (and any future framework-managed additions), run:
216
+
217
+ ```bash
218
+ plumbus init --patch # replaces only the Plumbus-managed block; preserves your edits outside the markers
219
+ # or
220
+ plumbus agent sync # same as --patch plus refreshes .plumbus/briefs/project.md
221
+ ```
222
+
223
+ Use `--dry-run` to preview, or `--force` to replace the entire file.
224
+
225
+ ### Non-breaking
226
+
227
+ - Capabilities without `exposeAs: ['mcp']` behave identically on HTTP and in tests.
228
+ - Upgrading `@plumbus/core` does **not** install `@plumbus/mcp`; install it explicitly when you want MCP support.
229
+ - `plumbus init --patch` only replaces content between the `plumbus:agent-wiring` markers — user-written content outside those markers is preserved.
230
+
231
+ ## Unreleased — security hardening
232
+
233
+ ### Security
234
+
235
+ - **Flow conditions** use a sandboxed expression evaluator (`evaluateFlowCondition`) instead of `new Function` (no arbitrary JS).
236
+ - **`auth.internal` removed as a god-mode bypass** — flow engine uses the `system` role; capabilities must list `system` in `access.roles` (included in scaffold).
237
+ - **`define*()` outputs are deep-frozen** (nested plain objects/arrays); Zod schemas and handlers are not frozen.
238
+ - **HTTP/SSE errors** expose only whitelisted `metadata` keys (`field`, `hint`, `reason`, `docUrl`, `httpStatus`, `retryAfter`, …); internal errors return a generic message.
239
+ - **CLI `.env` load** only runs inside a Plumbus project (`config/app.config.ts` or `plumbus.config.*`).
240
+ - **AI env providers** limited to `openai` and `anthropic` only; local Ollama uses `AI_OPENAI_BASE_URL` (no URL validation).
241
+ - **`translation import`** rejects paths outside the project root.
242
+ - **Workers** no longer set `bypassTenantScope` when `tenantId` is absent.
243
+ - **JWT adapter** requires secrets ≥ 32 characters.
244
+ - **Hook failures** (`onCapabilityError`, `onAICostRecorded`, process error hooks) are logged instead of swallowed.
245
+
246
+ ### Fixed
247
+
248
+ - AI explainability `validation.passed` reflects whether validation succeeded on the first attempt.
249
+ - `define*()` validation throws `PlumbusError` with `code: validation`.
250
+
251
+ ### Developer experience
252
+
253
+ - **`AGENT_WIRING_VERSION` 4** — `plumbus init` references `@plumbus/knowledge-base/instructions/*` (conventions, defining-sources, providers, chat-integration, testing, README) alongside core, UI, and chat. Run `plumbus init --patch` to refresh existing agent wiring files.
254
+ - Centralized `ErrorHints` / `ErrorDocUrls` for flow conditions, tenant denials, and CLI messages.
255
+ - `DatabaseConnection` + `resolveDatabaseConnection()` used by `plumbus start` / `plumbus dev`.
256
+ - Migration snapshot parsing covered by unit tests (`migrate-snapshot-schema`).
257
+
258
+ ### Migration notes
259
+
260
+ | Change | Action |
261
+ |--------|--------|
262
+ | Flow `if` expressions | Use `state.field` comparisons (`state.amount > 100`). `ctx.state.*` is normalized automatically. No method calls or arbitrary JS. |
263
+ | `AI_OLLAMA_*` / other `AI_*_API_KEY` | Use `AI_OPENAI_API_KEY` + `AI_OPENAI_BASE_URL=http://…/v1` |
264
+ | Capabilities called from flows | Ensure `access.roles` includes `"system"` |
265
+ | `auth.secret` shorter than 32 chars | Lengthen to ≥ 32 characters (HS256 key strength); `createJwtAdapter` now throws on shorter secrets |
266
+ | Custom `AI_*` providers in env | Only `openai` and `anthropic` are registered |
267
+ | Relying on missing `tenantId` + cross-tenant data in flows | Provide `tenantId` on flow execution or use `access.tenantScoped: false` for admin capabilities |
268
+
269
+ ## 0.3.0
270
+
271
+ ### Upgrade checklist
272
+
273
+ Read this before bumping to 0.3.0 — there is one mandatory step.
274
+
275
+ 1. **Run migrations.** 0.3.0 adds `lease_owner` and `lease_expires_at` columns
276
+ (plus a `flow_exec_lease_idx` index) to `flow_executions` to support
277
+ lease-based claiming. Workers refuse to start until these exist; the
278
+ startup preflight emits an actionable error pointing at this checklist.
279
+
280
+ plumbus migrate generate
281
+ plumbus migrate apply
282
+
283
+ 2. **`AIIncompleteOutputError` is now thrown when a structured-output call
284
+ hits `finish_reason === 'length'` / `'max_tokens'`.** Free-text prompts
285
+ (no `responseSchema`, no `responseFormat: 'json'`) return the partial
286
+ content as before — no behavior change. If you catch this error and
287
+ re-issue with a higher `maxTokens`, no migration is needed.
288
+
289
+ 3. **`AICostRecord` now carries `status` (default `'success'`) and an
290
+ optional `fallbackUsed` boolean.** Reading code is unaffected. If you
291
+ construct `AICostRecord` literals (custom tracker, test fixture), set
292
+ `status` explicitly. The `operation` field keeps the original union —
293
+ `'generate' | 'extract' | 'classify' | 'embed'` — so exhaustive
294
+ `switch` statements continue to compile.
295
+
296
+ 4. **New typed errors exported**: `AIValidationError`,
297
+ `AIIncompleteOutputError`, `AIRefusalError`, `LeaseLostError`,
298
+ `FlowCancelledError`. All extend `Error`; existing `catch` blocks are
299
+ unaffected. The previous "AI output validation failed after N attempts"
300
+ `Error` is now this typed subclass.
301
+
302
+ 5. **Failed AI calls now count toward `dailyCostLimit`.** Sunk provider
303
+ spend on validation-retry loops is real spend; tight ceilings may deny
304
+ retries sooner on failure-heavy workloads. Set `dailyCostLimit` with
305
+ headroom, or install `onAICostRecorded` to persist a ledger and tune.
306
+
307
+ 6. **Default AI request timeout remains 120_000 ms.** Set
308
+ `AIProviderConfig.requestTimeout` if your prompts need longer.
309
+
310
+ ### Added
311
+
312
+ - `AICostContext` type (in `@plumbus/core` ai module barrel) — optional
313
+ per-call billing metadata (`projectId`, `serviceArea`, `operationName`,
314
+ `relatedEntityType`, `relatedEntityId`) you can pass to every
315
+ `ctx.ai.generate*` / `ctx.ai.extract` / `ctx.ai.classify` /
316
+ `ctx.ai.streamGenerate` call.
317
+ - `AIServiceConfig.onAICostRecorded` and
318
+ `ServerConfig.onAICostRecorded(record, costContext, db)` hooks — fired
319
+ after every AI call completes (success *or* failure) and the in-memory
320
+ cost tracker has been updated. Use this to persist a ledger row per
321
+ provider round-trip so sunk spend on retries is visible.
322
+ - `AICostRecord.status: 'success' | 'failed' | 'refused' | 'incomplete'`
323
+ and `AICostRecord.errorMessage?: string` — new fields on cost records
324
+ so failures are distinguishable from successes.
325
+ - `AICostRecord.fallbackUsed?: boolean` — set when the streaming call
326
+ fell back to a non-streaming retry after the streamed output failed
327
+ validation; both attempts are billed, so this flag is the signal for
328
+ duplicate-billing detection.
329
+ - `AICostRecordInput` — explicit input type for `CostTracker.record`,
330
+ keeps `status` optional so pre-0.3.0 call sites keep compiling.
331
+ - `AIValidationError` now carries `usage: TokenUsage`, `model: string`,
332
+ and `provider: string` so failure-path cost recording knows what the
333
+ provider actually billed across the retry loop.
334
+ - **`ChatMessage` type** and optional **`messages`** on `ctx.ai.generate`,
335
+ `ctx.ai.generateWithUsage`, and **`ctx.ai.streamGenerate`**. When `messages`
336
+ is a non-empty array of `{ role: 'user' | 'assistant', content }` turns,
337
+ OpenAI and Anthropic adapters send the thread natively instead of folding
338
+ everything into a single user message built from `prompt`. The rendered
339
+ prompt description (`buildBasePrompt`) is merged into the provider **`system`**
340
+ instruction so per-turn template context is preserved; `prompt` is not used
341
+ as an extra user turn in that mode. Sub-agents and single-turn callers can
342
+ omit `messages` unchanged.
343
+ - Lease-based flow claiming: workers atomically claim flow executions
344
+ with `FOR UPDATE SKIP LOCKED`, hold a lease for the duration of the
345
+ step, and recover crashed-worker rows via expired leases. New
346
+ `flow_executions.lease_owner` / `lease_expires_at` columns.
347
+ - `FlowService.heartbeat()` — extends the current flow execution lease
348
+ from inside a long-running step handler.
349
+ - `ExecutionContext.signal: AbortSignal` and `workerId: string` — set
350
+ inside flow step execution; cooperative cancellation now flows from
351
+ `flows.cancel()` (and lease loss) through to in-flight AI / HTTP calls.
352
+ - Lease-column preflight: `createWorkerPool().start()` probes
353
+ `flow_executions` for the new columns and refuses to start with a
354
+ clear migration prompt when they're missing. Also exported as
355
+ `assertFlowLeaseColumns(db)` for direct use.
356
+
357
+ ### Changed
358
+
359
+ - `costTracker.record(...)` now ALSO fires on the failure path when usage
360
+ is known (e.g. via `AIValidationError.usage`). Previously the in-memory
361
+ tracker only recorded successful calls, which under-counted sunk spend.
362
+ Consumers who configured `budget.dailyCostLimit` will see failed-call
363
+ tokens start contributing to the daily running total. Tight ceilings
364
+ may deny retries sooner on failure-heavy workloads.
365
+ - `AIIncompleteOutputError` is thrown only when the request is in
366
+ structured-output mode (`responseFormat: 'json'` or a `responseSchema`
367
+ is set). Text-mode generations that hit `finish_reason === 'length'`
368
+ return the partial content as in 0.2.x.
369
+ - `applyMigrations(config)` now returns `Promise<MigrationApplyResult>`
370
+ (`{ applied, tags }`) instead of `Promise<void>`. Existing callers
371
+ that ignore the return value are unaffected.
372
+
373
+ ### Migration
374
+
375
+ For consumers upgrading from `0.2.x`:
376
+
377
+ 1. Run `plumbus migrate generate` then `plumbus migrate apply` (mandatory —
378
+ see Upgrade checklist item 1).
379
+ 2. Existing `costTracker.record({ model, provider, usage, cost, ... })`
380
+ calls without `status` keep compiling and default to `'success'`.
381
+ 3. Existing `catch (err) { ... }` blocks reading `err.attempts`,
382
+ `err.rawOutput`, or `err.validationMessage` from `AIValidationError`
383
+ are unaffected — the new fields are additive.
384
+ 4. Existing `ServerConfig` usages without `onAICostRecorded` are
385
+ unaffected — the hook is optional, no hook installed = no behavior
386
+ change.
387
+
388
+ To opt into the new failure-ledger persistence:
389
+
390
+ 1. Pass `costContext: { projectId, ... }` on your `ctx.ai.*` calls.
391
+ 2. Install `onAICostRecorded` in `createServer({ ... })` and write the
392
+ `record` (with its `status`) to your persistent ledger.
393
+
394
+ For chat-style prompts (optional):
395
+
396
+ - Build `messages` from your transcript (roles `user` / `assistant` only)
397
+ and pass it alongside `input` for template substitution. Ensure the
398
+ **last** message is a `user` turn when the model should reply to the latest
399
+ subject input. No code changes required for consumers that never pass
400
+ `messages`.
package/README.md CHANGED
@@ -107,7 +107,7 @@ export const classifyTicket = definePrompt({
107
107
  category: z.enum(["billing", "technical", "general"]),
108
108
  priority: z.enum(["low", "medium", "high"]),
109
109
  }),
110
- systemPrompt: "Classify the support ticket and return structured JSON.",
110
+ system: "Classify the support ticket and return structured JSON.",
111
111
  });
112
112
  ```
113
113
 
@@ -140,16 +140,26 @@ This package ships instruction files that teach AI coding agents (Copilot, Curso
140
140
 
141
141
  ```
142
142
  node_modules/@plumbus/core/instructions/
143
- ├── framework.md # Core abstractions and project structure
144
- ├── capabilities.md # Capability definitions and handlers
145
- ├── entities.md # Entity fields and classifications
146
- ├── events.md # Event emission and outbox pattern
147
- ├── flows.md # Workflow steps and retry logic
148
- ├── ai.md # AI prompts, RAG, cost tracking
149
- ├── security.md # Access policies and tenant isolation
150
- ├── governance.md # Advisory rules and compliance
151
- ├── testing.md # Test utilities and patterns
152
- └── patterns.md # Naming conventions and best practices
143
+ ├── README.md # Index — start here
144
+ ├── guardrails.md # Mandatory framework boundaries and git safety
145
+ ├── framework.md # Core abstractions and project structure
146
+ ├── capabilities.md # Capability definitions and handlers
147
+ ├── entities.md # Entity fields and classifications
148
+ ├── events.md # Event emission and outbox pattern
149
+ ├── flows.md # Workflow steps and retry logic
150
+ ├── prompts.md # Prompt content, system/description, model config
151
+ ├── ai.md # ctx.ai operations, RAG, cost tracking
152
+ ├── translations.md # i18n catalogs and ctx.translations
153
+ ├── security.md # Access policies and tenant isolation
154
+ ├── governance.md # Advisory rules and compliance
155
+ ├── testing.md # Test utilities and patterns
156
+ ├── patterns.md # Naming conventions and best practices
157
+ ├── cli.md # CLI command reference
158
+ ├── mcp.md # Core MCP surface (exposeAs, plumbus mcp *)
159
+ ├── api.md # Core partner API surface (exposeAs: ['api'])
160
+ ├── deployment.md # Production deployment and workers
161
+ ├── peer-dependencies.md # Add-on peer range literals (framework devs)
162
+ └── upgrading-0.5-capabilities.md # 0.5.x capability invocation migration
153
163
  ```
154
164
 
155
165
  Wire them up with `plumbus init --agent all`.
@@ -165,11 +175,11 @@ Full documentation: [github.com/plumbus-framework/plumbus/docs](https://github.c
165
175
  | **`@plumbus/core`** | **You are here.** Foundation — capabilities, entities, events, flows, prompts, translations, runtime, CLI, audit, governance. | Always (required). |
166
176
  | [`@plumbus/ui`](../ui/) | Next.js/React UI — typed API clients, auth helpers, form metadata, scaffolds. | When building a Plumbus web UI. |
167
177
  | [`@plumbus/api`](../api/) | Partner external API — manifest, OpenAPI, docs, compatibility diff, test intent. | Optional peer `0.1.x` — when publishing a documented partner-facing HTTP API. |
168
- | [`@plumbus/mcp`](../mcp/) | MCP runtime — serve capabilities to AI agents (`tools/*`, `tasks/*`, transports). | Optional peer `0.5.x` — when exposing capabilities to MCP clients. |
178
+ | [`@plumbus/mcp`](../mcp/) | MCP runtime — serve capabilities to AI agents (`tools/*`, `tasks/*`, transports). | Optional peer `0.5.x \|\| 0.6.x` — when exposing capabilities to MCP clients. |
169
179
  | [`@plumbus/chat`](../chat/) | Conversational runtime — `defineChat`, policy guards, context sources, streamed events. | Optional peer `0.1.x` — when adding a chat surface. |
170
180
  | [`@plumbus/chat-ui`](../chat-ui/) | React chat UI — hooks and `<ChatPanel />` for the `@plumbus/chat` turn protocol. | Peer of `@plumbus/chat` — when adding a browser chat client. |
171
181
  | [`@plumbus/knowledge-base`](../knowledge-base/) | Knowledge providers — scoped sources, registry, chat `knowledgeContext` integration. | Optional peer of `@plumbus/chat` `0.1.x` — when sharing named knowledge across features. |
172
- | [`@plumbus/voice`](../voice/) | Real-time voice runtime — `defineVoice`, STT/TTS/transport providers, session worker, cost ledger. | Optional peer `0.1.x` — when adding speech I/O (not speech-to-speech); complements `@plumbus/chat` text surfaces. |
182
+ | [`@plumbus/voice`](../voice/) | Real-time voice runtime — `defineVoice`, STT/TTS/transport providers, session worker, cost ledger. | Optional peer `0.3.x` on `@plumbus/core` `0.6.x` — when adding speech I/O (not speech-to-speech); complements `@plumbus/chat` text surfaces. |
173
183
  | [`@plumbus/browser-extension`](../browser-extension/) | Extension scaffolder — WXT Chrome/Firefox project wired to your capabilities. | With `@plumbus/ui` (`0.1.x`) — when shipping a browser extension UI. |
174
184
 
175
185
  ## License