@dsh-workbench/core 1.1.8 → 1.1.10

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 (127) hide show
  1. package/README.md +3 -3
  2. package/bin/dsh-workbench +11 -45
  3. package/client.js +549 -459
  4. package/dist/client/client.body.js +549 -459
  5. package/dist/client/index.js +422 -332
  6. package/dist/host/index.js +4661 -3954
  7. package/dist/types/app/layouts/approval-detail.d.ts +5 -5
  8. package/dist/types/app/layouts/env-gate/gate-text.d.ts +6 -4
  9. package/dist/types/app/layouts/market/discover-view.d.ts +1 -0
  10. package/dist/types/app/layouts/rightbar/MarketView.d.ts +25 -3
  11. package/dist/types/app/layouts/rightbar/market-rows.d.ts +0 -1
  12. package/dist/types/app/layouts/rightbar/market-view-text.d.ts +1 -2
  13. package/dist/types/app/layouts/sidebar/ProjectSwitcher.d.ts +1 -1
  14. package/dist/types/app/layouts/sidebar/workspace-groups.d.ts +4 -1
  15. package/dist/types/kernel/contract/index.d.ts +1 -0
  16. package/dist/types/modules/panels/model/diy-browser-act.d.ts +2 -2
  17. package/dist/types/modules/panels/model/diy-browser.d.ts +4 -2
  18. package/dist/types/modules/panels/model/diy-page.d.ts +2 -1
  19. package/dist/types/modules/panels/model/diy-record.d.ts +2 -1
  20. package/dist/types/modules/panels/model/diy-tools.d.ts +1 -0
  21. package/dist/types/modules/panels/model/market-dependency.d.ts +1 -1
  22. package/dist/types/modules/panels/model/market-discover.d.ts +1 -0
  23. package/dist/types/modules/panels/model/market-env.d.ts +2 -0
  24. package/dist/types/modules/panels/model/market.d.ts +1 -1
  25. package/dist/types/modules/panels/model/plugin-ledger.d.ts +3 -0
  26. package/dist/types/modules/panels/model/plugin-name.d.ts +7 -3
  27. package/dist/types/modules/sessions/index.d.ts +1 -1
  28. package/dist/types/modules/sessions/model/attention.d.ts +1 -0
  29. package/dist/types/shared/api/host/diy-publish-preview.d.ts +4 -4
  30. package/dist/types/shared/api/host/diy-recon-fs.d.ts +1 -1
  31. package/dist/types/shared/api/host/diy-recon.d.ts +12 -5
  32. package/dist/types/shared/api/host/flow/task.d.ts +10 -0
  33. package/dist/types/shared/api/host/flow/tool.d.ts +12 -0
  34. package/dist/types/shared/api/host/git-exec.d.ts +1 -0
  35. package/dist/types/shared/api/host/git-probe.d.ts +6 -6
  36. package/dist/types/shared/api/host/git-process.d.ts +13 -0
  37. package/dist/types/shared/api/host/git-routes.d.ts +5 -2
  38. package/dist/types/shared/api/host/host-routes.d.ts +2 -2
  39. package/dist/types/shared/api/host/market-doc.d.ts +2 -2
  40. package/dist/types/shared/api/host/market-index-fetch.d.ts +2 -2
  41. package/dist/types/shared/api/host/market-source-init.d.ts +2 -2
  42. package/dist/types/shared/api/host/plugin-term.d.ts +2 -0
  43. package/dist/types/shared/api/host/runtime-surface.d.ts +3 -0
  44. package/dist/types/shared/hooks/locale-text.d.ts +3 -0
  45. package/dist/types/shared/hooks/runtime-queries.d.ts +6 -0
  46. package/dist/types/shared/hooks/runtime-terms.d.ts +2 -0
  47. package/dist/types/shared/hooks/use-runtime-capabilities.d.ts +6 -0
  48. package/package.json +6 -3
  49. package/scripts/seed-workshop.sh +1 -1
  50. package/skills/workbench-module-diy/DESIGN.md +3 -1
  51. package/skills/workbench-module-diy/FLOW.md +117 -0
  52. package/skills/workbench-module-diy/PANEL.md +9 -7
  53. package/skills/workbench-module-diy/SKILL.md +7 -1
  54. package/skills/workbench-module-diy/STEPS.md +12 -1
  55. package/skills/workbench-module-diy/TOOLS.md +16 -4
  56. package/skills/workbench-module-diy/WIRING.md +2 -2
  57. package/skills/workbench-module-diy/WRITES.md +2 -2
  58. package/bin/opencli-isolated +0 -62
  59. package/bin/opencli-isolated.mjs +0 -44
  60. package/bin/opencli-node-mode.cjs +0 -1
  61. package/dist/types/app/layouts/rightbar/AskAgentButton.d.ts +0 -6
  62. package/dist/types/app/layouts/rightbar/board-columns.test.d.ts +0 -1
  63. package/dist/types/app/layouts/rightbar/dsh-borrow.test.d.ts +0 -1
  64. package/dist/types/app/layouts/rightbar/dsh-column-source.test.d.ts +0 -1
  65. package/dist/types/app/layouts/rightbar/dsh-surface.test.d.ts +0 -1
  66. package/dist/types/app/layouts/rightbar/presentation.test.d.ts +0 -1
  67. package/dist/types/app/layouts/rightbar/rightbar-width.test.d.ts +0 -1
  68. package/dist/types/app/layouts/rightbar/store.test.d.ts +0 -1
  69. package/dist/types/kernel/contract/contracts.test.d.ts +0 -1
  70. package/dist/types/kernel/contract/index.test.d.ts +0 -1
  71. package/dist/types/modules/panels/model/diy-browser-act.test.d.ts +0 -1
  72. package/dist/types/modules/panels/model/diy-browser-tools-shot.test.d.ts +0 -1
  73. package/dist/types/modules/panels/model/diy-browser-tools.test.d.ts +0 -1
  74. package/dist/types/modules/panels/model/diy-browser.test.d.ts +0 -1
  75. package/dist/types/modules/panels/model/diy-components.test.d.ts +0 -1
  76. package/dist/types/modules/panels/model/diy-context.test.d.ts +0 -1
  77. package/dist/types/modules/panels/model/diy-debug-routes.test.d.ts +0 -1
  78. package/dist/types/modules/panels/model/diy-debug-tools.test.d.ts +0 -1
  79. package/dist/types/modules/panels/model/diy-logs.test.d.ts +0 -1
  80. package/dist/types/modules/panels/model/diy-observers.test.d.ts +0 -1
  81. package/dist/types/modules/panels/model/diy-page.test.d.ts +0 -1
  82. package/dist/types/modules/panels/model/diy-record-bar.test.d.ts +0 -1
  83. package/dist/types/modules/panels/model/diy-record-beat.test.d.ts +0 -1
  84. package/dist/types/modules/panels/model/diy-record-capture.test.d.ts +0 -1
  85. package/dist/types/modules/panels/model/diy-record-close.test.d.ts +0 -1
  86. package/dist/types/modules/panels/model/diy-record-failure.test.d.ts +0 -1
  87. package/dist/types/modules/panels/model/diy-record-hook.test.d.ts +0 -1
  88. package/dist/types/modules/panels/model/diy-record-open.test.d.ts +0 -1
  89. package/dist/types/modules/panels/model/diy-record-routes.test.d.ts +0 -1
  90. package/dist/types/modules/panels/model/diy-record-shot.test.d.ts +0 -1
  91. package/dist/types/modules/panels/model/diy-record-text.test.d.ts +0 -1
  92. package/dist/types/modules/panels/model/diy-record.test.d.ts +0 -1
  93. package/dist/types/modules/panels/model/diy-schema.test.d.ts +0 -1
  94. package/dist/types/modules/panels/model/diy-spec.test.d.ts +0 -1
  95. package/dist/types/modules/panels/model/handoff.test.d.ts +0 -1
  96. package/dist/types/modules/panels/model/long-task-tools.test.d.ts +0 -1
  97. package/dist/types/modules/panels/model/market-install-error.test.d.ts +0 -1
  98. package/dist/types/modules/panels/model/market-installed.test.d.ts +0 -1
  99. package/dist/types/modules/panels/model/market-registry.test.d.ts +0 -1
  100. package/dist/types/modules/panels/model/market-remove.test.d.ts +0 -1
  101. package/dist/types/modules/panels/model/market-restart.test.d.ts +0 -1
  102. package/dist/types/modules/panels/model/market-sources-tool.test.d.ts +0 -1
  103. package/dist/types/modules/panels/model/market-swap-stuck.test.d.ts +0 -1
  104. package/dist/types/modules/panels/model/plugin-name.test.d.ts +0 -1
  105. package/dist/types/modules/panels/model/routes.test.d.ts +0 -1
  106. package/dist/types/modules/sessions/model/attention-long-task.test.d.ts +0 -1
  107. package/dist/types/modules/sessions/model/attention.test.d.ts +0 -1
  108. package/dist/types/modules/sessions/model/scroll-edges.test.d.ts +0 -1
  109. package/dist/types/modules/sessions/model/session-node.test.d.ts +0 -1
  110. package/dist/types/shared/api/config-sync.test.d.ts +0 -1
  111. package/dist/types/shared/api/diy.test.d.ts +0 -1
  112. package/dist/types/shared/api/dsh-plugins.test.d.ts +0 -1
  113. package/dist/types/shared/api/host/bundle-inspect-kind.test.d.ts +0 -1
  114. package/dist/types/shared/api/host/bundle-routes-self.test.d.ts +0 -1
  115. package/dist/types/shared/api/host/bundle-routes.test.d.ts +0 -1
  116. package/dist/types/shared/api/host/diy-facts.test.d.ts +0 -1
  117. package/dist/types/shared/api/host/diy-recon-fs.test.d.ts +0 -1
  118. package/dist/types/shared/api/host/diy-recon.test.d.ts +0 -1
  119. package/dist/types/shared/api/host/diy.test.d.ts +0 -1
  120. package/dist/types/shared/api/host/http.test.d.ts +0 -1
  121. package/dist/types/shared/api/host/png-crop.test.d.ts +0 -1
  122. package/dist/types/shared/api/host/runtime-seed.test.d.ts +0 -1
  123. package/dist/types/shared/api/host/self-update-marker.test.d.ts +0 -1
  124. package/dist/types/shared/api/host/shell.test.d.ts +0 -1
  125. package/dist/types/shared/api/unit-manifests.test.d.ts +0 -1
  126. package/dist/types/shared/components/blocker-action.test.d.ts +0 -1
  127. package/dist/types/shared/hooks/panel-state-report.test.d.ts +0 -1
@@ -1,4 +1,4 @@
1
- import type { ApprovalInput, ReactNode, Translate, UnitManifest, UnitToolOpencli } from '@dsh-workbench/shared';
1
+ import type { ApprovalInput, ReactNode, Translate, UnitManifest, UnitToolRuntime } from '@dsh-workbench/shared';
2
2
  import type { MarketSourcesPayload, PublishPreview } from '../../kernel/contract/market-index';
3
3
  export interface ApprovalRow {
4
4
  readonly label: string;
@@ -12,9 +12,9 @@ export interface ApprovalPlanView {
12
12
  readonly warn?: string | undefined;
13
13
  }
14
14
  export declare function marketSourceRows(tool: string, args: Readonly<Record<string, unknown>>, payload: MarketSourcesPayload | null | undefined, t: Translate): readonly ApprovalRow[];
15
- export declare function pluginToolIndexOf(manifests: readonly UnitManifest[]): ReadonlyMap<string, UnitToolOpencli>;
16
- export declare function pluginApprovalRows(origin: UnitToolOpencli, args: Readonly<Record<string, unknown>>, t: Translate): readonly ApprovalRow[];
15
+ export declare function pluginToolIndexOf(manifests: readonly UnitManifest[]): ReadonlyMap<string, UnitToolRuntime>;
16
+ export declare function pluginApprovalRows(origin: UnitToolRuntime, args: Readonly<Record<string, unknown>>, t: Translate): readonly ApprovalRow[];
17
17
  export declare function shellApprovalRenderer(manifests: () => readonly UnitManifest[]): (input: ApprovalInput, t: Translate) => ReactNode;
18
18
  export declare function shellClaimsApprovalDetail(tool: string): boolean;
19
- export declare function shellApprovalPlan(input: ApprovalInput, t: Translate, pluginTools?: ReadonlyMap<string, UnitToolOpencli> | undefined): ApprovalPlanView | undefined;
20
- export declare function shellApprovalDetail(input: ApprovalInput, t: Translate, pluginTools?: ReadonlyMap<string, UnitToolOpencli> | undefined): ReactNode;
19
+ export declare function shellApprovalPlan(input: ApprovalInput, t: Translate, pluginTools?: ReadonlyMap<string, UnitToolRuntime> | undefined): ApprovalPlanView | undefined;
20
+ export declare function shellApprovalDetail(input: ApprovalInput, t: Translate, pluginTools?: ReadonlyMap<string, UnitToolRuntime> | undefined): ReactNode;
@@ -1,14 +1,16 @@
1
1
  import type { Translate } from '@dsh-workbench/shared';
2
2
  import type { PreflightBridgeIssue, PreflightGuidance, PreflightSnapshot, PreflightStep } from '@dsh-workbench/shared/host';
3
+ import type { RuntimeProfile } from '@dsh-workbench/shared';
3
4
  export declare function failedStepText(guidance: PreflightGuidance | undefined, t: Translate): string;
4
5
  export declare function stepDetailText(step: PreflightStep, snapshot: PreflightSnapshot, t: Translate): string;
6
+ export declare function gateHintOf(snapshot: PreflightSnapshot, t: Translate): string;
5
7
  export declare function showsRawDetails(snapshot: PreflightSnapshot): boolean;
6
- export declare const OPENCLI_EXTENSION_URL = "https://chromewebstore.google.com/detail/opencli/ildkmabpimmkaediidaifkhjpohdnifk";
8
+ export declare function showsRawAll(snapshot: PreflightSnapshot, panelShown: boolean): boolean;
7
9
  export interface BridgeAdvice {
8
- readonly textKey: string;
10
+ readonly text: string;
9
11
  readonly link?: {
10
- readonly labelKey: string;
12
+ readonly label: string;
11
13
  readonly href: string;
12
14
  };
13
15
  }
14
- export declare function bridgeAdvice(issue: PreflightBridgeIssue): BridgeAdvice;
16
+ export declare function bridgeAdvice(issue: PreflightBridgeIssue, t: Translate, fixes?: RuntimeProfile['bridge']): BridgeAdvice;
@@ -1,5 +1,6 @@
1
1
  import 'dayjs/locale/zh-cn';
2
2
  import type { DiscoverEntry, DiscoverSourceRow, DiscoverVersionRow, MarketSourceConfig } from '../../../kernel/contract/market-index';
3
+ export declare function localeNow(): string;
3
4
  export type DiscoverSort = 'default' | 'published';
4
5
  export declare const DISCOVER_PAGE_SIZE = 50;
5
6
  export interface DiscoverFilterState {
@@ -1,13 +1,15 @@
1
- import type { Translate } from '@dsh-workbench/shared';
1
+ import type { ReactNode, Translate } from '@dsh-workbench/shared';
2
2
  import type { UnitManifest } from '@dsh-workbench/shared';
3
3
  import type { CapabilityMap } from '../../../shared/hooks/use-capabilities';
4
4
  import type { MarketFreshness } from './market-freshness';
5
5
  import type { InstalledPlugin } from '../../../shared/api/installed-plugins';
6
- import { type InstalledWorkbenchModule } from './market-rows';
6
+ import { type InstalledWorkbenchModule, type MarketRow, type MarketRowAction, type SharedRow } from './market-rows';
7
7
  import type { TitleResolve } from './market-names';
8
8
  import type { MarketMock } from './market-mock';
9
+ import type { MarketFailure } from './market-row-types';
9
10
  import type { ModuleUpdateMap } from './market-rows';
10
11
  import type { WorkbenchSelfUpdate, WorkbenchVersion } from '../../../kernel/contract/bundle-install';
12
+ import { type Pending } from './market-view-text';
11
13
  import type { VersionsCheck, VersionsPart } from '../market/use-module-versions';
12
14
  export interface MarketViewProps {
13
15
  readonly t: Translate;
@@ -15,6 +17,7 @@ export interface MarketViewProps {
15
17
  readonly manifests: readonly UnitManifest[];
16
18
  readonly installable?: ReadonlySet<string> | null | undefined;
17
19
  readonly capabilities: CapabilityMap | null;
20
+ readonly runtimePluginMarket?: boolean | undefined;
18
21
  readonly freshness: MarketFreshness;
19
22
  readonly onChanged: (options?: {
20
23
  readonly force?: boolean;
@@ -35,4 +38,23 @@ export interface MarketViewProps {
35
38
  readonly defaults?: readonly string[] | undefined;
36
39
  readonly changed?: Readonly<Record<string, number>> | undefined;
37
40
  }
38
- export declare function MarketView({ t, titleOf, manifests, installable, capabilities, freshness, onChanged, onPending, updates, modulesCheck, pluginsCheck, onCheck, installed, installedRead, workbench, selfUpdate, plugins, settling, installing, mock, defaults, changed, }: MarketViewProps): JSX.Element;
41
+ export declare function MarketBody({ t, self, shown, pluginList, installedList, shared, pending, failed, notice, act, onConfirming, setDefault, boardBusy, checks, onRecheck, rechecking, runtimePluginMarket, }: {
42
+ readonly t: Translate;
43
+ readonly runtimePluginMarket?: boolean | undefined;
44
+ readonly self: MarketRow | undefined;
45
+ readonly shown: readonly MarketRow[];
46
+ readonly pluginList: readonly MarketRow[];
47
+ readonly installedList: readonly MarketRow[];
48
+ readonly shared: readonly SharedRow[];
49
+ readonly pending: Pending | null;
50
+ readonly failed: MarketFailure | null;
51
+ readonly notice: string | null;
52
+ readonly act: (id: string, action: MarketRowAction) => Promise<void>;
53
+ readonly onConfirming: (id: string | null) => void;
54
+ readonly setDefault: (id: string, next: boolean) => Promise<void>;
55
+ readonly boardBusy: boolean;
56
+ readonly checks: Readonly<Record<VersionsPart, ReactNode>>;
57
+ readonly onRecheck: () => void;
58
+ readonly rechecking: boolean;
59
+ }): JSX.Element;
60
+ export declare function MarketView({ t, titleOf, manifests, installable, capabilities, runtimePluginMarket, freshness, onChanged, onPending, updates, modulesCheck, pluginsCheck, onCheck, installed, installedRead, workbench, selfUpdate, plugins, settling, installing, mock, defaults, changed, }: MarketViewProps): JSX.Element;
@@ -41,7 +41,6 @@ export declare function latestCheckSummary(modules: readonly InstalledWorkbenchM
41
41
  export declare function checkedPluginCount(plugins: readonly InstalledPlugin[] | null | undefined): number;
42
42
  export declare function installedRows(modules: readonly InstalledWorkbenchModule[], manifests: readonly UnitManifest[], listed: ReadonlySet<string>, names?: MarketNameMap | undefined, defaults?: ReadonlySet<string>, changed?: Readonly<Record<string, number>>): MarketRow[];
43
43
  export declare function marketSwitchLocked(row: MarketRow): boolean;
44
- export declare function marketAsksAgent(row: MarketRow): boolean;
45
44
  export declare function marketActions(row: MarketRow): MarketRowAction[];
46
45
  export declare function capabilityOutdated(capabilities: CapabilityMap | null, unit: string): boolean;
47
46
  export declare function marketCatalog(manifests: readonly UnitManifest[], installable: ReadonlySet<string> | null | undefined): readonly UnitManifest[];
@@ -5,6 +5,7 @@ import type { MarketRow, MarketRowAction, ModuleUpdateMap } from './market-rows'
5
5
  import type { SharedRow } from './market-shared-rows';
6
6
  export declare const PROGRESS_KEY: Readonly<Record<MarketRowAction, string>>;
7
7
  export declare const ACTION_LABEL_KEY: Readonly<Record<MarketRowAction, string>>;
8
+ export declare const UPDATE_ACTIONS: readonly MarketRowAction[];
8
9
  export interface HeldRow {
9
10
  readonly id: string;
10
11
  readonly row: MarketRow;
@@ -48,5 +49,3 @@ export declare function pendingRowOf(input: {
48
49
  readonly rows: readonly MarketRow[];
49
50
  readonly names: MarketNameMap;
50
51
  }): MarketRow | undefined;
51
- export declare function askAgentReason(row: MarketRow, t: Translate): string;
52
- export declare function askAgentText(row: MarketRow, t: Translate): string;
@@ -1,5 +1,5 @@
1
1
  import type { Translate, WorkspaceView } from '@dsh-workbench/shared';
2
- import type { Attention } from '../../../modules/sessions';
2
+ import { type Attention } from '../../../modules/sessions';
3
3
  export interface ProjectSwitcherProps {
4
4
  items: readonly WorkspaceView[];
5
5
  current: WorkspaceView | null;
@@ -9,7 +9,10 @@ export interface WorkspaceSectionPlan<T> {
9
9
  readonly heading: string | null;
10
10
  readonly items: readonly T[];
11
11
  }
12
+ export interface WorkspaceSectionOptions<T> {
13
+ readonly rankOf?: ((item: T) => number | null) | undefined;
14
+ }
12
15
  export declare function workspaceSections<T extends {
13
16
  readonly path: string;
14
17
  readonly title: string;
15
- }>(items: readonly T[], headings: WorkspaceHeadings): readonly WorkspaceSectionPlan<T>[];
18
+ }>(items: readonly T[], headings: WorkspaceHeadings, options?: WorkspaceSectionOptions<T>): readonly WorkspaceSectionPlan<T>[];
@@ -1,4 +1,5 @@
1
1
  export type { UnitModuleFace, UnitMountDeps, UnitMountResult } from '@dsh-workbench/shared/host';
2
+ export type { FlowAction, FlowActionContext, FlowActionRegistry, FlowActionStep, FlowCheck, FlowDefinition, FlowForEach, FlowHost, FlowPoll, FlowPredicate, FlowProblem, FlowResult, FlowRetry, FlowRunOptions, FlowScope, FlowStep, FlowStepEvent, FlowSubFlowStep, FlowValue, HostKit, } from '@dsh-workbench/shared/host';
2
3
  export type { ExtensionCaller, ExtensionCallOptions, ExtensionNeed, ExtensionSession, CommandReader, ExtensionValue, GitReader, LibReader } from '@dsh-workbench/shared';
3
4
  export type { BoardModuleProps as BoardProps, CallOverrides, DataError, DataReader, DataRequest, DataResult, RequestRecipe, UnitClientApi, UnitClientFace, } from '@dsh-workbench/shared';
4
5
  export type { DshClientContext as ClientContext, DshHostContext as HostContext } from '@dsh-workbench/shared';
@@ -1,10 +1,10 @@
1
1
  import type { DshShell } from '@dsh-workbench/shared';
2
- import { type BrowserStep } from './diy-browser';
2
+ import { type LineMaker, type BrowserStep } from './diy-browser';
3
3
  export declare const ACT_TIMEOUT_MS = 15000;
4
4
  export interface ActStep extends BrowserStep {
5
5
  readonly payload: Record<string, unknown> | undefined;
6
6
  }
7
- export declare function actBrowser(shell: DshShell, command: string, session: string, argv: readonly string[], timeoutMs?: number): Promise<ActStep>;
7
+ export declare function actBrowser(shell: DshShell, command: string, session: string, argv: readonly string[], timeoutMs?: number, line?: LineMaker): Promise<ActStep>;
8
8
  export declare function actErrorOf(step: ActStep): string;
9
9
  export declare const SWEEP_TIMEOUT_MS = 4000;
10
10
  export declare function stopNetworkExact(shell: DshShell, file: string, timeoutMs?: number): Promise<boolean>;
@@ -8,7 +8,9 @@ export interface BrowserStep {
8
8
  readonly timedOut: boolean;
9
9
  readonly truncated: boolean;
10
10
  }
11
- export declare function runBrowserStep(shell: DshShell, command: string, argv: readonly string[], timeoutMs?: number): Promise<BrowserStep>;
11
+ export type LineMaker = (command: string, argv: readonly string[]) => string;
12
+ export declare function plainLine(command: string, argv: readonly string[]): string;
13
+ export declare function runBrowserStep(shell: DshShell, command: string, argv: readonly string[], timeoutMs?: number, line?: LineMaker): Promise<BrowserStep>;
12
14
  export declare function jsonOf(raw: string): Record<string, unknown> | undefined;
13
15
  export declare function textOf(value: unknown): string;
14
16
  export interface BoundTab {
@@ -17,7 +19,7 @@ export interface BoundTab {
17
19
  readonly title: string;
18
20
  readonly reason: string;
19
21
  }
20
- export declare function bindCurrentTab(shell: DshShell, command: string, session: string): Promise<BoundTab>;
22
+ export declare function bindCurrentTab(shell: DshShell, command: string, session: string, timeoutMs?: number, line?: LineMaker): Promise<BoundTab>;
21
23
  export interface WorkbenchPage {
22
24
  readonly ok: boolean;
23
25
  readonly url: string;
@@ -1,7 +1,7 @@
1
1
  import type { DshHostContext, DshShell, DshToolRunContext } from '@dsh-workbench/shared';
2
2
  import type { DebugState } from '@dsh-workbench/shared/host';
3
3
  import { type BoardFactState, type BoardProbe, type BoardSituation } from '@dsh-workbench/shared/host';
4
- import { type WorkbenchPage } from './diy-browser';
4
+ import { type LineMaker, type WorkbenchPage } from './diy-browser';
5
5
  export type BoardState = BoardFactState;
6
6
  export interface PageHandle {
7
7
  readonly root: string;
@@ -11,6 +11,7 @@ export interface PageHandle {
11
11
  readonly shell: DshShell;
12
12
  readonly command: string;
13
13
  readonly session: string;
14
+ readonly line?: LineMaker;
14
15
  readonly bound: boolean;
15
16
  readonly board: BoardState;
16
17
  readonly boardPath: string;
@@ -1,5 +1,6 @@
1
1
  import type { DshHostContext, DshShell } from '@dsh-workbench/shared';
2
2
  import type { RecordState, RecordStore } from '@dsh-workbench/shared/host';
3
+ import { type LineMaker } from './diy-browser';
3
4
  import type { CaptureEntry } from './diy-record-capture';
4
5
  import type { RecordCall, RecordListRow, RecordPageRead } from './diy-record-text';
5
6
  export declare const OPEN_TIMEOUT_MS = 30000;
@@ -15,7 +16,7 @@ export declare function captureFileOf(artifactsDir: string, unit: string): strin
15
16
  export declare function lastCaptureFileOf(file: string): string;
16
17
  export declare function shotFileOf(captureFile: string, unit: string, n: number): string;
17
18
  export declare function takeShotOf(input: WatchFinishDeps, held: RecordState, n: number): Promise<void>;
18
- export declare function startRecordCapture(shell: DshShell, command: string, session: string, file: string): Promise<boolean>;
19
+ export declare function startRecordCapture(shell: DshShell, command: string, session: string, file: string, makeLine?: LineMaker): Promise<boolean>;
19
20
  export interface WatchFinishDeps {
20
21
  readonly ctx: DshHostContext;
21
22
  readonly shell: DshShell;
@@ -1,5 +1,6 @@
1
1
  import type { DshHostContext } from '@dsh-workbench/shared';
2
2
  import type { DebugStore } from '@dsh-workbench/shared/host';
3
+ export declare function browserBridgeOn(ctx: DshHostContext): boolean;
3
4
  import type { PublishPreview } from '@dsh-workbench/shared/contract/protocol/market-index';
4
5
  import type { MarketService } from './market';
5
6
  import type { PanelsService } from './service';
@@ -25,7 +25,7 @@ export declare function parseDependencyId(id: string): {
25
25
  readonly kind: DependencyKind;
26
26
  readonly name: string;
27
27
  } | undefined;
28
- export declare function findDependency(manifests: readonly UnitManifest[], id: string, isReleased?: ((unit: string) => boolean) | undefined): DependencyTarget | undefined;
28
+ export declare function findDependency(manifests: readonly UnitManifest[], id: string, isReleased?: ((unit: string) => boolean) | undefined, packagePrefix?: string | undefined): DependencyTarget | undefined;
29
29
  export declare function affectedUnitsOf(manifests: readonly UnitManifest[], request: {
30
30
  readonly id?: string | undefined;
31
31
  readonly unit?: string | undefined;
@@ -16,6 +16,7 @@ export interface MarketDiscoverOptions {
16
16
  readonly docs: MarketDocReader;
17
17
  readonly modules: () => readonly ProfileModule[];
18
18
  readonly defaultRegistry: () => Promise<string | undefined>;
19
+ readonly profilePath?: string | undefined;
19
20
  readonly shell?: DshShell | undefined;
20
21
  readonly shellVersion?: string | undefined;
21
22
  readonly fetchImpl?: ((url: string, init: RequestInit) => Promise<Response>) | undefined;
@@ -12,6 +12,8 @@ export declare function createEnvDropper(options: {
12
12
  readonly references?: (() => PluginReferences) | undefined;
13
13
  readonly command: string;
14
14
  readonly run: (line: string, optional?: boolean) => Promise<void>;
15
+ readonly libUninstallCommand: (need: Need) => string;
16
+ readonly pluginPackagePrefix?: string | undefined;
15
17
  readonly logger?: {
16
18
  info?(message: string): void;
17
19
  warn?(message: string): void;
@@ -16,7 +16,7 @@ export declare function createMarketService(options: {
16
16
  manifestsNow?: (() => readonly UnitManifest[]) | undefined;
17
17
  probe?: UnitMountDeps['probe'];
18
18
  shell?: DshShell | undefined;
19
- command?: string | undefined;
19
+ command: string;
20
20
  onInstalled?: (unit: string) => void;
21
21
  onUninstalled?: (unit: string) => void;
22
22
  isReleased?: (unit: string) => boolean;
@@ -1,4 +1,5 @@
1
1
  import type { PluginLedgerEntry, WorkspaceStore } from '@dsh-workbench/shared/host';
2
+ import { type PluginFiles } from './plugin-name';
2
3
  export interface PluginLedgerIntent {
3
4
  readonly package: string;
4
5
  readonly registry?: string | undefined;
@@ -6,6 +7,7 @@ export interface PluginLedgerIntent {
6
7
  }
7
8
  export interface PluginLedger {
8
9
  readonly home: string;
10
+ readonly pluginFiles?: PluginFiles | undefined;
9
11
  list(): readonly PluginLedgerEntry[];
10
12
  all(): readonly PluginLedgerEntry[];
11
13
  read(pkg: string): PluginLedgerEntry | undefined;
@@ -19,4 +21,5 @@ export interface PluginLedger {
19
21
  export declare function createPluginLedger(options: {
20
22
  readonly store: WorkspaceStore;
21
23
  readonly home: string;
24
+ readonly pluginFiles?: PluginFiles | undefined;
22
25
  }): PluginLedger;
@@ -3,6 +3,10 @@ export interface PluginEntryRef {
3
3
  readonly local?: boolean | undefined;
4
4
  readonly name?: string | undefined;
5
5
  }
6
- export declare function pluginDirOf(entry: PluginEntryRef): string;
7
- export declare function pluginOnDisk(entry: PluginEntryRef): boolean;
8
- export declare function pluginNameOf(entry: PluginEntryRef): string | undefined;
6
+ export interface PluginFiles {
7
+ readonly dir?: string | undefined;
8
+ readonly manifest?: string | undefined;
9
+ }
10
+ export declare function pluginDirOf(entry: PluginEntryRef, files: PluginFiles | undefined): string;
11
+ export declare function pluginOnDisk(entry: PluginEntryRef, files: PluginFiles | undefined): boolean;
12
+ export declare function pluginNameOf(entry: PluginEntryRef, files: PluginFiles | undefined): string | undefined;
@@ -1,3 +1,3 @@
1
1
  export { currentSessionId, orderByRecency, sessionNode, orderSessionRows, sessionRows, workspaceOfSession, sessionStatuses, visiblePendingKind, type SessionNode, type SessionStatusDot, } from './model/session-node';
2
2
  export { scrollEdgesOf, type ScrollEdges } from './model/scroll-edges';
3
- export { attentionLabel, attentionOf, attentionOfSession, attentionSessionIdOf, attentionWordLabel, longTaskPresenceOf, type Attention, type AttentionInput, type AttentionSeverity, type LongTaskPresence, type WorkspaceAttention, } from './model/attention';
3
+ export { attentionLabel, attentionListRank, attentionOf, attentionOfSession, attentionSessionIdOf, attentionWordLabel, longTaskPresenceOf, type Attention, type AttentionInput, type AttentionSeverity, type LongTaskPresence, type WorkspaceAttention, } from './model/attention';
@@ -26,6 +26,7 @@ export interface AttentionInput {
26
26
  readonly currentWorkspaceId: string | null;
27
27
  readonly longTasks?: LongTaskPresence | undefined;
28
28
  }
29
+ export declare function attentionListRank(attention: WorkspaceAttention | null | undefined): number;
29
30
  export declare function attentionOfSession(summary: SessionSummary, statusById: SessionStatusSnapshot, sessions: SessionsSnapshot, longTaskIds?: ReadonlySet<string>): AttentionSeverity | undefined;
30
31
  export interface AttentionPickInput {
31
32
  readonly workspace: WorkspaceView | null;
@@ -1,14 +1,14 @@
1
- import type { DshShell } from '@dsh-workbench/shared';
2
1
  import type { PublishPreview } from '@dsh-workbench/shared/contract/protocol/market-index';
2
+ import type { GitRunner } from './git-process';
3
3
  export interface PublishModuleFact {
4
4
  readonly dir: string;
5
5
  readonly name: string;
6
6
  readonly author: string;
7
7
  }
8
8
  export declare function moduleFactOf(root: string | null | undefined, unit: string): PublishModuleFact | null;
9
- export declare function localGitIdentityOf(shell: DshShell | undefined, dir: string): Promise<string | undefined>;
10
- export declare function lastCommitAuthorOf(shell: DshShell | undefined, dir: string): Promise<string | undefined>;
11
- export declare function inferredAuthorOf(root: string | null | undefined, unit: string, shell: DshShell | undefined): Promise<string | undefined>;
9
+ export declare function localGitIdentityOf(dir: string, runGit?: GitRunner): Promise<string | undefined>;
10
+ export declare function lastCommitAuthorOf(dir: string, runGit?: GitRunner): Promise<string | undefined>;
11
+ export declare function inferredAuthorOf(root: string | null | undefined, unit: string, runGit?: GitRunner): Promise<string | undefined>;
12
12
  export declare function publishPreviewOf(root: string | null | undefined, unit: string, options?: {
13
13
  readonly version?: string | undefined;
14
14
  readonly author?: string | undefined;
@@ -1,3 +1,3 @@
1
1
  import { type ReconCommand, type ReconPlugin } from './diy-recon';
2
2
  export declare function reconCatalogOf(path: string): readonly ReconCommand[] | undefined;
3
- export declare function installedPluginsOf(dir: string): readonly ReconPlugin[];
3
+ export declare function installedPluginsOf(dir: string, prefix: string): readonly ReconPlugin[];
@@ -26,6 +26,13 @@ export interface ReconSite {
26
26
  readonly browser: boolean;
27
27
  readonly commands: readonly ReconCommand[];
28
28
  }
29
+ export interface ReconSurface {
30
+ readonly name: string;
31
+ readonly pluginPrefix: string;
32
+ invoke(site: string, command?: string): string;
33
+ help(site: string): string;
34
+ readonly authorHint?: string;
35
+ }
29
36
  export interface ReconPlugin {
30
37
  readonly name: string;
31
38
  readonly commands: readonly string[];
@@ -37,13 +44,13 @@ export interface ReconAnswer {
37
44
  readonly next: string;
38
45
  readonly text: string;
39
46
  }
40
- export declare function invocableOf(command: ReconCommand): string;
47
+ export declare function invocableOf(command: ReconCommand, surface: ReconSurface): string;
41
48
  export declare function manifestCommandsOf(raw: string): readonly ReconCommand[];
42
- export declare function pluginNamesOf(entries: readonly string[]): readonly string[];
49
+ export declare function pluginNamesOf(entries: readonly string[], prefix: string): readonly string[];
43
50
  export declare function pluginCommandsOf(files: readonly string[]): readonly string[];
44
51
  export declare function hostOf(url: string): string;
45
52
  export declare function keywordsOf(keyword: string, url: string): readonly string[];
46
53
  export declare function scoreOf(command: ReconCommand, word: string): number;
47
- export declare function reconOf(commands: readonly ReconCommand[], plugins: readonly ReconPlugin[], keywords: readonly string[]): ReconAnswer;
48
- export declare function nextOf(answer: ReconAnswer): string;
49
- export declare function textOf(answer: ReconAnswer): string;
54
+ export declare function reconOf(commands: readonly ReconCommand[], plugins: readonly ReconPlugin[], keywords: readonly string[], surface: ReconSurface): ReconAnswer;
55
+ export declare function nextOf(answer: ReconAnswer, surface: ReconSurface): string;
56
+ export declare function textOf(answer: ReconAnswer, surface: ReconSurface): string;
@@ -0,0 +1,10 @@
1
+ import { type FlowActionRegistry, type FlowDefinition, type LongTaskBase, type LongTaskDeps, type LongTaskRegistry } from '@dsh-workbench/shared/host';
2
+ export declare function flowTaskDeps(actions: FlowActionRegistry): Pick<LongTaskDeps<LongTaskBase>, 'run' | 'outcome' | 'view' | 'stopped'>;
3
+ export interface StartFlowOptions {
4
+ readonly runs: LongTaskRegistry<LongTaskBase>;
5
+ readonly flow: FlowDefinition;
6
+ readonly input: unknown;
7
+ readonly workspace: string;
8
+ readonly session?: string | undefined;
9
+ }
10
+ export declare function startFlow(options: StartFlowOptions): LongTaskBase;
@@ -0,0 +1,12 @@
1
+ import type { DshToolDefinition, DshToolRunContext } from '@dsh-workbench/shared';
2
+ import { type FlowActionRegistry, type FlowDefinition, type LongTaskBase, type LongTaskRegistry } from '@dsh-workbench/shared/host';
3
+ export interface FlowToolOptions {
4
+ readonly name: string;
5
+ readonly description: string;
6
+ readonly flow: FlowDefinition;
7
+ readonly actions: FlowActionRegistry;
8
+ readonly runs: LongTaskRegistry<LongTaskBase>;
9
+ readonly workspaceOf?: ((exec: DshToolRunContext | undefined) => string | null) | undefined;
10
+ readonly sessionOf?: ((exec: DshToolRunContext | undefined) => string | null) | undefined;
11
+ }
12
+ export declare function flowTool(options: FlowToolOptions): DshToolDefinition;
@@ -1,2 +1,3 @@
1
+ export declare const GIT_NO_PROMPT_ENV: Readonly<Record<string, string>>;
1
2
  export declare function gitNoPromptPrefix(): string;
2
3
  export declare function withoutAskpassNoise(text: string): string;
@@ -1,9 +1,9 @@
1
- import type { DshShell } from '@dsh-workbench/shared';
2
1
  import type { GitProbePayload, GitProbeStatus } from '../../../kernel/contract/market-index';
2
+ import type { GitRunner } from './git-process.js';
3
3
  export declare function classifyGitProbe(stderr: string, timedOut: boolean): GitProbeStatus;
4
- export declare function probeGitAddress(shell: DshShell, url: string, options?: {
4
+ export interface GitProbeOptions {
5
5
  readonly timeoutMs?: number;
6
- }): Promise<GitProbePayload>;
7
- export declare function probeGitAddressCached(shell: DshShell, url: string, options?: {
8
- readonly timeoutMs?: number;
9
- }): Promise<GitProbePayload>;
6
+ readonly runGit?: GitRunner;
7
+ }
8
+ export declare function probeGitAddress(url: string, options?: GitProbeOptions): Promise<GitProbePayload>;
9
+ export declare function probeGitAddressCached(url: string, options?: GitProbeOptions): Promise<GitProbePayload>;
@@ -0,0 +1,13 @@
1
+ export interface GitRunResult {
2
+ readonly exitCode: number | null;
3
+ readonly stdout: string;
4
+ readonly stderr: string;
5
+ readonly timedOut: boolean;
6
+ }
7
+ export interface GitRunOptions {
8
+ readonly cwd?: string;
9
+ readonly timeoutMs?: number;
10
+ readonly maxBytes?: number;
11
+ }
12
+ export type GitRunner = (args: readonly string[], options?: GitRunOptions) => Promise<GitRunResult>;
13
+ export declare const runGitProcess: GitRunner;
@@ -1,3 +1,6 @@
1
- import type { DshHostContext } from '@dsh-workbench/shared';
2
1
  import { type RouteHandler } from '@dsh-workbench/shared/host';
3
- export declare function gitProbeHandler(ctx: DshHostContext): RouteHandler;
2
+ import type { GitRunner } from './git-process.js';
3
+ export interface GitProbeHandlerOptions {
4
+ readonly runGit?: GitRunner;
5
+ }
6
+ export declare function gitProbeHandler(options?: GitProbeHandlerOptions): RouteHandler;
@@ -1,10 +1,10 @@
1
1
  import type { DshHostContext } from '@dsh-workbench/shared';
2
2
  import type { FactLog, ProfilePort, RouteTable } from '@dsh-workbench/shared/host';
3
- import type { OpencliResolution } from '@dsh-workbench/shared/host';
3
+ import type { RuntimeStatus } from '@dsh-workbench/shared/host';
4
4
  export declare function createHostRoutes(input: {
5
5
  readonly ctx: DshHostContext;
6
6
  readonly facts: FactLog;
7
- readonly opencli: OpencliResolution;
7
+ readonly runtimes: Readonly<Record<string, RuntimeStatus>>;
8
8
  readonly running: string | undefined;
9
9
  readonly profile: ProfilePort;
10
10
  }): RouteTable;
@@ -1,5 +1,5 @@
1
- import type { DshShell } from '@dsh-workbench/shared';
2
1
  import type { DiscoverDoc, DiscoverDocKind, MarketIndexSource, MarketSourceConfig } from '@dsh-workbench/shared/contract/protocol/market-index';
2
+ import type { GitRunner } from './git-process.js';
3
3
  export interface MarketDocTarget {
4
4
  readonly name: string;
5
5
  readonly version: string;
@@ -10,7 +10,7 @@ export interface MarketDocReader {
10
10
  }
11
11
  export interface MarketDocReaderOptions {
12
12
  readonly root: string;
13
- readonly shell?: DshShell | undefined;
13
+ readonly runGit?: GitRunner | undefined;
14
14
  readonly fetchImpl?: ((url: string, init: RequestInit) => Promise<Response>) | undefined;
15
15
  readonly timeoutMs?: number | undefined;
16
16
  readonly maxBytes?: number | undefined;
@@ -1,5 +1,5 @@
1
- import type { DshShell } from '@dsh-workbench/shared';
2
1
  import type { DiscoverProblem, IndexSourceSpec, MarketIndex, MarketSourceConfig } from '@dsh-workbench/shared/contract/protocol/market-index';
2
+ import type { GitRunner } from './git-process.js';
3
3
  export interface CachedIndex {
4
4
  readonly index: MarketIndex;
5
5
  readonly fetchedAt: number;
@@ -24,7 +24,7 @@ export interface MarketIndexReader {
24
24
  }
25
25
  export interface MarketIndexReaderOptions {
26
26
  readonly root: string;
27
- readonly shell?: DshShell | undefined;
27
+ readonly runGit?: GitRunner | undefined;
28
28
  readonly fetchImpl?: ((url: string, init: RequestInit) => Promise<Response>) | undefined;
29
29
  readonly now?: (() => number) | undefined;
30
30
  readonly ttlMs?: number | undefined;
@@ -1,5 +1,5 @@
1
- import type { DshShell } from '@dsh-workbench/shared';
2
1
  import type { MarketSourceConfig } from '@dsh-workbench/shared/contract/protocol/market-index';
2
+ import type { GitRunner } from './git-process';
3
3
  import type { MarketSourcesStore } from './market-sources-store';
4
4
  export interface MarketSourceInitRequest {
5
5
  readonly id: string;
@@ -17,7 +17,7 @@ export type MarketSourceInitializer = (request: MarketSourceInitRequest) => Prom
17
17
  export interface MarketSourceInitOptions {
18
18
  readonly root: string;
19
19
  readonly store: MarketSourcesStore;
20
- readonly shell?: DshShell | undefined;
20
+ readonly runGit?: GitRunner | undefined;
21
21
  readonly timeoutMs?: number | undefined;
22
22
  }
23
23
  export declare function createMarketSourceInitializer(options: MarketSourceInitOptions): MarketSourceInitializer;
@@ -0,0 +1,2 @@
1
+ import type { DshHostContext } from '@dsh-workbench/shared';
2
+ export declare function pluginTermOf(ctx: DshHostContext): string;
@@ -0,0 +1,3 @@
1
+ import type { DshHostContext } from '@dsh-workbench/shared';
2
+ import type { RuntimeCommandSurface } from '@dsh-workbench/shared/host';
3
+ export declare function surfaceOf(ctx: DshHostContext): RuntimeCommandSurface | undefined;
@@ -0,0 +1,3 @@
1
+ import type { RuntimeText } from '@dsh-workbench/shared';
2
+ export declare function setRuntimeTextResolver(next?: (text: RuntimeText) => string): void;
3
+ export declare function runtimeText(text: RuntimeText): string;
@@ -0,0 +1,6 @@
1
+ import type { ApiResponse, RuntimeCapabilities, RuntimeProfile } from '@dsh-workbench/shared';
2
+ export type RuntimeCapabilitiesPayload = {
3
+ readonly capabilities: RuntimeCapabilities;
4
+ readonly runtimeProfile?: RuntimeProfile | null;
5
+ };
6
+ export declare function readRuntimeCapabilities(): Promise<ApiResponse<RuntimeCapabilitiesPayload>>;
@@ -0,0 +1,2 @@
1
+ import type { Translate } from '@dsh-workbench/shared';
2
+ export declare function runtimeTermsOf(t: Translate): Readonly<Record<string, string>>;
@@ -0,0 +1,6 @@
1
+ import type { RuntimeCapabilities, RuntimeProfile } from '@dsh-workbench/shared';
2
+ export declare function pluginMarketOf(capabilities: RuntimeCapabilities | undefined): boolean;
3
+ export declare function runtimeCapabilitiesValue(): RuntimeCapabilities | undefined;
4
+ export declare function runtimeProfileValue(): RuntimeProfile | undefined;
5
+ export declare function resetRuntimeCapabilities(): void;
6
+ export declare function useRuntimeCapabilities(): RuntimeCapabilities | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dsh-workbench/core",
3
- "version": "1.1.8",
3
+ "version": "1.1.10",
4
4
  "description": "个人工作台:Agent 工作台(左栏 + 常驻对话 + 自研右侧数据面板)。",
5
5
  "type": "module",
6
6
  "icon": "./icon.svg",
@@ -100,8 +100,8 @@
100
100
  "proper-lockfile": "^4.1.2",
101
101
  "which": "^7.0.0",
102
102
  "write-file-atomic": "^8.0.0",
103
- "@dsh-workbench/shared": "1.1.8",
104
- "@dsh-workbench/adapters-default": "1.1.8"
103
+ "@dsh-workbench/shared": "1.1.10",
104
+ "@dsh-workbench/adapters-default": "1.1.10"
105
105
  },
106
106
  "license": "MIT",
107
107
  "repository": {
@@ -113,6 +113,9 @@
113
113
  "bugs": {
114
114
  "url": "https://github.com/novaeth/dsh-workbench/issues"
115
115
  },
116
+ "workbench": {
117
+ "adapterSet": "@dsh-workbench/adapters-default"
118
+ },
116
119
  "scripts": {
117
120
  "build": "node scripts/build.mjs && node scripts/build-types.mjs",
118
121
  "build:host": "node scripts/build.mjs host",
@@ -524,7 +524,7 @@ fi
524
524
  # 且那句 pnpm 前缀每次都要写对)。这里给一个**与 cwd 无关**的同名入口,启动器把它
525
525
  # 挂进 PATH —— 于是"在工坊里"和"在别的目录里"都叫得动同一个工具链。
526
526
  #
527
- # 转发脚本而不是软链:同 `bin/opencli-isolated` 那条坑 —— pnpm publish 之后包里的脚本没有 x 位,
527
+ # 转发脚本而不是软链:同运行时包装那条坑 —— pnpm publish 之后包里的脚本没有 x 位,
528
528
  # 软链过去一执行就是 Permission denied。x 位由 chmod 当场给。
529
529
  # ⚠️ 先 rm -f:旧版本留下的软链还在时,`>` 会顺着软链把真脚本覆盖掉。
530
530
  ENTRY_DIR="$WORKBENCH_HOME/bin"
@@ -14,10 +14,12 @@
14
14
  | agent 写平台(提交、发布、改配置) | DIY | 预览 + 确认两拍([TOOLS.md](TOOLS.md) §5–§7) |
15
15
  | 用户已在浏览器登录过该系统,只是不知道数据在哪 | DIY | 复用登录探([DATASOURCE.md](DATASOURCE.md)) |
16
16
  | 要**新凭据**(账号 / 密钥 / token) | 工程 | 停;说清谁配什么 |
17
- | 多步长流程(要等、中途要人、失败要续) | 工程 | 同上 |
17
+ | 多步、要等、要重试、以后还要跑 | 先问 | 一次性 → 直接用工具跑;固化 → DIY 的 workflow([FLOW.md](FLOW.md));要新凭据 / 新服务 → 工程 |
18
18
  | 新服务 / 新进程 / 新依赖 | 工程 | 同上 |
19
19
  | 改工作台外壳,或改已发布模块 | 工程 | 同上 |
20
20
 
21
+ 多步长流程不是一律工程:复用现有登录、没有新凭据、要固化 → DIY 的 workflow;只有新凭据 / 新服务 / 新依赖才停。
22
+
21
23
  输出:一句结论 + 下一步 + 预计发生什么。
22
24
 
23
25
  ## 1 分工