@yadsh/dsh-qa-surface 0.6.1 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (287) hide show
  1. package/README.md +163 -7
  2. package/capability-policy.json +1 -1
  3. package/lib/access/capability-catalog.js +144 -0
  4. package/lib/access/capability-catalog.js.map +1 -0
  5. package/lib/access/model.js +379 -0
  6. package/lib/access/model.js.map +1 -0
  7. package/lib/access/role-repository.js +195 -0
  8. package/lib/access/role-repository.js.map +1 -0
  9. package/lib/access/service.js +380 -0
  10. package/lib/access/service.js.map +1 -0
  11. package/lib/access/skill-metadata.js +234 -0
  12. package/lib/access/skill-metadata.js.map +1 -0
  13. package/lib/account-remotes.js +20 -10
  14. package/lib/account-remotes.js.map +1 -1
  15. package/lib/accounts/errors.js.map +1 -1
  16. package/lib/accounts/file.js.map +1 -1
  17. package/lib/accounts/store.js +202 -3
  18. package/lib/accounts/store.js.map +1 -1
  19. package/lib/admin/conversation-log.js +256 -0
  20. package/lib/admin/conversation-log.js.map +1 -0
  21. package/lib/admin/index.js +17 -0
  22. package/lib/admin/index.js.map +1 -0
  23. package/lib/admin/metrics.js +103 -0
  24. package/lib/admin/metrics.js.map +1 -0
  25. package/lib/admin/paging.js +23 -0
  26. package/lib/admin/paging.js.map +1 -0
  27. package/lib/admin/permissions.js +50 -0
  28. package/lib/admin/permissions.js.map +1 -0
  29. package/lib/admin/quality-store.js +485 -0
  30. package/lib/admin/quality-store.js.map +1 -0
  31. package/lib/admin/queue.js +107 -0
  32. package/lib/admin/queue.js.map +1 -0
  33. package/lib/admin/redaction.js +45 -0
  34. package/lib/admin/redaction.js.map +1 -0
  35. package/lib/admin/service.js +897 -0
  36. package/lib/admin/service.js.map +1 -0
  37. package/lib/admin/session-log.js +142 -0
  38. package/lib/admin/session-log.js.map +1 -0
  39. package/lib/cli.js +9 -6
  40. package/lib/cli.js.map +1 -1
  41. package/lib/client/QaSessionController.js +28 -2
  42. package/lib/client/QaSessionController.js.map +1 -1
  43. package/lib/client/QaSurface.js +143 -5
  44. package/lib/client/QaSurface.js.map +1 -1
  45. package/lib/client/QaTranscriptAdapter.js +1 -0
  46. package/lib/client/QaTranscriptAdapter.js.map +1 -1
  47. package/lib/client/admin/QaAdmin.js +458 -0
  48. package/lib/client/admin/QaAdmin.js.map +1 -0
  49. package/lib/client/admin/format.js +177 -0
  50. package/lib/client/admin/format.js.map +1 -0
  51. package/lib/client/admin/pages/Conversations.js +114 -0
  52. package/lib/client/admin/pages/Conversations.js.map +1 -0
  53. package/lib/client/admin/pages/Overview.js +24 -0
  54. package/lib/client/admin/pages/Overview.js.map +1 -0
  55. package/lib/client/admin/pages/Quality.js +71 -0
  56. package/lib/client/admin/pages/Quality.js.map +1 -0
  57. package/lib/client/admin/pages/Review.js +93 -0
  58. package/lib/client/admin/pages/Review.js.map +1 -0
  59. package/lib/client/admin/pages/Users.js +95 -0
  60. package/lib/client/admin/pages/Users.js.map +1 -0
  61. package/lib/client/admin/routes.js +143 -0
  62. package/lib/client/admin/routes.js.map +1 -0
  63. package/lib/client/admin/shared.js +91 -0
  64. package/lib/client/admin/shared.js.map +1 -0
  65. package/lib/client/admin/styles.js +111 -0
  66. package/lib/client/admin/styles.js.map +1 -0
  67. package/lib/client/components/QaChangelog.js +53 -0
  68. package/lib/client/components/QaChangelog.js.map +1 -1
  69. package/lib/client/components/QaHeader.js +3 -3
  70. package/lib/client/components/QaHeader.js.map +1 -1
  71. package/lib/client/components/QaMessage.js +61 -2
  72. package/lib/client/components/QaMessage.js.map +1 -1
  73. package/lib/client/create-session.js +1 -1
  74. package/lib/client/create-session.js.map +1 -1
  75. package/lib/client/index.js +48 -1
  76. package/lib/client/index.js.map +1 -1
  77. package/lib/client/role/RoleSelector.js +31 -0
  78. package/lib/client/role/RoleSelector.js.map +1 -0
  79. package/lib/client/session-sources.js +37 -1
  80. package/lib/client/session-sources.js.map +1 -1
  81. package/lib/client/settings/card.js +2 -2
  82. package/lib/client/settings/card.js.map +1 -1
  83. package/lib/client/settings/sections.js +0 -1
  84. package/lib/client/settings/sections.js.map +1 -1
  85. package/lib/client/settings-extensions/index.js +1 -0
  86. package/lib/client/settings-extensions/index.js.map +1 -1
  87. package/lib/client/settings-extensions/user-session.js +62 -0
  88. package/lib/client/settings-extensions/user-session.js.map +1 -0
  89. package/lib/client/styles.js +31 -0
  90. package/lib/client/styles.js.map +1 -1
  91. package/lib/client/types.js.map +1 -1
  92. package/lib/client.js +9993 -4848
  93. package/lib/client.js.map +1 -1
  94. package/lib/config-resolvers/defaults.js +0 -2
  95. package/lib/config-resolvers/defaults.js.map +1 -1
  96. package/lib/config.js +0 -249
  97. package/lib/config.js.map +1 -1
  98. package/lib/enforcement/skill-policy.js +172 -0
  99. package/lib/enforcement/skill-policy.js.map +1 -0
  100. package/lib/enforcement/tool-grants.js +151 -0
  101. package/lib/enforcement/tool-grants.js.map +1 -0
  102. package/lib/index.js +224 -42
  103. package/lib/index.js.map +1 -1
  104. package/lib/personal-skills/service.js +10 -3
  105. package/lib/personal-skills/service.js.map +1 -1
  106. package/lib/qa-tools/index.js +4 -0
  107. package/lib/qa-tools/index.js.map +1 -1
  108. package/lib/resolve-config.js +0 -2
  109. package/lib/resolve-config.js.map +1 -1
  110. package/lib/secure-session.js +71 -17
  111. package/lib/secure-session.js.map +1 -1
  112. package/lib/typert.host.js +2237 -202
  113. package/lib/typert.remote-client.d.ts +49 -3
  114. package/lib/typert.remote-client.js +1863 -183
  115. package/lib/types/access/capability-catalog.d.ts +37 -0
  116. package/lib/types/access/model.d.ts +60 -0
  117. package/lib/types/access/role-repository.d.ts +32 -0
  118. package/lib/types/access/service.d.ts +57 -0
  119. package/lib/types/access/skill-metadata.d.ts +53 -0
  120. package/lib/types/account-remotes.d.ts +6 -0
  121. package/lib/types/accounts/errors.d.ts +1 -1
  122. package/lib/types/accounts/file.d.ts +16 -5
  123. package/lib/types/accounts/store.d.ts +83 -3
  124. package/lib/types/admin/conversation-log.d.ts +39 -0
  125. package/lib/types/admin/index.d.ts +24 -0
  126. package/lib/types/admin/metrics.d.ts +29 -0
  127. package/lib/types/admin/paging.d.ts +33 -0
  128. package/lib/types/admin/permissions.d.ts +10 -0
  129. package/lib/types/admin/quality-store.d.ts +82 -0
  130. package/lib/types/admin/queue.d.ts +21 -0
  131. package/lib/types/admin/redaction.d.ts +29 -0
  132. package/lib/types/admin/service.d.ts +105 -0
  133. package/lib/types/admin/session-log.d.ts +53 -0
  134. package/lib/types/client/QaSessionController.d.ts +12 -1
  135. package/lib/types/client/QaSurface.d.ts +7 -1
  136. package/lib/types/client/admin/QaAdmin.d.ts +17 -0
  137. package/lib/types/client/admin/format.d.ts +43 -0
  138. package/lib/types/client/admin/pages/Conversations.d.ts +21 -0
  139. package/lib/types/client/admin/pages/Overview.d.ts +13 -0
  140. package/lib/types/client/admin/pages/Quality.d.ts +18 -0
  141. package/lib/types/client/admin/pages/Review.d.ts +15 -0
  142. package/lib/types/client/admin/pages/Users.d.ts +22 -0
  143. package/lib/types/client/admin/routes.d.ts +60 -0
  144. package/lib/types/client/admin/shared.d.ts +53 -0
  145. package/lib/types/client/admin/styles.d.ts +11 -0
  146. package/lib/types/client/components/QaHeader.d.ts +5 -1
  147. package/lib/types/client/components/QaMessage.d.ts +14 -1
  148. package/lib/types/client/create-session.d.ts +2 -0
  149. package/lib/types/client/role/RoleSelector.d.ts +14 -0
  150. package/lib/types/client/session-sources.d.ts +9 -0
  151. package/lib/types/client/settings/sections.d.ts +0 -1
  152. package/lib/types/client/settings-extensions/index.d.ts +2 -0
  153. package/lib/types/client/settings-extensions/user-session.d.ts +59 -0
  154. package/lib/types/client/types.d.ts +39 -2
  155. package/lib/types/enforcement/skill-policy.d.ts +29 -0
  156. package/lib/types/enforcement/tool-grants.d.ts +84 -0
  157. package/lib/types/index.d.ts +62 -14
  158. package/lib/types/qa-tools/index.d.ts +2 -0
  159. package/lib/types/secure-session.d.ts +10 -1
  160. package/lib/types/types.d.ts +568 -5
  161. package/package.json +2 -2
  162. package/lib/client/settings/sections/documents.js +0 -88
  163. package/lib/client/settings/sections/documents.js.map +0 -1
  164. package/lib/documents/artifacts/ids.js +0 -43
  165. package/lib/documents/artifacts/ids.js.map +0 -1
  166. package/lib/documents/artifacts/manifest.js +0 -66
  167. package/lib/documents/artifacts/manifest.js.map +0 -1
  168. package/lib/documents/artifacts/store.js +0 -169
  169. package/lib/documents/artifacts/store.js.map +0 -1
  170. package/lib/documents/capabilities.js +0 -93
  171. package/lib/documents/capabilities.js.map +0 -1
  172. package/lib/documents/config.js +0 -302
  173. package/lib/documents/config.js.map +0 -1
  174. package/lib/documents/defaults.js +0 -78
  175. package/lib/documents/defaults.js.map +0 -1
  176. package/lib/documents/errors.js +0 -101
  177. package/lib/documents/errors.js.map +0 -1
  178. package/lib/documents/index.js +0 -80
  179. package/lib/documents/index.js.map +0 -1
  180. package/lib/documents/inspect/facts.js +0 -161
  181. package/lib/documents/inspect/facts.js.map +0 -1
  182. package/lib/documents/inspect/zip.js +0 -108
  183. package/lib/documents/inspect/zip.js.map +0 -1
  184. package/lib/documents/markdown/directives.js +0 -135
  185. package/lib/documents/markdown/directives.js.map +0 -1
  186. package/lib/documents/markdown/frontmatter.js +0 -35
  187. package/lib/documents/markdown/frontmatter.js.map +0 -1
  188. package/lib/documents/markdown/normalize.js +0 -113
  189. package/lib/documents/markdown/normalize.js.map +0 -1
  190. package/lib/documents/orchestrator/assets.js +0 -243
  191. package/lib/documents/orchestrator/assets.js.map +0 -1
  192. package/lib/documents/orchestrator/convert-document.js +0 -186
  193. package/lib/documents/orchestrator/convert-document.js.map +0 -1
  194. package/lib/documents/orchestrator/create-document.js +0 -292
  195. package/lib/documents/orchestrator/create-document.js.map +0 -1
  196. package/lib/documents/orchestrator/extract-document.js +0 -162
  197. package/lib/documents/orchestrator/extract-document.js.map +0 -1
  198. package/lib/documents/orchestrator/inspect-document.js +0 -89
  199. package/lib/documents/orchestrator/inspect-document.js.map +0 -1
  200. package/lib/documents/orchestrator/runtime-deps.js +0 -59
  201. package/lib/documents/orchestrator/runtime-deps.js.map +0 -1
  202. package/lib/documents/orchestrator/scope.js +0 -132
  203. package/lib/documents/orchestrator/scope.js.map +0 -1
  204. package/lib/documents/providers/docling.js +0 -247
  205. package/lib/documents/providers/docling.js.map +0 -1
  206. package/lib/documents/providers/libreoffice.js +0 -130
  207. package/lib/documents/providers/libreoffice.js.map +0 -1
  208. package/lib/documents/providers/markitdown.js +0 -89
  209. package/lib/documents/providers/markitdown.js.map +0 -1
  210. package/lib/documents/providers/pandoc.js +0 -161
  211. package/lib/documents/providers/pandoc.js.map +0 -1
  212. package/lib/documents/providers/process.js +0 -164
  213. package/lib/documents/providers/process.js.map +0 -1
  214. package/lib/documents/providers/registry.js +0 -152
  215. package/lib/documents/providers/registry.js.map +0 -1
  216. package/lib/documents/providers/shared.js +0 -75
  217. package/lib/documents/providers/shared.js.map +0 -1
  218. package/lib/documents/runtime.js +0 -114
  219. package/lib/documents/runtime.js.map +0 -1
  220. package/lib/documents/security/file-types.js +0 -188
  221. package/lib/documents/security/file-types.js.map +0 -1
  222. package/lib/documents/security/limits.js +0 -78
  223. package/lib/documents/security/limits.js.map +0 -1
  224. package/lib/documents/security/mime.js +0 -43
  225. package/lib/documents/security/mime.js.map +0 -1
  226. package/lib/documents/security/paths.js +0 -133
  227. package/lib/documents/security/paths.js.map +0 -1
  228. package/lib/documents/templates/registry.js +0 -147
  229. package/lib/documents/templates/registry.js.map +0 -1
  230. package/lib/documents/templates/resolver.js +0 -59
  231. package/lib/documents/templates/resolver.js.map +0 -1
  232. package/lib/documents/tools/convert.js +0 -125
  233. package/lib/documents/tools/convert.js.map +0 -1
  234. package/lib/documents/tools/create.js +0 -187
  235. package/lib/documents/tools/create.js.map +0 -1
  236. package/lib/documents/tools/index.js +0 -41
  237. package/lib/documents/tools/index.js.map +0 -1
  238. package/lib/documents/tools/inspect.js +0 -135
  239. package/lib/documents/tools/inspect.js.map +0 -1
  240. package/lib/documents/tools/shared.js +0 -88
  241. package/lib/documents/tools/shared.js.map +0 -1
  242. package/lib/documents/tools/to-markdown.js +0 -125
  243. package/lib/documents/tools/to-markdown.js.map +0 -1
  244. package/lib/documents/types.js +0 -12
  245. package/lib/documents/types.js.map +0 -1
  246. package/lib/types/client/settings/sections/documents.d.ts +0 -13
  247. package/lib/types/documents/artifacts/ids.d.ts +0 -14
  248. package/lib/types/documents/artifacts/manifest.d.ts +0 -32
  249. package/lib/types/documents/artifacts/store.d.ts +0 -67
  250. package/lib/types/documents/capabilities.d.ts +0 -32
  251. package/lib/types/documents/config.d.ts +0 -27
  252. package/lib/types/documents/defaults.d.ts +0 -161
  253. package/lib/types/documents/errors.d.ts +0 -42
  254. package/lib/types/documents/index.d.ts +0 -63
  255. package/lib/types/documents/inspect/facts.d.ts +0 -43
  256. package/lib/types/documents/inspect/zip.d.ts +0 -28
  257. package/lib/types/documents/markdown/directives.d.ts +0 -39
  258. package/lib/types/documents/markdown/frontmatter.d.ts +0 -15
  259. package/lib/types/documents/markdown/normalize.d.ts +0 -30
  260. package/lib/types/documents/orchestrator/assets.d.ts +0 -55
  261. package/lib/types/documents/orchestrator/convert-document.d.ts +0 -25
  262. package/lib/types/documents/orchestrator/create-document.d.ts +0 -18
  263. package/lib/types/documents/orchestrator/extract-document.d.ts +0 -24
  264. package/lib/types/documents/orchestrator/inspect-document.d.ts +0 -12
  265. package/lib/types/documents/orchestrator/runtime-deps.d.ts +0 -43
  266. package/lib/types/documents/orchestrator/scope.d.ts +0 -52
  267. package/lib/types/documents/providers/docling.d.ts +0 -54
  268. package/lib/types/documents/providers/libreoffice.d.ts +0 -40
  269. package/lib/types/documents/providers/markitdown.d.ts +0 -28
  270. package/lib/types/documents/providers/pandoc.d.ts +0 -42
  271. package/lib/types/documents/providers/process.d.ts +0 -54
  272. package/lib/types/documents/providers/registry.d.ts +0 -68
  273. package/lib/types/documents/providers/shared.d.ts +0 -27
  274. package/lib/types/documents/runtime.d.ts +0 -59
  275. package/lib/types/documents/security/file-types.d.ts +0 -39
  276. package/lib/types/documents/security/limits.d.ts +0 -24
  277. package/lib/types/documents/security/mime.d.ts +0 -13
  278. package/lib/types/documents/security/paths.d.ts +0 -38
  279. package/lib/types/documents/templates/registry.d.ts +0 -50
  280. package/lib/types/documents/templates/resolver.d.ts +0 -30
  281. package/lib/types/documents/tools/convert.d.ts +0 -9
  282. package/lib/types/documents/tools/create.d.ts +0 -14
  283. package/lib/types/documents/tools/index.d.ts +0 -33
  284. package/lib/types/documents/tools/inspect.d.ts +0 -9
  285. package/lib/types/documents/tools/shared.d.ts +0 -77
  286. package/lib/types/documents/tools/to-markdown.d.ts +0 -12
  287. package/lib/types/documents/types.d.ts +0 -294
@@ -1,4 +1,3 @@
1
- import type { QaDocumentsConfig, ResolvedQaDocumentsConfig } from "./documents/config.js";
2
1
  import type { QaTurnSources } from "./provenance/types.js";
3
2
  export type QaSessionPolicy = "browser-persistent" | "new-on-load" | "fixed";
4
3
  export type QaSandboxMode = "read-only" | "workspace-write";
@@ -29,7 +28,236 @@ export interface QaQuestionAnswerItem {
29
28
  readonly selected: readonly string[];
30
29
  readonly custom?: string;
31
30
  }
32
- export type QaAccountRole = "user" | "admin";
31
+ /**
32
+ * Authorization inside QA Surface. It is deliberately independent of a QA
33
+ * subrole: an admin may work as any analyst profile while still holding the
34
+ * administrative permissions, and a reviewer answers conversations without
35
+ * being able to manage accounts.
36
+ */
37
+ export type QaAccountRole = "user" | "reviewer" | "admin";
38
+ /** Administrative permissions a role grants; see `admin/permissions.ts`. */
39
+ export type QaPermission = "users.read" | "users.manage" | "roles.read" | "roles.manage" | "conversations.read.all" | "conversations.read.own" | "reviews.read" | "reviews.write" | "analytics.read" | "audit.read" | "settings.manage";
40
+ /**
41
+ * Tools split by how they become available. `always` is visible from the first
42
+ * model step; `skillGrantable` is a ceiling — the tool only appears once an
43
+ * activated skill requires it, and never outside this list.
44
+ */
45
+ export interface QaToolSelection {
46
+ readonly always: readonly string[];
47
+ readonly skillGrantable: readonly string[];
48
+ }
49
+ /** Tool/skill selection shared by the common layer and one QA subrole. */
50
+ export interface QaCapabilitySelection {
51
+ readonly tools: QaToolSelection;
52
+ readonly skills: readonly string[];
53
+ /** Reserved extension seams; v1 enforcement intentionally ignores them. */
54
+ readonly mcpServers?: readonly string[];
55
+ readonly knowledgeSources?: readonly string[];
56
+ readonly promptAdditions?: readonly string[];
57
+ }
58
+ /** Audience one skill declares for itself in its own SKILL.md metadata. */
59
+ export type QaSkillAudience = {
60
+ readonly type: "unassigned";
61
+ } | {
62
+ readonly type: "common";
63
+ } | {
64
+ readonly type: "subroles";
65
+ readonly include: readonly string[];
66
+ };
67
+ /**
68
+ * Normalized `metadata.qa-surface` of one skill. Discovery never throws on a
69
+ * malformed block: the fields fall back to the fail-closed defaults and every
70
+ * complaint lands in `warnings` for the administration surface.
71
+ */
72
+ export interface QaSkillDescriptor {
73
+ readonly name: string;
74
+ readonly audience: QaSkillAudience;
75
+ /** Tools the skill needs to work; the role ceiling still decides the grant. */
76
+ readonly requiredTools: readonly string[];
77
+ /** Whether activation must be refused when one required tool is unavailable. */
78
+ readonly requireAll: boolean;
79
+ readonly lifecycle: "session";
80
+ /** `metadata.qa-surface.version`; 0 when the block declared none. */
81
+ readonly schemaVersion: number;
82
+ /** Whether the skill carried a readable qa-surface metadata block. */
83
+ readonly declared: boolean;
84
+ readonly warnings: readonly string[];
85
+ }
86
+ /**
87
+ * Administrator overlay over one skill's declared audience. The skill file is
88
+ * never rewritten: assignments are stored beside the policy and merged here.
89
+ */
90
+ export interface QaSkillAssignmentOverride {
91
+ readonly skillName: string;
92
+ readonly addToSubroles?: readonly string[];
93
+ readonly removeFromSubroles?: readonly string[];
94
+ readonly forceCommon?: boolean;
95
+ readonly disabled?: boolean;
96
+ }
97
+ export type QaSkillHealth = "healthy" | "degraded" | "blocked" | "unassigned";
98
+ /** Per-role projection of one skill: what the role sees and what it may grant. */
99
+ export interface QaSkillRoleGrant {
100
+ readonly roleId: string;
101
+ readonly visible: boolean;
102
+ readonly declared: boolean;
103
+ readonly addedByAdmin: boolean;
104
+ readonly removedByAdmin: boolean;
105
+ readonly disabled: boolean;
106
+ /** Required tools this role's ceiling admits. */
107
+ readonly grantableTools: readonly string[];
108
+ /** Required tools this role cannot grant: outside the ceiling or not installed. */
109
+ readonly unavailableTools: readonly string[];
110
+ }
111
+ /** One row of the administration Skills table plus its detail view. */
112
+ export interface QaSkillAccess {
113
+ readonly name: string;
114
+ readonly description?: string;
115
+ readonly whenToUse?: string;
116
+ readonly source: QaCapabilityDescriptor["source"];
117
+ readonly status: "available" | "missing";
118
+ readonly descriptor: QaSkillDescriptor;
119
+ /** Roles whose policy currently exposes the skill. */
120
+ readonly visibleTo: readonly string[];
121
+ readonly disabled: boolean;
122
+ readonly forceCommon: boolean;
123
+ readonly overridden: boolean;
124
+ readonly health: QaSkillHealth;
125
+ /** Every required tool with the union of roles that could grant it. */
126
+ readonly tools: readonly {
127
+ readonly id: string;
128
+ readonly installed: boolean;
129
+ readonly grantableBy: readonly string[];
130
+ readonly blockedFor: readonly string[];
131
+ }[];
132
+ readonly roles: readonly QaSkillRoleGrant[];
133
+ }
134
+ /** Why a skill activation was attempted; recorded for conversation review. */
135
+ export type QaSkillActivationOrigin = "model" | "user" | "preview";
136
+ /**
137
+ * One activation attempt on a live session, appended to the session record.
138
+ * `denied` covers an audience refusal, `rejected` a failed `requireAll` check.
139
+ */
140
+ export interface QaSkillActivationRecord {
141
+ readonly timestamp: string;
142
+ readonly skillName: string;
143
+ readonly origin: QaSkillActivationOrigin;
144
+ readonly outcome: "activated" | "rejected" | "denied";
145
+ readonly requestedTools: readonly string[];
146
+ readonly grantedTools: readonly string[];
147
+ readonly deniedTools: readonly string[];
148
+ readonly reason?: string;
149
+ }
150
+ /** One agent capability profile. It never grants administrative access. */
151
+ export interface QaSubrole {
152
+ readonly id: string;
153
+ readonly name: string;
154
+ readonly description?: string;
155
+ readonly enabled: boolean;
156
+ readonly capabilities: QaCapabilitySelection;
157
+ readonly ui?: {
158
+ readonly icon?: string;
159
+ readonly accent?: string;
160
+ };
161
+ }
162
+ /** Host-owned, versioned capability configuration. */
163
+ export interface QaCapabilityConfig {
164
+ readonly version: 1;
165
+ readonly common: QaCapabilitySelection;
166
+ readonly subroles: readonly QaSubrole[];
167
+ /** Administrator assignments layered over what each skill declares. */
168
+ readonly skillOverrides: readonly QaSkillAssignmentOverride[];
169
+ }
170
+ /** The QA profiles one account may choose, independently of its access role. */
171
+ export interface QaUserAccess {
172
+ readonly allowedSubroles: readonly string[];
173
+ readonly defaultSubrole: string;
174
+ }
175
+ export type QaCapabilitySourceKind = "core" | "plugin" | "mcp" | "filesystem" | "runtime";
176
+ /** One capability currently installed, or retained as a missing selection. */
177
+ export interface QaCapabilityDescriptor {
178
+ readonly type: "tool" | "skill";
179
+ readonly id: string;
180
+ readonly title: string;
181
+ readonly description?: string;
182
+ readonly source: {
183
+ readonly kind: QaCapabilitySourceKind;
184
+ readonly name?: string;
185
+ };
186
+ readonly status: "available" | "missing";
187
+ readonly modelInvocable?: boolean;
188
+ readonly userInvocable?: boolean;
189
+ }
190
+ /** JSON-safe projection of an immutable policy snapshot. */
191
+ export interface QaEffectiveCapabilityPolicy {
192
+ readonly subroleId: string;
193
+ /** Tools visible from the first model step, before any skill is loaded. */
194
+ readonly tools: readonly string[];
195
+ /** Ceiling for the tools an activated skill may add to this session. */
196
+ readonly grantableTools: readonly string[];
197
+ /** Skills the model may see and load for the frozen subrole. */
198
+ readonly skills: readonly string[];
199
+ /**
200
+ * Visible skills a person may invoke with `/name`, including skills that
201
+ * opted out of model invocation and therefore stay out of the catalog.
202
+ */
203
+ readonly userSkills: readonly string[];
204
+ readonly sources: {
205
+ readonly systemTools: readonly string[];
206
+ readonly commonTools: readonly string[];
207
+ readonly roleTools: readonly string[];
208
+ readonly commonGrantableTools: readonly string[];
209
+ readonly roleGrantableTools: readonly string[];
210
+ readonly systemSkills: readonly string[];
211
+ readonly commonSkills: readonly string[];
212
+ readonly roleSkills: readonly string[];
213
+ /** Skills this subrole received from their own SKILL.md audience. */
214
+ readonly declaredSkills: readonly string[];
215
+ };
216
+ readonly missingTools: readonly string[];
217
+ readonly missingSkills: readonly string[];
218
+ /** Revision of the resolved policy, recorded with the session snapshot. */
219
+ readonly policyRevision: string;
220
+ }
221
+ export type QaAccessAuditAction = "subrole.created" | "subrole.updated" | "subrole.deleted" | "common.updated" | "assignment.updated" | "skill.assignment-updated";
222
+ export interface QaAccessAuditEvent {
223
+ readonly timestamp: string;
224
+ readonly actorId: string;
225
+ readonly action: QaAccessAuditAction;
226
+ readonly targetId?: string;
227
+ /** JSON snapshots serialized at the storage boundary for a strict Remote type. */
228
+ readonly before?: string;
229
+ readonly after?: string;
230
+ }
231
+ /** Admin table row: credentials and token material are never projected. */
232
+ export interface QaAccessUser {
233
+ readonly id: string;
234
+ readonly email: string;
235
+ readonly displayName: string;
236
+ readonly accessRole: QaAccountRole;
237
+ readonly disabled: boolean;
238
+ readonly access: QaUserAccess;
239
+ }
240
+ /** Ordinary user's role selector data. */
241
+ export interface QaCurrentAccess {
242
+ readonly subroles: readonly QaSubrole[];
243
+ readonly defaultSubrole: string;
244
+ }
245
+ /** The role pinned to one existing session. */
246
+ export interface QaSessionAccess {
247
+ readonly subrole: QaSubrole;
248
+ readonly adminPreview: boolean;
249
+ }
250
+ /** One authoritative payload for the /qa/admin application. */
251
+ export interface QaAccessAdminSnapshot {
252
+ readonly config: QaCapabilityConfig;
253
+ /** Immutable capabilities inherited by every role; exposed read-only. */
254
+ readonly systemRequired: QaCapabilitySelection;
255
+ readonly catalog: readonly QaCapabilityDescriptor[];
256
+ /** Every discovered skill with its declared audience and grant ceiling. */
257
+ readonly skills: readonly QaSkillAccess[];
258
+ readonly users: readonly QaAccessUser[];
259
+ readonly audit: readonly QaAccessAuditEvent[];
260
+ }
33
261
  /** The account fields projected to browsers; never includes credentials. */
34
262
  export interface QaAccountUserPublic {
35
263
  readonly id: string;
@@ -401,8 +629,6 @@ export interface QaSurfaceConfig {
401
629
  };
402
630
  readonly sources?: QaSourcesConfig;
403
631
  readonly attachments?: QaAttachmentsConfig;
404
- /** Document pipeline: creation, conversion and extraction (see documents/). */
405
- readonly documents?: QaDocumentsConfig;
406
632
  }
407
633
  /** What a QA visitor may attach to one message. */
408
634
  export interface QaAttachmentsConfig {
@@ -577,7 +803,6 @@ export interface ResolvedQaSurfaceConfig {
577
803
  readonly maxPending: number;
578
804
  readonly extensions: readonly string[];
579
805
  };
580
- readonly documents: ResolvedQaDocumentsConfig;
581
806
  }
582
807
  export interface QaSourceFilePreview {
583
808
  readonly path: string;
@@ -626,6 +851,12 @@ export type QaMessage = QaUserMessage | {
626
851
  readonly text: string;
627
852
  readonly status: "streaming" | "committed" | "failed";
628
853
  readonly timestamp?: number;
854
+ /**
855
+ * Position of this answer in the session's durable event log. Feedback is
856
+ * keyed to it: a rating survives a replay, a reload and a role change,
857
+ * while the browser's own message id does not.
858
+ */
859
+ readonly seq?: number;
629
860
  /** Host turn this answer belongs to; groups regenerations into variants. */
630
861
  readonly turn?: number;
631
862
  /** Canonical evidence snapshot shared with this answer's source drawer. */
@@ -813,4 +1044,336 @@ export interface QaSessionState {
813
1044
  export interface QaPrincipal {
814
1045
  readonly userId: string;
815
1046
  }
1047
+ /** A user's verdict on one assistant message. Binary by design. */
1048
+ export type QaFeedbackRating = "positive" | "negative";
1049
+ /**
1050
+ * Optional negative-feedback reasons. The list is short on purpose: asking for
1051
+ * a precise cause at rating time costs more answers than it buys insight, and
1052
+ * a reviewer classifies the hard cases afterwards.
1053
+ */
1054
+ export type QaFeedbackReason = "incorrect" | "instruction_not_followed" | "missing_information" | "outdated_information" | "tool_issue" | "too_verbose" | "too_short" | "other";
1055
+ /** One user's rating of one assistant message. */
1056
+ export interface QaMessageFeedback {
1057
+ readonly id: string;
1058
+ readonly conversationId: string;
1059
+ readonly messageId: string;
1060
+ readonly userId: string;
1061
+ readonly rating: QaFeedbackRating;
1062
+ readonly reasons?: readonly QaFeedbackReason[];
1063
+ readonly comment?: string;
1064
+ readonly createdAt: string;
1065
+ readonly updatedAt?: string;
1066
+ }
1067
+ /** The rating fields a browser may write; identity and time are Host-owned. */
1068
+ export interface QaMessageFeedbackInput {
1069
+ readonly rating: QaFeedbackRating;
1070
+ readonly reasons?: readonly QaFeedbackReason[];
1071
+ readonly comment?: string;
1072
+ }
1073
+ /** Review workflow state of a conversation or one of its messages. */
1074
+ export type QaReviewStatus = "unreviewed" | "in_review" | "reviewed" | "needs_followup";
1075
+ /**
1076
+ * Reviewer taxonomy, grouped the way the spec groups it. Issue ids stay flat so
1077
+ * aggregations never depend on walking a tree in the browser.
1078
+ */
1079
+ export type QaQualityIssueType = "answer.incorrect" | "answer.incomplete" | "answer.hallucination" | "answer.request_not_followed" | "answer.poor_formatting" | "answer.communication" | "context.missing_conversation" | "context.missing_knowledge" | "context.outdated_knowledge" | "tool.wrong_selection" | "tool.should_have_been_used" | "tool.bad_arguments" | "tool.failure" | "tool.unavailable" | "skill.missing" | "skill.wrong" | "skill.not_followed" | "skill.prompt_policy" | "access.missing_capability" | "access.excessive_capability" | "other";
1080
+ export type QaQualitySeverity = "minor" | "major" | "critical";
1081
+ /** Where a reviewer thinks the fix belongs; the loop's change target. */
1082
+ export type QaRemediationTarget = "prompt" | "skill" | "tool" | "knowledge" | "role" | "model" | "product_ux" | "user_misunderstanding" | "unknown";
1083
+ /** One reviewer result. `needs_followup` keeps the item in the queue. */
1084
+ export interface QaConversationReview {
1085
+ readonly id: string;
1086
+ readonly conversationId: string;
1087
+ readonly messageId?: string;
1088
+ readonly reviewerId: string;
1089
+ readonly status: "reviewed" | "needs_followup";
1090
+ readonly issues: readonly QaQualityIssueType[];
1091
+ readonly severity: QaQualitySeverity;
1092
+ readonly notes?: string;
1093
+ readonly target?: QaRemediationTarget;
1094
+ readonly suggestedAction?: string;
1095
+ readonly createdAt: string;
1096
+ readonly updatedAt?: string;
1097
+ }
1098
+ /** A reviewer's write; ids, author and first-seen time are Host-owned. */
1099
+ export interface QaConversationReviewInput {
1100
+ readonly conversationId: string;
1101
+ readonly messageId?: string;
1102
+ readonly status: "reviewed" | "needs_followup";
1103
+ readonly issues: readonly QaQualityIssueType[];
1104
+ readonly severity: QaQualitySeverity;
1105
+ readonly notes?: string;
1106
+ readonly target?: QaRemediationTarget;
1107
+ readonly suggestedAction?: string;
1108
+ }
1109
+ /** Why a conversation entered the review queue. */
1110
+ export type QaReviewReason = "negative_feedback" | "manual" | "tool_failure" | "automatic";
1111
+ export type QaReviewPriority = "low" | "normal" | "high";
1112
+ /** One queue row: a conversation needing attention, with its derived state. */
1113
+ export interface QaReviewQueueItem {
1114
+ readonly conversationId: string;
1115
+ readonly messageId?: string;
1116
+ readonly reason: QaReviewReason;
1117
+ readonly priority: QaReviewPriority;
1118
+ readonly status: QaReviewStatus;
1119
+ readonly assignedReviewerId?: string;
1120
+ /** ISO time of the signal that put the item in the queue. */
1121
+ readonly raisedAt: string;
1122
+ readonly reviewerId?: string;
1123
+ readonly reviewId?: string;
1124
+ readonly feedbackId?: string;
1125
+ }
1126
+ /** Administrative actions recorded in the audit trail. */
1127
+ export type QaAdminAuditAction = "user.created" | "user.updated" | "user.enabled" | "user.disabled" | "authorization.changed" | "subrole.assignment.changed" | "subrole.created" | "subrole.updated" | "subrole.deleted" | "common_capabilities.updated" | "conversation.reviewed" | "review.updated" | "review.queued" | "admin.settings.updated";
1128
+ export interface QaAdminAuditEvent {
1129
+ readonly id: string;
1130
+ readonly timestamp: string;
1131
+ readonly actorId: string;
1132
+ readonly action: QaAdminAuditAction;
1133
+ readonly targetType?: string;
1134
+ readonly targetId?: string;
1135
+ /** JSON snapshots serialized at the storage boundary for a strict Remote type. */
1136
+ readonly before?: string;
1137
+ readonly after?: string;
1138
+ }
1139
+ /**
1140
+ * One tool call as the review viewer shows it. `arguments` and `result` are
1141
+ * preview strings, not raw payloads: the admin redaction seam owns trimming.
1142
+ */
1143
+ export interface QaConversationToolCall {
1144
+ readonly callId: string;
1145
+ readonly name: string;
1146
+ readonly arguments: string;
1147
+ readonly result?: string;
1148
+ readonly error?: string;
1149
+ readonly time?: number;
1150
+ readonly durationMs?: number;
1151
+ }
1152
+ /** Token accounting of one assistant message, when the log carries it. */
1153
+ export interface QaMessageUsage {
1154
+ readonly inputTokens: number;
1155
+ readonly outputTokens: number;
1156
+ readonly totalTokens?: number;
1157
+ }
1158
+ /** One message in the review viewer, in log order. */
1159
+ export interface QaConversationMessage {
1160
+ /** Stable message identity: the session event seq it was projected from. */
1161
+ readonly id: string;
1162
+ readonly seq: number;
1163
+ readonly role: "user" | "assistant" | "system";
1164
+ readonly text: string;
1165
+ readonly time: number;
1166
+ readonly model?: string;
1167
+ readonly provider?: string;
1168
+ readonly usage?: QaMessageUsage;
1169
+ readonly interrupted?: boolean;
1170
+ readonly toolCalls?: readonly QaConversationToolCall[];
1171
+ /** Ratings of this message by its owner, newest first. */
1172
+ readonly feedback?: readonly QaMessageFeedback[];
1173
+ /** Reviewer results attached to this exact message. */
1174
+ readonly reviews?: readonly QaConversationReview[];
1175
+ }
1176
+ /**
1177
+ * What the agent could use in a conversation, frozen when the session was
1178
+ * reserved. Reviewing an old answer against today's role configuration would
1179
+ * answer the wrong question.
1180
+ */
1181
+ export interface QaConversationRuntime {
1182
+ readonly subroleId: string;
1183
+ readonly adminPreview: boolean;
1184
+ readonly model?: string;
1185
+ readonly provider?: string;
1186
+ readonly agentPreset?: string;
1187
+ readonly effectiveTools?: readonly string[];
1188
+ readonly effectiveSkills?: readonly string[];
1189
+ /** Skills the model actually loaded, derived from the log's skill tool calls. */
1190
+ readonly loadedSkills?: readonly string[];
1191
+ /** True when the stored log could not be read; counts stay 0 and text is absent. */
1192
+ readonly transcriptUnavailable?: QaTranscriptUnavailableReason;
1193
+ }
1194
+ /** Why a stored transcript could not be projected for the reviewer. */
1195
+ export type QaTranscriptUnavailableReason = "storage-unavailable" | "not-found" | "unreadable";
1196
+ /** One conversation row of the administrative list. */
1197
+ export interface QaConversationSummary {
1198
+ readonly conversationId: string;
1199
+ readonly userId: string;
1200
+ readonly displayName: string;
1201
+ readonly subroleId: string;
1202
+ readonly createdAt: string;
1203
+ /** Newest activity the deployment can see: creation, log tail, or a review. */
1204
+ readonly updatedAt: string;
1205
+ readonly title?: string;
1206
+ readonly messageCount: number;
1207
+ readonly positiveFeedback: number;
1208
+ readonly negativeFeedback: number;
1209
+ readonly reviewStatus: QaReviewStatus;
1210
+ }
1211
+ /** The full review payload of one conversation. */
1212
+ export interface QaConversationDetail {
1213
+ readonly conversationId: string;
1214
+ readonly summary: QaConversationSummary;
1215
+ readonly runtime: QaConversationRuntime;
1216
+ readonly messages: readonly QaConversationMessage[];
1217
+ readonly reviews: readonly QaConversationReview[];
1218
+ readonly queueItems: readonly QaReviewQueueItem[];
1219
+ }
1220
+ /**
1221
+ * Server-side filter for the conversation list. Every field is optional and
1222
+ * accepts an explicit null: the wire carries whatever the browser has, and an
1223
+ * absent filter must never be mistaken for a filter on `null`.
1224
+ */
1225
+ export interface QaConversationQuery {
1226
+ readonly userId?: string | null;
1227
+ readonly subroleId?: string | null;
1228
+ readonly from?: string | null;
1229
+ readonly to?: string | null;
1230
+ readonly rating?: QaFeedbackRating | null;
1231
+ readonly reviewStatus?: QaReviewStatus | null;
1232
+ /** Search matches the conversation title and the owner's name or email. */
1233
+ readonly search?: string | null;
1234
+ }
1235
+ /** Server-side filter for the feedback table. */
1236
+ export interface QaFeedbackQuery {
1237
+ readonly rating?: QaFeedbackRating | null;
1238
+ readonly userId?: string | null;
1239
+ readonly subroleId?: string | null;
1240
+ readonly reason?: QaFeedbackReason | null;
1241
+ readonly from?: string | null;
1242
+ readonly to?: string | null;
1243
+ readonly reviewStatus?: QaReviewStatus | null;
1244
+ }
1245
+ /** Server-side filter for the audit table. */
1246
+ export interface QaAuditQuery {
1247
+ readonly actorId?: string | null;
1248
+ readonly action?: QaAdminAuditAction | null;
1249
+ readonly from?: string | null;
1250
+ readonly to?: string | null;
1251
+ }
1252
+ /** Server-side filter for the user list. */
1253
+ export interface QaUserQuery {
1254
+ readonly search?: string | null;
1255
+ readonly status?: "active" | "disabled" | null;
1256
+ readonly role?: QaAccountRole | null;
1257
+ readonly subroleId?: string | null;
1258
+ }
1259
+ /** Cursor page of any admin list. `nextCursor` is null on the last page. */
1260
+ export interface QaAdminPage<T> {
1261
+ readonly items: readonly T[];
1262
+ readonly nextCursor: string | null;
1263
+ readonly total: number;
1264
+ }
1265
+ /** One pending item of the review queue, with the context to triage it. */
1266
+ export interface QaReviewQueueRow extends QaReviewQueueItem {
1267
+ readonly displayName: string;
1268
+ readonly subroleId: string;
1269
+ readonly title?: string;
1270
+ readonly raisedAtLabel: string;
1271
+ readonly issueSummary?: readonly QaQualityIssueType[];
1272
+ readonly severity?: QaQualitySeverity;
1273
+ }
1274
+ /** One row of the feedback table (spec §33). */
1275
+ export interface QaFeedbackRow extends QaMessageFeedback {
1276
+ readonly displayName: string;
1277
+ readonly subroleId: string;
1278
+ readonly conversationTitle?: string;
1279
+ readonly reviewStatus: QaReviewStatus;
1280
+ }
1281
+ /** Aggregated quality counters (spec §27). */
1282
+ export interface QaQualityIssueCount {
1283
+ readonly issue: QaQualityIssueType;
1284
+ readonly count: number;
1285
+ }
1286
+ export interface QaQualityRatingBreakdown {
1287
+ readonly key: string;
1288
+ readonly label: string;
1289
+ readonly rated: number;
1290
+ readonly positive: number;
1291
+ readonly negative: number;
1292
+ readonly positiveRate: number | null;
1293
+ }
1294
+ export interface QaQualityTrendPoint {
1295
+ /** ISO date (UTC) of the bucket. */
1296
+ readonly date: string;
1297
+ readonly rated: number;
1298
+ readonly positive: number;
1299
+ readonly negative: number;
1300
+ }
1301
+ export interface QaQualityMetrics {
1302
+ readonly conversations: number;
1303
+ readonly activeUsers: number;
1304
+ readonly assistantMessages: number;
1305
+ readonly ratedMessages: number;
1306
+ readonly positiveRatings: number;
1307
+ readonly negativeRatings: number;
1308
+ /** Share of assistant messages that carry a rating; null without messages. */
1309
+ readonly ratingRate: number | null;
1310
+ /** Share of positive ratings among rated messages; null without ratings. */
1311
+ readonly positiveRate: number | null;
1312
+ readonly unreviewedNegatives: number;
1313
+ readonly reviewedItems: number;
1314
+ readonly issues: readonly QaQualityIssueCount[];
1315
+ readonly bySubrole: readonly QaQualityRatingBreakdown[];
1316
+ readonly trend: readonly QaQualityTrendPoint[];
1317
+ }
1318
+ /**
1319
+ * One attention line on the admin overview. The Host reports the condition and
1320
+ * its numbers; the browser owns the wording, so an operator's language never
1321
+ * depends on the deployment's locale.
1322
+ */
1323
+ export interface QaOverviewAlert {
1324
+ readonly level: "critical" | "warning" | "info";
1325
+ readonly code: "unreviewed-negatives" | "subrole-satisfaction" | "recurring-reason";
1326
+ readonly count: number;
1327
+ /** Subrole id or feedback reason, when the condition names one. */
1328
+ readonly subject?: string;
1329
+ /** Positive-feedback share of the subject, when the condition measured one. */
1330
+ readonly rate?: number;
1331
+ }
1332
+ /** The /qa/admin landing payload. */
1333
+ export interface QaAdminOverview {
1334
+ readonly metrics: QaQualityMetrics;
1335
+ readonly alerts: readonly QaOverviewAlert[];
1336
+ readonly recentFeedback: readonly QaFeedbackRow[];
1337
+ readonly queue: readonly QaReviewQueueRow[];
1338
+ }
1339
+ /** The account columns the store owns, without any joined counters. */
1340
+ export interface QaAdminAccountRow {
1341
+ readonly id: string;
1342
+ readonly email: string;
1343
+ readonly displayName: string;
1344
+ readonly fullName: string;
1345
+ readonly role: QaAccountRole;
1346
+ readonly disabled: boolean;
1347
+ readonly createdAt: string;
1348
+ readonly lastLoginAt: string | null;
1349
+ readonly access: QaUserAccess;
1350
+ }
1351
+ /** One user row of the admin user list (spec §5). */
1352
+ export interface QaAdminUserRow extends QaAdminAccountRow {
1353
+ readonly conversations: number;
1354
+ readonly feedbackGiven: number;
1355
+ }
1356
+ /** Everything the user detail page renders, in one payload (spec §6). */
1357
+ export interface QaAdminUserDetail {
1358
+ readonly user: QaAdminUserRow;
1359
+ /** Effective capability counts per assigned subrole, for the access preview. */
1360
+ readonly effective: readonly {
1361
+ readonly subroleId: string;
1362
+ readonly name: string;
1363
+ readonly tools: number;
1364
+ readonly skills: number;
1365
+ }[];
1366
+ readonly activity: {
1367
+ readonly conversations: number;
1368
+ readonly messages: number;
1369
+ readonly positiveRatings: number;
1370
+ readonly negativeRatings: number;
1371
+ };
1372
+ }
1373
+ /** The administrative write of one account; absent fields stay unchanged. */
1374
+ export interface QaAdminUserUpdate {
1375
+ readonly role?: QaAccountRole | null;
1376
+ readonly disabled?: boolean | null;
1377
+ readonly access?: QaUserAccess | null;
1378
+ }
816
1379
  //# sourceMappingURL=types.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yadsh/dsh-qa-surface",
3
- "version": "0.6.1",
3
+ "version": "0.7.1",
4
4
  "description": "A focused end-user QA surface backed by native DeepSeek Harness sessions",
5
5
  "repository": {
6
6
  "type": "git",
@@ -174,8 +174,8 @@
174
174
  "tsdown": "^0.22.14",
175
175
  "typescript": "^7.0.2",
176
176
  "vitest": "^4.1.11",
177
- "@yadsh/dsh-config": "^0.0.0",
178
177
  "@yadsh/dsh-plugin-kit": "^0.1.0",
178
+ "@yadsh/dsh-config": "^0.0.0",
179
179
  "@yadsh/dsh-plugin-scripts": "^0.0.0"
180
180
  },
181
181
  "publishConfig": {