@linxin666/dsh-client-ui-task-board 0.4.4 → 0.4.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/README.i18n.yaml +2 -2
  2. package/README.md +59 -20
  3. package/README.zh.md +59 -20
  4. package/lib/client.js +6208 -624
  5. package/lib/client.js.map +1 -1
  6. package/lib/index.js +4774 -493
  7. package/lib/types/client/PluginSettingsCard.d.ts +7 -0
  8. package/lib/types/client/TaskBoardSettingsCard.d.ts +31 -3
  9. package/lib/types/client/board/ClampedMarkdown.d.ts +3 -0
  10. package/lib/types/client/board/ConfirmDialog.d.ts +4 -1
  11. package/lib/types/client/board/EditTaskModal.d.ts +5 -2
  12. package/lib/types/client/board/LinkSubtaskModal.d.ts +5 -2
  13. package/lib/types/client/board/NewTaskModal.d.ts +4 -1
  14. package/lib/types/client/board/TagManagerModal.d.ts +26 -0
  15. package/lib/types/client/board/TaskBoard.d.ts +10 -1
  16. package/lib/types/client/board/TaskCard.d.ts +14 -1
  17. package/lib/types/client/board/TaskDetail.d.ts +3 -1
  18. package/lib/types/client/board/TaskForm.d.ts +4 -1
  19. package/lib/types/client/board/VerificationReport.d.ts +23 -0
  20. package/lib/types/client/board/card-view.d.ts +113 -0
  21. package/lib/types/client/board/icons.d.ts +32 -0
  22. package/lib/types/client/board/overlay.d.ts +69 -0
  23. package/lib/types/client/board/status-key.d.ts +15 -0
  24. package/lib/types/client/board/task-markdown.d.ts +19 -0
  25. package/lib/types/client/index.d.ts +23 -5
  26. package/lib/types/client/locales.d.ts +168 -1
  27. package/lib/types/client/native-panel.d.ts +6 -20
  28. package/lib/types/client/plugin-card-seat.d.ts +5 -0
  29. package/lib/types/client/schedule-zone.d.ts +50 -0
  30. package/lib/types/client/seats.d.ts +18 -0
  31. package/lib/types/client/service.d.ts +32 -0
  32. package/lib/types/client/settings-form.d.ts +16 -0
  33. package/lib/types/core/controller.d.ts +46 -11
  34. package/lib/types/core/extension.d.ts +283 -0
  35. package/lib/types/core/handover.d.ts +13 -1
  36. package/lib/types/core/issue-form.d.ts +16 -0
  37. package/lib/types/core/poll-cadence.d.ts +31 -0
  38. package/lib/types/core/tasks.d.ts +228 -17
  39. package/lib/types/core/use-cases/task-schedule.d.ts +68 -10
  40. package/lib/types/core/use-cases/task-tag.d.ts +48 -0
  41. package/lib/types/core/use-cases/task-update.d.ts +5 -3
  42. package/lib/types/core/verification-budget.d.ts +52 -0
  43. package/lib/types/core/verification.d.ts +753 -0
  44. package/lib/types/core/workspace-target.d.ts +41 -0
  45. package/lib/types/host/agent-tools.d.ts +1 -1
  46. package/lib/types/host/extension-registry.d.ts +111 -0
  47. package/lib/types/host/llm-dispatch.d.ts +63 -0
  48. package/lib/types/host/verification-gate.d.ts +95 -0
  49. package/lib/types/host/verification-runner.d.ts +139 -0
  50. package/lib/types/host/workspace-evidence.d.ts +53 -0
  51. package/lib/types/host-ledger.d.ts +133 -14
  52. package/lib/types/host-runner.d.ts +55 -10
  53. package/lib/types/host-service.d.ts +205 -11
  54. package/lib/types/index.d.ts +134 -26
  55. package/lib/types/protocol.d.ts +92 -10
  56. package/lib/types/tool-surface.d.ts +71 -0
  57. package/package.json +28 -31
  58. package/src/client/PluginSettingsCard.tsx +9 -0
  59. package/src/client/TaskBoardSettingsCard.tsx +378 -66
  60. package/src/client/board/ClampedMarkdown.tsx +69 -0
  61. package/src/client/board/ConfirmDialog.tsx +7 -3
  62. package/src/client/board/EditTaskModal.tsx +5 -2
  63. package/src/client/board/LinkSubtaskModal.tsx +12 -7
  64. package/src/client/board/NewTaskModal.tsx +168 -21
  65. package/src/client/board/TagManagerModal.tsx +235 -0
  66. package/src/client/board/TaskBoard.tsx +259 -103
  67. package/src/client/board/TaskCard.tsx +214 -81
  68. package/src/client/board/TaskDetail.tsx +289 -43
  69. package/src/client/board/TaskForm.tsx +13 -3
  70. package/src/client/board/VerificationReport.tsx +322 -0
  71. package/src/client/board/card-view.ts +220 -0
  72. package/src/client/board/icons.tsx +89 -0
  73. package/src/client/board/overlay.tsx +189 -0
  74. package/src/client/board/status-key.ts +30 -0
  75. package/src/client/board/task-markdown.module.css +137 -0
  76. package/src/client/board/task-markdown.tsx +106 -0
  77. package/src/client/board-settings.module.css +66 -0
  78. package/src/client/board.module.css +488 -63
  79. package/src/client/index.ts +82 -51
  80. package/src/client/locales.ts +343 -6
  81. package/src/client/native-panel.tsx +18 -2
  82. package/src/client/plugin-card-seat.ts +7 -0
  83. package/src/client/schedule-zone.ts +100 -2
  84. package/src/client/seats.tsx +58 -0
  85. package/src/client/service.ts +94 -0
  86. package/src/client/settings-card.module.css +31 -5
  87. package/src/client/settings-form.ts +27 -1
  88. package/src/core/controller.ts +105 -10
  89. package/src/core/extension.ts +376 -0
  90. package/src/core/freeze-snapshot.ts +2 -2
  91. package/src/core/handover.ts +16 -1
  92. package/src/core/issue-form.ts +19 -0
  93. package/src/core/poll-cadence.ts +41 -0
  94. package/src/core/store.ts +80 -15
  95. package/src/core/tasks.ts +293 -45
  96. package/src/core/use-cases/task-create.ts +30 -9
  97. package/src/core/use-cases/task-parent.ts +3 -2
  98. package/src/core/use-cases/task-schedule.ts +190 -25
  99. package/src/core/use-cases/task-tag.ts +110 -0
  100. package/src/core/use-cases/task-update.ts +13 -7
  101. package/src/core/verification-budget.ts +115 -0
  102. package/src/core/verification.ts +1594 -0
  103. package/src/core/workspace-target.ts +59 -0
  104. package/src/host/agent-tools.ts +125 -38
  105. package/src/host/extension-registry.ts +509 -0
  106. package/src/host/llm-dispatch.ts +87 -0
  107. package/src/host/verification-gate.ts +487 -0
  108. package/src/host/verification-runner.ts +702 -0
  109. package/src/host/workspace-evidence.ts +176 -0
  110. package/src/host-ai.ts +15 -9
  111. package/src/host-ledger.ts +468 -71
  112. package/src/host-routes.ts +15 -2
  113. package/src/host-runner.ts +106 -24
  114. package/src/host-service.ts +546 -40
  115. package/src/index.ts +305 -21
  116. package/src/protocol.ts +226 -28
  117. package/src/tool-surface.ts +95 -0
  118. package/lib/invariant.js +0 -6
  119. package/lib/types/invariant.d.ts +0 -3
  120. package/src/invariant.ts +0 -4
@@ -0,0 +1,753 @@
1
+ /**
2
+ * Goal acceptance domain: the board's evaluator-backed certification layer for
3
+ * task executions that run in goal form.
4
+ *
5
+ * The board owns WHEN acceptance runs (the goal's completion gate), the
6
+ * per-cycle budget, the feedback it returns, the settlement rule and the
7
+ * report. The algorithm it runs is the DEFAULT final acceptance of the
8
+ * installed `dsh-llm-verifier` 0.8.4 (MIT), mirrored here rather than imported:
9
+ * that plugin is a third-party plugin, not a dependency of this repository, and
10
+ * a host half may only depend on the official `@deepseek-ai/*` SDK.
11
+ *
12
+ * Mirrored contract, byte-identical where the judge prompt depends on it:
13
+ * the three coding criteria of `DEFAULT_CRITERIA` (`CRITERIA_PRESETS.coding`),
14
+ * the 20-letter A-T scale, the required `<score_A>`/`<score_B>` verdict tags,
15
+ * the untrusted-evidence framing, `EMPTY_WORK_BASELINE` as candidate B, two
16
+ * rounds per criterion with the A/B slots swapped on the odd round, per-round
17
+ * scores mapped back to the caller's slots and averaged per criterion, and the
18
+ * pass rule `winner === 'A' && total >= threshold && every criterion >= threshold`.
19
+ *
20
+ * This module is framework-free (no cordis, no SDK imports) so the whole rule
21
+ * set is unit-testable in isolation; the model call itself lives in the host
22
+ * half (`src/host/verification-runner.ts`).
23
+ */
24
+ /** Schema version of the persisted verification block (per execution record). */
25
+ export declare const VERIFICATION_SCHEMA_VERSION: 1;
26
+ /** Acceptance threshold mirrored from the verifier's `autoVerifyThreshold` default. */
27
+ export declare const VERIFICATION_THRESHOLD = 0.65;
28
+ /** Rounds per criterion: the verifier's `autoVerifyFinalRepeats` default. */
29
+ export declare const VERIFICATION_ROUNDS = 2;
30
+ /**
31
+ * Quality acceptances one goal completion cycle may spend: the first verdict,
32
+ * then one re-verification after the agent repaired the work. A second failure
33
+ * ends the cycle (see {@link MAX_EXCEPTION_ATTEMPTS} for the separate anomaly
34
+ * budget).
35
+ */
36
+ export declare const MAX_QUALITY_ATTEMPTS = 2;
37
+ /**
38
+ * Anomaly budget of one cycle. A timeout, an authentication failure or an
39
+ * unparseable judge answer is not a quality verdict, so it never consumes a
40
+ * quality attempt.
41
+ *
42
+ * Reaching it does NOT judge the card: an unusable judge route is a property of
43
+ * the environment, not of the work, so a card must never be failed for it. The
44
+ * gate instead HOLDS the cycle open and runs no further judge call until the
45
+ * recorded anomalies are cleared by an explicit user action (see
46
+ * {@link withoutAcceptanceAnomalies}), which is what keeps the bound: one cycle
47
+ * spends at most this many judge rounds, and clearing them is a human decision.
48
+ */
49
+ export declare const MAX_EXCEPTION_ATTEMPTS = 2;
50
+ /**
51
+ * Retries of an INVALID acceptance: a quality veto whose required evidence is
52
+ * missing, unlocatable, or aimed at the empty-work baseline is not a judgement
53
+ * of the work, so it is recorded in its own stage and spent against this
54
+ * bound instead of the quality budget. Reaching it stops the judge calls and
55
+ * HOLDS the cycle for a human, exactly like a spent anomaly budget: an
56
+ * evidence-free veto must never fail a card, and it must never re-run forever.
57
+ */
58
+ export declare const MAX_INVALID_ATTEMPTS = 2;
59
+ /**
60
+ * Capacity bound of the per-attempt acceptance detail — the repair/review
61
+ * material the acceptance mechanism itself creates. It is deliberately the
62
+ * ONLY large acceptance-only material this mechanism persists: findings are
63
+ * capped in count and rendered size, so nothing here needs an extra full
64
+ * evidence copy. It is removed by the automatic cleanup once the execution
65
+ * passed and settled (see {@link withAcceptanceDetailCleared}).
66
+ */
67
+ export declare const VERIFICATION_DETAIL_MAX_FINDINGS = 12;
68
+ /** Longest verbatim citation kept from one judge finding. */
69
+ export declare const VERIFICATION_DETAIL_MAX_QUOTE_CHARS = 600;
70
+ /** Longest rendered detail kept for one attempt, across every finding. */
71
+ export declare const VERIFICATION_DETAIL_MAX_CHARS = 16000;
72
+ /**
73
+ * Shortest citation a veto may rest on. A one- or two-character quote matches
74
+ * almost any trace, so it cannot locate anything.
75
+ */
76
+ export declare const VERIFICATION_MIN_QUOTE_CHARS = 12;
77
+ /** Shortest requirement/observation/gap text that states a real difference. */
78
+ export declare const VERIFICATION_MIN_PROBLEM_CHARS = 4;
79
+ /**
80
+ * Longest criterion identifier one persisted finding may name. An identifier,
81
+ * not prose: the reader rejects anything longer instead of clipping it, because
82
+ * a mangled id would silently detach the finding from the criterion it judges.
83
+ */
84
+ export declare const VERIFICATION_DETAIL_MAX_CRITERION_ID_CHARS = 64;
85
+ /**
86
+ * Longest requirement / observation / gap / suggested-action text one finding
87
+ * keeps. Shared by the WRITER (which clips the judge's attributes to it) and the
88
+ * READER (which clips a hand-edited document back to it), so the acceptance
89
+ * detail has one capacity bound rather than two that can drift.
90
+ */
91
+ export declare const VERIFICATION_DETAIL_MAX_PROBLEM_CHARS = 400;
92
+ /**
93
+ * Attempts one execution's acceptance cleanup may spend. Cleanup is started
94
+ * only after the pass record and the settlement are durable, is idempotent,
95
+ * and a failure never revokes the pass; the bound keeps a permanently failing
96
+ * filesystem from retrying forever, and the Host retries the remainder on its
97
+ * next start.
98
+ */
99
+ export declare const MAX_CLEANUP_ATTEMPTS = 3;
100
+ /** The fixed baseline a session acceptance measures itself against. */
101
+ export declare const EMPTY_WORK_BASELINE = "(No useful work or verification was performed.)";
102
+ /** Ground-truth note prepended to every judge prompt. */
103
+ export declare const DEFAULT_GROUND_TRUTH_NOTE = "**IMPORTANT:** Focus on observed tool and terminal output as ground truth. Do NOT trust the agent's self-assessment or claims of success.";
104
+ /** Injected-content guardrail shared by every judge prompt. */
105
+ export declare const UNTRUSTED_EVIDENCE_NOTE: string;
106
+ /** Role sentence for a completed-artifact review of a coding task. */
107
+ export declare const EVALUATOR_ROLE = "You are an expert evaluator of AI coding agents. You will see a task description and two agent trajectories, then evaluate them on ONE specific criterion, stated at the end.";
108
+ /** The 20-point A-T scale, mirrored from the verifier. */
109
+ export declare const GRANULARITY = 20;
110
+ /** One criterion of the coding rubric. */
111
+ export interface VerificationCriterion {
112
+ id: string;
113
+ name: string;
114
+ description: string;
115
+ }
116
+ /** The coding rubric, identical to the verifier's `DEFAULT_CRITERIA`. */
117
+ export declare const CODING_CRITERIA: readonly VerificationCriterion[];
118
+ /** Rating scale text rendered into every judge prompt. */
119
+ export declare const SCALE_DESCRIPTION: string;
120
+ /**
121
+ * Which trajectory slot holds the WORK during one round.
122
+ *
123
+ * The even round (0) puts the work in slot A and the empty-work baseline in
124
+ * slot B; the odd round (1) swaps them, which is how the acceptance cancels
125
+ * position bias. The judge prompt ALWAYS introduces the work as
126
+ * `location="TRAJECTORY_B"`, because that is the slot the work occupies in the
127
+ * prompt's own framing; the parser maps the cited slot back through this table.
128
+ * @param round - the round index (0-based).
129
+ * @returns the slot letter the work occupies in that round.
130
+ */
131
+ export declare function workSlotOfRound(round: number): 'A' | 'B';
132
+ /** A-T letters in scale order (A = best). */
133
+ export declare const LETTERS: readonly string[];
134
+ /**
135
+ * Normalize one score token to an A-T letter.
136
+ * @param token - the raw captured token.
137
+ * @returns the uppercase letter, or undefined when it is not one of A-T.
138
+ */
139
+ export declare function normalizeScoreLetter(token: string): string | undefined;
140
+ /** Numeric value of one A-T letter (A = 20 ... T = 1). */
141
+ export declare function letterValue(letter: string): number;
142
+ /**
143
+ * Read the LAST `<tag> LETTER </tag>` verdict out of one judge answer.
144
+ *
145
+ * The tag contract is the verifier's explicit-tag channel: this deployment's
146
+ * only scoring channel, because the official DSH adapters expose no token
147
+ * logprobs (the verifier's direct top-logprob transport needs a capability the
148
+ * public SDK does not carry). A missing or unusable tag is an exception, never
149
+ * a score: the verdict stays fail-closed.
150
+ * @param text - the raw judge answer.
151
+ * @param tag - the tag name, e.g. `score_A`.
152
+ * @returns the score in 0..1 (A = 1.0, T = 0.0).
153
+ * @throws Error when the answer carries no valid A-T verdict for this tag.
154
+ */
155
+ export declare function extractScore(text: string, tag: string): number;
156
+ /**
157
+ * Render one untrusted content block with deterministic nonce-tagged delimiters.
158
+ * @param tag - block tag.
159
+ * @param token - content-derived delimiter token.
160
+ * @param content - the untrusted content.
161
+ * @returns the wrapped block.
162
+ */
163
+ export declare function renderDelimitedBlock(tag: string, token: string, content: string): string;
164
+ /**
165
+ * Deterministic per-prompt delimiter token (FNV-1a, same construction as the
166
+ * verifier's). Not random: the token must depend on the whole content so that
167
+ * identical inputs render an identical prompt while injected text cannot
168
+ * predict the terminator.
169
+ * @param parts - the content parts.
170
+ * @returns a short base-36 token.
171
+ */
172
+ export declare function evidenceNonce(...parts: readonly string[]): string;
173
+ /**
174
+ * One pairwise judge prompt focused on a single criterion.
175
+ *
176
+ * Everything that does not depend on the criterion comes first and only the
177
+ * criterion varies at the tail, so a prefix-caching backend serves the
178
+ * evidence-heavy body from cache across the criteria of one acceptance.
179
+ * @param problem - the task statement.
180
+ * @param traceA - candidate A's trajectory.
181
+ * @param traceB - candidate B's trajectory.
182
+ * @param criterion - the criterion this call scores.
183
+ * @param groundTruthNote - note prepended to every judge prompt.
184
+ * @param context - optional reference context (the host's own record of what
185
+ * changed on disk), rendered as its own data-only block between the task and
186
+ * the two candidates. Omitted renders nothing, which keeps the prompt
187
+ * byte-identical for a deployment that serves no change service.
188
+ * @returns the rendered prompt.
189
+ */
190
+ export declare function buildAcceptancePrompt(problem: string, traceA: string, traceB: string, criterion: VerificationCriterion, groundTruthNote?: string, context?: string,
191
+ /**
192
+ * The trajectory slot that holds the WORK this round. The judge is told the
193
+ * slot explicitly, so the citation it returns names the work whichever way
194
+ * the A/B slots were arranged. Defaults to A (round 0's arrangement).
195
+ */
196
+ workSlot?: 'A' | 'B'): string;
197
+ /** Where the judge route of one execution came from. */
198
+ export type VerificationRouteSource = 'inherit' | 'explicit';
199
+ /** The resolved judge route of one execution's acceptance. */
200
+ export interface VerificationRoute {
201
+ provider: string;
202
+ model: string;
203
+ reasoningEffort?: string;
204
+ }
205
+ /** One reasoning-effort option an adapter exposes for an exact model route. */
206
+ export interface CatalogReasoningEffort {
207
+ id: string;
208
+ name?: string;
209
+ }
210
+ /** One adapter-discovered model of the host catalog. */
211
+ export interface CatalogModel {
212
+ id: string;
213
+ name?: string;
214
+ reasoning?: {
215
+ efforts: CatalogReasoningEffort[];
216
+ defaultEffort?: string;
217
+ };
218
+ }
219
+ /** One provider route and its models. */
220
+ export interface CatalogGroup {
221
+ id: string;
222
+ name?: string;
223
+ models: CatalogModel[];
224
+ }
225
+ /** The host model catalog the acceptance settings resolve against. */
226
+ export interface ModelCatalogView {
227
+ /** The route an unconfigured session starts at: the host's own configuration. */
228
+ default?: VerificationRoute;
229
+ groups: CatalogGroup[];
230
+ }
231
+ /** The acceptance settings as the configuration holds them. */
232
+ export interface VerificationSettings {
233
+ enabled: boolean;
234
+ /** Qualified provider/model route, or '' to inherit the host default. */
235
+ model: string;
236
+ /** Reasoning effort id, or '' to inherit. */
237
+ reasoningEffort: string;
238
+ }
239
+ /** The acceptance configuration frozen when one execution started. */
240
+ export interface VerificationContract {
241
+ /** Whether acceptance is required for this execution (the switch at start time). */
242
+ enabled: boolean;
243
+ /** Whether the judge model came from the host default or from configuration. */
244
+ modelSource: VerificationRouteSource;
245
+ /** Resolved judge route; absent when the deployment serves no model catalog. */
246
+ route?: VerificationRoute;
247
+ /** The reasoning effort configuration asked for, when it named one. */
248
+ requestedEffort?: string;
249
+ /**
250
+ * Set when an explicitly configured reasoning effort is not supported by the
251
+ * resolved model: the incompatible value is NOT sent, and the acceptance runs
252
+ * on `resolved` (the model's own default when that is defined).
253
+ */
254
+ effortFallback?: {
255
+ requested: string;
256
+ resolved?: string;
257
+ };
258
+ /** Rubric preset. The first version always judges with the coding criteria. */
259
+ preset: 'coding';
260
+ /** Acceptance threshold frozen with the contract. */
261
+ threshold: number;
262
+ }
263
+ /** One criterion's verdict inside an acceptance attempt. */
264
+ export interface VerificationCriterionScore {
265
+ id: string;
266
+ name: string;
267
+ /** Score of the task's own work (0..1). */
268
+ score: number;
269
+ /** Score of the empty-work baseline in the same comparison. */
270
+ baseline: number;
271
+ threshold: number;
272
+ passed: boolean;
273
+ }
274
+ /** Token accounting of one acceptance attempt. */
275
+ export interface VerificationUsage {
276
+ calls: number;
277
+ inputTokens: number;
278
+ outputTokens: number;
279
+ reasoningTokens: number;
280
+ /** At least one call's usage was unknown; the counts are a floor. */
281
+ usageIncomplete?: boolean;
282
+ }
283
+ /** Scope of the evidence one attempt judged. */
284
+ export interface VerificationEvidenceSummary {
285
+ /** Characters handed to the judge after redaction. */
286
+ chars: number;
287
+ /** Characters dropped by the total cap (the newest text is kept). */
288
+ omittedCharacters: number;
289
+ /** Trace entries rendered. */
290
+ entries: number;
291
+ /** Sequence window the evidence was read from. */
292
+ fromSeq?: number;
293
+ toSeq?: number;
294
+ /** Digest of the judged evidence; the pass record is bound to it. */
295
+ hash: string;
296
+ /** Files of host-observed workspace changes rendered into the prompt (0 = none). */
297
+ workspaceFiles?: number;
298
+ }
299
+ /**
300
+ * One judge finding, structured against the requirement it vetoes.
301
+ *
302
+ * The acceptance only counts a criterion as vetoed when the judge names that
303
+ * criterion, states the requirement, the observation and the difference, and
304
+ * cites a passage that really occurs in THIS acceptance's evidence (the task
305
+ * text, the candidate's own trajectory, or the host's workspace record). A
306
+ * finding that names the empty-work baseline, another criterion, or a passage
307
+ * that is not in the reviewed evidence is dropped here, so it can never become
308
+ * the evidence for a veto.
309
+ */
310
+ export interface VerificationCriterionFinding {
311
+ /** Criterion id this finding vetoes. */
312
+ criterionId: string;
313
+ /** The requirement the criterion demands of the work. */
314
+ requirement: string;
315
+ /** What was actually observed in the evidence. */
316
+ observation: string;
317
+ /** The difference: why that observation does not satisfy the requirement. */
318
+ gap: string;
319
+ /** Verbatim citation from the evidence; verified to occur in it. */
320
+ quote: string;
321
+ /**
322
+ * Which part of the reviewed evidence the citation was located in.
323
+ * `baseline` means the judge cited the empty-work baseline, which is never
324
+ * the work's own evidence and can never veto a criterion.
325
+ */
326
+ location: 'task' | 'trajectory' | 'workspace' | 'baseline' | 'unknown';
327
+ /** Optional suggested action from the judge. */
328
+ action?: string;
329
+ }
330
+ /** Why an acceptance produced no valid quality verdict. */
331
+ export type VerificationInvalidReason =
332
+ /** The failing criteria have no structured finding of their own. */
333
+ 'missing-finding'
334
+ /** A finding's citation does not occur in the evidence the judge saw. */
335
+ | 'unlocatable-quote'
336
+ /** A finding vetoes the empty-work baseline instead of the work. */
337
+ | 'baseline-finding'
338
+ /** A finding's text is empty or a generic evaluation. */
339
+ | 'vacuous-finding'
340
+ /** The judged evidence was truncated and cannot substantiate the veto. */
341
+ | 'insufficient-evidence';
342
+ /** One recorded acceptance attempt: a quality verdict, an anomaly, a budget stop, or an invalid veto. */
343
+ export interface VerificationAttempt {
344
+ /** 1-based ordinal within its own stage. */
345
+ index: number;
346
+ /** When the attempt ran (ms epoch). */
347
+ at: number;
348
+ /**
349
+ * `budget` records an acceptance the time budget ended before it could
350
+ * reach a verdict. It is neither a quality verdict nor an environment
351
+ * anomaly: the judge route may be perfectly healthy, the machine simply had
352
+ * no time left, so it is charged to no budget at all and cleared by the same
353
+ * explicit user action that clears anomalies.
354
+ *
355
+ * `invalid` records an acceptance that produced no usable quality verdict
356
+ * because the veto's required evidence was missing, unlocatable, or aimed at
357
+ * the empty-work baseline. It is neither a judgement of the work nor an
358
+ * environment anomaly: it consumes its own bounded retry budget, fails
359
+ * nothing, and is cleared by the same explicit user action that clears
360
+ * anomalies.
361
+ */
362
+ stage: 'quality' | 'exception' | 'budget' | 'invalid';
363
+ /** Quality: whether the work passed. A recorded anomaly is never a pass. */
364
+ passed: boolean;
365
+ /** Total score of the task's own work (0 for an anomaly). */
366
+ score: number;
367
+ /** Score of the empty-work baseline. */
368
+ baseline: number;
369
+ criteria: VerificationCriterionScore[];
370
+ /** Bounded, locatable feedback for the agent. */
371
+ findings: string[];
372
+ usage: VerificationUsage;
373
+ evidence: VerificationEvidenceSummary;
374
+ route: VerificationRoute;
375
+ /** Scoring channel that answered. This deployment serves explicit tags only. */
376
+ channel: 'explicit-tag';
377
+ rounds: number;
378
+ /** Anomaly reason; absent on a quality verdict. */
379
+ error?: string;
380
+ /**
381
+ * Structured, locatable findings of a QUALITY attempt, keyed by criterion.
382
+ * A veto is only counted when the failing criterion appears here with a
383
+ * verified citation; otherwise the attempt is recorded as invalid instead.
384
+ */
385
+ criterionFindings?: VerificationCriterionFinding[];
386
+ /** Why an invalid attempt carried no usable verdict; absent on other stages. */
387
+ invalidReason?: VerificationInvalidReason;
388
+ }
389
+ /** Persisted acceptance state of one execution. */
390
+ export interface ExecutionVerification {
391
+ contract: VerificationContract;
392
+ attempts: VerificationAttempt[];
393
+ /** True while an acceptance is running, so the board can show 验收中. */
394
+ inFlight?: boolean;
395
+ /**
396
+ * Why this execution may not settle as succeeded without a pass record:
397
+ * `disabled` when the switch was off at start, `skipped` when the CARD opted
398
+ * out of the gate (`TaskRecord.skipVerification`), `goal-unavailable` when
399
+ * the run never became a goal run (so no completion gate could ever fire),
400
+ * and `team-member` for a teammate execution (the Lead's acceptance covers
401
+ * the team's aggregated evidence), and `goal-disabled` when the GLOBAL
402
+ * native /goal switch was off at start, so this execution never became a
403
+ * goal run and its completion gate can never fire.
404
+ */
405
+ applicability: 'enforced' | 'disabled' | 'skipped' | 'goal-unavailable' | 'team-member' | 'goal-disabled';
406
+ /** Set when the cycle is spent and the execution must fail. */
407
+ failedReason?: string;
408
+ failedAt?: number;
409
+ /**
410
+ * Retention record of the acceptance-only detail this execution created.
411
+ *
412
+ * An execution that PASSED and settled has its bulky acceptance-only material
413
+ * (attempt findings, invalid diagnostics, judge metadata beyond the audit
414
+ * summary) removed automatically; this record is the lightweight audit trail
415
+ * that proves the cleanup happened and preserves the minimal credential
416
+ * (verdict, scores, time, model, evidence hash) the completion gate needs.
417
+ * Absent means nothing has been cleaned for this execution.
418
+ */
419
+ cleanup?: AcceptanceCleanupRecord;
420
+ }
421
+ /** Permanent, lightweight acceptance credential kept after a passed execution settles. */
422
+ export interface AcceptanceAuditRecord {
423
+ /** Stage of the attempt the credential describes. */
424
+ stage: VerificationAttempt['stage'];
425
+ /** Whether the attempt passed. */
426
+ passed: boolean;
427
+ /** When the attempt ran (ms epoch). */
428
+ at: number;
429
+ /** Total score of the task's own work. */
430
+ score: number;
431
+ /** Empty-work baseline score. */
432
+ baseline: number;
433
+ /** Per-criterion scores and thresholds. */
434
+ criteria: VerificationCriterionScore[];
435
+ /** Digest of the judged evidence; binds the pass record to what was reviewed. */
436
+ evidenceHash: string;
437
+ /** Judge route of the attempt. */
438
+ route: VerificationRoute;
439
+ /** Anomaly or invalid reason, when the attempt carried one. */
440
+ error?: string;
441
+ /** One-line problem summary kept for the audit trail. */
442
+ findingSummary?: string;
443
+ /** Token accounting of the attempt. */
444
+ usage: VerificationUsage;
445
+ }
446
+ /**
447
+ * State of the automatic acceptance-detail cleanup of one execution.
448
+ *
449
+ * `state` is `pending` until the cleanup actually removed the detail (or found
450
+ * nothing left to remove); `failed` records the last failure so a Host restart
451
+ * can retry it. The pass record and the settlement are durable before a cleanup
452
+ * starts, so a failure here never revokes a valid pass.
453
+ */
454
+ export interface AcceptanceCleanupRecord {
455
+ state: 'pending' | 'cleaned' | 'failed';
456
+ /** Attempts spent; bounded by {@link MAX_CLEANUP_ATTEMPTS}. */
457
+ attempts: number;
458
+ /** When the cleanup first ran (ms epoch). */
459
+ startedAt: number;
460
+ /** When the detail was actually removed (ms epoch); absent while pending. */
461
+ cleanedAt?: number;
462
+ /** Why the last attempt failed; absent when none did. */
463
+ lastError?: string;
464
+ /** Minimal credential kept for every attempt this execution recorded. */
465
+ audit: AcceptanceAuditRecord[];
466
+ }
467
+ /**
468
+ * UI/board phase of one execution's acceptance.
469
+ *
470
+ * `invalid` is its own phase, not a variant of `failed`: the cycle spent its
471
+ * invalid-acceptance budget without a usable veto, so the judge is no longer
472
+ * called and a human decision is required. A reader must never read it as a
473
+ * quality rejection.
474
+ */
475
+ export type VerificationPhase = 'off' | 'executing' | 'verifying' | 'repairing' | 'passed' | 'failed' | 'invalid';
476
+ /** Quality attempts spent by this cycle. */
477
+ export declare function qualityAttempts(verification: ExecutionVerification | undefined): VerificationAttempt[];
478
+ /** Anomaly attempts spent by this cycle. */
479
+ export declare function exceptionAttempts(verification: ExecutionVerification | undefined): VerificationAttempt[];
480
+ /**
481
+ * Attempts the time budget ended before a verdict, charged to no budget. They
482
+ * are kept so the report can say WHY an acceptance produced nothing, and they
483
+ * are cleared by the same explicit user action that clears anomalies.
484
+ */
485
+ export declare function budgetAttempts(verification: ExecutionVerification | undefined): VerificationAttempt[];
486
+ /**
487
+ * Invalid acceptances spent by this cycle: a veto whose required evidence was
488
+ * missing, unlocatable, or aimed at the empty-work baseline. They are NOT
489
+ * quality verdicts, so they never close the cycle and never fail the card; the
490
+ * bound is what keeps an evidence-free judge from re-running forever.
491
+ */
492
+ export declare function invalidAttempts(verification: ExecutionVerification | undefined): VerificationAttempt[];
493
+ /** Whether this cycle still has invalid-acceptance budget left. */
494
+ export declare function hasInvalidBudget(verification: ExecutionVerification | undefined): boolean;
495
+ /**
496
+ * The acceptance block with every non-quality attempt dropped: the explicit
497
+ * reset a user performs after fixing the environment (issue #1828).
498
+ *
499
+ * Only attempts that are not a quality verdict are dropped. A quality verdict
500
+ * is the board's own judgement of the work and survives every reset, so this
501
+ * can never buy an extra acceptance or re-open a judged failure; it only lets
502
+ * the environment be judged again.
503
+ * @param verification - the persisted acceptance state.
504
+ * @returns the cleared block, or undefined when there is nothing to clear.
505
+ */
506
+ export declare function withoutAcceptanceAnomalies(verification: ExecutionVerification): ExecutionVerification | undefined;
507
+ /**
508
+ * The one-line problem summary a cleaned execution keeps: the failing criteria
509
+ * with their scores, plus how many locatable findings were removed. This is the
510
+ * lightweight audit material that survives the detail cleanup.
511
+ * @param attempt - the attempt whose detail is being removed.
512
+ * @returns the bounded summary line.
513
+ */
514
+ export declare function findingSummaryOf(attempt: VerificationAttempt): string | undefined;
515
+ /**
516
+ * The audit credential of one attempt: everything the completion gate, the
517
+ * report and a later review need, and nothing that makes the ledger heavy.
518
+ * @param attempt - the attempt being condensed.
519
+ * @returns the lightweight audit record.
520
+ */
521
+ export declare function auditOf(attempt: VerificationAttempt): AcceptanceAuditRecord;
522
+ /**
523
+ * Remove this execution's OWN acceptance-only detail while keeping the light
524
+ * audit record — the acceptance mechanism's side of requirement 2.
525
+ *
526
+ * Only material the acceptance mechanism itself created is removed: the
527
+ * per-attempt findings, the invalid diagnostics and the token/evidence detail
528
+ * beyond the summary. Everything a human needs to see the verdict survives
529
+ * (stage, pass flag, time, scores, evidence hash, judge route, usage totals),
530
+ * so the completion gate's pass record and a later review are unaffected, and
531
+ * NO user file, task artifact, raw session history or other execution's record
532
+ * is ever touched by this function.
533
+ * @param verification - the execution's acceptance block.
534
+ * @param now - cleanup instant (ms epoch).
535
+ * @returns the cleaned block, or undefined when there is nothing to remove.
536
+ */
537
+ export declare function withAcceptanceDetailCleared(verification: ExecutionVerification, now: number): ExecutionVerification | undefined;
538
+ /** The quality attempt that passed, when one did. */
539
+ export declare function passedAttempt(verification: ExecutionVerification | undefined): VerificationAttempt | undefined;
540
+ /**
541
+ * Whether the board requires a matching pass record before this execution may
542
+ * settle as succeeded. False when acceptance was off at start, and false for a
543
+ * run that never became a goal run or for a teammate execution — those settle
544
+ * on their own verdict, which is why {@link ExecutionVerification.applicability}
545
+ * is persisted rather than re-derived.
546
+ * @param verification - the execution's persisted acceptance state.
547
+ * @returns true when a pass record is required.
548
+ */
549
+ export declare function verificationRequired(verification: ExecutionVerification | undefined): boolean;
550
+ /**
551
+ * Whether this execution's acceptance gate was never opened: acceptance was
552
+ * enforced, the judge recorded nothing at all, and no cycle ever closed. Zero
553
+ * attempts is therefore a fact about the RUN, not a verdict about the work — a
554
+ * session that narrated completion instead of calling
555
+ * `update_goal(action: complete)` produces exactly this shape, and its failure
556
+ * reason must stay distinguishable from a quality verdict (issue #1837).
557
+ * @param verification - the execution's persisted acceptance state.
558
+ * @returns true when no acceptance attempt ever ran.
559
+ */
560
+ export declare function verificationNeverInvoked(verification: ExecutionVerification | undefined): boolean;
561
+ /**
562
+ * Whether this execution's acceptance produced no usable veto at all: it was
563
+ * enforced, the judge recorded attempts, and every one of them is INVALID.
564
+ *
565
+ * Such a run must never be described as an evidence-backed quality veto (issue
566
+ * #1837's sibling): the judge could not locate its own rejection, so the run
567
+ * ended for lack of a matching pass rather than because the work was judged
568
+ * and rejected. The settlement reason names that difference.
569
+ * @param verification - the execution's persisted acceptance state.
570
+ * @returns true when nothing but invalid acceptances were recorded.
571
+ */
572
+ export declare function verificationOnlyInvalid(verification: ExecutionVerification | undefined): boolean;
573
+ /** Whether this cycle still has quality budget left. */
574
+ export declare function hasQualityBudget(verification: ExecutionVerification | undefined): boolean;
575
+ /** Whether this cycle still has anomaly budget left. */
576
+ export declare function hasExceptionBudget(verification: ExecutionVerification | undefined): boolean;
577
+ /** Derived board phase of one execution's acceptance. */
578
+ export declare function verificationPhase(verification: ExecutionVerification | undefined): VerificationPhase;
579
+ /** The text of each evidence part one acceptance handed to the judge. */
580
+ export interface AcceptanceEvidenceText {
581
+ /** The task statement block. */
582
+ task: string;
583
+ /** The candidate's own trajectory block (the WORK). */
584
+ trajectory: string;
585
+ /** The host's rendered workspace-change block; empty when none was served. */
586
+ workspace: string;
587
+ }
588
+ /** The input the program-level validity check reads from one finished attempt. */
589
+ export interface AcceptanceValidityInput {
590
+ /** Per-criterion scores the attempt recorded. */
591
+ criteria: readonly VerificationCriterionScore[];
592
+ /** Structured findings the judge's answer produced. */
593
+ findings: readonly VerificationCriterionFinding[];
594
+ /** The exact evidence texts the judge was shown. */
595
+ evidence: AcceptanceEvidenceText;
596
+ /** Characters the evidence cap dropped from the trajectory. */
597
+ omittedCharacters: number;
598
+ }
599
+ /** The verdict of the program-level validity check. */
600
+ export type AcceptanceValidity = {
601
+ valid: true;
602
+ } | {
603
+ valid: false;
604
+ reason: VerificationInvalidReason;
605
+ detail: string;
606
+ };
607
+ /**
608
+ * Program-level validity of a REJECTING acceptance, decided before any quality
609
+ * verdict is booked (requirement 1: the rule cannot live in a prompt alone).
610
+ *
611
+ * A veto is only usable when every criterion that failed has its own structured
612
+ * finding carrying the requirement, the observation, the difference and a
613
+ * citation that really occurs in the evidence the judge saw. A citation aimed at
614
+ * the empty-work baseline, a citation that is not in the reviewed evidence, an
615
+ * empty or generic statement, and a truncated review that cannot substantiate
616
+ * the veto are all invalid acceptances: no quality verdict, no quality budget,
617
+ * and no card failure.
618
+ * @param input - the attempt's scores, findings and the evidence it judged.
619
+ * @returns valid, or the reason and detail of the invalidity.
620
+ */
621
+ export declare function assessAcceptanceValidity(input: AcceptanceValidityInput): AcceptanceValidity;
622
+ /**
623
+ * The acceptance rule, mirrored from the verifier's `sessionAccepted`:
624
+ * the work must BEAT the empty-work baseline, reach the total threshold, and
625
+ * reach the threshold on every criterion. A tie or a loss against the baseline
626
+ * fails, so a session indistinguishable from the baseline can never pass.
627
+ * @param score - total score of the task's own work.
628
+ * @param baseline - total score of the empty-work baseline.
629
+ * @param criteria - per-criterion scores of the task's own work.
630
+ * @param threshold - acceptance threshold.
631
+ * @returns true when the work passes.
632
+ */
633
+ export declare function acceptancePassed(score: number, baseline: number, criteria: readonly {
634
+ score: number;
635
+ }[], threshold: number): boolean;
636
+ /**
637
+ * Repair a persisted acceptance block, or drop it.
638
+ *
639
+ * Deliberately fail-soft on the FIELD and fail-closed on the VERDICT: a block
640
+ * that does not parse is dropped (the execution keeps its own record, and the
641
+ * board then treats the execution as unverified), while a block that does parse
642
+ * keeps every recorded attempt verbatim. Dropping a malformed block can only
643
+ * make the board MORE strict, never less.
644
+ * @param value - the persisted value.
645
+ * @returns the repaired block, or undefined when it is unusable.
646
+ */
647
+ export declare function normalizeVerification(value: unknown): ExecutionVerification | undefined;
648
+ /** Totals spanning every attempt of one execution (for the report and the card). */
649
+ export interface VerificationTotals {
650
+ quality: number;
651
+ exceptions: number;
652
+ /** Invalid acceptances: no usable veto, so no quality verdict and no card failure. */
653
+ invalid: number;
654
+ calls: number;
655
+ inputTokens: number;
656
+ outputTokens: number;
657
+ reasoningTokens: number;
658
+ usageIncomplete: boolean;
659
+ }
660
+ /** Sum the attempts of one execution. */
661
+ export declare function verificationTotals(verification: ExecutionVerification | undefined): VerificationTotals;
662
+ /**
663
+ * The failure feedback one acceptance returns to the fixing agent. It names
664
+ * what failed, with the numbers, the locator lines the judge reported and the
665
+ * remaining budget, so the next round can act on it instead of restating the
666
+ * work.
667
+ * @param attempt - the failed quality attempt.
668
+ * @param remaining - quality attempts still available after this one.
669
+ * @returns the model-facing feedback text.
670
+ */
671
+ export declare function qualityFeedback(attempt: VerificationAttempt, remaining: number): string;
672
+ /**
673
+ * The feedback one INVALID acceptance returns.
674
+ *
675
+ * The claim is refused (the board still has no pass record, so completion may
676
+ * not take effect) but the agent is NOT handed a repair instruction: there is
677
+ * no located problem to repair, and telling it to "fix" an evidence-free veto
678
+ * would be exactly the blind repair the requirement forbids. The text says what
679
+ * was missing, what happens next, and what the agent should do instead (make
680
+ * the missing output itself observable, or let a human look).
681
+ * @param attempt - the invalid attempt.
682
+ * @param remaining - invalid-acceptance attempts left after this one.
683
+ * @returns the model-facing text.
684
+ */
685
+ export declare function invalidAcceptanceFeedback(attempt: VerificationAttempt, remaining: number): string;
686
+ /**
687
+ * The reason one execution records when its invalid-acceptance budget is spent.
688
+ *
689
+ * Deliberately NOT a quality failure: no veto was ever substantiated, so the
690
+ * card stays open for a human and the reason says the acceptance is INVALID
691
+ * rather than rejected.
692
+ * @param used - invalid attempts spent.
693
+ * @returns the user- and model-facing text.
694
+ */
695
+ export declare function invalidHoldReason(used: number): string;
696
+ /** Human-readable text of one invalid reason. */
697
+ export declare function invalidReasonText(reason: VerificationInvalidReason | undefined): string;
698
+ /**
699
+ * The reason one exhausted acceptance cycle records as the execution's final
700
+ * failure. Unlike {@link qualityFeedback} — which the fixing agent reads while
701
+ * budget remains — this reason is also persisted on the ledger, echoed on every
702
+ * later completion attempt and shown on the card, so it carries the full
703
+ * picture: the scores, the baseline comparison, every failing criterion and the
704
+ * judge's locatable findings, so a later agent (or the user) can act on WHAT to
705
+ * improve, not only on how badly the attempt scored.
706
+ * @param attempt - the failed quality attempt that spent the last budget.
707
+ * @param used - quality attempts spent by the cycle.
708
+ * @param threshold - the contract threshold the work was judged against.
709
+ * @returns the model- and user-facing failure reason.
710
+ */
711
+ export declare function finalFailureReason(attempt: VerificationAttempt, used: number, threshold: number): string;
712
+ /**
713
+ * The locatable problem lines of one attempt, structured findings first.
714
+ *
715
+ * A structured finding renders the requirement, the observed fact, the gap and
716
+ * the citation in a fixed order, so the fixing agent reads WHAT was required,
717
+ * WHAT was seen, WHY it falls short and WHERE to look — never a bare complaint.
718
+ * @param attempt - the attempt whose findings are rendered.
719
+ * @returns one line per finding, bounded.
720
+ */
721
+ export declare function locatedFindingLines(attempt: VerificationAttempt): string[];
722
+ /** `0.42` style percentage. */
723
+ export declare function percent(value: number): string;
724
+ /** Split a qualified `provider/model` route; undefined when it is not one. */
725
+ export declare function parseModelRoute(qualified: string | undefined): {
726
+ provider: string;
727
+ model: string;
728
+ } | undefined;
729
+ /**
730
+ * Normalize the raw `session/modelCatalog` reply into the shape the acceptance
731
+ * settings read. Everything is optional in the wire value, so every level is
732
+ * checked: an unreadable catalog degrades to "unknown", never to a crash.
733
+ * @param value - the raw gateway reply.
734
+ * @returns the normalized catalog, or undefined when nothing usable arrived.
735
+ */
736
+ export declare function normalizeCatalog(value: unknown): ModelCatalogView | undefined;
737
+ /** Whether the catalog declares the route at all. */
738
+ export declare function catalogHasRoute(catalog: ModelCatalogView | undefined, provider: string, model: string): boolean;
739
+ /**
740
+ * Resolve the acceptance configuration into the contract one execution freezes.
741
+ *
742
+ * "Inherit host" means the host's own model catalog default, never the card's
743
+ * pinned execution model. An explicitly configured reasoning effort is sent
744
+ * ONLY when the target model's adapter declares it: an unsupported value is
745
+ * dropped instead of being passed through, and the fallback to the target
746
+ * model's own default is recorded so the settings card and the report can show
747
+ * exactly what will be sent.
748
+ * @param settings - the live configuration.
749
+ * @param catalog - the host model catalog, when this cohort serves one.
750
+ * @param threshold - acceptance threshold to freeze.
751
+ * @returns the contract.
752
+ */
753
+ export declare function resolveContract(settings: VerificationSettings, catalog: ModelCatalogView | undefined, threshold?: number): VerificationContract;