@mingmaple/dsh-handover 0.9.14 → 1.0.0

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 (102) hide show
  1. package/README.md +123 -92
  2. package/docs/migrate.md +52 -41
  3. package/docs/releases/0.9.12.md +2 -3
  4. package/docs/releases/0.9.14.md +1 -5
  5. package/docs/releases/0.9.22.md +34 -0
  6. package/docs/releases/1.0.0.md +33 -0
  7. package/docs/troubleshoot.md +230 -46
  8. package/package.json +74 -71
  9. package/scripts/behavior.mjs +398 -0
  10. package/scripts/blank-dsh.mjs +41 -25
  11. package/scripts/blank-smoke.mjs +278 -109
  12. package/scripts/check-docs.mjs +7 -0
  13. package/scripts/e2e-migration.mjs +2 -2
  14. package/scripts/office.mjs +3 -3
  15. package/scripts/portability.mjs +71 -0
  16. package/scripts/style-gate.mjs +571 -0
  17. package/src/client.js +1028 -955
  18. package/src/index.mjs +313 -142
  19. package/src/lib/absrefs.mjs +1 -1
  20. package/src/lib/api.mjs +18 -10
  21. package/src/lib/archive.mjs +1 -1
  22. package/src/lib/brief.mjs +8 -6
  23. package/src/lib/config.mjs +23 -8
  24. package/src/lib/consent.mjs +54 -1
  25. package/src/lib/docmap.mjs +140 -0
  26. package/src/lib/drift.mjs +1 -1
  27. package/src/lib/events.mjs +1 -1
  28. package/src/lib/facts.mjs +19 -12
  29. package/src/lib/gates.mjs +30 -6
  30. package/src/lib/global-task.mjs +69 -0
  31. package/src/lib/guide.mjs +81 -85
  32. package/src/lib/handover-io.mjs +69 -6
  33. package/src/lib/identity.mjs +330 -0
  34. package/src/lib/legacy.mjs +89 -0
  35. package/src/lib/lint.mjs +17 -13
  36. package/src/lib/manual.mjs +135 -59
  37. package/src/lib/mover.mjs +23 -19
  38. package/src/lib/names.mjs +14 -19
  39. package/src/lib/office.mjs +63 -15
  40. package/src/lib/pack-ops.mjs +11 -11
  41. package/src/lib/pathkey.mjs +24 -0
  42. package/src/lib/peer.mjs +4 -4
  43. package/src/lib/phase.mjs +8 -13
  44. package/src/lib/profile.mjs +1 -1
  45. package/src/lib/reminder.mjs +110 -0
  46. package/src/lib/role.mjs +9 -6
  47. package/src/lib/scaffold.mjs +68 -26
  48. package/src/lib/schedule.mjs +5 -6
  49. package/src/lib/session-create.mjs +3 -3
  50. package/src/lib/session-ops.mjs +80 -51
  51. package/src/lib/sessions.mjs +41 -3
  52. package/src/lib/sevenzip.mjs +10 -1
  53. package/src/lib/status.mjs +337 -176
  54. package/src/lib/succession.mjs +16 -16
  55. package/src/lib/system.mjs +364 -0
  56. package/src/lib/zstd-log.mjs +1 -1
  57. package/src/selftest.mjs +6 -6
  58. package/src/templates/Changelog.skeleton.md +3 -3
  59. package/src/templates/Charter.skeleton.md +13 -9
  60. package/src/templates/Handover.global.skeleton.md +20 -13
  61. package/src/templates/Handover.template.md +89 -0
  62. package/src/templates/Plan.skeleton.md +34 -0
  63. package/src/templates/Prompt_Templates.md +101 -20
  64. package/src/templates/Runtime_Manual.md +263 -122
  65. package/src/templates/System.skeleton.md +31 -0
  66. package/src/templates/Systems.global.skeleton.md +13 -0
  67. package/src/templates/rules/Delegation_Rules.md +45 -0
  68. package/src/templates/rules/Handover_Rules.md +46 -23
  69. package/src/templates/rules/Migration_Rules.md +7 -7
  70. package/src/templates/rules/Misc_Task_Standard.md +17 -10
  71. package/src/templates/rules/Writing_Rules.md +33 -16
  72. package/src/templates/standards/README.md +37 -0
  73. package/src/templates/standards//345/206/231/344/275/234/350/247/204/350/214/203/README.md +120 -0
  74. package/src/templates/standards//345/206/231/344/275/234/350/247/204/350/214/203//344/276/235/346/215/256_/350/256/272/346/226/207.md +389 -0
  75. package/src/tools/ho_backup.mjs +135 -0
  76. package/src/tools/ho_changelog.mjs +4 -4
  77. package/src/tools/ho_charter.mjs +7 -6
  78. package/src/tools/ho_checkpoint.mjs +36 -32
  79. package/src/tools/ho_docmap.mjs +239 -0
  80. package/src/tools/ho_gate.mjs +11 -5
  81. package/src/tools/ho_handover.mjs +61 -35
  82. package/src/tools/ho_office.mjs +46 -5
  83. package/src/tools/ho_profile.mjs +3 -3
  84. package/src/tools/ho_sessions.mjs +46 -26
  85. package/src/tools/ho_status.mjs +251 -0
  86. package/src/tools/ho_succeed.mjs +3 -3
  87. package/src/tools/ho_workspace.mjs +146 -42
  88. package/src/tools/peer.mjs +416 -0
  89. package/src/tools/ho_brief.mjs +0 -57
  90. package/src/tools/ho_diag.mjs +0 -87
  91. package/src/tools/ho_drift.mjs +0 -41
  92. package/src/tools/ho_init.mjs +0 -82
  93. package/src/tools/ho_pack.mjs +0 -38
  94. package/src/tools/ho_phase.mjs +0 -37
  95. package/src/tools/ho_snapshot.mjs +0 -104
  96. package/src/tools/ho_tokens.mjs +0 -57
  97. package/src/tools/peer_list.mjs +0 -37
  98. package/src/tools/peer_new.mjs +0 -75
  99. package/src/tools/peer_peek.mjs +0 -41
  100. package/src/tools/peer_rename.mjs +0 -31
  101. package/src/tools/peer_send.mjs +0 -52
  102. package/src/tools/peer_status.mjs +0 -46
@@ -22,6 +22,13 @@ const problems = [];
22
22
  const readmeLines = fs.readFileSync(readme, 'utf8').split(/\r?\n/).length;
23
23
  if (readmeLines > 200) problems.push('README 应不超过 200 行(当前 ' + readmeLines + ' 行)');
24
24
 
25
+ // 1.1 README「为什么需要」一节为用户 2026-11-13 与 2026-11-15 两次指定的正文(例外 E-01):逐字比对,改动即失败
26
+ const WHY_PINNED = '单个会话的上下文越用越多,用到一定程度之后,出错的可能也会随之上升;可若这时压缩上下文,或者写好交接换一个会话,又会丢掉已经积累的信息。面对这样的两难,有没有更好的取舍?\n\n本插件一定能很好地帮助你。来试试吧;不满意,随时关闭插件并删除即可。';
27
+ {
28
+ const m = fs.readFileSync(readme, 'utf8').match(/## 为什么需要\s*\n+([\s\S]*?)\n+## /);
29
+ const got = m ? m[1].trim() : '';
30
+ if (got !== WHY_PINNED) problems.push('README「为什么需要」一节为用户指定正文(E-01),不得改写');
31
+ }
25
32
  // 2. 旧数与旧术语
26
33
  const FORBIDDEN = ['21 个工具', '27 个工具', '未分类', '追加系统提示词', '4,028', '4.6 KB', '每库 24 行', 'CHANGELOG'];
27
34
  // 审阅语境与内部用语:这些词只应出现在桌面审阅材料里,不能进对外文档与版本说明。
@@ -15,7 +15,7 @@ const argIdx = process.argv.indexOf('--dist');
15
15
  const dist = argIdx !== -1 ? path.resolve(process.argv[argIdx + 1]) : path.join(repo, 'dist');
16
16
 
17
17
  const imp = (rel) => import(pathToFileURL(path.join(dist, rel)).href);
18
- const { pmPackTool } = await imp('tools/ho_pack.mjs');
18
+ const { pmBackupTool } = await imp('tools/ho_backup.mjs');
19
19
  const { resolveConfig } = await imp('lib/config.mjs');
20
20
 
21
21
  const fails = [];
@@ -47,7 +47,7 @@ const env = {
47
47
  selfId: () => null,
48
48
  selfCwd: () => null,
49
49
  };
50
- const packTool = pmPackTool(env);
50
+ const packTool = pmBackupTool(env);
51
51
  /** action 分流:pack/verify/restore 都走同一个工具(合并口径)。 */
52
52
  const run = (args) => packTool.execute(args, null);
53
53
 
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * 命令行查在任登记表:`node scripts/office.mjs 全局 全局3 Mingent`
3
+ * 命令行查在任登记表:`node scripts/office.mjs 全局 全局3 Demo1`
4
4
  *
5
5
  * 与工具 ho_office 同一份实现、同一份记录(_Control_Center/records/Office.json),
6
6
  * 区别只是不起会话也能查。工作区根按 --root → DSH_OFFICE_ROOT → 从 cwd 向上找 _Control_Center 的顺序解析。
@@ -32,14 +32,14 @@ for (let i = 0; i < argv.length; i++) {
32
32
  if (a === '--all' || a === '-a') { all = true; continue; }
33
33
  if (a === '-h' || a === '--help') {
34
34
  console.log('用法:node scripts/office.mjs [查询…] [--all] [--json] [--root <工作区根>]');
35
- console.log('示例:node scripts/office.mjs 全局 全局3 Mingent');
35
+ console.log('示例:node scripts/office.mjs 全局 全局3 Demo1');
36
36
  process.exit(0);
37
37
  }
38
38
  queries.push(a);
39
39
  }
40
40
  if (!root) root = walkUp(process.cwd());
41
41
  if (!root) {
42
- console.error('找不到工作区根(没有 _Control_Center):用 --root 指定,例如 --root E:\\_Project_Mate\\_Workspace');
42
+ console.error('找不到工作区根(没有 _Control_Center):用 --root 指定,例如 --root <全局根绝对路径>');
43
43
  process.exit(2);
44
44
  }
45
45
 
@@ -0,0 +1,71 @@
1
+ /**
2
+ * 跨平台可移植性测试(1.0):
3
+ * 1. 路径等价键按平台折叠大小写:Windows 与 macOS 折叠,Linux 保留;
4
+ * 2. 7-Zip 探测覆盖 Windows、macOS、Linux 的常见位置与 PATH;
5
+ * 3. 工作区相对路径一律用 path.sep 组装,不写死分隔符;
6
+ * 4. 迁移助手不依赖 PowerShell 或 bash,链接类型按平台选择;
7
+ * 5. 路径比较不再无条件折叠大小写。
8
+ *
9
+ * 全程只读源码与构建产物,不碰真实工作区与真实 HOME。
10
+ * 用法:node scripts/portability.mjs [--dist <dist 目录>]
11
+ */
12
+ import fs from 'node:fs';
13
+ import path from 'node:path';
14
+ import { fileURLToPath, pathToFileURL } from 'node:url';
15
+
16
+ const here = path.dirname(fileURLToPath(import.meta.url));
17
+ const repo = path.resolve(here, '..');
18
+ const dist = (() => {
19
+ const i = process.argv.indexOf('--dist');
20
+ return i !== -1 && process.argv[i + 1] ? path.resolve(process.argv[i + 1]) : path.join(repo, 'dist');
21
+ })();
22
+
23
+ const fails = [];
24
+ function ok(cond, msg, extra) {
25
+ if (cond) console.log(' 通过 ' + msg);
26
+ else { fails.push(msg + (extra ? ' → ' + extra : '')); console.log(' 未通过 ' + msg + (extra ? ' → ' + extra : '')); }
27
+ }
28
+ function section(t) { console.log(''); console.log('== ' + t + ' =='); }
29
+ const imp = (rel) => import(pathToFileURL(path.join(dist, rel)).href);
30
+ const read = (rel) => fs.readFileSync(path.join(repo, rel), 'utf8');
31
+
32
+ const { pathKey, samePath, relToAbs } = await imp('lib/pathkey.mjs');
33
+
34
+ section('1 路径等价键');
35
+ ok(pathKey('C:\\Data\\WS\\', 'win32') === 'c:/data/ws', 'Windows 折叠大小写并去分隔符', pathKey('C:\\Data\\WS\\', 'win32'));
36
+ ok(pathKey('C:\\Data\\WS', 'darwin') === 'c:/data/ws', 'macOS 折叠大小写', pathKey('C:\\Data\\WS', 'darwin'));
37
+ ok(pathKey('/data/WS', 'linux') === '/data/WS', 'Linux 保留大小写', pathKey('/data/WS', 'linux'));
38
+ ok(samePath('C:\\A\\b', 'c:/a/B', 'win32') === true, 'Windows 两种写法视为同一路径');
39
+ ok(samePath('/data/WS', '/data/ws', 'linux') === false, 'Linux 大小写不同视为不同路径');
40
+ ok(relToAbs('/root', 'a/b') === path.join('/root', 'a', 'b'), '相对路径按平台分隔符组装');
41
+
42
+ section('2 7-Zip 探测');
43
+ const seven = read('src/lib/sevenzip.mjs');
44
+ for (const p of ['/usr/bin/7z', '/usr/local/bin/7z', '/opt/homebrew/bin/7z', '/usr/bin/7za', '/opt/homebrew/bin/7zz', '7z.exe']) {
45
+ ok(seven.indexOf(p) !== -1, '候选含 ' + p);
46
+ }
47
+ ok(seven.indexOf('BARE') !== -1, 'PATH 上的 7z、7zz、7za 也探测');
48
+
49
+ section('3 路径组装');
50
+ ok(read('src/lib/scaffold.mjs').indexOf(".split('/').join(path.sep)") !== -1, '脚手架用 path.sep 组装相对路径');
51
+ ok(read('src/lib/archive.mjs').indexOf(".split('/').join(path.sep)") !== -1, '归档恢复用 path.sep 组装相对路径');
52
+
53
+ section('4 迁移与链接');
54
+ const mover = read('src/lib/mover.mjs');
55
+ ok(mover.indexOf("process.platform === 'win32' ? 'junction' : 'dir'") !== -1, '链接类型按平台选择');
56
+ ok(mover.indexOf('不依赖 PowerShell') !== -1, '迁移助手不依赖外部 shell');
57
+ ok(mover.indexOf("process.platform === 'win32' ? t.toLowerCase() : t") !== -1, '链接目标比较按平台折叠大小写');
58
+
59
+ section('5 路径比较不再无条件折叠');
60
+ const files = ['src/lib/mover.mjs', 'src/lib/api.mjs', 'src/lib/session-ops.mjs', 'src/lib/status.mjs', 'src/lib/scaffold.mjs', 'src/tools/ho_workspace.mjs'];
61
+ const bad = files.filter((f) => read(f).indexOf(".replace(/\\/+$/, '').toLowerCase()") !== -1);
62
+ ok(bad.length === 0, '以上文件不再写死「转斜杠 + 去尾 + 小写」', bad.join(', '));
63
+ ok(read('src/lib/pathkey.mjs').indexOf('process.platform') !== -1, '大小写折叠集中在 pathkey.mjs');
64
+
65
+ console.log('');
66
+ if (fails.length) {
67
+ console.log('PORTABILITY FAIL ' + fails.length + ' 项:');
68
+ for (const f of fails) console.log(' - ' + f);
69
+ process.exit(1);
70
+ }
71
+ console.log('PORTABILITY OK(跨平台检查全过)');