@linxin666/dsh-client-ui-task-board 0.4.5 → 0.4.7

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 (83) hide show
  1. package/README.i18n.yaml +2 -2
  2. package/README.md +34 -18
  3. package/README.zh.md +34 -18
  4. package/lib/client.js +2804 -1024
  5. package/lib/client.js.map +1 -1
  6. package/lib/index.js +2576 -416
  7. package/lib/types/client/CardDefaultPresetField.d.ts +35 -0
  8. package/lib/types/client/TaskBoardSettingsCard.d.ts +61 -0
  9. package/lib/types/client/board/ReasoningEffortField.d.ts +25 -0
  10. package/lib/types/client/board/model-options.d.ts +67 -0
  11. package/lib/types/client/board/preset-label.d.ts +21 -0
  12. package/lib/types/client/board/preset-roster.d.ts +45 -0
  13. package/lib/types/client/board/team-run-promotion.d.ts +26 -0
  14. package/lib/types/client/index.d.ts +4 -5
  15. package/lib/types/client/locales.d.ts +81 -0
  16. package/lib/types/client/plugin-card-seat.d.ts +5 -0
  17. package/lib/types/client/schedule-zone.d.ts +50 -0
  18. package/lib/types/core/card-defaults.d.ts +78 -0
  19. package/lib/types/core/controller.d.ts +41 -17
  20. package/lib/types/core/launch-width.d.ts +31 -0
  21. package/lib/types/core/poll-cadence.d.ts +31 -0
  22. package/lib/types/core/reasoning-effort.d.ts +57 -0
  23. package/lib/types/core/subtask.d.ts +30 -8
  24. package/lib/types/core/tasks.d.ts +163 -14
  25. package/lib/types/core/use-cases/task-create.d.ts +10 -5
  26. package/lib/types/core/use-cases/task-schedule.d.ts +68 -10
  27. package/lib/types/core/use-cases/task-update.d.ts +1 -1
  28. package/lib/types/core/verification-budget.d.ts +52 -0
  29. package/lib/types/core/verification.d.ts +376 -9
  30. package/lib/types/host/launch-admission.d.ts +72 -0
  31. package/lib/types/host/verification-gate.d.ts +24 -0
  32. package/lib/types/host/verification-runner.d.ts +38 -7
  33. package/lib/types/host-ledger.d.ts +91 -11
  34. package/lib/types/host-runner.d.ts +111 -13
  35. package/lib/types/host-service.d.ts +199 -8
  36. package/lib/types/index.d.ts +141 -0
  37. package/lib/types/protocol.d.ts +63 -12
  38. package/package.json +29 -33
  39. package/src/client/CardDefaultPresetField.tsx +101 -0
  40. package/src/client/TaskBoardSettingsCard.tsx +288 -17
  41. package/src/client/board/LinkSubtaskModal.tsx +8 -0
  42. package/src/client/board/NewTaskModal.tsx +237 -60
  43. package/src/client/board/ReasoningEffortField.tsx +50 -0
  44. package/src/client/board/TaskCard.tsx +3 -3
  45. package/src/client/board/TaskDetail.tsx +261 -24
  46. package/src/client/board/VerificationReport.tsx +132 -13
  47. package/src/client/board/model-options.ts +178 -0
  48. package/src/client/board/preset-label.ts +32 -0
  49. package/src/client/board/preset-roster.ts +58 -0
  50. package/src/client/board/status-key.ts +3 -0
  51. package/src/client/board/team-run-promotion.ts +39 -0
  52. package/src/client/index.ts +105 -108
  53. package/src/client/locales.ts +171 -6
  54. package/src/client/plugin-card-seat.ts +7 -0
  55. package/src/client/schedule-zone.ts +100 -2
  56. package/src/client/settings-entry-form.ts +0 -1
  57. package/src/core/card-defaults.ts +132 -0
  58. package/src/core/controller.ts +55 -16
  59. package/src/core/launch-width.ts +38 -0
  60. package/src/core/poll-cadence.ts +41 -0
  61. package/src/core/reasoning-effort.ts +92 -0
  62. package/src/core/store.ts +69 -15
  63. package/src/core/subtask.ts +48 -13
  64. package/src/core/tasks.ts +213 -39
  65. package/src/core/use-cases/task-create.ts +57 -25
  66. package/src/core/use-cases/task-schedule.ts +190 -25
  67. package/src/core/use-cases/task-update.ts +9 -4
  68. package/src/core/verification-budget.ts +115 -0
  69. package/src/core/verification.ts +785 -17
  70. package/src/host/agent-tools.ts +127 -29
  71. package/src/host/launch-admission.ts +140 -0
  72. package/src/host/verification-gate.ts +172 -16
  73. package/src/host/verification-runner.ts +207 -40
  74. package/src/host-ledger.ts +346 -48
  75. package/src/host-runner.ts +234 -35
  76. package/src/host-service.ts +539 -52
  77. package/src/index.ts +250 -7
  78. package/src/protocol.ts +160 -32
  79. package/lib/invariant.js +0 -6
  80. package/lib/types/client/board-card-seat.d.ts +0 -34
  81. package/lib/types/invariant.d.ts +0 -3
  82. package/src/client/board-card-seat.ts +0 -102
  83. package/src/invariant.ts +0 -4
@@ -0,0 +1,35 @@
1
+ /**
2
+ * The default-agent-preset picker of the settings card's new-card-defaults
3
+ * topic.
4
+ *
5
+ * It renders the rows the create dialog's own mode picker renders — built-in
6
+ * presets first, then user presets, each labelled with its default and
7
+ * unavailable suffixes (board/preset-label.ts owns both) — and it renders a
8
+ * preset that cannot compose a session as a row that is visible but NOT
9
+ * selectable, so the board never stores a default no session could be composed
10
+ * from.
11
+ *
12
+ * The shared ChoiceField cannot express that: its choices carry no disabled
13
+ * state, and a stored pin the roster no longer serves would render as an empty
14
+ * trigger rather than as the unavailable preset it is. Both need a native
15
+ * `<select>` (the fallback the shared SelectField itself takes under an
16
+ * appearance skin), styled with the settings card's own field classes so the
17
+ * control stays a sibling of the fields beside it.
18
+ */
19
+ import type { ExecutionPresetOption } from '../core/controller.ts';
20
+ import type { FieldProps } from './PluginSettingsCard.tsx';
21
+ /** Props of the default-preset field: the shared field contract plus the roster. */
22
+ export interface CardDefaultPresetFieldProps extends FieldProps {
23
+ /**
24
+ * The deployment's agent-preset roster, or undefined while its runtime read
25
+ * has not answered: an unread roster offers the inherit choice alone instead
26
+ * of calling every stored pin "removed".
27
+ */
28
+ presets: readonly ExecutionPresetOption[] | undefined;
29
+ }
30
+ /**
31
+ * Render the default-preset select.
32
+ * @param props - the field contract and the roster to list.
33
+ * @returns the field.
34
+ */
35
+ export declare function CardDefaultPresetField(props: CardDefaultPresetFieldProps): import("react").JSX.Element;
@@ -7,6 +7,7 @@ import type { InjectFace, PropsLocale, PropsRenderSlots, PropsRuntime } from '@d
7
7
  import type { SnapshotStore } from '@deepseek-ai/dsh-client-store';
8
8
  import type { ConfigForm } from '@deepseek-ai/dsh-client-ui-settings/client';
9
9
  import type { TaskBoardExtensionDispatch } from '../core/extension.ts';
10
+ import type { ExecutionPresetOption } from '../core/controller.ts';
10
11
  import { type CardActions, type CardShell, type FieldState as CardFieldState } from './settings-form.ts';
11
12
  /** The task-board fields this card edits (the namespace's full schema). */
12
13
  export interface TaskBoardSettings {
@@ -18,12 +19,40 @@ export interface TaskBoardSettings {
18
19
  preventIdleSleep?: boolean;
19
20
  /** Subtask depth limit (1..3); 1 means a single level of subtasks. */
20
21
  maxSubtaskDepth?: number;
22
+ /** Roster-poll cadence in seconds while the board has work to reconcile. */
23
+ sessionPollSeconds?: number;
24
+ /**
25
+ * How many run launches may be in flight at once (1..16, default 3). One run
26
+ * opens its whole subtree, so this bounds the burst of sessions a single run
27
+ * action creates; members enter the running column in batches, none is dropped.
28
+ */
29
+ runLaunchWidth?: number;
30
+ /**
31
+ * GLOBAL native /goal switch (default off): the master control over whether
32
+ * this board starts a run with dsh's built-in /goal at all. Frozen per
33
+ * execution.
34
+ */
35
+ goalRunEnabled?: boolean;
21
36
  /** Goal acceptance for this board's executions (default on). */
22
37
  goalVerification?: boolean;
23
38
  /** Judge model route for goal acceptance; blank inherits the host default. */
24
39
  goalVerificationModel?: string;
25
40
  /** Judge reasoning effort; blank inherits the host default level. */
26
41
  goalVerificationReasoningEffort?: string;
42
+ /**
43
+ * Agent preset the create dialog of this board opens with. Blank pins
44
+ * nothing, so a new card follows the deployment default as before.
45
+ */
46
+ cardDefaultMode?: string;
47
+ /** Permission the create dialog opens with; blank applies no default. */
48
+ cardDefaultPermission?: string;
49
+ /** Execution model route the create dialog opens with; blank applies none. */
50
+ cardDefaultModel?: string;
51
+ /**
52
+ * Reasoning level bound to `cardDefaultModel`; it applies only while a
53
+ * card's final model IS that configured route, and is inert without one.
54
+ */
55
+ cardDefaultReasoningEffort?: string;
27
56
  }
28
57
  /** What the task-board card renders. */
29
58
  export interface TaskBoardSettingsCardState extends CardShell {
@@ -35,12 +64,32 @@ export interface TaskBoardSettingsCardState extends CardShell {
35
64
  preventIdleSleep: CardFieldState;
36
65
  /** Subtask depth limit field. */
37
66
  maxSubtaskDepth: CardFieldState;
67
+ /** Roster-poll cadence field. */
68
+ sessionPollSeconds: CardFieldState;
69
+ /** Run-launch admission width field. */
70
+ runLaunchWidth: CardFieldState;
71
+ /** GLOBAL native /goal switch. */
72
+ goalRunEnabled: CardFieldState;
38
73
  /** Goal-acceptance switch. */
39
74
  goalVerification: CardFieldState;
40
75
  /** Judge model route field. */
41
76
  goalVerificationModel: CardFieldState;
42
77
  /** Judge reasoning-effort field. */
43
78
  goalVerificationReasoningEffort: CardFieldState;
79
+ /** New-card default agent preset. */
80
+ cardDefaultMode: CardFieldState;
81
+ /** New-card default permission. */
82
+ cardDefaultPermission: CardFieldState;
83
+ /** New-card default model route. */
84
+ cardDefaultModel: CardFieldState;
85
+ /** New-card default reasoning level. */
86
+ cardDefaultReasoningEffort: CardFieldState;
87
+ /**
88
+ * The deployment's agent-preset roster, published by the runtime read the
89
+ * plugin wires; undefined until it answers, which leaves the default-preset
90
+ * field offering the inherit choice alone.
91
+ */
92
+ presets?: readonly ExecutionPresetOption[];
44
93
  }
45
94
  /** The registration-side face the card's slot entry injects. */
46
95
  export interface TaskBoardSettingsCardFace extends CardActions {
@@ -56,9 +105,21 @@ export declare class TaskBoardSettingsCardController {
56
105
  private readonly dispatch;
57
106
  private readonly form;
58
107
  private readonly store;
108
+ /** The deployment's agent-preset roster, once its runtime read has answered. */
109
+ private presets;
59
110
  /** @param scope - the bound configuration form for the `task-board` namespace. */
60
111
  constructor(scope: ConfigForm<TaskBoardSettings>, dispatch: TaskBoardExtensionDispatch);
61
112
  private projection;
113
+ /**
114
+ * Publish the deployment's agent-preset roster to the default-preset field.
115
+ * The roster is a runtime fact read outside this card (src/client/index.ts
116
+ * wires it once for both the board's pickers and this topic); it can arrive
117
+ * late or not at all, and until it does the field lists the inherit choice
118
+ * alone. This never blocks a save: a deployment that serves no roster still
119
+ * has a writable settings document.
120
+ * @param presets - the roster rows.
121
+ */
122
+ setPresetRoster(presets: readonly ExecutionPresetOption[]): void;
62
123
  /**
63
124
  * Build the face the card's slot registration injects.
64
125
  * @returns the card's snapshot and its form actions.
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Reasoning-effort field: one picker shared by both execution-target editors
3
+ * (the create dialog and the detail page), so the two never describe the same
4
+ * capability differently. The levels are the ones the picked model's catalog
5
+ * entry declares; an empty value is a real choice — "follow the model or Host
6
+ * default" — and is the default state.
7
+ *
8
+ * A stored level the roster no longer lists (the model left the roster, or its
9
+ * adapter changed) stays shown and labelled, but is not offered again, so the
10
+ * field never silently shows a different value than the one the card will ask
11
+ * for while the choosable set stays exactly the levels the model declares.
12
+ */
13
+ import type { ExecutionModelOption } from '../../core/controller.ts';
14
+ /** The controlled reasoning-effort picker. */
15
+ export declare function ReasoningEffortField({ models, modelId, value, pending, onChange }: {
16
+ /** The roster the picked model is looked up in. */
17
+ models: readonly ExecutionModelOption[];
18
+ /** The model this card pins; '' means "no pin". */
19
+ modelId: string;
20
+ /** The selected effort; '' means "follow the model or Host default". */
21
+ value: string;
22
+ /** Whether a mutation is in flight (the field locks with the rest of the form). */
23
+ pending: boolean;
24
+ onChange: (next: string) => void;
25
+ }): import("react").JSX.Element;
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Execution model options: the picker rows built from the official
3
+ * `session/modelCatalog` reply, and the reasoning-effort derivation both
4
+ * execution-target editors read off them (the create dialog and the detail
5
+ * page share one contract here, so they cannot promise different levels).
6
+ *
7
+ * The pickers must offer each model's real reasoning levels, which only the
8
+ * catalog declares — so the reply is normalized once, here, instead of every
9
+ * picker re-reading the wire shape. The fallback discovery path carries no
10
+ * capability metadata at all; its rows stay silent about reasoning rather than
11
+ * claiming a model supports none.
12
+ */
13
+ import type { ExecutionModelOption } from '../../core/controller.ts';
14
+ import type { TaskBoardKey } from '../locales.ts';
15
+ /**
16
+ * Normalize a `session/modelCatalog` reply into picker rows: one row per model
17
+ * of every provider group, keyed by the qualified route an execution pins.
18
+ * @param value - the raw catalog reply.
19
+ * @returns the rows, empty when the reply is unreadable.
20
+ */
21
+ export declare function modelOptionsFromCatalog(value: unknown): ExecutionModelOption[];
22
+ /**
23
+ * Normalize the flat `llm/discoverModels` list into picker rows. That reply
24
+ * names models only, so every row leaves the reasoning capability unknown.
25
+ * @param value - the raw discovery list.
26
+ * @returns the rows, empty when the list is unreadable.
27
+ */
28
+ export declare function modelOptionsFromDiscoveredModels(value: unknown): ExecutionModelOption[];
29
+ /**
30
+ * The picker rows of a model roster: the qualified `provider/model` route as
31
+ * the value a pin stores, and the provider beside the model name so two
32
+ * providers offering one model name stay distinguishable.
33
+ * @param models - the roster rows.
34
+ * @returns the choice rows, in roster order.
35
+ */
36
+ export declare function modelChoiceRows(models: readonly ExecutionModelOption[]): Array<{
37
+ value: string;
38
+ label: string;
39
+ }>;
40
+ /**
41
+ * The capability row the roster publishes for one model route.
42
+ * @returns undefined when no model is pinned, or the roster does not describe
43
+ * the pinned one — an unknown model is not the same as a model without
44
+ * reasoning.
45
+ */
46
+ export declare function reasoningOfModel(models: readonly ExecutionModelOption[], modelId: string): ExecutionModelOption['reasoning'] | undefined;
47
+ /**
48
+ * The effort ids the picker offers for a model, in catalog order.
49
+ * @returns an empty list when the model is unpinned, unknown, declares no
50
+ * reasoning, or publishes no selectable level.
51
+ */
52
+ export declare function reasoningEffortsFor(models: readonly ExecutionModelOption[], modelId: string): string[];
53
+ /** Whether the effort picker may be operated: a pinned model with declared, selectable levels. */
54
+ export declare function reasoningPickerEnabled(models: readonly ExecutionModelOption[], modelId: string): boolean;
55
+ /**
56
+ * The effort to keep when the picked model changes. Only a model that declares
57
+ * its levels can invalidate one: a model the roster cannot describe keeps the
58
+ * stored value, because the roster has no grounds to call it invalid.
59
+ * @param effort - the effort currently stored/selected ('' = follow the default).
60
+ * @returns the effort to keep.
61
+ */
62
+ export declare function reconcileReasoningEffort(models: readonly ExecutionModelOption[], modelId: string, effort: string): string;
63
+ /**
64
+ * The copy explaining why the picker is in its current state. One lookup for
65
+ * both editors, so the create dialog and the detail page never drift apart.
66
+ */
67
+ export declare function reasoningHintKey(models: readonly ExecutionModelOption[], modelId: string): TaskBoardKey;
@@ -20,3 +20,24 @@ export declare function presetLabel(preset: Pick<ExecutionPresetOption, 'id' | '
20
20
  * marks with `isDefault`.
21
21
  */
22
22
  export declare function inheritPresetLabel(presets: readonly ExecutionPresetOption[]): string;
23
+ /** One preset row a picker renders: the stored id, its label, and whether it may be picked. */
24
+ export interface PresetChoiceRow {
25
+ /** The value a pin stores. */
26
+ id: string;
27
+ /** Display label, already carrying the default and unavailable suffixes. */
28
+ label: string;
29
+ /** True when the preset cannot compose a session: the row is shown but not selectable. */
30
+ disabled: boolean;
31
+ }
32
+ /**
33
+ * The picker rows of one roster, split into the built-in and the user presets.
34
+ * Both pickers render these rows — the create dialog's mode select and the
35
+ * settings card's default-preset field — so their wording and their
36
+ * unavailable rows cannot drift apart.
37
+ * @param presets - the roster options.
38
+ * @returns one row list per group, in roster order.
39
+ */
40
+ export declare function presetChoiceRows(presets: readonly ExecutionPresetOption[]): {
41
+ builtin: PresetChoiceRow[];
42
+ custom: PresetChoiceRow[];
43
+ };
@@ -0,0 +1,45 @@
1
+ /**
2
+ * The agent-preset roster the execution-target pickers read: one read of the
3
+ * generated api-remotes face, and its normalization into the option rows the
4
+ * board controller and the settings card's new-card-defaults topic both
5
+ * consume.
6
+ *
7
+ * The roster is a runtime fact of the deployment, not ledger state. The
8
+ * namespace mounts with the official api-remotes assembly, so the read itself
9
+ * is wired through a scoped inject at the call site (see src/client/index.ts);
10
+ * this module owns only the shape both consumers agree on, so neither has to
11
+ * know how the wire face answers.
12
+ */
13
+ import type { ClientRemote } from '@deepseek-ai/dsh-api-remotes/client';
14
+ import type { ExecutionPresetOption } from '../../core/controller.ts';
15
+ /** The generated Remote namespace the mode pickers read their roster from. */
16
+ export type PresetRemote = ClientRemote['agentPresets'];
17
+ /** One agent-preset row the wire face answers with. */
18
+ export interface PresetRosterRow {
19
+ id: string;
20
+ name?: string;
21
+ description?: string;
22
+ /** Why this preset cannot compose a session; absent when it can. */
23
+ broken?: string;
24
+ isDefault: boolean;
25
+ }
26
+ /**
27
+ * Read the agent-preset roster of one deployment. The caller passes the
28
+ * namespace resolved inside its scoped inject, so a host that serves no such
29
+ * namespace never reaches here; a host that serves it answers `ok: false`
30
+ * instead, which leaves the caller's options untouched.
31
+ * @param remote - the `remote.agentPresets` namespace.
32
+ * @returns the roster, or a failed read the caller ignores.
33
+ */
34
+ export declare function readPresetRoster(remote: PresetRemote): Promise<{
35
+ ok: boolean;
36
+ presets: readonly PresetRosterRow[];
37
+ }>;
38
+ /**
39
+ * Normalize one roster into the picker rows the UI consumes. A preset that
40
+ * cannot compose a session keeps its `broken` reason: the pickers show it and
41
+ * disable it, so a missing preset never looks like a missing roster.
42
+ * @param presets - the roster rows.
43
+ * @returns the picker options.
44
+ */
45
+ export declare function presetOptionsFromRoster(presets: readonly PresetRosterRow[]): ExecutionPresetOption[];
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Team-run promotion for a parent card that just gained a subtask. A card with
3
+ * subtasks is exactly what the Agent Team mode is for, so the two join actions
4
+ * (create a subtask, link an existing task) opt the parent in — but only after
5
+ * the Host confirmed the join, and only where the deployment serves Agent
6
+ * Teams. A refused join changes nothing, and a parent that already opted in is
7
+ * left alone rather than rewritten.
8
+ *
9
+ * Nothing here runs on mount or from a render effect: an existing card is only
10
+ * ever touched by the user's own join action, so switching the option off by
11
+ * hand stays off.
12
+ */
13
+ import type { BoardController } from '../../core/controller.ts';
14
+ import type { TaskRecord } from '../../core/tasks.ts';
15
+ /**
16
+ * Whether a join would promote this parent: the deployment serves Agent Teams
17
+ * and the parent has not opted in yet.
18
+ * @param controller - the board controller (the snapshot carries both facts).
19
+ * @param parent - the task that gained a subtask, if there is one.
20
+ */
21
+ export declare function parentAwaitsTeamRunPromotion(controller: BoardController, parent: TaskRecord | undefined): boolean;
22
+ /**
23
+ * Opt the parent in after the Host confirmed the join.
24
+ * @returns true when the opt-in was written; false when it did not apply.
25
+ */
26
+ export declare function promoteParentForTeamRun(controller: BoardController, parent: TaskRecord | undefined): Promise<boolean>;
@@ -88,11 +88,10 @@ declare module '@deepseek-ai/cordis' {
88
88
  }
89
89
  /**
90
90
  * Required services (fiber inject waiting — the runtime must be up first).
91
- * The generated remote faces are probed at use time instead of injected:
92
- * `remote.agentPresets` only registers on 0.1.2-alpha.2 hosts (the
93
- * api-remotes contribution), so a hard wait would pend the entry forever
94
- * on hosts below that cohort, which serve the same roster through the
95
- * connection RPC face.
91
+ * The generated remote namespaces are not all hard injects: `remote.session`
92
+ * is one, while `remote.agentPresets` is reached through a scoped inject at
93
+ * use time (see mountUi), because the namespace mounts with the official
94
+ * api-remotes assembly applied beside this entry rather than before it.
96
95
  */
97
96
  export declare const inject: string[];
98
97
  /**
@@ -150,6 +150,7 @@ export declare const zh: {
150
150
  'detail.noSession': string;
151
151
  'detail.executionStarted': string;
152
152
  'detail.execution.initiator': string;
153
+ 'detail.execution.external': string;
153
154
  'detail.executionEnded': string;
154
155
  'detail.result.succeeded': string;
155
156
  'detail.result.failed': string;
@@ -192,7 +193,34 @@ export declare const zh: {
192
193
  'detail.schedule.duration.hours': string;
193
194
  'detail.schedule.duration.minutes': string;
194
195
  'detail.schedule.duration.seconds': string;
196
+ 'detail.schedule.mode': string;
197
+ 'detail.schedule.mode.cron': string;
198
+ 'detail.schedule.mode.once': string;
199
+ 'detail.schedule.at': string;
200
+ 'detail.schedule.atHint': string;
201
+ 'detail.schedule.atInvalid': string;
202
+ 'detail.schedule.plannedAt': string;
203
+ 'detail.schedule.zoneOnceHint': string;
204
+ 'detail.schedule.maxRuns': string;
205
+ 'detail.schedule.maxRunsUnlimited': string;
206
+ 'detail.schedule.maxRunsValue': string;
207
+ 'detail.schedule.maxRunsCustom': string;
208
+ 'detail.schedule.maxRunsInvalid': string;
209
+ 'detail.schedule.runs': string;
210
+ 'detail.schedule.runsUnlimited': string;
211
+ 'detail.schedule.remaining': string;
212
+ 'detail.schedule.cancel': string;
213
+ 'detail.schedule.ended': string;
214
+ 'detail.schedule.skipped': string;
215
+ 'detail.schedule.stop.fired': string;
216
+ 'detail.schedule.stop.limit': string;
217
+ 'detail.schedule.stop.no-target': string;
218
+ 'detail.schedule.stop.missed': string;
219
+ 'detail.schedule.stop.busy': string;
220
+ 'detail.schedule.stop.permission': string;
221
+ 'detail.schedule.stop.launch-failed': string;
195
222
  'card.scheduled': string;
223
+ 'card.scheduledOnce': string;
196
224
  'new.workspace': string;
197
225
  'new.agentPreset': string;
198
226
  'new.permission': string;
@@ -216,6 +244,14 @@ export declare const zh: {
216
244
  'exec.permission.danger-full-access': string;
217
245
  'exec.model.default': string;
218
246
  'exec.model.unknown': string;
247
+ 'exec.reasoning': string;
248
+ 'exec.reasoning.inherit': string;
249
+ 'exec.reasoning.unknown': string;
250
+ 'exec.reasoning.hint.pickModel': string;
251
+ 'exec.reasoning.hint.unknownModel': string;
252
+ 'exec.reasoning.hint.noEfforts': string;
253
+ 'exec.reasoning.hint.inherit': string;
254
+ 'exec.teamRunAutoHint': string;
219
255
  'exec.reuseSession': string;
220
256
  'exec.teamRun': string;
221
257
  'exec.teamRunHint': string;
@@ -255,9 +291,18 @@ export declare const zh: {
255
291
  'settings.unsaved': string;
256
292
  'settings.saveFailed': string;
257
293
  'settings.invalidNumber': string;
294
+ 'settings.sessionPollSeconds': string;
295
+ 'settings.sessionPollSecondsHint': string;
258
296
  'settings.maxSubtaskDepth': string;
259
297
  'settings.maxSubtaskDepthHint': string;
260
298
  'settings.maxSubtaskDepthOption': string;
299
+ 'settings.runLaunchWidth': string;
300
+ 'settings.runLaunchWidthHint': string;
301
+ 'settings.runBehaviorTitle': string;
302
+ 'settings.runBehaviorCardHint': string;
303
+ 'settings.goalRunGlobal': string;
304
+ 'settings.goalRunGlobalHint': string;
305
+ 'settings.goalRunGlobalDisabledTaskOption': string;
261
306
  'settings.goalVerificationTitle': string;
262
307
  'settings.goalVerification': string;
263
308
  'settings.goalVerificationCardHint': string;
@@ -282,11 +327,17 @@ export declare const zh: {
282
327
  'settings.goalVerificationEffortFallback': string;
283
328
  'settings.goalVerificationEffortFallbackNone': string;
284
329
  'settings.goalVerificationModelInvalid': string;
330
+ 'settings.cardDefaultsTitle': string;
331
+ 'settings.cardDefaultsCardHint': string;
332
+ 'settings.cardDefaultModeHint': string;
333
+ 'settings.cardDefaultPermissionHint': string;
334
+ 'settings.cardDefaultModelHint': string;
285
335
  'running.executing': string;
286
336
  'running.verifying': string;
287
337
  'running.repairing': string;
288
338
  'running.verificationPassed': string;
289
339
  'running.verificationFailed': string;
340
+ 'running.verificationInvalid': string;
290
341
  'verify.title': string;
291
342
  'verify.status.passed': string;
292
343
  'verify.status.failed': string;
@@ -294,6 +345,34 @@ export declare const zh: {
294
345
  'verify.status.verifying': string;
295
346
  'verify.status.pending': string;
296
347
  'verify.status.off': string;
348
+ 'verify.status.invalid': string;
349
+ 'verify.status.invalidHeld': string;
350
+ 'verify.attemptInvalid': string;
351
+ 'verify.invalidReason.missing-finding': string;
352
+ 'verify.invalidReason.unlocatable-quote': string;
353
+ 'verify.invalidReason.baseline-finding': string;
354
+ 'verify.invalidReason.vacuous-finding': string;
355
+ 'verify.invalidReason.insufficient-evidence': string;
356
+ 'verify.invalidReason.unknown': string;
357
+ 'verify.invalidCounts': string;
358
+ 'verify.invalidDetail': string;
359
+ 'verify.criterionFindings': string;
360
+ 'verify.criterionFinding': string;
361
+ 'verify.criterionFindingFull': string;
362
+ 'verify.location.task': string;
363
+ 'verify.location.trajectory': string;
364
+ 'verify.location.workspace': string;
365
+ 'verify.location.baseline': string;
366
+ 'verify.location.unknown': string;
367
+ 'verify.detailRemoved': string;
368
+ 'verify.cleanup.cleaned': string;
369
+ 'verify.cleanup.pending': string;
370
+ 'verify.cleanup.failed': string;
371
+ 'verify.cleanup.audit': string;
372
+ 'verify.cleanup.stage.quality': string;
373
+ 'verify.cleanup.stage.invalid': string;
374
+ 'verify.cleanup.stage.exception': string;
375
+ 'verify.cleanup.stage.budget': string;
297
376
  'verify.summary': string;
298
377
  'verify.criteria': string;
299
378
  'verify.criterion': string;
@@ -315,6 +394,7 @@ export declare const zh: {
315
394
  'verify.applicability.goalUnavailable': string;
316
395
  'verify.applicability.skipped': string;
317
396
  'verify.applicability.teamMember': string;
397
+ 'verify.applicability.goalDisabled': string;
318
398
  'verify.effortFallback': string;
319
399
  'verify.thresholdValue': string;
320
400
  'detail.parent': string;
@@ -326,6 +406,7 @@ export declare const zh: {
326
406
  'detail.subtasks.detach': string;
327
407
  'detail.subtasks.runningLock': string;
328
408
  'detail.subtasks.runHint': string;
409
+ 'detail.subtasks.runHintSettled': string;
329
410
  'detail.subtasks.waiting': string;
330
411
  'detail.subtasks.depthLimit': string;
331
412
  'detail.subtasks.hostOnly': string;
@@ -78,6 +78,11 @@ export interface PluginCardSeat {
78
78
  label?: () => string;
79
79
  /** Locale namespace the card renders with. */
80
80
  locale: string;
81
+ /**
82
+ * Child slots this card declares and renders. Forwarded to whichever seat
83
+ * the host renders; absent for a card that declares none.
84
+ */
85
+ children?: Record<string, unknown>;
81
86
  /** Business-face factory of the registration. */
82
87
  inject?: () => object;
83
88
  /**
@@ -1,3 +1,5 @@
1
+ import { type ScheduleRule, type ScheduleStopReason } from '../core/tasks.ts';
2
+ import { type TaskBoardKey } from './locales.ts';
1
3
  /** One selectable zone, in the order the picker shows it. */
2
4
  export interface ZoneChoice {
3
5
  /** Canonical IANA id, or `''` for the Host-zone entry. */
@@ -32,6 +34,54 @@ export declare function zoneChoices(hostTimeZone: string | undefined, storedTime
32
34
  * @returns localized relative wording.
33
35
  */
34
36
  export declare function relativeTimeLabel(targetMs: number, now: number): string;
37
+ /**
38
+ * The `datetime-local` input value for an instant, read in an explicit zone:
39
+ * `YYYY-MM-DDTHH:mm`. Uses the shared engine's zone reader, so the editor
40
+ * shows the same wall clock the Host schedules by.
41
+ * @param epochMs - the instant to render.
42
+ * @param timeZone - zone to read it in; absent uses the Host zone.
43
+ * @returns the input value.
44
+ */
45
+ export declare function zonedInputValue(epochMs: number, timeZone?: string): string;
46
+ /**
47
+ * Parse a `datetime-local` input value back to an instant, read in an explicit
48
+ * zone. Returns undefined when the text is not a whole calendar wall clock or
49
+ * names one the zone skips (a spring-forward gap), so the editor can refuse an
50
+ * unusable instant instead of silently moving it.
51
+ * @param value - the input text.
52
+ * @param timeZone - zone to interpret it in; absent uses the Host zone.
53
+ * @returns the instant, or undefined when it is not a usable wall clock.
54
+ */
55
+ export declare function parseZonedInput(value: string, timeZone?: string): number | undefined;
56
+ /**
57
+ * The default instant a new one-shot editor opens on: the next whole hour,
58
+ * rendered in the zone the rule will be read in.
59
+ * @param now - reference instant.
60
+ * @param timeZone - zone the rule is read in.
61
+ * @returns the input value for a near-future default.
62
+ */
63
+ export declare function defaultZonedInputValue(now: number, timeZone?: string): string;
64
+ /**
65
+ * The editor's run-cap option for a stored cap: the two named presets, the
66
+ * unlimited entry, or a custom value the editor shows in its own field.
67
+ * @param maxRuns - the stored cap, when any.
68
+ * @returns the select option value.
69
+ */
70
+ export declare function runCapOption(maxRuns: number | undefined): string;
71
+ /** The locale key describing why a rule stopped or skipped an occurrence. */
72
+ export declare function stopReasonKey(reason: ScheduleStopReason): TaskBoardKey;
73
+ /**
74
+ * The run-budget line: how many scheduled executions the Host opened and how
75
+ * many remain. Derived from the counter and the cap rather than stored, so the
76
+ * display cannot drift from the ledger.
77
+ * @param rule - the schedule rule.
78
+ * @returns localized wording.
79
+ */
80
+ export declare function budgetLabel(rule: ScheduleRule): string;
81
+ /** The line describing a rule that stopped itself, or undefined while it may still fire. */
82
+ export declare function endedLabel(rule: ScheduleRule): string | undefined;
83
+ /** The line describing the last skipped occurrence, or undefined when none. */
84
+ export declare function skippedLabel(rule: ScheduleRule): string | undefined;
35
85
  /**
36
86
  * The full next-run label: the absolute wall clock in the schedule's own zone,
37
87
  * plus the relative distance in parentheses. Showing both matters because a
@@ -0,0 +1,78 @@
1
+ /**
2
+ * New-card defaults: the execution targets a freshly created card starts from,
3
+ * and how they combine with what the caller picked and with the card a subtask
4
+ * or a duplicate is created from.
5
+ *
6
+ * Framework-free (no cordis, no runtime imports) because BOTH halves compile
7
+ * it: the Host resolves the seed when it writes the card, and the browser
8
+ * resolves the same seed to open the new-task dialog on it. One pure function
9
+ * is the only place the rules live, so the dialog and the ledger cannot drift.
10
+ *
11
+ * Every target is resolved in ONE order: what the caller picked wins over the
12
+ * value carried over from the card this one is created from, which wins over
13
+ * the board's new-card defaults, and a target nothing supplies stays blank
14
+ * ("no pin, resolved at run time"). A duplicate is a copy of its source and a
15
+ * subtask is derived from its parent, so both keep the source's own pins and
16
+ * fill only the fields that source left unset.
17
+ *
18
+ * The permission of a PARENT is the one exception: it never participates. The
19
+ * permission is not copied onto a card at creation — doing so would also have
20
+ * to copy the parent's human confirmation to stay runnable, and a detached
21
+ * child would keep both, so one confirmed parent would mint unbounded confirmed
22
+ * elevated roots. It is resolved along the ancestor chain at launch instead
23
+ * (core/subtask.ts), which is what makes detaching remove the inheritance by
24
+ * construction. A duplicate is not a hierarchy link, so it copies the
25
+ * permission like every other target. The board's own default permission is not
26
+ * a parent binding either and does apply to a subtask; it only pre-fills the
27
+ * card, and a value above the session baseline still needs a human
28
+ * confirmation before the card may run.
29
+ *
30
+ * The reasoning level is bound to the model route it was chosen for and never
31
+ * crosses to another one:
32
+ *
33
+ * - a level the caller picked is used as it stands;
34
+ * - a caller that pinned a model of its own inherits no level at all, not
35
+ * even one the same model happens to carry on the source card;
36
+ * - otherwise the source card's level travels with the source value it was
37
+ * stored on, exactly as the card's own model/level pair does, and wins over
38
+ * the board default level, so a board that configures none behaves exactly
39
+ * as the create path always has;
40
+ * - a board default level applies only while the card's final model IS the
41
+ * configured default model, and a blank default model makes it inert —
42
+ * a level the resolved model does not declare could only be refused by
43
+ * model selection at run time.
44
+ */
45
+ import type { TaskRecord } from './tasks.ts';
46
+ /** The board's configured new-card defaults; a blank target means "not set". */
47
+ export interface CardDefaults {
48
+ /** Agent preset a new card starts from. */
49
+ mode?: string;
50
+ /** Permission a new card starts from. */
51
+ permission?: string;
52
+ /** Model a new card starts from. */
53
+ model?: string;
54
+ /** Reasoning level a new card starts from, for the model above. */
55
+ reasoningEffort?: string;
56
+ }
57
+ /** The card a new one is created from, and how it is derived from it. */
58
+ export interface CardTargetSource {
59
+ /** A copy of the source card, or a subtask of it. */
60
+ kind: 'duplicate' | 'parent';
61
+ /** The source card's execution targets. */
62
+ task: Pick<TaskRecord, 'mode' | 'permission' | 'model' | 'reasoningEffort'>;
63
+ }
64
+ /** The resolved targets of the card about to be created; blank means "unset". */
65
+ export interface CardTargetSeed {
66
+ mode: string;
67
+ permission: string;
68
+ model: string;
69
+ reasoningEffort: string;
70
+ }
71
+ /**
72
+ * Resolve the execution targets a new card starts from.
73
+ * @param defaults - the board's configured new-card defaults, if any.
74
+ * @param source - the card this one is created from (a duplicate or a parent), if any.
75
+ * @param picked - what the caller chose explicitly; a non-blank value wins.
76
+ * @returns the four targets, blank where nothing supplies a value.
77
+ */
78
+ export declare function resolveCardTargets(defaults: CardDefaults | undefined, source: CardTargetSource | undefined, picked?: Partial<CardTargetSeed>): CardTargetSeed;