dsh-config-manager 0.1.76 → 0.1.77
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/lib/adapters/plugin-data-declared.d.ts +12 -0
- package/lib/adapters/plugin-data-declared.js +57 -0
- package/lib/adapters/plugin-data.d.ts +4 -6
- package/lib/adapters/plugin-data.js +8 -36
- package/lib/adapters/plugins.js +92 -12
- package/lib/client.d.ts +104 -9
- package/lib/client.js +1796 -714
- package/lib/core/messages.d.ts +1 -0
- package/lib/core/messages.js +2 -0
- package/lib/core/rollback-attribution.d.ts +81 -0
- package/lib/core/rollback-attribution.js +236 -0
- package/lib/core/rollback-merge.d.ts +22 -0
- package/lib/core/rollback-merge.js +203 -0
- package/lib/core/rollback-point.d.ts +114 -0
- package/lib/core/rollback-point.js +534 -17
- package/lib/core/types.d.ts +18 -0
- package/lib/index.d.ts +26 -3
- package/lib/index.js +129 -16
- package/lib/routes/recovery.js +11 -0
- package/lib/schema/section-registry.js +5 -5
- package/lib/ui/badge-tone.d.ts +16 -0
- package/lib/ui/badge-tone.js +20 -0
- package/lib/ui/i18n.d.ts +4 -4
- package/lib/ui/i18n.js +8 -8
- package/lib/ui/rollback-view.d.ts +95 -0
- package/lib/ui/rollback-view.js +55 -0
- package/lib/ui/selection-model.d.ts +140 -1
- package/lib/ui/selection-model.js +241 -9
- package/package.json +1 -1
- package/src/adapters/plugin-data-declared.ts +60 -0
- package/src/adapters/plugin-data.ts +7 -33
- package/src/adapters/plugins.ts +98 -13
- package/src/adapters/units.test.ts +26 -0
- package/src/client/chat/ChatEntryView.tsx +147 -46
- package/src/client/chat/chat-entry-view.test.ts +277 -1
- package/src/client/chat/chat-entry-view.ts +98 -4
- package/src/client/chat/chat-node-registration.ts +71 -0
- package/src/client/chat/chat-slots.ts +30 -12
- package/src/client/common/ContentPicker.tsx +581 -175
- package/src/client/common/host-primitives.ts +64 -1
- package/src/client/common/ui.tsx +17 -3
- package/src/client/config-manager.module.css +630 -397
- package/src/client/css-scale-guard.test.ts +41 -3
- package/src/client/css-token-guard.test.ts +10 -4
- package/src/client/export/ExportView.tsx +2 -0
- package/src/client/index.ts +15 -3
- package/src/client/locales.ts +54 -10
- package/src/client/recovery/RollbackCard.tsx +56 -2
- package/src/client/recovery/RollbackDiffPane.tsx +5 -0
- package/src/client/recovery/RollbackFileChanges.tsx +46 -2
- package/src/client/recovery/recovery-locales.ts +22 -0
- package/src/client/recovery/rollback-file-changes.test.ts +1 -1
- package/src/core/messages.ts +2 -0
- package/src/core/rollback-attribution.test.ts +120 -0
- package/src/core/rollback-attribution.ts +267 -0
- package/src/core/rollback-merge.test.ts +133 -0
- package/src/core/rollback-merge.ts +213 -0
- package/src/core/rollback-point.test.ts +412 -0
- package/src/core/rollback-point.ts +560 -20
- package/src/core/types.ts +19 -0
- package/src/index.facade.test.ts +60 -0
- package/src/index.ts +133 -19
- package/src/routes/recovery.ts +11 -0
- package/src/schema/section-registry.ts +5 -5
- package/src/ui/badge-tone.test.ts +23 -0
- package/src/ui/badge-tone.ts +27 -0
- package/src/ui/i18n.ts +8 -8
- package/src/ui/rollback-view.test.ts +27 -0
- package/src/ui/rollback-view.ts +139 -0
- package/src/ui/selection-model.test.ts +240 -2
- package/src/ui/selection-model.ts +349 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type DiffHunk } from '../utils/line-diff.ts';
|
|
2
|
+
import type { RollbackWriteAttributionPort, RollbackWriteRecorder } from './rollback-attribution.ts';
|
|
2
3
|
import { ROLLBACK_DEFAULT_LEDGER_BYTES } from './rollback-ledger.ts';
|
|
3
4
|
export declare const ROLLBACK_SCHEMA_VERSION = 2;
|
|
4
5
|
/** 回滚点库目录名(dataDir/rollback-points)——路由族 /recovery/rollback-points/* 同源 */
|
|
@@ -575,6 +576,23 @@ export interface RollbackPreviewFile {
|
|
|
575
576
|
* **宁可说「不知道」,也绝不谎报行数。**
|
|
576
577
|
*/
|
|
577
578
|
truncated: boolean;
|
|
579
|
+
/**
|
|
580
|
+
* true = 该文件在留点**之后**是**别的会话**写的(写入归属台账证明;见 core/rollback-attribution.ts)。
|
|
581
|
+
* 界面据此默认不勾选它(用户仍可勾上)。缺字段 / false = **没有归属证据**,
|
|
582
|
+
* 而不是「本会话写的」——「未判定」与「确知是本会话」必须分开。
|
|
583
|
+
*/
|
|
584
|
+
foreign?: boolean;
|
|
585
|
+
/** 那些「别的会话」的会话 id(仅当 foreign 为 true) */
|
|
586
|
+
foreignSessionId?: string;
|
|
587
|
+
/** 那次写入的时间(毫秒;仅当 foreign 为 true) */
|
|
588
|
+
foreignAt?: number;
|
|
589
|
+
/**
|
|
590
|
+
* true = 这次回退**不会改动它**:要么与其它对话的改动冲突、要么无法安全合并(缺共同祖先 / 二进制 /
|
|
591
|
+
* 差异被降级 / 对方删了它)。行级统计一律为 null —— 「不改动」不是「0 行变化」。
|
|
592
|
+
*/
|
|
593
|
+
skipped?: boolean;
|
|
594
|
+
/** 不改动的机器原因(界面映射成字典键,绝不裸渲染) */
|
|
595
|
+
mergeReason?: string;
|
|
578
596
|
}
|
|
579
597
|
/** 单文件差异里一侧(当前磁盘 / 回退点快照)的展示信息。 */
|
|
580
598
|
export interface RollbackFileDiffSide {
|
|
@@ -616,6 +634,15 @@ export interface RollbackFileDiffResult {
|
|
|
616
634
|
degraded: boolean;
|
|
617
635
|
/** 无法逐行对比的原因(有值时 hunks 为空) */
|
|
618
636
|
reason?: RollbackFileDiffReason;
|
|
637
|
+
/** true = 「回退后」一侧显示的是**三方合并**的结果,而不是记录里的原文 */
|
|
638
|
+
merged?: boolean;
|
|
639
|
+
/**
|
|
640
|
+
* true = 这次回退**不会改动**它(与其它对话的改动冲突 / 无法安全合并)—— 此时 after 与 before 相同。
|
|
641
|
+
* 界面必须把「不会改动」与「0 行变化」分开说。
|
|
642
|
+
*/
|
|
643
|
+
mergeSkipped?: boolean;
|
|
644
|
+
/** 不改动的机器原因(界面映射成字典键,绝不裸渲染) */
|
|
645
|
+
mergeReason?: string;
|
|
619
646
|
limits: typeof ROLLBACK_FILE_DIFF_LIMITS;
|
|
620
647
|
}
|
|
621
648
|
export interface RollbackPreviewWorkspace {
|
|
@@ -784,6 +811,28 @@ export interface RollbackSegmentResult {
|
|
|
784
811
|
*/
|
|
785
812
|
createdRefusedReason?: 'capture-incomplete';
|
|
786
813
|
writtenBytes?: number;
|
|
814
|
+
/**
|
|
815
|
+
* 因路径选择(onlyPaths)而未恢复 / 未删除的条目数。
|
|
816
|
+
* 与 createdSkipped(安全拒删)**分开**:这里的原因是用户自己没勾它,不是安全判据挡下。
|
|
817
|
+
*/
|
|
818
|
+
selectionSkipped?: number;
|
|
819
|
+
/**
|
|
820
|
+
* 因**归属隔离**(2026-10-17 定案 B)而跳过的记录条目数:该文件在留点之后是**别的会话**写的。
|
|
821
|
+
* 只在**没有显式点名**(`onlyPaths` 缺省)时生效;显式点名 = 用户明确要它,归属不再拦。
|
|
822
|
+
*/
|
|
823
|
+
foreignSkipped?: number;
|
|
824
|
+
/** 三方合并成功、写回「撤销本会话 + 保留对方改动」的条目数(有界清单同给) */
|
|
825
|
+
mergedCount?: number;
|
|
826
|
+
mergedPaths?: string[];
|
|
827
|
+
/** 冲突:两侧改到同一处 ⇒ **未写**,交给用户处理 */
|
|
828
|
+
conflictCount?: number;
|
|
829
|
+
conflictPaths?: string[];
|
|
830
|
+
/** 无法安全撤销(无中间版本 / 二进制 / 差异被降级 / 对方改成了不存在)⇒ **未写** */
|
|
831
|
+
unavailableCount?: number;
|
|
832
|
+
unavailablePaths?: string[];
|
|
833
|
+
/** 写入前发现又被改过(并发)⇒ **未写** */
|
|
834
|
+
concurrentCount?: number;
|
|
835
|
+
concurrentPaths?: string[];
|
|
787
836
|
/** 会话段:fork 出来的子会话 id */
|
|
788
837
|
childSessionId?: string;
|
|
789
838
|
guidance?: RollbackGuidance[];
|
|
@@ -803,6 +852,16 @@ export interface RollbackRewindInput {
|
|
|
803
852
|
* (把已写回的文件还原、把已删的文件写回)。拒删判据见 createdRemovalRefusal。
|
|
804
853
|
*/
|
|
805
854
|
removeCreated?: boolean;
|
|
855
|
+
/**
|
|
856
|
+
* **路径级选择性恢复**(2026-10-17 用户定案 A):只恢复 / 只删除这些路径。
|
|
857
|
+
*
|
|
858
|
+
* 缺省(undefined)= 既有全量口径,行为一字不变。给了值就:
|
|
859
|
+
* · 记录在案的文件里**不在**清单中的:不写(计入 selectionSkipped);
|
|
860
|
+
* · 「留点后新建」的候选里**不在**清单中的:不删(同样计入)。
|
|
861
|
+
* 清单里出现**既未记录、也不在删除候选**里的路径 ⇒ **fail-closed 拒绝、零写入**(invalid-input):
|
|
862
|
+
* 绝不把「用户打错一个路径」变成「静默少恢复几个文件」。
|
|
863
|
+
*/
|
|
864
|
+
onlyPaths?: readonly string[];
|
|
806
865
|
}
|
|
807
866
|
export interface RollbackRewindResult {
|
|
808
867
|
ok: boolean;
|
|
@@ -829,6 +888,11 @@ export type RollbackStorageProbe = () => Promise<{
|
|
|
829
888
|
export interface RollbackEngineOptions {
|
|
830
889
|
/** 插件数据目录(= $DSH_HOME/dsh-config-manager);回滚点库在 dataDir/rollback-points */
|
|
831
890
|
dataDir: string;
|
|
891
|
+
/**
|
|
892
|
+
* 写入归属台账(2026-10-17 用户定案 B)。缺省 = 没有归属信息 ⇒ 预览不标 foreign,
|
|
893
|
+
* 回退行为与旧版**逐字一致**(未判定绝不当作「别的会话写的」)。
|
|
894
|
+
*/
|
|
895
|
+
attribution?: RollbackWriteAttributionPort;
|
|
832
896
|
/** DSH home(会话根 = homeDir/sessions) */
|
|
833
897
|
homeDir: string;
|
|
834
898
|
now?: () => number;
|
|
@@ -1020,6 +1084,8 @@ export declare class RollbackPointEngine {
|
|
|
1020
1084
|
private ledgerSnapshotCache;
|
|
1021
1085
|
/** 台账存储层(v3:清单 + 单条记录 + 内容寻址载荷;issue #89) */
|
|
1022
1086
|
private readonly ledger;
|
|
1087
|
+
/** 写入归属(2026-10-17 定案 B)。undefined = 没有归属信息 ⇒ 预览不标 foreign */
|
|
1088
|
+
private readonly attribution;
|
|
1023
1089
|
private readonly ledgerBytesBudget;
|
|
1024
1090
|
/**
|
|
1025
1091
|
* 工作区捕获的挂钟时间预算(毫秒;见 ROLLBACK_DEFAULT_CAPTURE_BUDGET_MS)。**可变**:
|
|
@@ -1377,6 +1443,13 @@ export declare class RollbackPointEngine {
|
|
|
1377
1443
|
* `budget` 是**单张预览**共享的累计预算(字节 + 步数),跨条目生效。
|
|
1378
1444
|
*/
|
|
1379
1445
|
private previewFileCounts;
|
|
1446
|
+
/**
|
|
1447
|
+
* **合并结果**的逐文件行级统计(与 `previewFileCounts` 同一套预算与降级判据)。
|
|
1448
|
+
*
|
|
1449
|
+
* 为什么单独一份:合并后要写进去的内容既不是记录里的原文(ours),也不是磁盘现状(theirs)——
|
|
1450
|
+
* 预览若照旧拿 ours 算差异,就会把「其实会被保留的对方改动」显示成「会被删掉」。
|
|
1451
|
+
*/
|
|
1452
|
+
private previewMergeCounts;
|
|
1380
1453
|
/** 只读预览:零写入(不过确认门、不拍 guard、不写任何字节)。 */
|
|
1381
1454
|
preview(id: string): Promise<RollbackPreviewResult>;
|
|
1382
1455
|
/**
|
|
@@ -1406,6 +1479,41 @@ export declare class RollbackPointEngine {
|
|
|
1406
1479
|
* · 不是绝对路径。
|
|
1407
1480
|
*/
|
|
1408
1481
|
private createdRemovalRefusal;
|
|
1482
|
+
/**
|
|
1483
|
+
* 把一条「留点之后被**别的会话**写过」的记录做成三方合并结果(2026-10-17 跨对话安全回退)。
|
|
1484
|
+
*
|
|
1485
|
+
* 三方:`ours` = 记录里的内容(回退目标)、`base` = 目标点之后**最早**那份中间版本、
|
|
1486
|
+
* `theirs` = 当前磁盘。结果是「撤销本会话那次改动 + 保留对方后来的改动」。
|
|
1487
|
+
*
|
|
1488
|
+
* 返回:`write`(合并干净且确实要写,带目标哈希 + 期望的当前哈希)、
|
|
1489
|
+
* `unchanged`(合并结果就是当前内容 —— 对方没动这一处,本来就不需要写)、
|
|
1490
|
+
* `blocked`(不能安全处理:冲突 / 没有中间版本 / 二进制 / 差异被降级 / 对方改成了不存在 / 读不出)。
|
|
1491
|
+
*/
|
|
1492
|
+
private mergeForeignRecord;
|
|
1493
|
+
/**
|
|
1494
|
+
* 三方合并的 **base**:目标点之后**最早**那份仍含该路径的中间版本(共同祖先)。
|
|
1495
|
+
*
|
|
1496
|
+
* 为什么这么取:回滚点的「工作区态」是回合开始前拍的 ⇒ 别的会话那个回合的点,
|
|
1497
|
+
* 正好是「本会话改动之后、对方改动之前」的版本 —— 标准三方合并的共同祖先。
|
|
1498
|
+
* 取**最早**而不是最近是刻意选安全方向:宁可少撤销,也绝不把对方更晚的改动算进 ours 侧。
|
|
1499
|
+
*
|
|
1500
|
+
* 排除四类:目标点自己(`createdAt > afterAt`)、**救援点 guard**(它在执行回退那一刻拍,
|
|
1501
|
+
* 内容 ≈ 当前磁盘,拿它当 base 会让合并结果直接等于 ours = 整文件覆盖,正是本机制要消灭的形态)、
|
|
1502
|
+
* **本会话的点**(见上)、以及内容读不出来的点(继续往后找 —— 找不到 ⇒ 调用方按「无法安全撤销」
|
|
1503
|
+
* 处理,绝不用近似值代替)。
|
|
1504
|
+
*/
|
|
1505
|
+
private baseVersionFor;
|
|
1506
|
+
/**
|
|
1507
|
+
* **别的会话的回合点里记录过的路径集合** —— 删除集保护的第二种证据(不依赖归属台账)。
|
|
1508
|
+
*
|
|
1509
|
+
* 为什么需要第二证据:归属可能整条缺失(工具不在白名单 / 另一个 DSH 进程把 attribution.json
|
|
1510
|
+
* 整体覆盖写 / 采集时机错过),而「别人的点里出现过这个路径」是**点台账本身**记录的事实 ——
|
|
1511
|
+
* 它足以证明「这条路径在留点之后被别的会话所在的回合捕获过」,因此删它就是销毁别人的工作。
|
|
1512
|
+
*
|
|
1513
|
+
* 有界:只扫目标点之后**最早**的 `limit` 个别的会话的点(按时间升序),且只读路径不读内容。
|
|
1514
|
+
* 扫不完不影响安全方向(少保护也会被归属那条兜一部分),但绝不因此声称「已扫全」。
|
|
1515
|
+
*/
|
|
1516
|
+
private foreignRecordedPaths;
|
|
1409
1517
|
private restoreWorkspace;
|
|
1410
1518
|
/**
|
|
1411
1519
|
* S3:会话回退 = 在目标回合前的稳定边界 **fork 子会话**。
|
|
@@ -1493,6 +1601,11 @@ export interface RollbackTrackerOptions {
|
|
|
1493
1601
|
size: number;
|
|
1494
1602
|
mtimeMs: number;
|
|
1495
1603
|
} | undefined>;
|
|
1604
|
+
/**
|
|
1605
|
+
* 写入归属采集器(2026-10-17 定案 B)。缺省 = 不采集 ⇒ 预览永远没有 foreign 标记,
|
|
1606
|
+
* 回退行为与旧版**逐字一致**。
|
|
1607
|
+
*/
|
|
1608
|
+
attribution?: RollbackWriteRecorder;
|
|
1496
1609
|
}
|
|
1497
1610
|
export interface RollbackTrackerResult {
|
|
1498
1611
|
captured: boolean;
|
|
@@ -1554,6 +1667,7 @@ export declare class RollbackAutoTracker {
|
|
|
1554
1667
|
private readonly pollIntervalMs;
|
|
1555
1668
|
private readonly log;
|
|
1556
1669
|
private readonly statSessionLog;
|
|
1670
|
+
private readonly attribution;
|
|
1557
1671
|
private readonly bindings;
|
|
1558
1672
|
private readonly open;
|
|
1559
1673
|
/**
|