@dsh-workbench/core 0.3.3 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client.js +512 -42
- package/cordis.patch.yml +32 -0
- package/dist/client/client.body.js +512 -42
- package/dist/client/index.js +512 -42
- package/dist/host/index.js +2486 -323
- package/dist/types/app/client.d.ts +108 -3
- package/dist/types/app/layouts/approval-detail.d.ts +13 -0
- package/dist/types/app/layouts/sidebar/RecordFooterAction.d.ts +16 -0
- package/dist/types/app/layouts/sidebar/record-footer.d.ts +4 -0
- package/dist/types/modules/panels/client.d.ts +1 -0
- package/dist/types/modules/panels/model/diy-components.d.ts +3 -0
- package/dist/types/modules/panels/model/diy-components.test.d.ts +1 -0
- package/dist/types/modules/panels/model/diy-record-bar.test.d.ts +1 -0
- package/dist/types/modules/panels/model/diy-record-capture.d.ts +27 -0
- package/dist/types/modules/panels/model/diy-record-capture.test.d.ts +1 -0
- package/dist/types/modules/panels/model/diy-record-failure.test.d.ts +1 -0
- package/dist/types/modules/panels/model/diy-record-routes.d.ts +2 -0
- package/dist/types/modules/panels/model/diy-record-routes.test.d.ts +1 -0
- package/dist/types/modules/panels/model/diy-record-scripts.d.ts +6 -0
- package/dist/types/modules/panels/model/diy-record-text.d.ts +89 -0
- package/dist/types/modules/panels/model/diy-record-text.test.d.ts +1 -0
- package/dist/types/modules/panels/model/diy-record-tools.d.ts +2 -0
- package/dist/types/modules/panels/model/diy-record.d.ts +76 -0
- package/dist/types/modules/panels/model/diy-record.test.d.ts +1 -0
- package/dist/types/modules/panels/model/handoff.d.ts +1 -0
- package/dist/types/modules/panels/unit.d.ts +10 -4
- package/dist/types/shared/api/host/diy-acts.d.ts +4 -0
- package/dist/types/shared/api/host/diy-components.d.ts +54 -0
- package/dist/types/shared/api/host/diy-debug-act.d.ts +24 -7
- package/dist/types/shared/api/host/diy-record-act.d.ts +19 -0
- package/dist/types/shared/api/host/diy-workshop.d.ts +1 -0
- package/dist/types/shared/api/host/mount-units.d.ts +4 -0
- package/dist/types/shared/hooks/use-diy-record.d.ts +8 -0
- package/package.json +2 -2
- package/scripts/seed-workshop.sh +42 -2
- package/skills/workbench-module-diy/BUILD.md +4 -3
- package/skills/workbench-module-diy/DESIGN.md +26 -1
- package/skills/workbench-module-diy/FAMILY.md +55 -0
- package/skills/workbench-module-diy/HOOKS.md +95 -0
- package/skills/workbench-module-diy/KIT.md +16 -6
- package/skills/workbench-module-diy/PANEL.md +5 -2
- package/skills/workbench-module-diy/REVIEW.md +5 -4
- package/skills/workbench-module-diy/SKILL.md +12 -3
- package/skills/workbench-module-diy/TOOLING.md +5 -2
- package/skills/workbench-module-diy/TOOLS.md +6 -40
- package/skills/workbench-module-diy/WIRING.md +12 -5
- package/skills/workbench-module-diy/WRITES.md +47 -6
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { RecordExpect, RecordMove, RecordRefusal, RecordState } from '@dsh-workbench/shared';
|
|
2
|
+
export interface RecordCall {
|
|
3
|
+
readonly key: string;
|
|
4
|
+
readonly method: string;
|
|
5
|
+
readonly url: string;
|
|
6
|
+
readonly body: string;
|
|
7
|
+
readonly status: number;
|
|
8
|
+
readonly ct: string;
|
|
9
|
+
readonly response: string;
|
|
10
|
+
readonly at: number;
|
|
11
|
+
readonly source: 'hook' | 'capture';
|
|
12
|
+
}
|
|
13
|
+
export interface RecordPageRead {
|
|
14
|
+
readonly ok: boolean;
|
|
15
|
+
readonly code: string;
|
|
16
|
+
readonly phase: string;
|
|
17
|
+
readonly t0: number | null;
|
|
18
|
+
readonly t1: number | null;
|
|
19
|
+
readonly href: string;
|
|
20
|
+
readonly here: string;
|
|
21
|
+
readonly dropped: number;
|
|
22
|
+
readonly unhooked: boolean;
|
|
23
|
+
readonly calls: readonly RecordCall[];
|
|
24
|
+
}
|
|
25
|
+
export declare function recordPageOf(payload: Record<string, unknown> | undefined): RecordPageRead;
|
|
26
|
+
export declare function filterTextOf(expect: RecordExpect | null): string;
|
|
27
|
+
export declare function probeCommandOf(calls: readonly RecordCall[]): string;
|
|
28
|
+
export declare function bodyMissingOf(calls: readonly RecordCall[]): boolean;
|
|
29
|
+
export declare function recordRefusalText(code: RecordRefusal, held?: RecordState): string;
|
|
30
|
+
export declare function recordMissingText(): string;
|
|
31
|
+
export declare function recordTalkOf(): string;
|
|
32
|
+
export interface RecordListRow {
|
|
33
|
+
readonly index: number;
|
|
34
|
+
readonly key: string;
|
|
35
|
+
readonly at: number;
|
|
36
|
+
readonly method: string;
|
|
37
|
+
readonly url: string;
|
|
38
|
+
readonly status: number;
|
|
39
|
+
readonly ct: string;
|
|
40
|
+
readonly size: number;
|
|
41
|
+
readonly source: 'hook' | 'capture';
|
|
42
|
+
readonly hasRequest: boolean;
|
|
43
|
+
readonly hasResponse: boolean;
|
|
44
|
+
readonly likelyWrite: boolean;
|
|
45
|
+
readonly marked: boolean;
|
|
46
|
+
}
|
|
47
|
+
export declare function listRowsOf(calls: readonly RecordCall[], expect: RecordExpect | null): readonly RecordListRow[];
|
|
48
|
+
export interface RecordReadFacts {
|
|
49
|
+
readonly phase: string;
|
|
50
|
+
readonly armed: boolean;
|
|
51
|
+
readonly hookCaught: number;
|
|
52
|
+
readonly rows: readonly RecordListRow[];
|
|
53
|
+
readonly merged: number;
|
|
54
|
+
readonly capturedLines: number;
|
|
55
|
+
readonly capturedInSegment: number;
|
|
56
|
+
readonly capturedOutside: number;
|
|
57
|
+
readonly capturedTotalLines: number;
|
|
58
|
+
readonly capturedTruncated: boolean;
|
|
59
|
+
readonly capturedTailLimit: number;
|
|
60
|
+
readonly dropped: number;
|
|
61
|
+
readonly nav: boolean;
|
|
62
|
+
readonly filter: string;
|
|
63
|
+
readonly captureRound: string;
|
|
64
|
+
}
|
|
65
|
+
export declare function renderRecordRead(input: RecordReadFacts): string;
|
|
66
|
+
export interface RecordDetailFacts {
|
|
67
|
+
readonly found: boolean;
|
|
68
|
+
readonly where: string;
|
|
69
|
+
readonly method: string;
|
|
70
|
+
readonly url: string;
|
|
71
|
+
readonly status: number;
|
|
72
|
+
readonly ct: string;
|
|
73
|
+
readonly at: number;
|
|
74
|
+
readonly request: string;
|
|
75
|
+
readonly response: string;
|
|
76
|
+
readonly headers: string;
|
|
77
|
+
readonly requestFullSize: number;
|
|
78
|
+
readonly responseFullSize: number;
|
|
79
|
+
readonly requestSizeExact: boolean;
|
|
80
|
+
readonly responseSizeExact: boolean;
|
|
81
|
+
readonly ambiguous: number;
|
|
82
|
+
readonly source: string;
|
|
83
|
+
readonly maxBytes: number;
|
|
84
|
+
readonly note: string;
|
|
85
|
+
}
|
|
86
|
+
export declare function renderRecordDetail(input: RecordDetailFacts): string;
|
|
87
|
+
export declare function moveOrThrow(move: RecordMove, held: RecordState | null): RecordState;
|
|
88
|
+
export declare function domainOf(url: string): string;
|
|
89
|
+
export declare function readDomainsOf(design: unknown): readonly string[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { DshHostContext, DshShell, RecordState, RecordStore } from '@dsh-workbench/shared';
|
|
2
|
+
import type { CaptureEntry } from './diy-record-capture';
|
|
3
|
+
import type { RecordCall, RecordListRow, RecordPageRead } from './diy-record-text';
|
|
4
|
+
export declare const OPEN_TIMEOUT_MS = 30000;
|
|
5
|
+
export declare const SETTLE_MS = 2000;
|
|
6
|
+
export declare const WAIT_CAP_MS: number;
|
|
7
|
+
export declare const POLL_MS = 1000;
|
|
8
|
+
export declare const DETAIL_MAX_BYTES = 60000;
|
|
9
|
+
export declare const pauseFor: (ms: number) => Promise<void>;
|
|
10
|
+
export declare function waitOf(value: unknown): number;
|
|
11
|
+
export declare function foreignDomainText(design: unknown, url: string): string;
|
|
12
|
+
export declare function captureFileOf(packagesDir: string, unit: string): string;
|
|
13
|
+
export declare function lastCaptureFileOf(file: string): string;
|
|
14
|
+
export declare function startRecordCapture(shell: DshShell, command: string, session: string, file: string): Promise<boolean>;
|
|
15
|
+
export interface WatchFinishDeps {
|
|
16
|
+
readonly ctx: DshHostContext;
|
|
17
|
+
readonly shell: DshShell;
|
|
18
|
+
readonly command: string;
|
|
19
|
+
readonly sessionId: string;
|
|
20
|
+
readonly store: RecordStore;
|
|
21
|
+
readonly url: string;
|
|
22
|
+
readonly captureFile: string;
|
|
23
|
+
}
|
|
24
|
+
export declare function watchFinishStepOf(input: WatchFinishDeps): Promise<{
|
|
25
|
+
readonly stop: boolean;
|
|
26
|
+
readonly delivered: boolean;
|
|
27
|
+
}>;
|
|
28
|
+
export declare function watchRecordFinish(input: WatchFinishDeps): void;
|
|
29
|
+
export interface CaptureRead {
|
|
30
|
+
readonly text: string;
|
|
31
|
+
readonly totalLines: number;
|
|
32
|
+
readonly tailLimit: number;
|
|
33
|
+
readonly truncated: boolean;
|
|
34
|
+
readonly round: string;
|
|
35
|
+
}
|
|
36
|
+
export declare function captureLinesOf(shell: DshShell, file: string, timeoutMs?: number): Promise<number>;
|
|
37
|
+
export declare function captureRoundOf(shell: DshShell, file: string, timeoutMs?: number): Promise<string>;
|
|
38
|
+
export declare function captureTextOf(shell: DshShell, file: string, timeoutMs?: number): Promise<{
|
|
39
|
+
readonly text: string;
|
|
40
|
+
readonly truncated: boolean;
|
|
41
|
+
}>;
|
|
42
|
+
export declare function captureReadOf(shell: DshShell, file: string, timeoutMs?: number): Promise<CaptureRead>;
|
|
43
|
+
export declare function keepCaptureOf(shell: DshShell, file: string, timeoutMs?: number): Promise<boolean>;
|
|
44
|
+
export declare function captureLinesWithKeyOf(shell: DshShell, file: string, key: string, timeoutMs?: number): Promise<string>;
|
|
45
|
+
export interface SegmentBundle {
|
|
46
|
+
readonly capture: CaptureRead;
|
|
47
|
+
readonly entries: readonly CaptureEntry[];
|
|
48
|
+
readonly inside: readonly CaptureEntry[];
|
|
49
|
+
readonly outside: number;
|
|
50
|
+
readonly merged: readonly RecordCall[];
|
|
51
|
+
readonly rows: readonly RecordListRow[];
|
|
52
|
+
}
|
|
53
|
+
export declare function bundleOf(capture: CaptureRead, page: RecordPageRead, state: RecordState): SegmentBundle;
|
|
54
|
+
export declare function hookCallOf(page: RecordPageRead, key: string): RecordCall | null;
|
|
55
|
+
export declare function detailOfEntry(entry: CaptureEntry, maxBytes: number, ambiguous?: number): Record<string, unknown>;
|
|
56
|
+
export declare function detailOfCall(call: RecordCall, maxBytes: number): Record<string, unknown>;
|
|
57
|
+
export declare function releaseRecord(input: {
|
|
58
|
+
readonly shell: DshShell;
|
|
59
|
+
readonly command: string;
|
|
60
|
+
readonly session: string;
|
|
61
|
+
readonly url: string;
|
|
62
|
+
readonly captureFile: string;
|
|
63
|
+
}): Promise<{
|
|
64
|
+
readonly tab: boolean;
|
|
65
|
+
readonly capture: boolean;
|
|
66
|
+
}>;
|
|
67
|
+
export declare function releaseQuietly(input: {
|
|
68
|
+
readonly shell: DshShell;
|
|
69
|
+
readonly command: string;
|
|
70
|
+
readonly session: string;
|
|
71
|
+
readonly url: string;
|
|
72
|
+
readonly captureFile: string;
|
|
73
|
+
}): Promise<{
|
|
74
|
+
readonly tab: boolean;
|
|
75
|
+
readonly capture: boolean;
|
|
76
|
+
}>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -3,6 +3,7 @@ import type { HandoffEntry } from '@dsh-workbench/shared/host';
|
|
|
3
3
|
import type { UnitManifest } from '@dsh-workbench/shared/host';
|
|
4
4
|
export declare const PANELS_FACT = "panels";
|
|
5
5
|
export declare const DIY_DEBUG_FACT = "diy-debug";
|
|
6
|
+
export declare const DIY_RECORD_FACT = "diy-record";
|
|
6
7
|
export declare function panelsHandoffEntry(target?: {
|
|
7
8
|
readonly path?: string | undefined;
|
|
8
9
|
}): HandoffEntry | undefined;
|
|
@@ -17,6 +17,7 @@ export declare const MODULES_UPDATE_WORKBENCH_TOOL = "workbench_modules_update_w
|
|
|
17
17
|
export declare const DIY_LIST_TOOL = "workbench_diy_list";
|
|
18
18
|
export declare const DIY_STATUS_TOOL = "workbench_diy_status";
|
|
19
19
|
export declare const DIY_PANEL_TOOL = "workbench_diy_panel";
|
|
20
|
+
export declare const DIY_COMPONENTS_TOOL = "workbench_diy_components";
|
|
20
21
|
export declare const DIY_RECON_TOOL = "workbench_diy_recon";
|
|
21
22
|
export declare const DIY_SPEC_TOOL = "workbench_diy_spec";
|
|
22
23
|
export declare const DIY_PROBE_TOOL = "workbench_diy_probe";
|
|
@@ -39,14 +40,19 @@ export declare const DIY_DIALOG_TOOL = "workbench_diy_dialog";
|
|
|
39
40
|
export declare const DIY_LOGS_WATCH_TOOL = "workbench_diy_logs_watch";
|
|
40
41
|
export declare const DIY_LOGS_READ_TOOL = "workbench_diy_logs_read";
|
|
41
42
|
export declare const DIY_LOGS_STOP_TOOL = "workbench_diy_logs_stop";
|
|
43
|
+
export declare const DIY_RECORD_PREPARE_TOOL = "workbench_diy_record_prepare";
|
|
44
|
+
export declare const DIY_RECORD_READ_TOOL = "workbench_diy_record_read";
|
|
45
|
+
export declare const DIY_RECORD_DETAIL_TOOL = "workbench_diy_record_detail";
|
|
46
|
+
export declare const DIY_RECORD_STOP_TOOL = "workbench_diy_record_stop";
|
|
42
47
|
export declare const DIY_DEBUG_START_TOOL = "workbench_diy_debug_start";
|
|
43
48
|
export declare const DIY_DEBUG_PAUSE_TOOL = "workbench_diy_debug_pause";
|
|
44
49
|
export declare const DIY_DEBUG_RESUME_TOOL = "workbench_diy_debug_resume";
|
|
45
50
|
export declare const DIY_DEBUG_STOP_TOOL = "workbench_diy_debug_stop";
|
|
46
|
-
export declare const ALL_TOOLS: readonly ["workbench_panels_list", "workbench_panels_show", "workbench_panels_hide", "workbench_panels_move", "workbench_panels_reset", "workbench_panels_follow", "workbench_modules_list", "workbench_modules_install", "workbench_modules_update", "workbench_modules_uninstall", "workbench_modules_install_bundle", "workbench_modules_update_dependency", "workbench_modules_update_plugin", "workbench_modules_uninstall_plugin", "workbench_modules_update_workbench", "workbench_diy_list", "workbench_diy_status", "workbench_diy_panel", "workbench_diy_recon", "workbench_diy_spec", "workbench_diy_probe", "workbench_diy_install", "workbench_diy_show", "workbench_diy_state", "workbench_diy_html", "workbench_diy_find", "workbench_diy_click", "workbench_diy_hover", "workbench_diy_type", "workbench_diy_fill", "workbench_diy_keys", "workbench_diy_scroll", "workbench_diy_wait", "workbench_diy_eval", "workbench_diy_screenshot", "workbench_diy_network", "workbench_diy_dialog", "workbench_diy_logs_watch", "workbench_diy_logs_read", "workbench_diy_logs_stop", "workbench_diy_debug_start", "workbench_diy_debug_pause", "workbench_diy_debug_resume", "workbench_diy_debug_stop"];
|
|
51
|
+
export declare const ALL_TOOLS: readonly ["workbench_panels_list", "workbench_panels_show", "workbench_panels_hide", "workbench_panels_move", "workbench_panels_reset", "workbench_panels_follow", "workbench_modules_list", "workbench_modules_install", "workbench_modules_update", "workbench_modules_uninstall", "workbench_modules_install_bundle", "workbench_modules_update_dependency", "workbench_modules_update_plugin", "workbench_modules_uninstall_plugin", "workbench_modules_update_workbench", "workbench_diy_list", "workbench_diy_status", "workbench_diy_panel", "workbench_diy_components", "workbench_diy_recon", "workbench_diy_spec", "workbench_diy_probe", "workbench_diy_install", "workbench_diy_show", "workbench_diy_state", "workbench_diy_html", "workbench_diy_find", "workbench_diy_click", "workbench_diy_hover", "workbench_diy_type", "workbench_diy_fill", "workbench_diy_keys", "workbench_diy_scroll", "workbench_diy_wait", "workbench_diy_eval", "workbench_diy_screenshot", "workbench_diy_network", "workbench_diy_dialog", "workbench_diy_logs_watch", "workbench_diy_logs_read", "workbench_diy_logs_stop", "workbench_diy_record_prepare", "workbench_diy_record_read", "workbench_diy_record_detail", "workbench_diy_record_stop", "workbench_diy_debug_start", "workbench_diy_debug_pause", "workbench_diy_debug_resume", "workbench_diy_debug_stop"];
|
|
47
52
|
export type PanelsToolName = (typeof ALL_TOOLS)[number];
|
|
48
|
-
export declare const READ_TOOLS: readonly ["workbench_panels_list", "workbench_modules_list", "workbench_diy_list", "workbench_diy_status", "workbench_diy_panel", "workbench_diy_recon", "workbench_diy_spec", "workbench_diy_probe", "workbench_diy_state", "workbench_diy_html", "workbench_diy_find", "workbench_diy_click", "workbench_diy_hover", "workbench_diy_type", "workbench_diy_fill", "workbench_diy_keys", "workbench_diy_scroll", "workbench_diy_wait", "workbench_diy_eval", "workbench_diy_screenshot", "workbench_diy_network", "workbench_diy_dialog", "workbench_diy_logs_watch", "workbench_diy_logs_read", "workbench_diy_logs_stop"];
|
|
49
|
-
export declare const WRITE_TOOLS: readonly ["workbench_panels_show", "workbench_panels_hide", "workbench_panels_move", "workbench_panels_reset", "workbench_panels_follow", "workbench_modules_install", "workbench_modules_update", "workbench_modules_uninstall", "workbench_modules_install_bundle", "workbench_modules_update_dependency", "workbench_modules_update_plugin", "workbench_modules_uninstall_plugin", "workbench_modules_update_workbench", "workbench_diy_install", "workbench_diy_show", "workbench_diy_debug_start", "workbench_diy_debug_pause", "workbench_diy_debug_resume", "workbench_diy_debug_stop"];
|
|
50
|
-
export declare const DIY_TOOLS: readonly ["workbench_diy_list", "workbench_diy_status", "workbench_diy_panel", "workbench_diy_recon", "workbench_diy_spec", "workbench_diy_probe", "workbench_diy_install", "workbench_diy_show", "workbench_diy_state", "workbench_diy_html", "workbench_diy_find", "workbench_diy_click", "workbench_diy_hover", "workbench_diy_type", "workbench_diy_fill", "workbench_diy_keys", "workbench_diy_scroll", "workbench_diy_wait", "workbench_diy_eval", "workbench_diy_screenshot", "workbench_diy_network", "workbench_diy_dialog", "workbench_diy_logs_watch", "workbench_diy_logs_read", "workbench_diy_logs_stop"];
|
|
53
|
+
export declare const READ_TOOLS: readonly ["workbench_panels_list", "workbench_modules_list", "workbench_diy_list", "workbench_diy_status", "workbench_diy_panel", "workbench_diy_components", "workbench_diy_recon", "workbench_diy_spec", "workbench_diy_probe", "workbench_diy_state", "workbench_diy_html", "workbench_diy_find", "workbench_diy_click", "workbench_diy_hover", "workbench_diy_type", "workbench_diy_fill", "workbench_diy_keys", "workbench_diy_scroll", "workbench_diy_wait", "workbench_diy_eval", "workbench_diy_screenshot", "workbench_diy_network", "workbench_diy_dialog", "workbench_diy_logs_watch", "workbench_diy_logs_read", "workbench_diy_logs_stop", "workbench_diy_record_read", "workbench_diy_record_detail", "workbench_diy_record_stop"];
|
|
54
|
+
export declare const WRITE_TOOLS: readonly ["workbench_panels_show", "workbench_panels_hide", "workbench_panels_move", "workbench_panels_reset", "workbench_panels_follow", "workbench_modules_install", "workbench_modules_update", "workbench_modules_uninstall", "workbench_modules_install_bundle", "workbench_modules_update_dependency", "workbench_modules_update_plugin", "workbench_modules_uninstall_plugin", "workbench_modules_update_workbench", "workbench_diy_install", "workbench_diy_show", "workbench_diy_record_prepare", "workbench_diy_debug_start", "workbench_diy_debug_pause", "workbench_diy_debug_resume", "workbench_diy_debug_stop"];
|
|
55
|
+
export declare const DIY_TOOLS: readonly ["workbench_diy_list", "workbench_diy_status", "workbench_diy_panel", "workbench_diy_components", "workbench_diy_recon", "workbench_diy_spec", "workbench_diy_probe", "workbench_diy_install", "workbench_diy_show", "workbench_diy_state", "workbench_diy_html", "workbench_diy_find", "workbench_diy_click", "workbench_diy_hover", "workbench_diy_type", "workbench_diy_fill", "workbench_diy_keys", "workbench_diy_scroll", "workbench_diy_wait", "workbench_diy_eval", "workbench_diy_screenshot", "workbench_diy_network", "workbench_diy_dialog", "workbench_diy_logs_watch", "workbench_diy_logs_read", "workbench_diy_logs_stop"];
|
|
56
|
+
export declare const DIY_RECORD_TOOLS: readonly ["workbench_diy_record_prepare", "workbench_diy_record_read", "workbench_diy_record_detail", "workbench_diy_record_stop"];
|
|
51
57
|
export declare const DIY_DEBUG_TOOLS: readonly ["workbench_diy_debug_start", "workbench_diy_debug_pause", "workbench_diy_debug_resume", "workbench_diy_debug_stop"];
|
|
52
58
|
export declare const panelsUnit: UnitManifest;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import type { DshShell } from '@dsh-workbench/shared';
|
|
2
|
+
export declare const SURFACE_TIMEOUT_MS = 30000;
|
|
3
|
+
export declare const EXCERPT_LINES = 60;
|
|
4
|
+
export declare const SUMMARY_PER_BUCKET = 12;
|
|
5
|
+
export declare const NEAR_LIMIT = 8;
|
|
6
|
+
export declare const PRUNE_CHARS = 8192;
|
|
7
|
+
export declare const PRIMITIVES_PKG = "@deepseek-ai/dsh-client-ui-primitives";
|
|
8
|
+
export declare const MANIFEST_TAIL = "//# sourceMappingURL=";
|
|
9
|
+
export type SurfaceScope = 'all' | 'primitives' | 'kit';
|
|
10
|
+
export interface SurfacePayload {
|
|
11
|
+
readonly [key: string]: unknown;
|
|
12
|
+
}
|
|
13
|
+
export interface SurfaceQuery {
|
|
14
|
+
readonly primitives?: SurfacePayload;
|
|
15
|
+
readonly kit?: SurfacePayload;
|
|
16
|
+
}
|
|
17
|
+
export declare function scopeOf(raw: string): SurfaceScope;
|
|
18
|
+
export declare function wantsPrimitives(scope: SurfaceScope): boolean;
|
|
19
|
+
export declare function wantsKit(scope: SurfaceScope): boolean;
|
|
20
|
+
export declare function toolchainBinOf(root: string): string | null;
|
|
21
|
+
export declare function queryCommandOf(bin: string, only: 'kit' | 'primitives'): string;
|
|
22
|
+
export declare function runSurfaceQuery(shell: DshShell, bin: string, only: 'kit' | 'primitives', root: string): Promise<SurfacePayload>;
|
|
23
|
+
export declare function filesOf(payload: SurfacePayload | undefined): Record<string, string>;
|
|
24
|
+
export declare function rootsOf(payload: SurfacePayload | undefined): Record<string, string>;
|
|
25
|
+
export declare function countsOf(payload: SurfacePayload | undefined): Record<string, number>;
|
|
26
|
+
export declare function installedVersionOf(payload: SurfacePayload | undefined): string | null;
|
|
27
|
+
export declare function nearNamesOf(name: string, names: readonly string[], limit?: number): readonly string[];
|
|
28
|
+
export declare function findFileOf(name: string, query: SurfaceQuery): {
|
|
29
|
+
readonly file: string;
|
|
30
|
+
readonly from: 'kit' | 'primitives';
|
|
31
|
+
} | null;
|
|
32
|
+
export declare function excerptOf(text: string, maxLines?: number): string;
|
|
33
|
+
export declare function excerptAt(file: string, maxLines?: number): string;
|
|
34
|
+
export declare function skillDirOf(from: string): string | null;
|
|
35
|
+
export declare function symbolsIn(heading: string): readonly string[];
|
|
36
|
+
export declare function docSectionOf(name: string, dir: string | null): {
|
|
37
|
+
readonly file: string;
|
|
38
|
+
readonly lines: string;
|
|
39
|
+
} | null;
|
|
40
|
+
export declare function byLocationOf(payload: SurfacePayload): readonly {
|
|
41
|
+
readonly where: string;
|
|
42
|
+
readonly names: readonly string[];
|
|
43
|
+
}[];
|
|
44
|
+
export declare function renderSurfaceText(query: SurfaceQuery, options: {
|
|
45
|
+
scope: SurfaceScope;
|
|
46
|
+
all: boolean;
|
|
47
|
+
}): string;
|
|
48
|
+
export declare function listedNamesOf(query: SurfaceQuery): readonly string[];
|
|
49
|
+
export type FaceState = 'not-queried' | 'ok' | 'unreadable';
|
|
50
|
+
export declare function faceStateOf(query: SurfaceQuery, face: 'kit' | 'primitives'): FaceState;
|
|
51
|
+
export declare function renderNameText(name: string, found: {
|
|
52
|
+
readonly file: string;
|
|
53
|
+
readonly from: 'kit' | 'primitives';
|
|
54
|
+
} | null, query: SurfaceQuery): string;
|
|
@@ -1,9 +1,26 @@
|
|
|
1
1
|
import type { DebugIntent, DebugState, DebugStore, PostResource } from '@dsh-workbench/shared/host';
|
|
2
2
|
export declare const DEBUG_NOTICE_KIND = "workbench-diy";
|
|
3
|
+
export interface NoticeTextBlock {
|
|
4
|
+
readonly type: 'text';
|
|
5
|
+
readonly text: string;
|
|
6
|
+
}
|
|
7
|
+
export interface NoticeSource {
|
|
8
|
+
readonly kind: string;
|
|
9
|
+
readonly form: 'notice';
|
|
10
|
+
readonly summary: string;
|
|
11
|
+
}
|
|
12
|
+
export interface NoticeMessage {
|
|
13
|
+
readonly role: 'user';
|
|
14
|
+
readonly id: string;
|
|
15
|
+
readonly content: readonly NoticeTextBlock[];
|
|
16
|
+
readonly source: NoticeSource;
|
|
17
|
+
}
|
|
18
|
+
export declare function noticeMessage(text: string, summary: string, kind?: string): NoticeMessage;
|
|
19
|
+
export declare function isNoticeMessage(value: unknown): value is NoticeMessage;
|
|
3
20
|
export interface NoticeAgent {
|
|
4
21
|
readonly status: string;
|
|
5
|
-
inject(message:
|
|
6
|
-
followup(message:
|
|
22
|
+
inject(message: NoticeMessage): void;
|
|
23
|
+
followup(message: NoticeMessage): void;
|
|
7
24
|
}
|
|
8
25
|
export interface AgentsLookup {
|
|
9
26
|
get(id: string): NoticeAgent | undefined;
|
|
@@ -11,20 +28,20 @@ export interface AgentsLookup {
|
|
|
11
28
|
export declare function debugNoticeText(intent: DebugIntent, state: DebugState): string;
|
|
12
29
|
export declare function debugNoticeSummary(intent: DebugIntent, state: DebugState): string;
|
|
13
30
|
export declare function debugNotice(intent: DebugIntent, state: DebugState): {
|
|
14
|
-
message:
|
|
31
|
+
message: NoticeMessage;
|
|
15
32
|
summary: string;
|
|
16
33
|
};
|
|
17
34
|
export type NoticeMode = 'wake' | 'hold' | 'drop';
|
|
18
35
|
export type NoticeDelivery = 'followup' | 'inject' | 'held' | 'none' | 'skipped-idle';
|
|
19
|
-
export declare function holdNotice(sessionId: string, message:
|
|
20
|
-
export declare function takeHeldNotices(sessionId: string):
|
|
21
|
-
export declare function deliverDebugNotice(agents: AgentsLookup | undefined, sessionId: string, message:
|
|
36
|
+
export declare function holdNotice(sessionId: string, message: NoticeMessage): void;
|
|
37
|
+
export declare function takeHeldNotices(sessionId: string): NoticeMessage[];
|
|
38
|
+
export declare function deliverDebugNotice(agents: AgentsLookup | undefined, sessionId: string, message: NoticeMessage, mode?: NoticeMode): NoticeDelivery;
|
|
22
39
|
export interface DebugActDeps {
|
|
23
40
|
readonly store: () => DebugStore | undefined;
|
|
24
41
|
readonly agents: () => AgentsLookup | undefined;
|
|
25
42
|
readonly now?: (() => number) | undefined;
|
|
26
43
|
readonly notice?: ((intent: DebugIntent, state: DebugState) => {
|
|
27
|
-
message:
|
|
44
|
+
message: NoticeMessage;
|
|
28
45
|
summary: string;
|
|
29
46
|
}) | undefined;
|
|
30
47
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { PostResource, RecordIntent, RecordState, RecordStore } from '@dsh-workbench/shared/host';
|
|
2
|
+
import { type AgentsLookup, type NoticeMessage } from './diy-debug-act';
|
|
3
|
+
export declare const RECORD_NOTICE_KIND = "workbench-diy-record";
|
|
4
|
+
export declare function recordNoticeText(intent: RecordIntent, state: RecordState): string;
|
|
5
|
+
export declare function recordNoticeSummary(intent: RecordIntent, state: RecordState): string;
|
|
6
|
+
export declare function recordNotice(intent: RecordIntent, state: RecordState): {
|
|
7
|
+
message: NoticeMessage;
|
|
8
|
+
summary: string;
|
|
9
|
+
};
|
|
10
|
+
export interface RecordActDeps {
|
|
11
|
+
readonly store: () => RecordStore | undefined;
|
|
12
|
+
readonly agents: () => AgentsLookup | undefined;
|
|
13
|
+
readonly now?: (() => number) | undefined;
|
|
14
|
+
readonly notice?: ((intent: RecordIntent, state: RecordState) => {
|
|
15
|
+
message: NoticeMessage;
|
|
16
|
+
summary: string;
|
|
17
|
+
}) | undefined;
|
|
18
|
+
}
|
|
19
|
+
export declare function recordActResource(deps: RecordActDeps): PostResource;
|
|
@@ -9,6 +9,7 @@ export interface WorkshopModule {
|
|
|
9
9
|
export declare function workshopPackagesDir(ctx: DshHostContext): string | null;
|
|
10
10
|
export declare function insideWorkshop(root: string, target: string): boolean;
|
|
11
11
|
export declare function workshopModules(packagesDir: string, installed?: readonly string[]): readonly WorkshopModule[];
|
|
12
|
+
export declare function readDesignOfModule(dir: string): unknown;
|
|
12
13
|
export declare function inWorkshopSession(ctx: DshHostContext, workspace: string | null): boolean;
|
|
13
14
|
export interface WorkshopSync {
|
|
14
15
|
readonly state: 'ok' | 'syncing' | 'failed';
|
|
@@ -4,6 +4,9 @@ import { type RouteTable } from '@dsh-workbench/shared/host';
|
|
|
4
4
|
import type { ContextRenderer, UnitMountDeps, UnitMountResult, UnitCall } from '@dsh-workbench/shared/host';
|
|
5
5
|
import type { HostUnit } from './unit-registry';
|
|
6
6
|
import { type UnitReadiness } from './unit-readiness';
|
|
7
|
+
export declare function declaredNotesOf(plans: Iterable<{
|
|
8
|
+
readonly declaredNotes: ReadonlySet<string>;
|
|
9
|
+
}>): ReadonlySet<string>;
|
|
7
10
|
export interface UnitFailure {
|
|
8
11
|
readonly id: string;
|
|
9
12
|
readonly reason: string;
|
|
@@ -35,6 +38,7 @@ export interface UnitsPlan {
|
|
|
35
38
|
}>;
|
|
36
39
|
readonly failed: readonly UnitFailure[];
|
|
37
40
|
readonly warmReads: () => readonly (readonly string[])[];
|
|
41
|
+
readonly declaredNotes: ReadonlySet<string>;
|
|
38
42
|
readonly disposeLongTasks: () => void;
|
|
39
43
|
}
|
|
40
44
|
interface NamedEntry {
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { RecordState } from '@dsh-workbench/shared';
|
|
2
|
+
import type { HostWrite } from './use-host-write';
|
|
3
|
+
export declare const DIY_RECORD_ROUTE = "panels/diy-record";
|
|
4
|
+
export declare const DIY_RECORD_FACT = "diy-record";
|
|
5
|
+
export declare function useDiyRecordState(): RecordState | null;
|
|
6
|
+
export declare function useDiyRecordAct(): HostWrite<{
|
|
7
|
+
text?: string;
|
|
8
|
+
}>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dsh-workbench/core",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.4",
|
|
4
4
|
"description": "个人工作台:Agent 工作台外壳(左栏 + 常驻对话 + 自研右侧数据面板)。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"icon": "./icon.svg",
|
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
"access": "public"
|
|
88
88
|
},
|
|
89
89
|
"dependencies": {
|
|
90
|
-
"@dsh-workbench/shared": "0.3.
|
|
90
|
+
"@dsh-workbench/shared": "0.3.4"
|
|
91
91
|
},
|
|
92
92
|
"scripts": {
|
|
93
93
|
"build": "node scripts/build.mjs && node scripts/build-types.mjs",
|
package/scripts/seed-workshop.sh
CHANGED
|
@@ -102,6 +102,24 @@ target_version() {
|
|
|
102
102
|
printf '%s\n' "$version"
|
|
103
103
|
}
|
|
104
104
|
|
|
105
|
+
# 外壳 manifest 里钉的那份 dsh UI 版本(模块模板默认带的那个 devDependency,见
|
|
106
|
+
# `.scratch/dsh-primitives-face/spec.md` §3.1)。源优先**基准**(正在跑的那份外壳),
|
|
107
|
+
# 没有才退回跑脚本这份副本 —— 与 link_workshop_skills 同一条口径。
|
|
108
|
+
# 读不到就留空:调用方按"不写这一项"处理(模块 `init` 那边有自己的兜底常量与一句人话)。
|
|
109
|
+
shell_primitives_version() {
|
|
110
|
+
local root="$SHELL_ROOT"
|
|
111
|
+
[ -n "$root" ] && [ -f "$root/package.json" ] || root="$REPO_DIR"
|
|
112
|
+
[ -f "$root/package.json" ] || return 0
|
|
113
|
+
node -e '
|
|
114
|
+
const fs = require("node:fs");
|
|
115
|
+
try {
|
|
116
|
+
const pinned = JSON.parse(fs.readFileSync(process.argv[1], "utf8"))
|
|
117
|
+
.devDependencies?.["@deepseek-ai/dsh-client-ui-primitives"];
|
|
118
|
+
process.stdout.write(typeof pinned === "string" ? pinned : "");
|
|
119
|
+
} catch {}
|
|
120
|
+
' "$root/package.json" 2>/dev/null || true
|
|
121
|
+
}
|
|
122
|
+
|
|
105
123
|
# 三个包的装法**只有一处真相**:仓库副本 link 进本仓,安装副本按目标版本装。
|
|
106
124
|
# skeleton 与 sync 都调它 —— 两份规则漂开的症状是"根清单是 link、overrides 是 ^",
|
|
107
125
|
# 于是同一个工坊里两代并存(正是要防的那件事),而且不报错。
|
|
@@ -124,6 +142,15 @@ compute_specs() {
|
|
|
124
142
|
TOOLS_SPEC="^$version"
|
|
125
143
|
SHARED_SPEC="^$version"
|
|
126
144
|
fi
|
|
145
|
+
# dsh 原语(模块模板默认带的那个):**精确版**,与模块自己那份 devDependency 对齐 ——
|
|
146
|
+
# 类型面要对齐对账过的那一版(`.scratch/dsh-primitives-face/spec.md` §3.1)。
|
|
147
|
+
# 空 = 读不到外壳 manifest,就**不写这一项**(模块 `init` 有自己的兜底常量)。
|
|
148
|
+
local primitives_version
|
|
149
|
+
primitives_version="$(shell_primitives_version)"
|
|
150
|
+
PRIMITIVES_SPEC=""
|
|
151
|
+
if [ -n "$primitives_version" ]; then
|
|
152
|
+
PRIMITIVES_SPEC="$primitives_version"
|
|
153
|
+
fi
|
|
127
154
|
}
|
|
128
155
|
|
|
129
156
|
# 日志**只有一处**去处:$DSH_HOME/workbench/seed.log(冻结接口)。
|
|
@@ -395,8 +422,8 @@ run_sync() {
|
|
|
395
422
|
log_line "→ ⚠️ 自愈失败:${reason}"
|
|
396
423
|
return 1
|
|
397
424
|
fi
|
|
398
|
-
node - "$DIY_DIR/package.json" "$CORE_SPEC" "$TOOLS_SPEC" "$SHARED_SPEC" <<'NODE'
|
|
399
|
-
const [file, core, tools, shared] = process.argv.slice(2);
|
|
425
|
+
node - "$DIY_DIR/package.json" "$CORE_SPEC" "$TOOLS_SPEC" "$SHARED_SPEC" "$PRIMITIVES_SPEC" <<'NODE'
|
|
426
|
+
const [file, core, tools, shared, primitives] = process.argv.slice(2);
|
|
400
427
|
const fs = require('node:fs');
|
|
401
428
|
const manifest = JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
402
429
|
const want = {
|
|
@@ -405,6 +432,11 @@ const want = {
|
|
|
405
432
|
'@dsh-workbench/shared': shared,
|
|
406
433
|
};
|
|
407
434
|
manifest.devDependencies = { ...(manifest.devDependencies ?? {}), ...want };
|
|
435
|
+
// dsh 原语(模块模板默认带的那个):只进 devDependencies,**不进 overrides** ——
|
|
436
|
+
// 它不是 @dsh-workbench 的包,覆盖它没有意义(那是"多个模块各装一份"的另一种病)。
|
|
437
|
+
if (primitives !== undefined && primitives !== '') {
|
|
438
|
+
manifest.devDependencies['@deepseek-ai/dsh-client-ui-primitives'] = primitives;
|
|
439
|
+
}
|
|
408
440
|
manifest.pnpm = {
|
|
409
441
|
...(manifest.pnpm ?? {}),
|
|
410
442
|
overrides: { ...(manifest.pnpm?.overrides ?? {}), ...want },
|
|
@@ -556,6 +588,13 @@ if [ -f "$DIY_DIR/package.json" ]; then
|
|
|
556
588
|
echo "→ DIY 工坊已存在,跳过建骨架(要重来就先删掉 ${DIY_DIR})"
|
|
557
589
|
else
|
|
558
590
|
echo "→ 建 DIY 工坊 $DIY_DIR"
|
|
591
|
+
# 原语那一行可能没有(读不到外壳 manifest 时不写):空行在 JSON 里无害。
|
|
592
|
+
# ⚠️ 这里是 `if` 不是 `[ … ] && …`:后者在 `set -e` 下,测试为假时整条语句返回 1,
|
|
593
|
+
# 脚本会**当场退出**(骨架只建到一半、自愈也不起了)—— 实测被 ④ 那一格抓到。
|
|
594
|
+
PRIMITIVES_LINE=""
|
|
595
|
+
if [ -n "$PRIMITIVES_SPEC" ]; then
|
|
596
|
+
PRIMITIVES_LINE=" \"@deepseek-ai/dsh-client-ui-primitives\": \"$PRIMITIVES_SPEC\","
|
|
597
|
+
fi
|
|
559
598
|
cat >"$DIY_DIR/package.json" <<EOF
|
|
560
599
|
{
|
|
561
600
|
"name": "dsh-workbench-diy",
|
|
@@ -567,6 +606,7 @@ else
|
|
|
567
606
|
"@dsh-workbench/core": "$CORE_SPEC",
|
|
568
607
|
"@dsh-workbench/module-tools": "$TOOLS_SPEC",
|
|
569
608
|
"@dsh-workbench/shared": "$SHARED_SPEC",
|
|
609
|
+
${PRIMITIVES_LINE}
|
|
570
610
|
"@types/node": "^24.19.0",
|
|
571
611
|
"@types/react": "^19.3.0",
|
|
572
612
|
"esbuild": "^0.28.2",
|
|
@@ -68,7 +68,7 @@ pnpm exec dsh-wb-module init <unit> --dir <工坊>/packages/module-<unit> --temp
|
|
|
68
68
|
|
|
69
69
|
| 文件 | 职责 |
|
|
70
70
|
|---|---|
|
|
71
|
-
| `package.json` | 自述清单:包名、`dsh.bundle.patch`、`dsh.client
|
|
71
|
+
| `package.json` | 自述清单:包名、`dsh.bundle.patch`、`dsh.client`(`external` 默认带 `@dsh-workbench/core/client` 与 dsh 原语那行)、`dsh.workbench.unit`、`dsh.workbenchFaces{host,client}`(工具链字段,门禁必填)、六个脚本、peer 依赖;原语那行由 `init` 盖精确版([KIT.md](KIT.md) §8) |
|
|
72
72
|
| `arch.config.mjs` | 模块自己的**架构方言**:**只有一行**工厂调用 `moduleArch()`(从 `@dsh-workbench/module-tools/arch` 来)。层序表 / 两个运行时 / 阈值只有那一份,随工具链同代 |
|
|
73
73
|
| `eslint.config.mjs` | 模块自己的**语法卫生方言**:**只有两行** —— `moduleLint({ rootDir: import.meta.dirname })`(从 `@dsh-workbench/module-tools/lint` 来;`rootDir` 把 tsconfig 根钉在这个模块上,多份配置并存时 typescript-eslint 才猜得出)。规则 / ignores 只有那一份,随工具链同代;要放行某条就从 `moduleLint({ rules, ignores })` 开口子,别改方言那些块(判据比整份 8 块,逐块点名),也别手写一份自己的(自己 import 方言再照抄整份则分不出来) |
|
|
74
74
|
| `cordis.patch.yml` | 把自己插进 profile 的那一行 |
|
|
@@ -104,6 +104,7 @@ dsh-wb-module build # 出 client.js 与 dist/host.js
|
|
|
104
104
|
dsh-wb-module check # 十三条判据,全跑
|
|
105
105
|
dsh-wb-module check --only cards # 单跑一条(contracts / protocol / bundles / source / arch / lint /
|
|
106
106
|
# primitives / kit / cards / standalone / markers / style / alias)
|
|
107
|
+
dsh-wb-module check --only primitives [--all|--json] # 查询口:dsh 原语里有什么
|
|
107
108
|
dsh-wb-module lint [--fix] # 跑模块自己那份 eslint 配置;--fix 写回
|
|
108
109
|
```
|
|
109
110
|
|
|
@@ -116,7 +117,7 @@ dsh-wb-module lint [--fix] # 跑模块自己那份 eslint 配置;--fi
|
|
|
116
117
|
|
|
117
118
|
```bash
|
|
118
119
|
pnpm build # 构建
|
|
119
|
-
pnpm typecheck # tsc --noEmit
|
|
120
|
+
pnpm typecheck # tsc --noEmit(init 后先 pnpm install)
|
|
120
121
|
pnpm test # vitest
|
|
121
122
|
pnpm selfcheck # 构建 + 把 client.js 当加载器跑一遍(`diy` 骨架里还多一条 `design check`)
|
|
122
123
|
pnpm check # dsh-wb-module check:十三条判据
|
|
@@ -134,7 +135,7 @@ pnpm lint # dsh-wb-module lint:语法卫生(`pnpm lint -- --fix` 写
|
|
|
134
135
|
`workbench_diy_status`(`unit=<单元 id>`)看它现在走到哪一步、`workbench_diy_install` 装上并上板、
|
|
135
136
|
`workbench_diy_show` 只上板 —— 见 §7。**上完板自己逐条走一遍(这就是验收那一拍)**:浏览器那 14 把
|
|
136
137
|
(`state` / `get html` / `find` / `click` / `hover` / `type` / `fill` / `keys` / `scroll` / `wait` / `eval` /
|
|
137
|
-
`screenshot` / `network` / `dialog`,argv 与结果原样转发,全表见 [
|
|
138
|
+
`screenshot` / `network` / `dialog`,argv 与结果原样转发,全表见 [FAMILY.md](FAMILY.md))打的是
|
|
138
139
|
**用户当前那一页**上工坊那块板里的那张卡 —— 用户那一页不会被换掉,但他得把工作台切到前台。
|
|
139
140
|
**看屏 / 动屏那一族(浏览器那 14 把 / `logs_*`)要先 `workbench_diy_debug_start`**(`unit=…`;
|
|
140
141
|
会请他点头一次)—— 没有这场约定它们一律当场拒;不看屏了先 `_pause`、收工 `_stop`。
|
|
@@ -75,13 +75,38 @@
|
|
|
75
75
|
画不成的只有这几类,写词(并说清意思):纯动作("点一下去平台")、agent 的下一步、
|
|
76
76
|
时间性的词("不变 / 自己变 / 立刻")、纯映射表(能力名 ↔ 用户会怎么说)。
|
|
77
77
|
|
|
78
|
+
### 审批屏:写工具族必答,而且那两格是固定的
|
|
79
|
+
|
|
80
|
+
有"要用户点头"的写工具,就把**审批屏**也画进图里。它的形状不是自由的(仓内 ADR-0065,这份指引不链仓内路径):
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
┌─ card(dsh 的壳)─────────────────────────────────────────┐
|
|
84
|
+
│ ● 等待审批 │ ← dsh 画的
|
|
85
|
+
├───────────────────────────────────────────────────────────┤
|
|
86
|
+
│ <标题:一句,≤40 字,…,允许吗?> │ ← 你写的 question / fallback
|
|
87
|
+
│ <详情:ApprovalPlan 的两列表 + warn> │ ← 你写的 approval.render
|
|
88
|
+
├───────────────────────────────────────────────────────────┤
|
|
89
|
+
│ [ 拒绝 ] [ 允许一次 ] │
|
|
90
|
+
└───────────────────────────────────────────────────────────┘
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
四条口径(同一份:[KIT.md](KIT.md) §3):
|
|
94
|
+
|
|
95
|
+
1. **标题只有一句**:`…,允许吗?` 收尾并点名"工作台"(工作台自己的动作可用 `申请…` 陈述句式);
|
|
96
|
+
装配后 ≤108 字(含数据)。
|
|
97
|
+
2. **事实放详情**,用外壳的 `ApprovalPlan`(`approval: { tools, render }`):等宽、能换行、能滚,
|
|
98
|
+
长 URL / diff / 多字段都住这儿。
|
|
99
|
+
3. **别把事实塞进标题**:宿主那句 `approvalDetail`(明细)只留给**没有详情表**的族,≤20 字一行 ——
|
|
100
|
+
你既然画了详情表,它就是空的。
|
|
101
|
+
4. **附注(`approval_note`)不是你的**:只有 opencli 插件命令那族才必填;模块定义的工具默认没有那一格。
|
|
102
|
+
|
|
78
103
|
## 4 做完的判据
|
|
79
104
|
|
|
80
105
|
- 全程**用户只说过需求相关的话**:没有一次被问"用什么、放在哪、叫什么、怎么测"。
|
|
81
106
|
- 三张表没有空格(`dsh-wb-module design check` 绿);表里每一格,都在真卡片上见过或点过,
|
|
82
107
|
验收清单逐条打上了勾(`design accept`)。
|
|
83
108
|
- **验收归谁按域分**:**DIY 域(工坊会话)的验收是 agent 自己走的** —— 调试族
|
|
84
|
-
(`workbench_diy_debug_start` + 浏览器那 14 把枚举工具 + `logs_*`,全表见 [
|
|
109
|
+
(`workbench_diy_debug_start` + 浏览器那 14 把枚举工具 + `logs_*`,全表见 [FAMILY.md](FAMILY.md))
|
|
85
110
|
就是取证面;用户不必在场、也不必逐条点头,走完把"装好了、面板上哪一格"告诉他即可。
|
|
86
111
|
**工程域没有那一族**,仍按「打开 :3081 → 右栏第 N 张卡 → 点 X → 应该看到 Y」请他看一次。
|
|
87
112
|
- 要用户点头的**写能力(审批)那一拍仍是他的**:他真用一次时点,agent 代不了 ——
|