@happyvertical/smrt-ingestion 0.55.7 → 0.55.9

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.
package/dist/proposals.js CHANGED
@@ -1,8 +1,8 @@
1
- import { l as __toESM, r as intakeBindingDigest, s as require_ajv, t as IntakeExecutionService } from "./chunks/execution-CYjtj9_l.js";
1
+ import { l as __toESM, r as intakeBindingDigest, s as require_ajv, t as IntakeExecutionService } from "./chunks/execution-C7sTFXFU.js";
2
2
  import { n as generationSnapshotRead, t as discoveryTransaction } from "./chunks/execution-internal-DWteDHM2.js";
3
3
  import { a as providerIdentity } from "./chunks/extraction-providers-C66ADDVe.js";
4
4
  import { i as proposeDocumentSplits, t as GenerationSnapshotStaleError } from "./chunks/proposal-errors-z24VKWnQ.js";
5
- import { t as IntakeFeedbackService } from "./chunks/feedback-B_NILilH.js";
5
+ import { t as IntakeFeedbackService } from "./chunks/feedback-C3OHD4sA.js";
6
6
  import { executeDecision } from "@happyvertical/smrt-core";
7
7
  //#region src/proposal-validation.ts
8
8
  var import_ajv = /* @__PURE__ */ __toESM(require_ajv(), 1);
package/dist/server.js CHANGED
@@ -681,7 +681,7 @@ var IngestionService = class {
681
681
  return (await this.proposals()).preview(input);
682
682
  }
683
683
  async feedback() {
684
- const { IntakeFeedbackService } = await import("./chunks/feedback-B_NILilH.js").then((n) => n.n);
684
+ const { IntakeFeedbackService } = await import("./chunks/feedback-C3OHD4sA.js").then((n) => n.n);
685
685
  return new IntakeFeedbackService(this.options);
686
686
  }
687
687
  async recordFeedback(input) {
@@ -3,21 +3,21 @@
3
3
  "sensitiveFieldsExcluded": true,
4
4
  "generatedAt": "1970-01-01T00:00:00.000Z",
5
5
  "packageName": "@happyvertical/smrt-ingestion",
6
- "packageVersion": "0.55.7",
6
+ "packageVersion": "0.55.9",
7
7
  "sourceManifestPath": "dist/manifest.json",
8
8
  "agentDocPath": "AGENTS.md",
9
9
  "sourceHashes": {
10
- "manifest": "d2b8807cdaf4690eeff056356bce545f23533df00f482a6fdf220016eafca25d",
11
- "packageJson": "29755f98deeebc0a33df0bd274b0735044fb7e7920d8219b3cb2557a8c3e38ce",
12
- "agents": "0ba8291b29534bbc8e4bd6178bac09d1ca301c3193f89fdec9453bac47bbfbd9",
10
+ "manifest": "f7c8e7cf3727e64a8e35de1abf0d1cfe03c75c00faefebc501b7a7384d21d557",
11
+ "packageJson": "5cb7ffb9651cd0621d55a91e7ee16ae136dd09893a6cb2bb17af5cc2ce89279b",
12
+ "agents": "dea14442054ec1de798cba9be1fbdd955f44b0e4672639cbf3db8101d290c1fb",
13
13
  "moduleDoc:agents/execution.md": "6153206adeea46fee1be57ccc01d171621ffb3dc3a754b3634bfe2ce367e8416",
14
- "moduleDoc:README.md": "be2a2fffb4642c387baef4b45a7f246795c431a98735977702c10c2187ecde83",
14
+ "moduleDoc:README.md": "c95d019573db738fa250b41e9e80527dee376fb9ff17efd6714e4debd4038c68",
15
15
  "moduleDoc:EXTRACTION.md": "b735a25a7be75f3a13f3f9e92b0c25834c1394835c16ccd73a076d5720c14243",
16
16
  "moduleDoc:PROPOSALS.md": "3accad9430e917e65319b7b7708d5c1df277eea7eaa0490df913cf361e80b7bc",
17
- "moduleDoc:FEEDBACK.md": "f834778a8d0c0c86b1667c2eda101c1b9de3c510cd9b42d794110db844b69824",
18
- "moduleDoc:REVIEW.md": "e3418b54de2620cbc761ab6a49e698172424f6e601785b48f156a780746578e9",
17
+ "moduleDoc:FEEDBACK.md": "795337ba256b486ecf0e836c4ad090d12f60c8c31dfb7c83155a8689da3d4dc5",
18
+ "moduleDoc:REVIEW.md": "a64c652cf862e8c064a965231b1cf9a49c4494f9e98fbec171403221dfa8e4b4",
19
19
  "agentSurface:src/test-support/execution.ts": "1df56aaf1a692d822ed45ecb7e50df7d6806977ff3c03f9eeaf171c64f496865",
20
- "agentSurface:src/test-support/proposals.ts": "bcb2d540c4e31517702f55cdbbc11d12f0e7fa4992aad5d89cd44437c4e45c7a"
20
+ "agentSurface:src/test-support/proposals.ts": "260483ad7407191365bfe514f0d1625856f1001c11905299954508d885559497"
21
21
  },
22
22
  "exports": [
23
23
  ".",
@@ -52,6 +52,8 @@
52
52
  "vite": "8.1.4",
53
53
  "vitest": "4.1.10",
54
54
  "@happyvertical/smrt-content": "workspace:*",
55
+ "@happyvertical/smrt-messages": "workspace:*",
56
+ "@happyvertical/email": "catalog:",
55
57
  "@happyvertical/smrt-users": "workspace:*",
56
58
  "@sveltejs/package": "^2.5.8",
57
59
  "@sveltejs/vite-plugin-svelte": "^7.3.0",
@@ -68,6 +70,7 @@
68
70
  "@happyvertical/smrt-content",
69
71
  "@happyvertical/smrt-core",
70
72
  "@happyvertical/smrt-jobs",
73
+ "@happyvertical/smrt-messages",
71
74
  "@happyvertical/smrt-playbooks",
72
75
  "@happyvertical/smrt-tenancy",
73
76
  "@happyvertical/smrt-types",
@@ -77,6 +80,7 @@
77
80
  ],
78
81
  "sdkDependencies": [
79
82
  "@happyvertical/ai",
83
+ "@happyvertical/email",
80
84
  "@happyvertical/ocr",
81
85
  "@happyvertical/pdf",
82
86
  "@happyvertical/sql"
@@ -1590,7 +1594,7 @@
1590
1594
  "polymorphicAssociations": 0,
1591
1595
  "uuidColumns": 46
1592
1596
  },
1593
- "agentDoc": "# @happyvertical/smrt-ingestion\n\nDurable foundation for ADR 0004. `src/models.ts` owns all ingestion tables;\n`src/server.ts` owns authenticated service boundaries and lifecycle primitives.\n`src/execution.ts` owns authoritative review/apply and imports server-only principals.\nSee [execution integration](agents/execution.md) for host transaction guarantees,\ncatalog contracts, deployment dependencies and continuation bindings.\nRoot, `/models`, and `/dto` remain browser-safe; provider/network/filesystem code\nbelongs under `/server`. Generated REST/CLI/MCP model mutation is disabled.\n\nSee [README.md](README.md) for host integration and recovery/deletion operation.\nSee [EXTRACTION.md](EXTRACTION.md) for extraction contracts, provider isolation\nrequirements and corpus validation.\nSee [PROPOSALS.md](PROPOSALS.md) for the optional server-only proposal stage,\ncurrent catalog/candidate authority and immutable source pinning.\n\nAll records require tenant and confidential scope. Hosts create service scopes\nfrom authenticated sessions; source metadata is never authority. Every read and\nwrite rechecks the host scope predicate. Analysis input revisions, attempts,\nproposals, decisions, executions and feedback are append-only except documented\nstate projections and retention redaction. Terminal actions outlive job cleanup.\n\nOnly SQLite and PostgreSQL are supported. Deploy manifest migrations before\nstarting services; runtime performs no application DDL. Storage planning and\npreservation use AssetRuntime/AssetStore public methods. Blob I/O and queue\nsubmission never run inside ingestion database transactions.\n\nValidation: `pnpm test`, `pnpm test:postgres`, `pnpm test:providers`, `pnpm typecheck`, `pnpm build`.\nThe PostgreSQL command provisions a real database and fails if unavailable.\nFixture teardown uses `src/test-support/postgres-cleanup.ts`: only owned\nexec_/ing_/ext_/sources_ names, normal DROP, bounded 55006-only retry. Never\nforce-terminate backends, grant signal privileges, or ignore leaked sessions.\nBuild includes browser import validation. The provider lane exercises local SDK\nadapters and process isolation, without claiming live remote recognition quality.\n`src/svelte` owns transport-neutral review components and browser-safe host callbacks.\nSee [FEEDBACK.md](FEEDBACK.md) for revision-bound explicit feedback, scoped example retrieval,\nprovider-boundary revalidation and authorized routing policy adoption.\nSee [REVIEW.md](REVIEW.md) for authenticated hosts, bounded saved-review reloads,\nassignment ownership, logical split re-extraction and the maintained browser proof.\nUI validation additionally requires `pnpm test:components` and `pnpm test:e2e`;\n`typecheck` includes Svelte and `build` includes the types-first `/svelte` entry.\nThe evaluation command remains reserved for #3677 and fails explicitly.\nSee ../../docs/test-matrix/3670-ingestion-foundation.md for behavior coverage.\n",
1597
+ "agentDoc": "# @happyvertical/smrt-ingestion\n\nDurable foundation for ADR 0004. `src/models.ts` owns all ingestion tables;\n`src/server.ts` owns authenticated service boundaries and lifecycle primitives.\n`src/execution.ts` owns authoritative review/apply and imports server-only principals.\nSee [execution integration](agents/execution.md) for host transaction guarantees,\ncatalog contracts, deployment dependencies and continuation bindings.\nRoot, `/models`, and `/dto` remain browser-safe; provider/network/filesystem code\nbelongs under `/server`. Generated REST/CLI/MCP model mutation is disabled.\n\nSee [README.md](README.md) for host integration and recovery/deletion operation.\nSee [EXTRACTION.md](EXTRACTION.md) for extraction contracts, provider isolation\nrequirements and corpus validation.\nSee [PROPOSALS.md](PROPOSALS.md) for the optional server-only proposal stage,\ncurrent catalog/candidate authority and immutable source pinning.\n\nAll records require tenant and confidential scope. Hosts create service scopes\nfrom authenticated sessions; source metadata is never authority. Every read and\nwrite rechecks the host scope predicate. Analysis input revisions, attempts,\nproposals, decisions, executions and feedback are append-only except documented\nstate projections and retention redaction. Terminal actions outlive job cleanup.\n\nOnly SQLite and PostgreSQL are supported. Deploy manifest migrations before\nstarting services; runtime performs no application DDL. Storage planning and\npreservation use AssetRuntime/AssetStore public methods. Blob I/O and queue\nsubmission never run inside ingestion database transactions.\n\nValidation: `pnpm test`, `pnpm test:postgres`, `pnpm test:providers`, `pnpm typecheck`, `pnpm build`.\nThe PostgreSQL command provisions a real database and fails if unavailable.\nFixture teardown uses `src/test-support/postgres-cleanup.ts`: only owned\nexec_/ing_/ext_/sources_ names, normal DROP, bounded 55006-only retry. Never\nforce-terminate backends, grant signal privileges, or ignore leaked sessions.\nBuild includes browser import validation. The provider lane exercises local SDK\nadapters and process isolation, without claiming live remote recognition quality.\n`src/svelte` owns transport-neutral review components and browser-safe host callbacks.\nSee [FEEDBACK.md](FEEDBACK.md) for revision-bound explicit feedback, scoped example retrieval,\nprovider-boundary revalidation and authorized routing policy adoption.\nSee [REVIEW.md](REVIEW.md) for authenticated hosts, bounded saved-review reloads,\nassignment ownership, logical split re-extraction and the maintained browser proof.\nUI validation additionally requires `pnpm test:components` and `pnpm test:e2e`;\n`typecheck` includes Svelte and `build` includes the types-first `/svelte` entry.\n`pnpm test:evaluation` runs repository evaluation tooling/format/fault contracts.\nMeasured held-out quality is a separate frozen-protocol, budget-gated run; tooling\nsuccess does not establish reference quality or permit automatic actions.\nSee ../../docs/test-matrix/3670-ingestion-foundation.md for behavior coverage.\n",
1594
1598
  "moduleDocs": [
1595
1599
  {
1596
1600
  "path": "agents/execution.md",
@@ -1600,7 +1604,7 @@
1600
1604
  {
1601
1605
  "path": "README.md",
1602
1606
  "module": "README",
1603
- "content": "# @happyvertical/smrt-ingestion\n\nDurable receipt, evidence, analysis attempts and action-journal foundations for\n[ADR 0004](../../docs/adr/0004-application-aware-ingestion.md).\n\nThe root, `/models` and `/dto` entry points are browser-safe. Import\n`IngestionService` from `/server` in trusted host code. Generated REST, CLI and\nMCP access to the persistence models is disabled; hosts expose authorized DTO\nmethods through their authenticated application transport.\n\nBefore starting a service, deploy the package manifest through the public s-m-r-t\nmigration APIs or `smrt db:migrate`. `assertReady()` only checks existing tables.\nSQLite and PostgreSQL are supported; other engines fail construction.\n\nA host supplies a database, AssetRuntime, authenticated tenant/actor/confidential\nscope, a live authorization callback, a registered jobs target, and an idempotent\n`purgeDerived` callback for host-owned previews, retrieval indexes and caches.\nThe authorization callback receives the captured ceiling and the current\ntransaction executor; it must intersect current grants with that ceiling. Never\nconstruct the scope, retention policy or budgets from incoming document labels.\n\n`receive` accepts bounded original byte buffers, with stable source part IDs,\nparent relationships and optional upstream identity/version. Source adapters own\nstreaming and upstream snapshot retrieval. Receipt identity is tenant + source +\ndelivery key; changing bytes or authenticated scope conflicts. Content equality\nin a different conversation does not deduplicate an arrival. The returned item\nID and version are safe acknowledgment data, never a storage URL.\n\nStorage intents contain a stable asset ID and a public AssetStore-planned URI\nbefore byte I/O. Preservation verifies existing bytes instead of replacing them.\nA receipt becomes ready only after every part is durable and its dispatch intent\ncommits. A source retries the same receive call after failure or lost\nacknowledgment. Hosts schedule `repairDispatches` after restart and periodically;\nit repairs missing/failed queue submissions through SmrtJobCollection. The host\njob restores the captured scope and calls the analysis lifecycle methods. Run\nTaskRunner with the `ingestion` queue enabled.\n\n`analyze` appends immutable input/configuration revisions. `claimAnalysis` uses\nleases, monotonic fences and attempt budgets; `completeAnalysis` rejects expired\nor superseded workers. Terminal attempt output/provenance is preserved. Queue\nsubmission budgets also stop repeated handler failures in visible\n`needs_attention`. Reprocessing does not mint actions. `createAction`,\n`publishProposal` and `appendPlan` persist explicit intentions and exact attempt\nbindings for the later review/execution layer. They do not approve or apply\nbusiness operations. Decision/execution/feedback models are persistence\nfoundations; policy, handler expansion, review and business apply belong to the\nlater epic children.\n\n`expire` revokes access and pending work before removing bytes and calling\n`purgeDerived`. Interrupted deletion is retried by `repairDeletions` and\n`sweepRetention`. Minimal receipt/action identities remain, including successful\naction result digests; all content-bearing journal payloads are redacted. Private\ncleanup locators remain in deletion tombstones so repeated sweeps can remove a\nlate stale writer's orphan bytes even after the asset owner row is gone. Source\nadapters must enforce their configured delivery-age cutoff; expired replay IDs\nnever become fresh work. Continue running the cleanup sweep for the retained\nstorage namespace. Upstream source mutation/deletion cannot change copied\noriginals; explicit privacy deletion revokes every ingestion-derived payload and\nrequires host cache/index purge.\n\nSee [EXTRACTION.md](EXTRACTION.md) for bounded extraction, lease-bound input\nsnapshots, provider isolation requirements and the extraction corpus.\n\nValidation commands are `pnpm test`, `pnpm test:postgres`, `pnpm test:providers`, `pnpm typecheck` and\n`pnpm build` (including built browser import inspection). The PostgreSQL lane\nrequires the repository's configured database service and never silently skips.\nThe provider lane exercises local SDK adapters and process isolation; it does not\nclaim live remote recognition quality. Component, e2e and evaluation command names are reserved by the ADR and\nexplicitly unavailable until their owning children deliver the corresponding\ncapability. See the [behavior matrix](../../docs/test-matrix/3670-ingestion-foundation.md).\n\n## Authoritative review and execution\n\nConfigure `IngestionOptions.execution` for policy, immutable previews, authenticated\ndecisions and idempotent domain execution. See [execution integration](agents/execution.md)\nfor the public handler catalog, required host authorization/target locks, deployment\nmigrations and jobs continuation integration. The maintained application reference\nin `reference/handlers.ts` creates draft ContentDocuments and attaches retained\nevidence through public domain APIs; it is not a published runtime adapter.\n\n## Configured source adapters\n\nThe server entry exports `createSourceDeliveryHandler`, `EmailSourceAdapter`,\n`WatchFolderSourceAdapter`, and `createVendorWebhookHandler`. Construct a\n`SourceBinding` from authenticated host configuration: enabled flag, scoped\n`IngestionService`, stable source ID/version, captured authority ceiling,\nretention policy, allowed media types and receipt limits. Re-resolve this binding\nwhen grants/configuration change. Source payloads never supply authority.\n\nThe reference POST handler authenticates before reading bytes and requires\n`Idempotency-Key`. JSON accepts exactly `capturedAt` and one of `text`,\n`structured`, or `reference: { owner: 'asset'|'message', id, version }`.\nThe host's `snapshotReference` must authorize current ownership and return copied\nbytes; an absent snapshot fails rather than acknowledging a mutable locator.\nMultipart accepts one `file` plus `captureId` (equal to the idempotency key),\n`capturedAt`, `captureSource` (`camera`, `native_picker`, `audio`, `document`), and optional\nlowercase SHA-256 `sha256`. This reuses mobile's durable UUID Idempotency-Key,\nMIME-bearing file part and explicit capture metadata convention. Captures retain\noriginal bytes and a parent metadata evidence record. Configure both the wire\nlimit `maxRequestBytes` and receipt `maxBytes`/`maxParts`; include\n`application/json` in the media allowlist for capture/email metadata. Signature\nchecks cover PDF, TIFF, PNG/JPEG/WebP and WAV/Ogg/WebM/MP3/MP4 audio; signature\nacceptance promises preservation, not extraction support or codec validity.\n\nEmail is explicitly opt-in per configured account. `EmailSourceAdapter` takes a\n`readMessage` callback compatible with the messages owner's\n`EmailAccount.readIntakeMessage(providerLookup, maxBytes, imapIdentity?)` snapshot.\nThe provider lookup is Gmail message ID, POP3 UIDL, or IMAP RFC Message-ID; it\nis separate from the delivery dedupe key. IMAP requires `{ folder, uidValidity,\nuid }`: the method selects the mailbox and verifies UIDVALIDITY and returned UID.\nAmbiguous sender IDs resolving to another UID fail explicitly. That method connects,\nfetches the full message including actual attachment bytes, copies the bytes,\nand disconnects. Metadata-only attachments fail explicitly. It never reads an\nattachment path supplied by a provider. A host lists provider deliveries using a\nstable account-specific locator (for IMAP include folder, UIDVALIDITY and UID),\nan explicit revision, and an opaque resumable checkpoint. Same locator/revision\nwith changed bytes conflicts; an explicit new revision creates a new receipt.\nDo not use sender-controlled RFC Message-ID as the sole transport identity.\n`receiveBatch` processes in order and stops at the first failure. The host owns\ndurable checkpoint storage and commits its `acknowledge` callback only after the\nadapter has received accepted/duplicate. If checkpoint persistence fails, retry\nreturns the original receipt. Message/thread/attachment relationships are copied;\ncredentials and arbitrary headers are excluded. The ordinary `syncFrom` metadata\nsync remains separate; `hasAttachments` is never proof of byte preservation.\n\nWatch-folder intake polls only an explicitly configured existing private local\ndirectory. Producers should close their files, preferably publishing with atomic\nrename. Two unchanged size/inode/mtime/ctime observations separated by\n`stabilityMs` are required, and the interval runs again after claim/restart.\nA private `.ingestion-claims/<UUID>/claim.json` intent is synced before atomically\nrenaming the original into that directory. Keep the directory on one filesystem,\nunder the host's ownership; symlink inputs are refused. A file descriptor still\nheld by an uncooperative producer can write after any stability window, so the\nproducer close/publish protocol is required for immutable input. Accepted or\nduplicate receipts move the entire claim to `.ingestion-processed`; do not delete\nclaims to retry. Polling recovers persisted UUIDs after process death, so receipt\nreplay deduplicates ready-without-ack. `failure.json` and poll results expose safe\ncategories while originals remain available. Intent directories without an\noriginal mean death before claim or a competing poll won; the producer original\nhas not been removed. Operators may remove these empty intents after confirming\nno active importer. Keep processed originals according to the host's retention\npolicy. This adapter does not watch arbitrary paths or start background loops.\n\nVendor webhooks use a host `verify(request, originalBytes)` callback after bounded\nraw-body reading. The callback must verify signature, delivery time/replay window\nand account ownership, then return trusted binding and durable delivery identity.\nNo vendor implementation or hardware driver is selected. All adapters invoke\nonly receipt preservation, never domain writes, AI tools or external actions.\n\nSee [PROPOSALS.md](PROPOSALS.md) for bounded application catalog discovery, durable\ninterpretation revisions, optional typed decisions and explicit generated preview.\n\n## Human review\n\nMount the `/svelte` inbox and review components through an authenticated host using\nthe browser-safe `IntakeReviewHost` DTO contract. See [REVIEW.md](REVIEW.md) for\nexact revision-bound callbacks, live evidence access, logical split corrections,\nassignment ownership, and the maintained upload-to-domain-result browser fixture.\n\nOptional explicit feedback and scoped example retrieval are documented in\n[FEEDBACK.md](FEEDBACK.md). Approval and execution outcomes remain separate from\ninterpretation correctness; routing policy adoption is explicit and versioned.\n"
1607
+ "content": "# @happyvertical/smrt-ingestion\n\nDurable receipt, evidence, analysis attempts and action-journal foundations for\n[ADR 0004](../../docs/adr/0004-application-aware-ingestion.md).\n\nThe root, `/models` and `/dto` entry points are browser-safe. Import\n`IngestionService` from `/server` in trusted host code. Generated REST, CLI and\nMCP access to the persistence models is disabled; hosts expose authorized DTO\nmethods through their authenticated application transport.\n\nBefore starting a service, deploy the package manifest through the public s-m-r-t\nmigration APIs or `smrt db:migrate`. `assertReady()` only checks existing tables.\nSQLite and PostgreSQL are supported; other engines fail construction.\n\nA host supplies a database, AssetRuntime, authenticated tenant/actor/confidential\nscope, a live authorization callback, a registered jobs target, and an idempotent\n`purgeDerived` callback for host-owned previews, retrieval indexes and caches.\nThe authorization callback receives the captured ceiling and the current\ntransaction executor; it must intersect current grants with that ceiling. Never\nconstruct the scope, retention policy or budgets from incoming document labels.\n\n`receive` accepts bounded original byte buffers, with stable source part IDs,\nparent relationships and optional upstream identity/version. Source adapters own\nstreaming and upstream snapshot retrieval. Receipt identity is tenant + source +\ndelivery key; changing bytes or authenticated scope conflicts. Content equality\nin a different conversation does not deduplicate an arrival. The returned item\nID and version are safe acknowledgment data, never a storage URL.\n\nStorage intents contain a stable asset ID and a public AssetStore-planned URI\nbefore byte I/O. Preservation verifies existing bytes instead of replacing them.\nA receipt becomes ready only after every part is durable and its dispatch intent\ncommits. A source retries the same receive call after failure or lost\nacknowledgment. Hosts schedule `repairDispatches` after restart and periodically;\nit repairs missing/failed queue submissions through SmrtJobCollection. The host\njob restores the captured scope and calls the analysis lifecycle methods. Run\nTaskRunner with the `ingestion` queue enabled.\n\n`analyze` appends immutable input/configuration revisions. `claimAnalysis` uses\nleases, monotonic fences and attempt budgets; `completeAnalysis` rejects expired\nor superseded workers. Terminal attempt output/provenance is preserved. Queue\nsubmission budgets also stop repeated handler failures in visible\n`needs_attention`. Reprocessing does not mint actions. `createAction`,\n`publishProposal` and `appendPlan` persist explicit intentions and exact attempt\nbindings for the later review/execution layer. They do not approve or apply\nbusiness operations. Decision/execution/feedback models are persistence\nfoundations; policy, handler expansion, review and business apply belong to the\nlater epic children.\n\n`expire` revokes access and pending work before removing bytes and calling\n`purgeDerived`. Interrupted deletion is retried by `repairDeletions` and\n`sweepRetention`. Minimal receipt/action identities remain, including successful\naction result digests; all content-bearing journal payloads are redacted. Private\ncleanup locators remain in deletion tombstones so repeated sweeps can remove a\nlate stale writer's orphan bytes even after the asset owner row is gone. Source\nadapters must enforce their configured delivery-age cutoff; expired replay IDs\nnever become fresh work. Continue running the cleanup sweep for the retained\nstorage namespace. Upstream source mutation/deletion cannot change copied\noriginals; explicit privacy deletion revokes every ingestion-derived payload and\nrequires host cache/index purge.\n\nSee [EXTRACTION.md](EXTRACTION.md) for bounded extraction, lease-bound input\nsnapshots, provider isolation requirements and the extraction corpus.\n\nValidation commands are `pnpm test`, `pnpm test:postgres`, `pnpm test:providers`, `pnpm typecheck` and\n`pnpm build` (including built browser import inspection). The PostgreSQL lane\nrequires the repository's configured database service and never silently skips.\nThe provider lane exercises local SDK adapters and process isolation; it does not\nclaim live remote recognition quality. `pnpm test:components` and `pnpm test:e2e`\ncover the maintained review surface. `pnpm test:evaluation` checks repository\nevaluation tooling contracts; measured held-out quality requires a separately\nfrozen protocol and an approved aggregate provider budget. See the [behavior matrix](../../docs/test-matrix/3670-ingestion-foundation.md).\n\n## Authoritative review and execution\n\nConfigure `IngestionOptions.execution` for policy, immutable previews, authenticated\ndecisions and idempotent domain execution. See [execution integration](agents/execution.md)\nfor the public handler catalog, required host authorization/target locks, deployment\nmigrations and jobs continuation integration. The maintained application reference\nin `reference/handlers.ts` creates draft ContentDocuments and attaches retained\nevidence through public domain APIs; it is not a published runtime adapter.\n\n## Configured source adapters\n\nThe server entry exports `createSourceDeliveryHandler`, `EmailSourceAdapter`,\n`WatchFolderSourceAdapter`, and `createVendorWebhookHandler`. Construct a\n`SourceBinding` from authenticated host configuration: enabled flag, scoped\n`IngestionService`, stable source ID/version, captured authority ceiling,\nretention policy, allowed media types and receipt limits. Re-resolve this binding\nwhen grants/configuration change. Source payloads never supply authority.\n\nThe reference POST handler authenticates before reading bytes and requires\n`Idempotency-Key`. JSON accepts exactly `capturedAt` and one of `text`,\n`structured`, or `reference: { owner: 'asset'|'message', id, version }`.\nThe host's `snapshotReference` must authorize current ownership and return copied\nbytes; an absent snapshot fails rather than acknowledging a mutable locator.\nMultipart accepts one `file` plus `captureId` (equal to the idempotency key),\n`capturedAt`, `captureSource` (`camera`, `native_picker`, `audio`, `document`), and optional\nlowercase SHA-256 `sha256`. This reuses mobile's durable UUID Idempotency-Key,\nMIME-bearing file part and explicit capture metadata convention. Captures retain\noriginal bytes and a parent metadata evidence record. Configure both the wire\nlimit `maxRequestBytes` and receipt `maxBytes`/`maxParts`; include\n`application/json` in the media allowlist for capture/email metadata. Signature\nchecks cover PDF, TIFF, PNG/JPEG/WebP and WAV/Ogg/WebM/MP3/MP4 audio; signature\nacceptance promises preservation, not extraction support or codec validity.\n\nEmail is explicitly opt-in per configured account. `EmailSourceAdapter` takes a\n`readMessage` callback compatible with the messages owner's\n`EmailAccount.readIntakeMessage(providerLookup, maxBytes, imapIdentity?)` snapshot.\nThe provider lookup is Gmail message ID, POP3 UIDL, or IMAP RFC Message-ID; it\nis separate from the delivery dedupe key. IMAP requires `{ folder, uidValidity,\nuid }`: the method selects the mailbox and verifies UIDVALIDITY and returned UID.\nAmbiguous sender IDs resolving to another UID fail explicitly. That method connects,\nfetches the full message including actual attachment bytes, copies the bytes,\nand disconnects. Metadata-only attachments fail explicitly. It never reads an\nattachment path supplied by a provider. A host lists provider deliveries using a\nstable account-specific locator (for IMAP include folder, UIDVALIDITY and UID),\nan explicit revision, and an opaque resumable checkpoint. Same locator/revision\nwith changed bytes conflicts; an explicit new revision creates a new receipt.\nDo not use sender-controlled RFC Message-ID as the sole transport identity.\n`receiveBatch` processes in order and stops at the first failure. The host owns\ndurable checkpoint storage and commits its `acknowledge` callback only after the\nadapter has received accepted/duplicate. If checkpoint persistence fails, retry\nreturns the original receipt. Message/thread/attachment relationships are copied;\ncredentials and arbitrary headers are excluded. The ordinary `syncFrom` metadata\nsync remains separate; `hasAttachments` is never proof of byte preservation.\n\nWatch-folder intake polls only an explicitly configured existing private local\ndirectory. Producers should close their files, preferably publishing with atomic\nrename. Two unchanged size/inode/mtime/ctime observations separated by\n`stabilityMs` are required, and the interval runs again after claim/restart.\nA private `.ingestion-claims/<UUID>/claim.json` intent is synced before atomically\nrenaming the original into that directory. Keep the directory on one filesystem,\nunder the host's ownership; symlink inputs are refused. A file descriptor still\nheld by an uncooperative producer can write after any stability window, so the\nproducer close/publish protocol is required for immutable input. Accepted or\nduplicate receipts move the entire claim to `.ingestion-processed`; do not delete\nclaims to retry. Polling recovers persisted UUIDs after process death, so receipt\nreplay deduplicates ready-without-ack. `failure.json` and poll results expose safe\ncategories while originals remain available. Intent directories without an\noriginal mean death before claim or a competing poll won; the producer original\nhas not been removed. Operators may remove these empty intents after confirming\nno active importer. Keep processed originals according to the host's retention\npolicy. This adapter does not watch arbitrary paths or start background loops.\n\nVendor webhooks use a host `verify(request, originalBytes)` callback after bounded\nraw-body reading. The callback must verify signature, delivery time/replay window\nand account ownership, then return trusted binding and durable delivery identity.\nNo vendor implementation or hardware driver is selected. All adapters invoke\nonly receipt preservation, never domain writes, AI tools or external actions.\n\nSee [PROPOSALS.md](PROPOSALS.md) for bounded application catalog discovery, durable\ninterpretation revisions, optional typed decisions and explicit generated preview.\n\n## Human review\n\nMount the `/svelte` inbox and review components through an authenticated host using\nthe browser-safe `IntakeReviewHost` DTO contract. See [REVIEW.md](REVIEW.md) for\nexact revision-bound callbacks, live evidence access, logical split corrections,\nassignment ownership, and the maintained upload-to-domain-result browser fixture.\n\nOptional explicit feedback and scoped example retrieval are documented in\n[FEEDBACK.md](FEEDBACK.md). Approval and execution outcomes remain separate from\ninterpretation correctness; routing policy adoption is explicit and versioned.\n"
1604
1608
  },
1605
1609
  {
1606
1610
  "path": "EXTRACTION.md",
@@ -1615,12 +1619,12 @@
1615
1619
  {
1616
1620
  "path": "FEEDBACK.md",
1617
1621
  "module": "FEEDBACK",
1618
- "content": "# Explicit ingestion feedback\n\nConfigure `IngestionOptions.feedback` to opt in. The existing `intake_feedback`\nledger owns these records; no new schema, embedding service or provider is added.\n`FeedbackConfiguration` sets a version, maximum examples, scan count, serialized\nbytes and lexical similarity threshold, plus a live scoped authorization callback.\nHard ceilings are 20 examples, 1,000 scanned records and 1 MB. Choose substantially\nsmaller application limits. The proposal's complete serialized request, including\nexamples, must also fit the current minimum application/source/provider budget.\n\n`recordFeedback` accepts the exact displayed action revision, review version and\nbinding hash, an explicit correct/incorrect judgment, optional reason text and a\nrequest ID. The server resolves reviewer, tenant/confidential scope, retained\nsource evidence, extraction/generation versions and current handler arguments.\nA replay returns the same immutable receipt; changed payloads conflict.\n`supersedesId` appends a replacement for the specified prior interpretation\njudgment. A second successor conflicts. Revised actions make old bindings\nineligible. Approval and successful execution never imply that extracted fields\nare correct.\n\nDecision and downstream execution facts are captured inside their owning\ntransaction, keyed by immutable event ID and signal, when the configured capture\nauthority allows the optional memory projection and it fits the configured byte\ncap. Denial or an oversized automatic projection leaves the underlying\nauthoritative decision/outcome intact, including failure and reconciliation.\nExplicit `recordFeedback` and `observeFeedback` requests still reject invalid or\noversized writes; actual database failures still propagate and roll back. Failed/rolled-back domain\nwork and unknown external outcomes remain distinct. `observeFeedback` can replay\nan authorized existing event; it cannot supply a correctness label or fabricate\nan execution result. An initial denial does not mutate retention. Once authorized,\na narrowed privacy ceiling survives business rollback and later revocation.\n\n## Retrieval and provider boundaries\n\n`retrieveFeedback({ itemId, query })` derives the current offered catalog,\ncandidates and model/prompt/configuration versions on the server. Callers cannot\nprovide candidate authority. The deterministic matcher uses lowercase Unicode\nword-set Jaccard similarity (minimum 0.2), then immutable record ID for ties.\nScanning, recursive provenance checks and returned examples are bounded; a limited scan does not promise an\nexhaustive history search. Both positive and negative explicit examples are kept.\n\nEvery selected source must still be readable in the same tenant and confidential\nscope, with its current action/analysis binding, target grants, handler version,\nmodel/prompt/configuration compatibility and retention. Each source's current\nprovider policy must allow the generation recipient and any configured decision\nrecipient; the source owner rechecks that policy on both initial and final live\ncontexts. Receiving checks cover every offered handler, before and after source\nchecks, using each live grant, actual provider recipients and the narrowest byte\nceiling. Both retrieval and reference revalidation budget the full reconstructed\nexamples. A receiving item's provider grant cannot substitute for a source grant.\nSuperseded, revoked, deleted or incompatible sources are excluded. Current explicit human corrections\ntake precedence: a generation carrying one does not retrieve learned examples.\n\nFull examples exist only in the authorized provider request. The SDK proposal\nadapter includes that typed selection in its serialized user message when\npresent; disabled feedback leaves the original request shape unchanged. Saved generation\nprovenance contains the receiving query, selection configuration digest and\nimmutable feedback IDs/digests, not copied source example content. Selected\nreferences are rechecked before generation, capability probing, decision calls,\npublication and completed-result reads. A newly added example does not invalidate\nan older selection; a revoked or superseded selected example does. Feedback\nlineage is bounded and fails closed. Saved-action reads and pending decisions,\nautomatic authorization, preview publication/replay and execution also revalidate\nselected lineage under the\nowning transaction. Revoking, deleting or superseding a selected example blocks\npending actions; regenerate their proposals and obtain fresh approval to recover.\nA preview replay checks the exact persisted proposal it returns, including its\nanalysis attempt; a newer action revision cannot supply replacement lineage.\nPlan replay and final sealed plan-step publication use the same gate.\nFor already successful actions, current-authorized durable outcomes remain\nreadable/replayable, but invalid learned lineage suppresses saved proposal\ndisplay, arguments and plan payload. An empty selection carries no learned source\nand does not turn optional feedback-capture denial into action denial. Examples\nnever expand the offered catalog, candidate IDs, operation permissions or\nautomation eligibility.\n\nAll durable feedback belongs to the source item's existing retention/redaction\nlifecycle. There is no separate memory store or delayed indexing writer to clean\nup. Hosts using other derived stores still implement the existing `purgeDerived`\ncontract. Core `LearningMemory` is intentionally not used here: its success/failure\nreinforcement and default ancestor-scope fallback do not represent separate\ncorrectness/decision/outcome signals and strict confidential-scope eligibility.\n\n## Routing suggestions and adoption\n\n`suggestRoutingRule` requires repeated current explicit positive judgments with\nfrom distinct source items with matching handler/version and arguments, and returns supporting immutable IDs,\nshared query terms and the policy owner's preview/version. Suggestions cannot\nexecute or modify policy. `getRoutingRule` rechecks the displayed binding and all\nsupporting examples. Arguments are routing preferences, never executable grants.\n\n`adoptRoutingRule` requires the exact suggestion digest and expected policy\nversion plus current reviewer and adoption authority. The configured policy owner\nmust perform its version compare-and-swap and audit on the supplied database\nexecutor. The ingestion transaction records the exact returned version/audit ID.\nReplays do not adopt twice. Revocation or permission/policy widening rolls back\nboth changes. The host callback may store routing preferences only: it must not\nchange grants, provider permissions or automation controls. Adoption always\nreturns `automaticActionEligible: false`; subsequent proposals retain normal\ncurrent policy and explicit review requirements.\n\n## Review UI and evidence\n\nThe optional `IntakeReviewHost.feedback` callback carries the exact displayed\nrevision and binding. Correct/incorrect controls are explicit and independent of\nApprove/Apply. Unsaved argument edits disable correctness controls until the\ndisplayed binding is current again. Hosts must authenticate that callback and connect it to\n`recordFeedback`; client-supplied reviewer/scope fields are not accepted. The\nmaintained browser fixture demonstrates this transport with CSRF protection and\nrejects substituted revisions.\n\nSee [the behavior matrix](../../docs/test-matrix/3676-ingestion-feedback.md) for\nvalidation and the frozen learning protocol. The small authored deterministic\ncohort demonstrates contract-level influence, not provider quality or measured\nproduction improvement. Real-provider evaluation belongs to #3677. There are no\nsampled automatic outcomes in this feature; reporting that stratum as unavailable\navoids inventing correctness labels from successful jobs.\n"
1622
+ "content": "# Explicit ingestion feedback\n\nConfigure `IngestionOptions.feedback` to opt in. The existing `intake_feedback`\nledger owns these records; no new schema, embedding service or provider is added.\n`FeedbackConfiguration` sets a version, maximum examples, scan count, serialized\nbytes and lexical similarity threshold, plus a live scoped authorization callback.\nHard ceilings are 20 examples, 1,000 scanned records and 1 MB. Choose substantially\nsmaller application limits. The proposal's complete serialized request, including\nexamples, must also fit the current minimum application/source/provider budget.\n\n`recordFeedback` accepts the exact displayed action revision, review version and\nbinding hash, an explicit correct/incorrect judgment, optional reason text and a\nrequest ID. The server resolves reviewer, tenant/confidential scope, retained\nsource evidence, extraction/generation versions and current handler arguments.\nA replay returns the same immutable receipt; changed payloads conflict.\n`supersedesId` appends a replacement for the specified prior interpretation\njudgment. A second successor conflicts. Revised actions make old bindings\nineligible. Approval and successful execution never imply that extracted fields\nare correct.\n\nDecision and downstream execution facts are captured inside their owning\ntransaction, keyed by immutable event ID and signal, when the configured capture\nauthority allows the optional memory projection and it fits the configured byte\ncap. Denial or an oversized automatic projection leaves the underlying\nauthoritative decision/outcome intact, including failure and reconciliation.\nExplicit `recordFeedback` and `observeFeedback` requests still reject invalid or\noversized writes; actual database failures still propagate and roll back. Failed/rolled-back domain\nwork and unknown external outcomes remain distinct. `observeFeedback` can replay\nan authorized existing event; it cannot supply a correctness label or fabricate\nan execution result. An initial denial does not mutate retention. Once authorized,\na narrowed privacy ceiling survives business rollback and later revocation.\n\n## Retrieval and provider boundaries\n\n`retrieveFeedback({ itemId, query })` derives the current offered catalog,\ncandidates and model/prompt/configuration versions on the server. Callers cannot\nprovide candidate authority. The deterministic matcher uses lowercase Unicode\nword-set Jaccard similarity (minimum 0.2), then immutable record ID for ties.\nScanning, recursive provenance checks and returned examples are bounded; a limited scan does not promise an\nexhaustive history search. Both positive and negative explicit examples are kept.\n\nEvery selected source must still be readable in the same tenant and confidential\nscope, with its current action/analysis binding, target grants, handler version,\nmodel/prompt/configuration compatibility and retention. Each source's current\nprovider policy must allow the generation recipient and any configured decision\nrecipient; the source owner rechecks that policy on both initial and final live\ncontexts. Receiving checks cover every offered handler, before and after source\nchecks, using each live grant, actual provider recipients and the narrowest byte\nceiling. Both retrieval and reference revalidation budget the full reconstructed\nexamples. A receiving item's provider grant cannot substitute for a source grant.\nSuperseded, revoked, deleted or incompatible sources are excluded. Current explicit human corrections\ntake precedence: a generation carrying one does not retrieve learned examples.\n\nFull examples exist only in the authorized provider request. The SDK proposal\nadapter includes that typed selection in its serialized user message when\npresent; disabled feedback leaves the original request shape unchanged. Saved generation\nprovenance contains the receiving query, selection configuration digest and\nimmutable feedback IDs/digests, not copied source example content. Selected\nreferences are rechecked before generation, capability probing, decision calls,\npublication and completed-result reads. A newly added example does not invalidate\nan older selection; a revoked or superseded selected example does. Feedback\nlineage is bounded and fails closed. Saved-action reads and pending decisions,\nautomatic authorization, preview publication/replay and execution also revalidate\nselected lineage under the\nowning transaction. Revoking, deleting or superseding a selected example blocks\npending actions; regenerate their proposals and obtain fresh approval to recover.\nA preview replay checks the exact persisted proposal it returns, including its\nanalysis attempt; a newer action revision cannot supply replacement lineage.\nPlan replay and final sealed plan-step publication use the same gate.\nFor already successful actions, current-authorized durable outcomes remain\nreadable/replayable, but invalid learned lineage suppresses saved proposal\ndisplay, arguments and plan payload. An empty selection carries no learned source\nand does not turn optional feedback-capture denial into action denial. Examples\nnever expand the offered catalog, candidate IDs, operation permissions or\nautomation eligibility.\n\nAll durable feedback belongs to the source item's existing retention/redaction\nlifecycle. There is no separate memory store or delayed indexing writer to clean\nup. Hosts using other derived stores still implement the existing `purgeDerived`\ncontract. Core `LearningMemory` is intentionally not used here: its success/failure\nreinforcement and default ancestor-scope fallback do not represent separate\ncorrectness/decision/outcome signals and strict confidential-scope eligibility.\n\n## Routing suggestions and adoption\n\n`suggestRoutingRule` requires repeated current explicit positive judgments\nfrom distinct source items with matching handler/version and arguments, and returns supporting immutable IDs,\nshared query terms and the policy owner's preview/version. Suggestions cannot\nexecute or modify policy. `getRoutingRule` rechecks the displayed binding and all\nsupporting examples. Arguments are routing preferences, never executable grants.\n\nBy default matching compares **all** action arguments, preserving existing host\nbehavior. Create handlers commonly have per-document content and idempotency\nkeys, which must remain distinct. Such hosts can explicitly declare a routing-only\nsubset in trusted server configuration before capturing judgments:\n\n```ts\nfeedback: {\n // ...existing limits, authorize and policy owner\n routing: [{\n handlerId: 'host:create-document',\n handlerVersion: '1',\n version: 'routing-fields-1',\n fields: ['destinationId', 'category'],\n }],\n}\n```\n\nEach declaration must name a configured handler/version and a nonempty, unique\nallowlist of its top-level `argsSchema.properties`; duplicate declarations,\nunknown properties and prototype keys reject. There are no dotted paths,\ncaller-supplied selectors or implicit exclusions (including request IDs).\nOptional absent fields stay absent and differ from explicit `null`; at least one\nselected value must be present. The host must select preferences only, never\ngrants, provider permissions or automation controls.\n\nCapture retains the full immutable action arguments and binding plus the\nversioned subset. For opted-in handlers `RoutingRule.args` contains only selected\nvalues and `RoutingRule.projection` carries the canonical sorted fields and\nversion. Independent support must match that entire contract and those values;\nfull original source arguments, provenance and current access are still checked.\nExisting unprojected feedback is not retroactively reinterpreted: record fresh\nexplicit judgments after enabling or changing a declaration. Changing a version,\nfield list or selected value invalidates old suggestions on reads, adoption and\nreplay, including changes inside policy-owner callbacks. Full argument feedback\nretrieval remains unchanged; hosts may present matching examples from\n`retrieveFeedback`, but suggestion creation revalidates every supplied ID.\n\n`adoptRoutingRule` requires the exact suggestion digest and expected policy\nversion plus current reviewer and adoption authority. The configured policy owner\nmust perform its version compare-and-swap and audit on the supplied database\nexecutor. The ingestion transaction records the exact returned version/audit ID.\nReplays do not adopt twice. Revocation or permission/policy widening rolls back\nboth changes. The host callback may store routing preferences only: it must not\nchange grants, provider permissions or automation controls. Adoption always\nreturns `automaticActionEligible: false`; subsequent proposals retain normal\ncurrent policy and explicit review requirements.\n\n## Review UI and evidence\n\nThe optional `IntakeReviewHost.feedback` callback carries the exact displayed\nrevision and binding. Correct/incorrect controls are explicit and independent of\nApprove/Apply. Unsaved argument edits disable correctness controls until the\ndisplayed binding is current again. Hosts must authenticate that callback and connect it to\n`recordFeedback`; client-supplied reviewer/scope fields are not accepted. The\nmaintained browser fixture demonstrates this transport with CSRF protection and\nrejects substituted revisions.\n\nSee [the behavior matrix](../../docs/test-matrix/3676-ingestion-feedback.md) for\nvalidation and the frozen learning protocol, and the\n[routing projection matrix](../../docs/test-matrix/3732-ingestion-routing-projection.md)\nfor the optional subset contract. The small authored deterministic\ncohort demonstrates contract-level influence, not provider quality or measured\nproduction improvement. Real-provider evaluation belongs to #3677. There are no\nsampled automatic outcomes in this feature; reporting that stratum as unavailable\navoids inventing correctness labels from successful jobs.\n"
1619
1623
  },
1620
1624
  {
1621
1625
  "path": "REVIEW.md",
1622
1626
  "module": "REVIEW",
1623
- "content": "# Authenticated review surfaces\n\n`@happyvertical/smrt-ingestion/svelte` exports `IntakeInbox`, `IntakeReview` and\n`EvidenceViewer`. The browser-safe DTO entry exports their `IntakeReviewHost`\ncallback contract. Import styling/theme configuration from smrt-ui in the host.\nComponents use smrt-ui primitives and the `ingestion.*` i18n catalog.\n\nThe host authenticates every request, resolves tenant/actor/confidential scope\nfrom its session, enforces CSRF on mutations, and constructs `IngestionService`.\nNever accept scope, reviewer, permissions or a principal from callback JSON.\nOnly supply authorized evidence URLs and escaped text; original URLs are\nsame-origin authenticated handlers that recheck `readEvidence` on every read.\nCandidate discovery uses `findCandidates` with current grants. Presentation\nstate and disabled buttons provide no server authority.\n\n`listReviews(itemId, {cursor?,limit?})` reloads saved action identities and their\ncurrent plan membership without browser storage. It returns at most 50 actions,\nwith an opaque action-ID cursor. Every payload requires current item, handler,\nparent plan and target access under the owning transaction. Denied reads fail\nclosed. Target reads check current authorization separately from historical\nrevision freshness: unfinished drift returns state-only stale reviews without\nremoving unrelated entries; succeeded results remain readable after authorized\ntarget changes. Apply still enforces exact bound target revisions. Expired entries\ncontain only review identity/state. Stale entries never disclose old args or target\nlabels; an authorized parent plan additionally exposes `stalePlan` identity, key,\ncurrent plan revision and handler identity. Hosts must collect fresh explicit args\nfrom the reviewer/current authorized evidence and call `previewPlan` with that\nexact plan CAS and the current completed analysis attempt. Action revision is not\nplan revision. Re-expansion preserves action identity and requires fresh approval.\nSuccess results are rechecked through the durable result reader.\nPlan membership contains the exact parent args/version so edits call\n`previewPlan`, not per-step correction. An item may have more review pages; the\nhost must aggregate state across pages when projecting a production inbox state.\n\nThe host's `load` callback supplies a current `ItemReviewView`, using\n`getCompletedAnalysis` with no historical fallback. Generated suggestions bind\nthe **current generation attempt**, not `generation.source.attemptId` (the prior\nextraction). `previewGeneratedProposals` publishes exact reviews and continues to reject stale\ngeneration candidate pins. When `listReviews` reports `generationStale`, the host\nomits obsolete generation output and renders authorized saved reviews/results.\nCompleted saved actions do not hide healthy unprepared suggestions. The saved-binding hint is not\nan authoritative generation-availability check: a fresh human preview can bind a\ncurrent target while the immutable generation still pins its former revision.\n`getCompletedAnalysis` remains strict and throws server-only\n`GenerationSnapshotStaleError` only after every current catalog/provider/candidate\nread is authorized and an immutable candidate revision differs. The maintained\nhost catches only that class, reacquires `listReviews` under current owning\nauthority, and returns that new page without generation output. It never reuses\nthe earlier page after an error. Denials and unknown failures propagate; healthy\ngeneration still exposes unprepared sibling suggestions. Stale entries expose handler\nand attempt identity only when that attempt is still the current completed/partial\nanalysis. An empty-args editor submits fresh explicit human arguments through\n`previewProposal` or `previewPlan` with the saved CAS; it never reuses old generated\narguments, rewrites the generation snapshot or transfers approval. Analysis-stale\nentries without an attempt require normal reprocessing. Approve,\nreject, defer and correct call `submitDecision`; corrected args create a new\nrevision which requires a separate human approval. After an approve/defer/reject\ndecision, optional `editAction` calls `previewProposal` with the current action\nrevision to publish a new review; completed/executing/unknown actions cannot be\nrevised. Local dirty args disable Apply but confer no authority. Plan edits re-expand through\n`previewPlan` with the current **plan** revision. `applyAction` accepts only an\naction ID. Unknown external outcomes require server reconciliation; the UI\nnever offers a blind resend. Stable result IDs survive reload and retry.\n\nReplace `contextKey` whenever authenticated tenant/session context changes.\nChanging it or itemId destroys the old view and fences late callback results.\nDenied refresh clears prior originals, candidates, arguments and results.\nMissing confidence is unavailable; page/time links exist only for observed\nlocations. Provider errors and unresolved/partial results remain review states.\n\n## Assignment and logical splits\n\nAssignment is explicitly host-owned, durable and versioned. `assign` receives\nan expected assignment version and request ID; the host must authorize the\nmanager, constrain eligible assignees, CAS the durable record and reject stale\nwrites. Assignment does not grant read, review or execution rights. The maintained\nfixture provisions its own SQLite assignment table before serving requests; no\nproduction ingestion table or migration is introduced for assignment.\n\n`reviseLogicalSplit` authorizes the current generation through the same-executor\ncatalog/candidate gate and the existing reviewer grant and policy reviewer list.\nProcess access alone cannot mint or replay a human correction; reviewer authority\nis checked before mutation and again before publication. A generation without a\nreviewable catalogue cannot be corrected through this reviewer API.\nIt requires all observed pages exactly once, an exact\ncurrent attempt/revision and a request ID. It records the authenticated actor\nand predecessor as a **human correction** in a new immutable extraction\nconfiguration, queues re-extraction and immediately makes previous suggestions\nand approvals stale. It never changes original bytes/evidence or labels a human\nedit as model output. The host processes the new extraction, then calls\n`prepareGeneration` and the normal fenced interpretation stage. The supported\nimmediate-predecessor extraction pin is unchanged. The generator receives a\nhuman correction only after its digest matches the authoritative source. Ordinary\n`analyze` calls cannot mint an extraction correction; the owning split API is the\nauthenticated origin, and forged interpretation corrections fail before provider\ndisclosure. If its proposed grouping differs from the correction, suggestions are withheld\nwith `human_split_not_respected`. New proposals require new explicit review.\nThe reference host runs these stages synchronously for browser determinism;\nproduction hosts dispatch the existing durable analysis jobs.\n\n`feedback` is an optional explicit correctness callback, separate from approval\nchoice and execution success. No learning, feedback storage or rule promotion is\nimplemented by these components; #3676 owns those services. Do not pass feedback\nor a feedback callback to readers without the relevant host grant.\n\n## Maintained browser proof\n\n`pnpm test:components` runs real Svelte component tests; `pnpm test:e2e` runs the\npackage-local authenticated Vite application under Chromium. The fixture uses\nHttpOnly same-site sessions, CSRF, real SQLite/assets/ingestion/content APIs,\nproduction unpdf child extraction and a deterministic proposal generator. Its\nhardcoded test login is fixture-only and is never a production auth provider.\nImage/audio originals remain inspectable when no OCR/speech provider is\nconfigured; the suite makes no recognition-quality claim and spends no provider\nbudget. `reference/review-host.ts` is a maintained development fixture, not a\npublished server entry. Browser tests show actual approved args and persisted\nContentDocument results, stale tabs, reload, retries and negative access.\n\nRun full package `test`, `test:postgres`, `test:providers`, `build`, `typecheck`,\n`test:components`, `test:e2e`; use the root Node/pnpm versions. Set a short\n`CI_TEST_TMPDIR`/`TMPDIR`, and optionally\n`PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH` to the supported installed Chromium.\nThe evaluation lane remains explicitly unavailable until #3677.\n\nThe existing CI browser job includes ingestion changes and shared UI primitive\nchanges in affected mode, and runs the ingestion browser suite in full mode. Its\nnormal dependency build precedes the suite and failed runs upload browser evidence.\n\nThe maintained host derives inbox state by traversing bounded public review pages,\nauthorizing every action/parent/target before classification. It retains only\nscalar totals and the requested page; an off-page denial denies the whole view.\nThe component's Load more and subsequent refresh/mutation reload every displayed\npage using fresh cursors, then publish the combined authorized set together. Old\npage payloads are cleared while loading; any unavailable page clears all payloads.\nThis keeps plan controls and earlier steps visible across page boundaries without\nreusing a prior authorization decision.\n"
1627
+ "content": "# Authenticated review surfaces\n\n`@happyvertical/smrt-ingestion/svelte` exports `IntakeInbox`, `IntakeReview` and\n`EvidenceViewer`. The browser-safe DTO entry exports their `IntakeReviewHost`\ncallback contract. Import styling/theme configuration from smrt-ui in the host.\nComponents use smrt-ui primitives and the `ingestion.*` i18n catalog.\n\nThe host authenticates every request, resolves tenant/actor/confidential scope\nfrom its session, enforces CSRF on mutations, and constructs `IngestionService`.\nNever accept scope, reviewer, permissions or a principal from callback JSON.\nOnly supply authorized evidence URLs and escaped text; original URLs are\nsame-origin authenticated handlers that recheck `readEvidence` on every read.\nCandidate discovery uses `findCandidates` with current grants. Presentation\nstate and disabled buttons provide no server authority.\n\n`listReviews(itemId, {cursor?,limit?})` reloads saved action identities and their\ncurrent plan membership without browser storage. It returns at most 50 actions,\nwith an opaque action-ID cursor. Every payload requires current item, handler,\nparent plan and target access under the owning transaction. Denied reads fail\nclosed. Target reads check current authorization separately from historical\nrevision freshness: unfinished drift returns state-only stale reviews without\nremoving unrelated entries; succeeded results remain readable after authorized\ntarget changes. Apply still enforces exact bound target revisions. Expired entries\ncontain only review identity/state. Stale entries never disclose old args or target\nlabels; an authorized parent plan additionally exposes `stalePlan` identity, key,\ncurrent plan revision and handler identity. Hosts must collect fresh explicit args\nfrom the reviewer/current authorized evidence and call `previewPlan` with that\nexact plan CAS and the current completed analysis attempt. Action revision is not\nplan revision. Re-expansion preserves action identity and requires fresh approval.\nSuccess results are rechecked through the durable result reader.\nPlan membership contains the exact parent args/version so edits call\n`previewPlan`, not per-step correction. An item may have more review pages; the\nhost must aggregate state across pages when projecting a production inbox state.\n\nThe host's `load` callback supplies a current `ItemReviewView`, using\n`getCompletedAnalysis` with no historical fallback. Generated suggestions bind\nthe **current generation attempt**, not `generation.source.attemptId` (the prior\nextraction). `previewGeneratedProposals` publishes exact reviews and continues to reject stale\ngeneration candidate pins. When `listReviews` reports `generationStale`, the host\nomits obsolete generation output and renders authorized saved reviews/results.\nCompleted saved actions do not hide healthy unprepared suggestions. The saved-binding hint is not\nan authoritative generation-availability check: a fresh human preview can bind a\ncurrent target while the immutable generation still pins its former revision.\n`getCompletedAnalysis` remains strict and throws server-only\n`GenerationSnapshotStaleError` only after every current catalog/provider/candidate\nread is authorized and an immutable candidate revision differs. The maintained\nhost catches only that class, reacquires `listReviews` under current owning\nauthority, and returns that new page without generation output. It never reuses\nthe earlier page after an error. Denials and unknown failures propagate; healthy\ngeneration still exposes unprepared sibling suggestions. Stale entries expose handler\nand attempt identity only when that attempt is still the current completed/partial\nanalysis. An empty-args editor submits fresh explicit human arguments through\n`previewProposal` or `previewPlan` with the saved CAS; it never reuses old generated\narguments, rewrites the generation snapshot or transfers approval. Analysis-stale\nentries without an attempt require normal reprocessing. Approve,\nreject, defer and correct call `submitDecision`; corrected args create a new\nrevision which requires a separate human approval. After an approve/defer/reject\ndecision, optional `editAction` calls `previewProposal` with the current action\nrevision to publish a new review; completed/executing/unknown actions cannot be\nrevised. Local dirty args disable Apply but confer no authority. Plan edits re-expand through\n`previewPlan` with the current **plan** revision. `applyAction` accepts only an\naction ID. Unknown external outcomes require server reconciliation; the UI\nnever offers a blind resend. Stable result IDs survive reload and retry.\n\nReplace `contextKey` whenever authenticated tenant/session context changes.\nChanging it or itemId destroys the old view and fences late callback results.\nDenied refresh clears prior originals, candidates, arguments and results.\nMissing confidence is unavailable; page/time links exist only for observed\nlocations. Provider errors and unresolved/partial results remain review states.\n\n## Assignment and logical splits\n\nAssignment is explicitly host-owned, durable and versioned. `assign` receives\nan expected assignment version and request ID; the host must authorize the\nmanager, constrain eligible assignees, CAS the durable record and reject stale\nwrites. Assignment does not grant read, review or execution rights. The maintained\nfixture provisions its own SQLite assignment table before serving requests; no\nproduction ingestion table or migration is introduced for assignment.\n\n`reviseLogicalSplit` authorizes the current generation through the same-executor\ncatalog/candidate gate and the existing reviewer grant and policy reviewer list.\nProcess access alone cannot mint or replay a human correction; reviewer authority\nis checked before mutation and again before publication. A generation without a\nreviewable catalogue cannot be corrected through this reviewer API.\nIt requires all observed pages exactly once, an exact\ncurrent attempt/revision and a request ID. It records the authenticated actor\nand predecessor as a **human correction** in a new immutable extraction\nconfiguration, queues re-extraction and immediately makes previous suggestions\nand approvals stale. It never changes original bytes/evidence or labels a human\nedit as model output. The host processes the new extraction, then calls\n`prepareGeneration` and the normal fenced interpretation stage. The supported\nimmediate-predecessor extraction pin is unchanged. The generator receives a\nhuman correction only after its digest matches the authoritative source. Ordinary\n`analyze` calls cannot mint an extraction correction; the owning split API is the\nauthenticated origin, and forged interpretation corrections fail before provider\ndisclosure. If its proposed grouping differs from the correction, suggestions are withheld\nwith `human_split_not_respected`. New proposals require new explicit review.\nThe reference host runs these stages synchronously for browser determinism;\nproduction hosts dispatch the existing durable analysis jobs.\n\n`feedback` is an optional explicit correctness callback, separate from approval\nchoice and execution success. No learning, feedback storage or rule promotion is\nimplemented by these components; #3676 owns those services. Do not pass feedback\nor a feedback callback to readers without the relevant host grant.\n\n## Maintained browser proof\n\n`pnpm test:components` runs real Svelte component tests; `pnpm test:e2e` runs the\npackage-local authenticated Vite application under Chromium. The fixture uses\nHttpOnly same-site sessions, CSRF, real SQLite/assets/ingestion/content APIs,\nproduction unpdf child extraction and a deterministic proposal generator. Its\nhardcoded test login is fixture-only and is never a production auth provider.\nImage/audio originals remain inspectable when no OCR/speech provider is\nconfigured; the suite makes no recognition-quality claim and spends no provider\nbudget. `reference/review-host.ts` is a maintained development fixture, not a\npublished server entry. Browser tests show actual approved args and persisted\nContentDocument results, stale tabs, reload, retries and negative access.\n\nRun full package `test`, `test:postgres`, `test:providers`, `build`, `typecheck`,\n`test:components`, `test:e2e`; use the root Node/pnpm versions. Set a short\n`CI_TEST_TMPDIR`/`TMPDIR`, and optionally\n`PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH` to the supported installed Chromium.\n`pnpm test:evaluation` checks repository evaluation tooling contracts; measured\nheld-out quality remains a separate frozen-protocol, budget-gated #3677 run.\n\nThe existing CI browser job includes ingestion changes and shared UI primitive\nchanges in affected mode, and runs the ingestion browser suite in full mode. Its\nnormal dependency build precedes the suite and failed runs upload browser evidence.\n\nThe maintained host derives inbox state by traversing bounded public review pages,\nauthorizing every action/parent/target before classification. It retains only\nscalar totals and the requested page; an off-page denial denies the whole view.\nThe component's Load more and subsequent refresh/mutation reload every displayed\npage using fresh cursors, then publish the combined authorized set together. Old\npage payloads are cleared while loading; any unavailable page clears all payloads.\nThis keeps plan controls and earlier steps visible across page boundaries without\nreusing a prior authorization decision.\n"
1624
1628
  }
1625
1629
  ],
1626
1630
  "agentSurface": {
@@ -1663,7 +1667,7 @@
1663
1667
  "code": "not-module-scope",
1664
1668
  "helper": "definePlaybook",
1665
1669
  "message": "`definePlaybook()` must be called at module scope to be emitted into the manifest and knowledge graph. A declaration the scanner cannot read without evaluating it is not emittable — use `useWebMcpTool` for a tool set derived from computed or fetched data.",
1666
- "line": 3473,
1670
+ "line": 3772,
1667
1671
  "column": 9,
1668
1672
  "sourceFile": "src/test-support/proposals.ts"
1669
1673
  },
@@ -1671,10 +1675,30 @@
1671
1675
  "code": "not-module-scope",
1672
1676
  "helper": "definePlaybook",
1673
1677
  "message": "`definePlaybook()` must be called at module scope to be emitted into the manifest and knowledge graph. A declaration the scanner cannot read without evaluating it is not emittable — use `useWebMcpTool` for a tool set derived from computed or fetched data.",
1674
- "line": 4098,
1678
+ "line": 4397,
1675
1679
  "column": 7,
1676
1680
  "sourceFile": "src/test-support/proposals.ts"
1677
1681
  }
1678
1682
  ]
1683
+ },
1684
+ "browser": {
1685
+ "status": "server-only",
1686
+ "issues": [
1687
+ "#3615",
1688
+ "#3617",
1689
+ "#3624",
1690
+ "#3625",
1691
+ "#3626",
1692
+ "#3627"
1693
+ ],
1694
+ "via": [
1695
+ "@happyvertical/smrt-agents",
1696
+ "@happyvertical/smrt-jobs",
1697
+ "@happyvertical/smrt-profiles",
1698
+ "@happyvertical/smrt-reports",
1699
+ "@happyvertical/smrt-secrets",
1700
+ "@happyvertical/smrt-tenancy",
1701
+ "@happyvertical/smrt-users"
1702
+ ]
1679
1703
  }
1680
1704
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@happyvertical/smrt-ingestion",
3
- "version": "0.55.7",
3
+ "version": "0.55.9",
4
4
  "description": "Durable tenant-scoped intake and evidence foundations",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -50,30 +50,32 @@
50
50
  }
51
51
  },
52
52
  "dependencies": {
53
- "@happyvertical/smrt-core": "0.55.7",
54
- "@happyvertical/smrt-types": "0.55.7",
55
- "@happyvertical/smrt-tenancy": "0.55.7",
56
- "@happyvertical/smrt-assets": "0.55.7",
57
- "@happyvertical/smrt-jobs": "0.55.7",
58
- "@happyvertical/sql": "^0.102.5",
53
+ "@happyvertical/smrt-core": "0.55.9",
54
+ "@happyvertical/smrt-types": "0.55.9",
55
+ "@happyvertical/smrt-tenancy": "0.55.9",
56
+ "@happyvertical/smrt-assets": "0.55.9",
57
+ "@happyvertical/smrt-jobs": "0.55.9",
58
+ "@happyvertical/sql": "^0.103.1",
59
59
  "@happyvertical/pdf": "^0.65.9",
60
60
  "@happyvertical/ocr": "^0.61.6",
61
- "@happyvertical/speech": "^0.102.5",
62
- "@happyvertical/ai": "^0.102.5",
61
+ "@happyvertical/speech": "^0.103.1",
62
+ "@happyvertical/ai": "^0.103.1",
63
63
  "sharp": "^0.35.5",
64
- "@happyvertical/smrt-agents": "0.55.7",
65
- "@happyvertical/smrt-playbooks": "0.55.7",
64
+ "@happyvertical/smrt-agents": "0.55.9",
65
+ "@happyvertical/smrt-playbooks": "0.55.9",
66
66
  "ajv": "8.20.0",
67
- "@happyvertical/smrt-ui": "0.55.7"
67
+ "@happyvertical/smrt-ui": "0.55.9"
68
68
  },
69
69
  "devDependencies": {
70
- "@happyvertical/smrt-vitest": "0.55.7",
70
+ "@happyvertical/smrt-vitest": "0.55.9",
71
71
  "@types/node": "24.13.6",
72
72
  "typescript": "6.0.3",
73
73
  "vite": "8.1.4",
74
74
  "vitest": "4.1.10",
75
- "@happyvertical/smrt-content": "0.55.7",
76
- "@happyvertical/smrt-users": "0.55.7",
75
+ "@happyvertical/smrt-content": "0.55.9",
76
+ "@happyvertical/smrt-messages": "0.55.9",
77
+ "@happyvertical/email": "^0.103.1",
78
+ "@happyvertical/smrt-users": "0.55.9",
77
79
  "@sveltejs/package": "^2.5.8",
78
80
  "@sveltejs/vite-plugin-svelte": "^7.3.0",
79
81
  "svelte": "^5.57.1",
@@ -109,6 +111,6 @@
109
111
  "test:providers": "vitest run src/extraction.providers.test.ts src/proposals.providers.test.ts",
110
112
  "test:components": "vitest run --config vitest.components.config.ts",
111
113
  "test:e2e": "playwright test -c e2e/review/playwright.config.ts",
112
- "test:evaluation": "node scripts/unavailable-lane.mjs evaluation"
114
+ "test:evaluation": "vitest run --config evaluation/vitest.config.ts"
113
115
  }
114
116
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"feedback-B_NILilH.js","names":["candidate","digest","id"],"sources":["../../src/feedback.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto';\nimport type { DatabaseInterface } from '@happyvertical/sql';\nimport {\n intakeBindingDigest as digest,\n IntakeExecutionService,\n} from './execution.js';\nimport type { FeedbackConfiguration } from './feedback-contracts.js';\nimport type {\n AdoptRuleInput,\n FeedbackBinding,\n FeedbackExample,\n FeedbackReceipt,\n FeedbackReferences,\n FeedbackSelection,\n ObserveFeedbackInput,\n ReadRuleInput,\n RecordFeedbackInput,\n RoutingRule,\n RuleAdoption,\n RuleSuggestion,\n SuggestRuleInput,\n} from './feedback-dto.js';\nimport {\n type FeedbackActionContext,\n feedbackActionTransaction,\n feedbackDiscoveryContext,\n} from './feedback-internal.js';\nimport type { GenerationOutput } from './proposal-dto.js';\nimport type { IngestionOptions } from './server.js';\n\ntype Row = Record<string, unknown>;\nfunction object(value: unknown): Row {\n const result = typeof value === 'string' ? JSON.parse(value) : value;\n if (!result || typeof result !== 'object' || Array.isArray(result))\n throw new Error('Feedback unavailable');\n return result as Row;\n}\nfunction text(value: unknown, max = 512): asserts value is string {\n if (typeof value !== 'string' || !value.trim() || value.length > max)\n throw new Error('Invalid feedback');\n}\nfunction resultData(data: Row): Row {\n return {\n status: data.status,\n provider: data.provider,\n model: data.model,\n version: data.version,\n output: data.output,\n usage: data.usage,\n ...(Object.hasOwn(data, 'error') ? { error: data.error } : {}),\n ...(Object.hasOwn(data, 'confidence')\n ? { confidence: data.confidence }\n : {}),\n };\n}\nexport function feedbackTerms(value: string): string[] {\n return [\n ...new Set(value.toLowerCase().match(/[\\p{L}\\p{N}]+/gu) ?? []),\n ].sort();\n}\nexport function feedbackSimilarity(left: string, right: string): number {\n const a = new Set(feedbackTerms(left)),\n b = new Set(feedbackTerms(right));\n const union = new Set([...a, ...b]);\n return union.size\n ? [...a].filter((value) => b.has(value)).length / union.size\n : 0;\n}\nexport interface RetrieveFeedbackInput {\n itemId: string;\n query: string;\n offered: GenerationOutput['offered'];\n promptVersion: string;\n configurationVersion: string;\n model: { provider: string; model: string; version: string };\n providers?: string[];\n}\n/** Owning ingestion ledger. Generic LearningMemory's success/ancestor fallback semantics are deliberately not used. */\nexport class IntakeFeedbackService {\n private readonly execution: IntakeExecutionService;\n private readonly config: FeedbackConfiguration;\n private readonly lineage = new Set<string>();\n private exampleChecks = 0;\n constructor(\n private readonly options: IngestionOptions,\n execution?: IntakeExecutionService,\n ) {\n if (!options.execution || !options.feedback)\n throw new Error('Feedback not configured');\n this.config = { ...options.feedback };\n this.execution =\n execution ?? new IntakeExecutionService(options, options.execution);\n text(this.config.version);\n for (const [value, max] of [\n [this.config.maxExamples, 20],\n [this.config.maxScan, 1000],\n [this.config.maxBytes, 1000000],\n ])\n if (!Number.isSafeInteger(value) || value < 1 || value > max)\n throw new Error('Invalid feedback limits');\n if (\n !Number.isFinite(this.config.minimumSimilarity) ||\n this.config.minimumSimilarity < 0.2 ||\n this.config.minimumSimilarity > 1\n )\n throw new Error('Invalid feedback similarity');\n }\n private configurationDigest() {\n const { version, maxExamples, maxScan, maxBytes, minimumSimilarity } =\n this.config;\n return digest({\n version,\n maxExamples,\n maxScan,\n maxBytes,\n minimumSimilarity,\n });\n }\n private scope() {\n return this.options.scope;\n }\n private async rows(\n db: DatabaseInterface,\n where: string,\n params: unknown[] = [],\n ): Promise<Row[]> {\n const scope = this.scope();\n return (\n await db.query(\n `SELECT * FROM intake_feedback WHERE tenant_id=? AND confidential_scope_id=? AND ${where}`,\n scope.tenantId,\n scope.confidentialScopeId,\n ...params,\n )\n ).rows;\n }\n private async authorize(\n ctx: FeedbackActionContext,\n operation: 'capture' | 'retrieve' | 'suggest' | 'adopt',\n ) {\n if (\n !(await this.config.authorize({\n db: ctx.db,\n scope: this.scope(),\n itemId: ctx.itemId,\n operation,\n }))\n )\n throw new Error('Feedback unavailable');\n }\n private checkBinding(input: FeedbackBinding, ctx: FeedbackActionContext) {\n if (\n input.itemId !== ctx.itemId ||\n input.actionId !== ctx.review.actionId ||\n input.expectedRevision !== ctx.review.revision ||\n input.expectedReviewVersion !== ctx.review.reviewVersion ||\n input.bindingHash !== ctx.review.bindingHash\n )\n throw new Error('Stale feedback binding');\n }\n private async insert(\n ctx: FeedbackActionContext,\n key: string,\n kind: string,\n data: Row,\n supersedesId: string | null = null,\n ): Promise<Row> {\n const serialized = JSON.stringify(data);\n if (\n Buffer.byteLength(serialized) >\n Math.min(this.config.maxBytes, ctx.context.policy.maxBytes)\n )\n throw new Error('Feedback limit');\n const scope = this.scope(),\n now = (this.options.now?.() ?? new Date()).toISOString();\n const row = {\n id: randomUUID(),\n slug: randomUUID(),\n context: '',\n created_at: now,\n updated_at: now,\n tenant_id: scope.tenantId,\n confidential_scope_id: scope.confidentialScopeId,\n item_id: ctx.itemId,\n request_key: key,\n supersedes_id: supersedesId,\n kind,\n data: serialized,\n };\n return (\n await ctx.db.query(\n `INSERT INTO intake_feedback (${Object.keys(row).join(',')}) VALUES (${Object.keys(\n row,\n )\n .map(() => '?')\n .join(',')}) RETURNING *`,\n ...Object.values(row),\n )\n ).rows[0];\n }\n private receipt(row: Row): FeedbackReceipt {\n return {\n id: String(row.id),\n digest: String(object(row.data).digest),\n kind: row.kind as FeedbackReceipt['kind'],\n };\n }\n private async provenance(ctx: FeedbackActionContext) {\n const output = object(ctx.result.output),\n generation = object(output.proposals),\n pin = object(generation.source),\n provenance = object(generation.provenance);\n if (provenance.feedback) {\n const inherited = object(provenance.feedback);\n const key = ctx.attemptId;\n if (this.lineage.has(key) || this.lineage.size >= 8)\n throw new Error('Feedback lineage unavailable');\n this.lineage.add(key);\n try {\n await this.assertSelection(\n {\n itemId: ctx.itemId,\n query: String(inherited.query),\n offered: generation.offered as GenerationOutput['offered'],\n promptVersion: String(provenance.promptVersion),\n configurationVersion: String(provenance.configurationVersion),\n model: provenance.generative as RetrieveFeedbackInput['model'],\n providers: [\n String(object(provenance.generative).provider),\n ...(object(provenance.decision).configured\n ? [String(object(provenance.decision).provider)]\n : []),\n ],\n },\n inherited.selection as unknown as FeedbackReferences,\n ctx.db,\n );\n } finally {\n this.lineage.delete(key);\n }\n }\n const scope = this.scope();\n const [source] = (\n await ctx.db.query(\n 'SELECT data,output_digest FROM intake_analysis_attempts WHERE tenant_id=? AND confidential_scope_id=? AND item_id=? AND id=?',\n scope.tenantId,\n scope.confidentialScopeId,\n ctx.itemId,\n pin.attemptId,\n )\n ).rows;\n if (!source || source.output_digest !== pin.outputDigest)\n throw new Error('Feedback source unavailable');\n const sourceResult = resultData(object(source.data));\n if (digest(sourceResult) !== pin.outputDigest)\n throw new Error('Feedback source integrity');\n const results = object(sourceResult.output).results;\n if (!Array.isArray(results))\n throw new Error('Feedback extraction unavailable');\n const query = results\n .flatMap((entry) => {\n const segments = object(entry).segments;\n return Array.isArray(segments)\n ? segments.map((segment) => String(object(segment).text ?? ''))\n : [];\n })\n .join('\\n')\n .slice(0, 4096);\n const model = object(provenance.generative);\n for (const field of ['provider', 'model', 'version']) text(model[field]);\n text(provenance.promptVersion);\n text(provenance.configurationVersion);\n return {\n query,\n model: {\n provider: String(model.provider),\n model: String(model.model),\n version: String(model.version),\n },\n promptVersion: String(provenance.promptVersion),\n configurationVersion: String(provenance.configurationVersion),\n attemptId: ctx.attemptId,\n evidence: object(ctx.analysis).inputs,\n source: pin,\n };\n }\n /** Internal saved-action gate; the execution owner supplies its transaction. */\n async assertActionLineage(\n actionId: string,\n db: DatabaseInterface,\n proposalId: string,\n ): Promise<void> {\n await this.execution[feedbackActionTransaction](\n actionId,\n false,\n async (ctx) => {\n await this.provenance(ctx);\n },\n db,\n undefined,\n proposalId,\n );\n }\n async record(input: RecordFeedbackInput): Promise<FeedbackReceipt> {\n digest(input);\n text(input.requestId);\n if (\n !['correct', 'incorrect'].includes(input.judgment) ||\n (input.comment !== undefined &&\n (typeof input.comment !== 'string' || input.comment.length > 4000))\n )\n throw new Error('Invalid feedback');\n const frozen = structuredClone(input);\n return this.execution[feedbackActionTransaction](\n input.actionId,\n true,\n async (ctx) => {\n await this.authorize(ctx, 'capture');\n this.checkBinding(frozen, ctx);\n const requestHash = digest(frozen),\n key = `judgment:${frozen.requestId}`;\n const [replay] = await this.rows(\n ctx.db,\n 'item_id=? AND request_key=?',\n [ctx.itemId, key],\n );\n if (replay) {\n const data = object(replay.data);\n if (\n data.requestHash !== requestHash ||\n data.reviewer !== this.scope().actorId\n )\n throw new Error('Feedback request conflict');\n return this.receipt(replay);\n }\n if (frozen.supersedesId) {\n const [old] = await this.rows(\n ctx.db,\n 'item_id=? AND id=? AND kind=?',\n [ctx.itemId, frozen.supersedesId, 'interpretation'],\n );\n if (\n !old ||\n object(old.data).actionId !== frozen.actionId ||\n (await this.rows(ctx.db, 'supersedes_id=?', [old.id])).length\n )\n throw new Error('Feedback supersession conflict');\n }\n const provenance = await this.provenance(ctx);\n const body = {\n version: 1,\n requestHash,\n reviewer: this.scope().actorId,\n actionId: ctx.review.actionId,\n revision: ctx.review.revision,\n reviewVersion: ctx.review.reviewVersion,\n bindingHash: ctx.review.bindingHash,\n handlerId: ctx.handlerId,\n handlerVersion: ctx.handlerVersion,\n args: ctx.args,\n judgment: frozen.judgment,\n comment: frozen.comment ?? '',\n ...provenance,\n };\n const row = await this.insert(\n ctx,\n key,\n 'interpretation',\n { ...body, digest: digest(body) },\n frozen.supersedesId ?? null,\n );\n await this.authorize(ctx, 'capture');\n return this.receipt(row);\n },\n );\n }\n /** Consume a durable owner event idempotently. Never derive correctness from these signals. */\n async observe(input: ObserveFeedbackInput): Promise<FeedbackReceipt> {\n digest(input);\n text(input.eventId);\n if (!['action_decision', 'downstream_outcome'].includes(input.kind))\n throw new Error('Invalid feedback kind');\n return this.execution[feedbackActionTransaction](\n input.actionId,\n true,\n async (ctx) => {\n await this.authorize(ctx, 'capture');\n this.checkBinding(input, ctx);\n const scope = this.scope();\n const table =\n input.kind === 'action_decision'\n ? 'intake_review_decisions'\n : 'intake_executions';\n const [event] = (\n await ctx.db.query(\n `SELECT * FROM ${table} WHERE tenant_id=? AND confidential_scope_id=? AND item_id=? AND action_id=? AND id=?`,\n scope.tenantId,\n scope.confidentialScopeId,\n ctx.itemId,\n input.actionId,\n input.eventId,\n )\n ).rows;\n if (!event || event.binding_hash !== ctx.review.bindingHash)\n throw new Error('Feedback event unavailable');\n const state =\n input.kind === 'action_decision' ? event.decision : event.state;\n if (\n input.kind === 'downstream_outcome' &&\n !['succeeded', 'failed', 'outcome_unknown'].includes(String(state))\n )\n throw new Error('Outcome is not terminal');\n const body = {\n version: 1,\n eventId: input.eventId,\n actionId: input.actionId,\n revision: ctx.review.revision,\n reviewer:\n input.kind === 'action_decision'\n ? object(event.data).reviewer\n : null,\n observedBy: this.scope().actorId,\n principalId: object(event.data).principalId ?? null,\n signal: state,\n provenance: await this.provenance(ctx),\n };\n const key = `event:${input.kind}:${input.eventId}:${String(state)}`;\n const [existing] = await this.rows(\n ctx.db,\n 'item_id=? AND request_key=?',\n [ctx.itemId, key],\n );\n if (existing) return this.receipt(existing);\n const row = await this.insert(ctx, key, input.kind, {\n ...body,\n digest: digest(body),\n });\n await this.authorize(ctx, 'capture');\n return this.receipt(row);\n },\n );\n }\n private async example(\n row: Row,\n input: RetrieveFeedbackInput,\n executor?: DatabaseInterface,\n ): Promise<FeedbackExample | undefined> {\n if (++this.exampleChecks > this.config.maxScan) return undefined;\n try {\n const candidate = object(row.data);\n // Retention deliberately redacts ledger payloads. Reject tombstones before\n // issuing a UUID query: catching a PostgreSQL cast error cannot repair its transaction.\n if (\n typeof candidate.actionId !== 'string' ||\n !/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(\n candidate.actionId,\n )\n )\n return undefined;\n return await this.execution[feedbackActionTransaction](\n candidate.actionId,\n false,\n async (ctx) => {\n await this.authorize(ctx, 'retrieve');\n await this.provenance(ctx);\n const [current] = await this.rows(\n ctx.db,\n 'id=? AND kind=? AND NOT EXISTS (SELECT 1 FROM intake_feedback successor WHERE successor.tenant_id=intake_feedback.tenant_id AND successor.confidential_scope_id=intake_feedback.confidential_scope_id AND successor.supersedes_id=intake_feedback.id)',\n [row.id, 'interpretation'],\n );\n if (!current) return undefined;\n const data = object(current.data);\n const { digest: stored, ...body } = data;\n if (digest(body) !== stored) throw new Error('Feedback integrity');\n if (\n data.revision !== ctx.review.revision ||\n data.bindingHash !== ctx.review.bindingHash ||\n data.attemptId !== ctx.attemptId ||\n data.promptVersion !== input.promptVersion ||\n data.configurationVersion !== input.configurationVersion ||\n digest(data.model) !== digest(input.model)\n )\n return undefined;\n const offered = input.offered.find(\n (entry) =>\n entry.handler.id === data.handlerId &&\n entry.handler.version === data.handlerVersion,\n );\n if (!offered) return undefined;\n const args = object(data.args);\n for (const [field, reference] of Object.entries(\n offered.handler.references,\n )) {\n if (\n reference.kind === 'candidate' &&\n Object.hasOwn(args, field) &&\n !offered.candidates.some(\n (candidate) =>\n candidate.id === args[field] &&\n candidate.model === reference.model,\n )\n )\n return undefined;\n }\n return {\n feedbackId: String(current.id),\n digest: String(stored),\n itemId: ctx.itemId,\n actionId: ctx.review.actionId,\n revision: ctx.review.revision,\n handlerId: ctx.handlerId,\n handlerVersion: ctx.handlerVersion,\n judgment: data.judgment as 'correct' | 'incorrect',\n query: String(data.query),\n args,\n model: data.model as FeedbackExample['model'],\n promptVersion: String(data.promptVersion),\n configurationVersion: String(data.configurationVersion),\n };\n },\n executor,\n input.providers ?? [input.model.provider],\n );\n } catch {\n return undefined;\n }\n }\n private receivingContext(\n input: RetrieveFeedbackInput,\n executor: DatabaseInterface | undefined,\n work: (\n context: import('./execution-contracts.js').HandlerContext,\n ) => Promise<FeedbackSelection>,\n ): Promise<FeedbackSelection> {\n let limit = this.config.maxBytes;\n let bytes: number | undefined;\n const validate = async (\n context: import('./execution-contracts.js').HandlerContext,\n ) => {\n if (\n (input.providers ?? [input.model.provider]).some(\n (provider) => !context.policy.providers.includes(provider),\n )\n )\n throw new Error('Feedback recipient unavailable');\n limit = Math.min(limit, context.policy.maxBytes);\n if (bytes !== undefined && bytes > limit)\n throw new Error('Feedback limit');\n };\n const visit = (\n index: number,\n db: DatabaseInterface | undefined,\n ): Promise<FeedbackSelection> => {\n const entry = input.offered[index];\n return this.execution[feedbackDiscoveryContext](\n db,\n input.itemId,\n entry.handler.id,\n entry.handler.version,\n async (context) => {\n await validate(context);\n const selection =\n index + 1 < input.offered.length\n ? await visit(index + 1, context.db)\n : await work(context);\n bytes = Buffer.byteLength(JSON.stringify(selection));\n if (bytes > limit) throw new Error('Feedback limit');\n return selection;\n },\n validate,\n );\n };\n return visit(0, executor);\n }\n async retrieve(\n input: RetrieveFeedbackInput,\n executor?: DatabaseInterface,\n ): Promise<FeedbackSelection> {\n text(input.query, 4096);\n const offered = input.offered[0];\n if (!offered)\n return {\n version: this.config.version,\n configurationDigest: this.configurationDigest(),\n examples: [],\n };\n const work = async (\n context: import('./execution-contracts.js').HandlerContext,\n ) => {\n const authorize = async () => {\n if (\n !(await this.config.authorize({\n db: context.db,\n scope: this.scope(),\n itemId: input.itemId,\n operation: 'retrieve',\n }))\n )\n throw new Error('Feedback unavailable');\n };\n await authorize();\n const scope = this.scope();\n const rows = (\n await context.db.query(\n \"SELECT * FROM intake_feedback WHERE tenant_id=? AND confidential_scope_id=? AND kind='interpretation' ORDER BY id LIMIT ?\",\n scope.tenantId,\n scope.confidentialScopeId,\n this.config.maxScan,\n )\n ).rows;\n const ranked: Array<{ example: FeedbackExample; score: number }> = [];\n for (const row of rows) {\n const example = await this.example(row, input, context.db);\n if (!example) continue;\n const score = feedbackSimilarity(input.query, example.query);\n if (score >= this.config.minimumSimilarity)\n ranked.push({ example, score });\n }\n ranked.sort(\n (a, b) =>\n b.score - a.score ||\n a.example.feedbackId.localeCompare(b.example.feedbackId),\n );\n const selection = {\n version: this.config.version,\n configurationDigest: this.configurationDigest(),\n examples: ranked\n .slice(0, this.config.maxExamples)\n .map((entry) => entry.example),\n };\n await authorize();\n return selection;\n };\n return this.receivingContext(input, executor, work);\n }\n async assertSelection(\n input: RetrieveFeedbackInput,\n selection: FeedbackReferences,\n executor?: DatabaseInterface,\n ): Promise<void> {\n if (\n selection.version !== this.config.version ||\n selection.configurationDigest !== this.configurationDigest() ||\n !Array.isArray(selection.examples) ||\n selection.examples.length > this.config.maxExamples ||\n new Set(selection.examples.map((example) => example.feedbackId)).size !==\n selection.examples.length ||\n Buffer.byteLength(JSON.stringify(selection)) > this.config.maxBytes\n )\n throw new Error('Feedback eligibility changed');\n const offered = input.offered[0];\n if (!offered) {\n if (selection.examples.length)\n throw new Error('Feedback eligibility changed');\n return;\n }\n const work = async (\n context: import('./execution-contracts.js').HandlerContext,\n ) => {\n if (\n !(await this.config.authorize({\n db: context.db,\n scope: this.scope(),\n itemId: input.itemId,\n operation: 'retrieve',\n }))\n )\n throw new Error('Feedback unavailable');\n const examples: FeedbackExample[] = [];\n for (const expected of selection.examples) {\n const [row] = await this.rows(context.db, 'id=? AND kind=?', [\n expected.feedbackId,\n 'interpretation',\n ]);\n const current = row\n ? await this.example(row, input, context.db)\n : undefined;\n if (\n !current ||\n current.digest !== expected.digest ||\n feedbackSimilarity(input.query, current.query) <\n this.config.minimumSimilarity\n )\n throw new Error('Feedback eligibility changed');\n examples.push(current);\n }\n if (\n !(await this.config.authorize({\n db: context.db,\n scope: this.scope(),\n itemId: input.itemId,\n operation: 'retrieve',\n }))\n )\n throw new Error('Feedback unavailable');\n return { ...selection, examples };\n };\n await this.receivingContext(input, executor, work);\n }\n private async support(\n ctx: FeedbackActionContext,\n ids: string[],\n ): Promise<Array<{ id: string; digest: string; query: string }>> {\n if (\n !Array.isArray(ids) ||\n ids.length < 2 ||\n ids.length > this.config.maxExamples ||\n new Set(ids).size !== ids.length\n )\n throw new Error('Insufficient rule evidence');\n const provenance = await this.provenance(ctx),\n origins = new Set<string>(),\n result: Array<{ id: string; digest: string; query: string }> = [];\n for (const id of [...ids].sort()) {\n text(id);\n const [row] = await this.rows(ctx.db, 'id=? AND kind=?', [\n id,\n 'interpretation',\n ]);\n if (!row) throw new Error('Rule evidence unavailable');\n const data = object(row.data);\n await this.execution[feedbackActionTransaction](\n String(data.actionId),\n false,\n async (source) => {\n await this.authorize(source, 'retrieve');\n await this.provenance(source);\n if (origins.has(source.itemId))\n throw new Error('Independent rule evidence required');\n origins.add(source.itemId);\n const { digest: stored, ...body } = data;\n if (\n digest(body) !== stored ||\n data.judgment !== 'correct' ||\n data.revision !== source.review.revision ||\n data.bindingHash !== source.review.bindingHash ||\n data.handlerId !== ctx.handlerId ||\n data.handlerVersion !== ctx.handlerVersion ||\n digest(data.args) !== digest(ctx.args) ||\n data.promptVersion !== provenance.promptVersion ||\n data.configurationVersion !== provenance.configurationVersion ||\n digest(data.model) !== digest(provenance.model) ||\n (await this.rows(ctx.db, 'supersedes_id=?', [id])).length\n )\n throw new Error('Rule evidence unavailable');\n result.push({\n id,\n digest: String(stored),\n query: String(data.query),\n });\n },\n ctx.db,\n );\n }\n return result;\n }\n async suggest(input: SuggestRuleInput): Promise<RuleSuggestion> {\n digest(input);\n text(input.requestId);\n if (!this.config.policy) throw new Error('Rule policy owner unavailable');\n return this.execution[feedbackActionTransaction](\n input.actionId,\n true,\n async (ctx) => {\n this.checkBinding(input, ctx);\n await this.authorize(ctx, 'suggest');\n const support = await this.support(ctx, input.supportingFeedbackIds);\n const terms = feedbackTerms(support[0].query).filter((term) =>\n support.every((example) =>\n feedbackTerms(example.query).includes(term),\n ),\n );\n if (!terms.length) throw new Error('No shared routing evidence');\n const rule: RoutingRule = {\n handlerId: ctx.handlerId,\n handlerVersion: ctx.handlerVersion,\n matchTerms: terms,\n args: ctx.args,\n };\n const preview = await this.config.policy!.preview({\n db: ctx.db,\n scope: this.scope(),\n rule: structuredClone(rule),\n });\n text(preview.version);\n text(preview.preview, 4000);\n const body = {\n version: 1,\n actionId: input.actionId,\n revision: ctx.review.revision,\n bindingHash: ctx.review.bindingHash,\n rule,\n supportingFeedback: support.map(({ id, digest }) => ({ id, digest })),\n expectedPolicyVersion: preview.version,\n preview: preview.preview,\n reviewer: this.scope().actorId,\n requestHash: digest(input),\n };\n const key = `rule:${input.requestId}`;\n let [row] = await this.rows(ctx.db, 'item_id=? AND request_key=?', [\n ctx.itemId,\n key,\n ]);\n if (row) {\n if (object(row.data).requestHash !== body.requestHash)\n throw new Error('Rule request conflict');\n } else\n row = await this.insert(ctx, key, 'rule_suggestion', {\n ...body,\n digest: digest(body),\n });\n await this.authorize(ctx, 'suggest');\n return this.ruleDTO(row);\n },\n );\n }\n private ruleDTO(row: Row): RuleSuggestion {\n const data = object(row.data);\n return {\n id: String(row.id),\n digest: String(data.digest),\n itemId: String(row.item_id),\n rule: data.rule as unknown as RoutingRule,\n supportingFeedback:\n data.supportingFeedback as RuleSuggestion['supportingFeedback'],\n expectedPolicyVersion: String(data.expectedPolicyVersion),\n preview: String(data.preview),\n automaticActionEligible: false,\n };\n }\n private async rule(ctx: FeedbackActionContext, id: string): Promise<Row> {\n const [row] = await this.rows(ctx.db, 'item_id=? AND id=? AND kind=?', [\n ctx.itemId,\n id,\n 'rule_suggestion',\n ]);\n if (!row) throw new Error('Rule unavailable');\n const data = object(row.data),\n { digest: stored, ...body } = data;\n if (\n digest(body) !== stored ||\n data.actionId !== ctx.review.actionId ||\n data.revision !== ctx.review.revision ||\n data.bindingHash !== ctx.review.bindingHash\n )\n throw new Error('Stale rule');\n const support = data.supportingFeedback as Array<{\n id: string;\n digest: string;\n }>;\n const current = await this.support(\n ctx,\n support.map((entry) => entry.id),\n );\n if (\n digest(current.map(({ id, digest }) => ({ id, digest }))) !==\n digest(support)\n )\n throw new Error('Rule evidence changed');\n return row;\n }\n async readRule(input: ReadRuleInput): Promise<RuleSuggestion> {\n return this.execution[feedbackActionTransaction](\n input.actionId,\n true,\n async (ctx) => {\n this.checkBinding(input, ctx);\n await this.authorize(ctx, 'suggest');\n const suggestion = this.ruleDTO(\n await this.rule(ctx, input.suggestionId),\n );\n if (!this.config.policy)\n throw new Error('Rule policy owner unavailable');\n const current = await this.config.policy.preview({\n db: ctx.db,\n scope: this.scope(),\n rule: structuredClone(suggestion.rule),\n });\n if (\n current.version !== suggestion.expectedPolicyVersion ||\n current.preview !== suggestion.preview\n )\n throw new Error('Rule policy changed');\n await this.authorize(ctx, 'suggest');\n return suggestion;\n },\n );\n }\n async adopt(input: AdoptRuleInput): Promise<RuleAdoption> {\n digest(input);\n text(input.requestId);\n if (!this.config.policy) throw new Error('Rule policy owner unavailable');\n return this.execution[feedbackActionTransaction](\n input.actionId,\n true,\n async (ctx) => {\n this.checkBinding(input, ctx);\n await this.authorize(ctx, 'adopt');\n const row = await this.rule(ctx, input.suggestionId),\n suggestion = this.ruleDTO(row);\n if (\n input.expectedDigest !== suggestion.digest ||\n input.expectedPolicyVersion !== suggestion.expectedPolicyVersion\n )\n throw new Error('Stale rule');\n const requestHash = digest(input),\n key = `adopt:${input.requestId}`;\n const [replay] = await this.rows(\n ctx.db,\n 'item_id=? AND request_key=?',\n [ctx.itemId, key],\n );\n if (replay) {\n const data = object(replay.data);\n if (\n data.requestHash !== requestHash ||\n data.reviewer !== this.scope().actorId\n )\n throw new Error('Rule request conflict');\n return {\n id: String(replay.id),\n policyVersion: String(data.policyVersion),\n auditId: String(data.auditId),\n automaticActionEligible: false,\n };\n }\n const current = await this.config.policy!.preview({\n db: ctx.db,\n scope: this.scope(),\n rule: structuredClone(suggestion.rule),\n });\n if (current.version !== input.expectedPolicyVersion)\n throw new Error('Policy version changed');\n const applied = await this.config.policy!.adopt({\n db: ctx.db,\n scope: this.scope(),\n rule: structuredClone(suggestion.rule),\n expectedVersion: input.expectedPolicyVersion,\n requestId: input.requestId,\n });\n text(applied.version);\n text(applied.auditId);\n if (applied.version === input.expectedPolicyVersion)\n throw new Error('Policy version did not advance');\n const verified = await this.config.policy!.preview({\n db: ctx.db,\n scope: this.scope(),\n rule: structuredClone(suggestion.rule),\n });\n if (verified.version !== applied.version)\n throw new Error('Policy adoption mismatch');\n const body = {\n version: 1,\n requestHash,\n suggestionId: suggestion.id,\n suggestionDigest: suggestion.digest,\n previousPolicyVersion: input.expectedPolicyVersion,\n policyVersion: applied.version,\n auditId: applied.auditId,\n reviewer: this.scope().actorId,\n automaticActionEligible: false,\n };\n const saved = await this.insert(ctx, key, 'rule_adoption', {\n ...body,\n digest: digest(body),\n });\n await this.authorize(ctx, 'adopt');\n return {\n id: String(saved.id),\n policyVersion: applied.version,\n auditId: applied.auditId,\n automaticActionEligible: false,\n };\n },\n );\n }\n}\n"],"mappings":"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"}