@fantasticit/sumi 0.7.4 → 0.7.5
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/dist/adapters.js +1 -1
- package/dist/adapters.js.map +1 -1
- package/dist/agent-hooks.d.ts +15 -0
- package/dist/agent-hooks.js +93 -5
- package/dist/agent-hooks.js.map +1 -1
- package/node_modules/@sumi/create/package.json +1 -1
- package/node_modules/@sumi/kernel/dist/config.d.ts +5 -0
- package/node_modules/@sumi/kernel/dist/config.js +16 -0
- package/node_modules/@sumi/kernel/dist/config.js.map +1 -1
- package/node_modules/@sumi/kernel/dist/engine.js +1 -0
- package/node_modules/@sumi/kernel/dist/engine.js.map +1 -1
- package/node_modules/@sumi/kernel/dist/registry.d.ts +2 -0
- package/node_modules/@sumi/kernel/dist/registry.js +15 -1
- package/node_modules/@sumi/kernel/dist/registry.js.map +1 -1
- package/node_modules/@sumi/kernel/package.json +2 -2
- package/node_modules/@sumi/plugin-sdk/README.md +23 -16
- package/node_modules/@sumi/plugin-sdk/dist/protocol.d.ts +9 -0
- package/node_modules/@sumi/plugin-sdk/dist/protocol.js +17 -0
- package/node_modules/@sumi/plugin-sdk/dist/protocol.js.map +1 -1
- package/node_modules/@sumi/plugin-sdk/package.json +1 -1
- package/node_modules/@sumi/plugins-core/README.md +14 -12
- package/node_modules/@sumi/plugins-core/dist/plugins/exec.js +7 -2
- package/node_modules/@sumi/plugins-core/dist/plugins/exec.js.map +1 -1
- package/node_modules/@sumi/plugins-core/dist/plugins/test-affected.js +12 -3
- package/node_modules/@sumi/plugins-core/dist/plugins/test-affected.js.map +1 -1
- package/node_modules/@sumi/plugins-core/dist/test-scope.d.ts +1 -1
- package/node_modules/@sumi/plugins-core/dist/test-scope.js +12 -6
- package/node_modules/@sumi/plugins-core/dist/test-scope.js.map +1 -1
- package/node_modules/@sumi/plugins-core/dist/vitest-runner.js +129 -5
- package/node_modules/@sumi/plugins-core/dist/vitest-runner.js.map +1 -1
- package/node_modules/@sumi/plugins-core/package.json +4 -4
- package/node_modules/@sumi/plugins-governance/README.md +10 -9
- package/node_modules/@sumi/plugins-governance/dist/checkout.d.ts +12 -2
- package/node_modules/@sumi/plugins-governance/dist/checkout.js +40 -3
- package/node_modules/@sumi/plugins-governance/dist/checkout.js.map +1 -1
- package/node_modules/@sumi/plugins-governance/dist/commands/gate.js +6 -2
- package/node_modules/@sumi/plugins-governance/dist/commands/gate.js.map +1 -1
- package/node_modules/@sumi/plugins-governance/dist/commands/pr-report.js +1 -1
- package/node_modules/@sumi/plugins-governance/dist/commands/pr-report.js.map +1 -1
- package/node_modules/@sumi/plugins-governance/dist/gate-cache.d.ts +25 -0
- package/node_modules/@sumi/plugins-governance/dist/gate-cache.js +83 -0
- package/node_modules/@sumi/plugins-governance/dist/gate-cache.js.map +1 -0
- package/node_modules/@sumi/plugins-governance/dist/protected.d.ts +1 -0
- package/node_modules/@sumi/plugins-governance/instructions/push.md +1 -1
- package/node_modules/@sumi/plugins-governance/package.json +2 -2
- package/node_modules/@sumi/plugins-openspec/package.json +2 -2
- package/node_modules/@sumi/plugins-openspec/sumi-plugins.yaml +2 -0
- package/node_modules/@sumi/plugins-precedent/README.md +2 -0
- package/node_modules/@sumi/plugins-precedent/dist/after-edit-context.d.ts +26 -0
- package/node_modules/@sumi/plugins-precedent/dist/after-edit-context.js +192 -0
- package/node_modules/@sumi/plugins-precedent/dist/after-edit-context.js.map +1 -0
- package/node_modules/@sumi/plugins-precedent/dist/commands/after-edit-context.d.ts +1 -0
- package/node_modules/@sumi/plugins-precedent/dist/commands/after-edit-context.js +13 -0
- package/node_modules/@sumi/plugins-precedent/dist/commands/after-edit-context.js.map +1 -0
- package/node_modules/@sumi/plugins-precedent/package.json +3 -3
- package/node_modules/@sumi/plugins-precedent/sumi-plugins.yaml +5 -0
- package/node_modules/@sumi/plugins-review/package.json +3 -3
- package/package.json +10 -10
- package/node_modules/@sumi/kernel/test/fixtures/fake-plugin.mjs +0 -44
- package/node_modules/@sumi/kernel/test/fixtures/py-plugin.py +0 -3
- package/node_modules/@sumi/plugin-sdk/test/isolate-tmpdir.ts +0 -27
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
2
|
+
import { mkdirSync, readFileSync, readdirSync, realpathSync, renameSync, statSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { dirname, isAbsolute, join, relative, resolve } from 'node:path';
|
|
4
|
+
import { configFile, PROJECT_SUMI, spawnCommandSync } from '@sumi/plugin-sdk';
|
|
5
|
+
import { parse } from 'yaml';
|
|
6
|
+
const LIMIT = 2500;
|
|
7
|
+
const QUERY_TIMEOUT = 8000;
|
|
8
|
+
function inside(root, path) {
|
|
9
|
+
const canonical = (value) => {
|
|
10
|
+
let parent = value;
|
|
11
|
+
for (;;) {
|
|
12
|
+
try {
|
|
13
|
+
return resolve(realpathSync(parent), relative(parent, value));
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
const next = dirname(parent);
|
|
17
|
+
if (next === parent)
|
|
18
|
+
throw new Error('无法解析编辑路径');
|
|
19
|
+
parent = next;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
const rel = relative(realpathSync(root), canonical(resolve(root, path))).replaceAll('\\', '/');
|
|
24
|
+
return rel && rel !== '..' && !rel.startsWith('../') && !isAbsolute(rel) ? rel : null;
|
|
25
|
+
}
|
|
26
|
+
/** 只接受编辑工具的明确路径,不猜测任意 shell 命令可能写入了什么。 */
|
|
27
|
+
export function editedPaths(root, input) {
|
|
28
|
+
try {
|
|
29
|
+
const payload = JSON.parse(input);
|
|
30
|
+
const tool = payload.tool_input;
|
|
31
|
+
if (!tool || typeof tool !== 'object')
|
|
32
|
+
return [];
|
|
33
|
+
const base = typeof payload.cwd === 'string' ? resolve(root, payload.cwd) : root;
|
|
34
|
+
const candidates = [tool.file_path, tool.notebook_path];
|
|
35
|
+
if (payload.tool_name === 'apply_patch') {
|
|
36
|
+
const patch = typeof tool.command === 'string' ? tool.command : tool.patch;
|
|
37
|
+
if (typeof patch === 'string') {
|
|
38
|
+
for (const match of patch.matchAll(/^\*\*\* (?:Add|Update|Delete|Move) File: (.+)$/gm))
|
|
39
|
+
candidates.push(match[1]);
|
|
40
|
+
for (const match of patch.matchAll(/^\*\*\* Move to: (.+)$/gm))
|
|
41
|
+
candidates.push(match[1]);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return [
|
|
45
|
+
...new Set(candidates
|
|
46
|
+
.filter((v) => typeof v === 'string')
|
|
47
|
+
.map((v) => inside(root, resolve(base, v)))
|
|
48
|
+
.filter((v) => !!v)),
|
|
49
|
+
];
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return [];
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function sessionId(input) {
|
|
56
|
+
try {
|
|
57
|
+
const value = JSON.parse(input).session_id;
|
|
58
|
+
return typeof value === 'string' && value ? value : null;
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function enabled(root) {
|
|
65
|
+
const file = configFile(root);
|
|
66
|
+
if (!file)
|
|
67
|
+
return false;
|
|
68
|
+
const data = parse(readFileSync(join(root, file), 'utf8'));
|
|
69
|
+
return data?.agentContext?.afterEdit !== false;
|
|
70
|
+
}
|
|
71
|
+
export function queryContext(root, paths, timeout = QUERY_TIMEOUT) {
|
|
72
|
+
const launcher = process.env.SUMI_BIN || join(root, 'control/bin/sumi.cjs');
|
|
73
|
+
const result = spawnCommandSync(process.execPath, [launcher, 'context', ...paths, '--json'], {
|
|
74
|
+
cwd: root,
|
|
75
|
+
encoding: 'utf8',
|
|
76
|
+
timeout,
|
|
77
|
+
maxBuffer: 1024 * 1024,
|
|
78
|
+
windowsHide: true,
|
|
79
|
+
});
|
|
80
|
+
if (result.status !== 0 || result.error)
|
|
81
|
+
return null;
|
|
82
|
+
const value = JSON.parse(result.stdout);
|
|
83
|
+
return Array.isArray(value.plugins) && Array.isArray(value.items) && Array.isArray(value.rules) && Array.isArray(value.generalRules)
|
|
84
|
+
? value
|
|
85
|
+
: null;
|
|
86
|
+
}
|
|
87
|
+
function stateFile(root, session) {
|
|
88
|
+
const key = createHash('sha256').update(session).digest('hex');
|
|
89
|
+
return join(root, '.sumi/after-edit-context', `${key}.json`);
|
|
90
|
+
}
|
|
91
|
+
function previous(root, session) {
|
|
92
|
+
if (!session)
|
|
93
|
+
return new Set();
|
|
94
|
+
try {
|
|
95
|
+
const value = JSON.parse(readFileSync(stateFile(root, session), 'utf8'));
|
|
96
|
+
return new Set(Array.isArray(value) ? value.filter((v) => typeof v === 'string') : []);
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return new Set();
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
function save(root, session, keys) {
|
|
103
|
+
try {
|
|
104
|
+
const file = stateFile(root, session);
|
|
105
|
+
const dir = join(root, '.sumi/after-edit-context');
|
|
106
|
+
mkdirSync(dir, { recursive: true });
|
|
107
|
+
const cutoff = Date.now() - 7 * 24 * 60 * 60 * 1000;
|
|
108
|
+
for (const name of readdirSync(dir)) {
|
|
109
|
+
if (!name.endsWith('.json'))
|
|
110
|
+
continue;
|
|
111
|
+
const stale = join(dir, name);
|
|
112
|
+
try {
|
|
113
|
+
if (statSync(stale).mtimeMs < cutoff)
|
|
114
|
+
unlinkSync(stale);
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
/* 去重状态清理是尽力而为 */
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const temporary = `${file}.${randomUUID()}.tmp`;
|
|
121
|
+
writeFileSync(temporary, JSON.stringify([...new Set([...previous(root, session), ...keys])]));
|
|
122
|
+
renameSync(temporary, file);
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
// 会话去重只是体验优化;状态不可写时仍放行编辑。
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
export function acknowledgeContext(root, input) {
|
|
129
|
+
try {
|
|
130
|
+
const value = JSON.parse(input);
|
|
131
|
+
const session = sessionId(value.originalInput ?? '');
|
|
132
|
+
if (session && Array.isArray(value.keys) && value.keys.every((key) => typeof key === 'string'))
|
|
133
|
+
save(root, session, value.keys);
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
/* 送达回执不可影响编辑操作 */
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/** 插件层的提示策略;查询函数可替换以测试失败、超时和异常。 */
|
|
140
|
+
export function afterEditContext(root, input, query = (paths) => queryContext(root, paths)) {
|
|
141
|
+
try {
|
|
142
|
+
if (!enabled(root))
|
|
143
|
+
return null;
|
|
144
|
+
const paths = editedPaths(root, input);
|
|
145
|
+
if (!paths.length)
|
|
146
|
+
return null;
|
|
147
|
+
const context = query(paths);
|
|
148
|
+
if (!context)
|
|
149
|
+
return null;
|
|
150
|
+
const session = sessionId(input);
|
|
151
|
+
const seen = previous(root, session);
|
|
152
|
+
const itemRow = (i) => ({
|
|
153
|
+
key: `item:${i.ref}`,
|
|
154
|
+
text: `- [${i.ref}] ${i.text}${i.source ? `(来源:${i.source})` : ''}`,
|
|
155
|
+
});
|
|
156
|
+
const ruleRow = (r) => ({ key: `rule:${r.file}:${r.line}`, text: `- ${r.file}:${r.line} ${r.text}` });
|
|
157
|
+
const pluginRow = (p) => ({
|
|
158
|
+
key: `plugin:${p.id}`,
|
|
159
|
+
text: `- 机械门 ${p.id}${p.description ? `:${p.description}` : ''}`,
|
|
160
|
+
});
|
|
161
|
+
const rows = [
|
|
162
|
+
...context.items.filter((i) => !i.global).map(itemRow),
|
|
163
|
+
...context.rules.map(ruleRow),
|
|
164
|
+
...context.plugins.filter((p) => !p.global).map(pluginRow),
|
|
165
|
+
]
|
|
166
|
+
.map((row) => ({ ...row, text: row.text.length > 220 ? `${row.text.slice(0, 219)}…` : row.text }))
|
|
167
|
+
.filter((row) => !seen.has(row.key));
|
|
168
|
+
if (!rows.length)
|
|
169
|
+
return null;
|
|
170
|
+
const footer = `\n原文:${PROJECT_SUMI} context ${paths.map((p) => JSON.stringify(p)).join(' ')}`;
|
|
171
|
+
let body = '本次编辑命中的项目约束(请核对原文):';
|
|
172
|
+
let count = 0;
|
|
173
|
+
const deliveryKeys = [];
|
|
174
|
+
for (const row of rows) {
|
|
175
|
+
if (body.length + row.text.length + footer.length + 20 > LIMIT)
|
|
176
|
+
break;
|
|
177
|
+
body += `\n${row.text}`;
|
|
178
|
+
deliveryKeys.push(row.key);
|
|
179
|
+
count += 1;
|
|
180
|
+
}
|
|
181
|
+
if (!count)
|
|
182
|
+
return { additionalContext: `${body}\n内容过长,已截断。${footer}`.slice(0, LIMIT) };
|
|
183
|
+
if (count < rows.length)
|
|
184
|
+
body += '\n其余条目已截断;';
|
|
185
|
+
body += footer;
|
|
186
|
+
return session ? { additionalContext: body.slice(0, LIMIT), deliveryKeys } : { additionalContext: body.slice(0, LIMIT) };
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=after-edit-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"after-edit-context.js","sourceRoot":"","sources":["../src/after-edit-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC9H,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,gBAAgB,EAA0C,MAAM,kBAAkB,CAAC;AACtH,OAAO,EAAE,KAAK,EAAE,MAAM,MAAM,CAAC;AAS7B,MAAM,KAAK,GAAG,IAAI,CAAC;AACnB,MAAM,aAAa,GAAG,IAAI,CAAC;AAE3B,SAAS,MAAM,CAAC,IAAY,EAAE,IAAY;IACxC,MAAM,SAAS,GAAG,CAAC,KAAa,EAAU,EAAE;QAC1C,IAAI,MAAM,GAAG,KAAK,CAAC;QACnB,SAAS,CAAC;YACR,IAAI,CAAC;gBACH,OAAO,OAAO,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;YAChE,CAAC;YAAC,MAAM,CAAC;gBACP,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;gBAC7B,IAAI,IAAI,KAAK,MAAM;oBAAE,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC;gBACjD,MAAM,GAAG,IAAI,CAAC;YAChB,CAAC;QACH,CAAC;IACH,CAAC,CAAC;IACF,MAAM,GAAG,GAAG,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC/F,OAAO,GAAG,IAAI,GAAG,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;AACxF,CAAC;AAED,0CAA0C;AAC1C,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,KAAa;IACrD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAiF,CAAC;QAClH,MAAM,IAAI,GAAG,OAAO,CAAC,UAAU,CAAC;QAChC,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;YAAE,OAAO,EAAE,CAAC;QACjD,MAAM,IAAI,GAAG,OAAO,OAAO,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACjF,MAAM,UAAU,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QACxD,IAAI,OAAO,CAAC,SAAS,KAAK,aAAa,EAAE,CAAC;YACxC,MAAM,KAAK,GAAG,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;YAC3E,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;gBAC9B,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,QAAQ,CAAC,kDAAkD,CAAC;oBAAE,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;gBAClH,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,QAAQ,CAAC,0BAA0B,CAAC;oBAAE,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;YAC5F,CAAC;QACH,CAAC;QACD,OAAO;YACL,GAAG,IAAI,GAAG,CACR,UAAU;iBACP,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC;iBACjD,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;iBAC1C,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CACnC;SACF,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,KAAa;IAC9B,IAAI,CAAC;QACH,MAAM,KAAK,GAAI,IAAI,CAAC,KAAK,CAAC,KAAK,CAA6B,CAAC,UAAU,CAAC;QACxE,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;IAC3D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAS,OAAO,CAAC,IAAY;IAC3B,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IAC9B,IAAI,CAAC,IAAI;QAAE,OAAO,KAAK,CAAC;IACxB,MAAM,IAAI,GAAG,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,CAAsD,CAAC;IAChH,OAAO,IAAI,EAAE,YAAY,EAAE,SAAS,KAAK,KAAK,CAAC;AACjD,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAY,EAAE,KAAe,EAAE,OAAO,GAAG,aAAa;IACjF,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,IAAI,CAAC,IAAI,EAAE,sBAAsB,CAAC,CAAC;IAC5E,MAAM,MAAM,GAAG,gBAAgB,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,QAAQ,CAAC,EAAE;QAC3F,GAAG,EAAE,IAAI;QACT,QAAQ,EAAE,MAAM;QAChB,OAAO;QACP,SAAS,EAAE,IAAI,GAAG,IAAI;QACtB,WAAW,EAAE,IAAI;KAClB,CAAC,CAAC;IACH,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACrD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAgB,CAAC;IACvD,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,YAAY,CAAC;QAClI,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,IAAI,CAAC;AACX,CAAC;AAED,SAAS,SAAS,CAAC,IAAY,EAAE,OAAe;IAC9C,MAAM,GAAG,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC/D,OAAO,IAAI,CAAC,IAAI,EAAE,0BAA0B,EAAE,GAAG,GAAG,OAAO,CAAC,CAAC;AAC/D,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY,EAAE,OAAsB;IACpD,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,GAAG,EAAE,CAAC;IAC/B,IAAI,CAAC;QACH,MAAM,KAAK,GAAY,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;QAClF,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACtG,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,GAAG,EAAE,CAAC;IACnB,CAAC;AACH,CAAC;AAED,SAAS,IAAI,CAAC,IAAY,EAAE,OAAe,EAAE,IAAc;IACzD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACtC,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,EAAE,0BAA0B,CAAC,CAAC;QACnD,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACpC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;QACpD,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;YACpC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;gBAAE,SAAS;YACtC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YAC9B,IAAI,CAAC;gBACH,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC,OAAO,GAAG,MAAM;oBAAE,UAAU,CAAC,KAAK,CAAC,CAAC;YAC1D,CAAC;YAAC,MAAM,CAAC;gBACP,iBAAiB;YACnB,CAAC;QACH,CAAC;QACD,MAAM,SAAS,GAAG,GAAG,IAAI,IAAI,UAAU,EAAE,MAAM,CAAC;QAChD,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9F,UAAU,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAC9B,CAAC;IAAC,MAAM,CAAC;QACP,0BAA0B;IAC5B,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAY,EAAE,KAAa;IAC5D,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAA+C,CAAC;QAC9E,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,aAAa,IAAI,EAAE,CAAC,CAAC;QACrD,IAAI,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,OAAO,GAAG,KAAK,QAAQ,CAAC;YAAE,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IAClI,CAAC;IAAC,MAAM,CAAC;QACP,kBAAkB;IACpB,CAAC;AACH,CAAC;AAED,mCAAmC;AACnC,MAAM,UAAU,gBAAgB,CAC9B,IAAY,EACZ,KAAa,EACb,QAAiD,CAAC,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC;IAErF,IAAI,CAAC;QACH,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QAChC,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QACvC,IAAI,CAAC,KAAK,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QAC/B,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;QAC7B,IAAI,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC;QAC1B,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;QACjC,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACrC,MAAM,OAAO,GAAG,CAAC,CAAc,EAAE,EAAE,CAAC,CAAC;YACnC,GAAG,EAAE,QAAQ,CAAC,CAAC,GAAG,EAAE;YACpB,IAAI,EAAE,MAAM,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;SACpE,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,CAAC,CAA+B,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACpI,MAAM,SAAS,GAAG,CAAC,CAAiC,EAAE,EAAE,CAAC,CAAC;YACxD,GAAG,EAAE,UAAU,CAAC,CAAC,EAAE,EAAE;YACrB,IAAI,EAAE,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE;SACjE,CAAC,CAAC;QACH,MAAM,IAAI,GAAG;YACX,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC;YACtD,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC;YAC7B,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC;SAC3D;aACE,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;aACjG,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;QACvC,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QAC9B,MAAM,MAAM,GAAG,QAAQ,YAAY,YAAY,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/F,IAAI,IAAI,GAAG,qBAAqB,CAAC;QACjC,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,MAAM,YAAY,GAAa,EAAE,CAAC;QAClC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,IAAI,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,GAAG,EAAE,GAAG,KAAK;gBAAE,MAAM;YACtE,IAAI,IAAI,KAAK,GAAG,CAAC,IAAI,EAAE,CAAC;YACxB,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC3B,KAAK,IAAI,CAAC,CAAC;QACb,CAAC;QACD,IAAI,CAAC,KAAK;YAAE,OAAO,EAAE,iBAAiB,EAAE,GAAG,IAAI,cAAc,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC;QACxF,IAAI,KAAK,GAAG,IAAI,CAAC,MAAM;YAAE,IAAI,IAAI,YAAY,CAAC;QAC9C,IAAI,IAAI,MAAM,CAAC;QACf,OAAO,OAAO,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC;IAC3H,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { acknowledgeContext, afterEditContext } from '../after-edit-context.js';
|
|
2
|
+
let input = '';
|
|
3
|
+
for await (const chunk of process.stdin)
|
|
4
|
+
input += chunk;
|
|
5
|
+
const root = process.env.SUMI_ROOT ?? process.cwd();
|
|
6
|
+
if (process.env.SUMI_AFTER_EDIT_DELIVERED === '1')
|
|
7
|
+
acknowledgeContext(root, input);
|
|
8
|
+
else {
|
|
9
|
+
const result = afterEditContext(root, input);
|
|
10
|
+
if (result)
|
|
11
|
+
process.stdout.write(JSON.stringify(result));
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=after-edit-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"after-edit-context.js","sourceRoot":"","sources":["../../src/commands/after-edit-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAEhF,IAAI,KAAK,GAAG,EAAE,CAAC;AACf,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,OAAO,CAAC,KAAK;IAAE,KAAK,IAAI,KAAK,CAAC;AACxD,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;AACpD,IAAI,OAAO,CAAC,GAAG,CAAC,yBAAyB,KAAK,GAAG;IAAE,kBAAkB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;KAC9E,CAAC;IACJ,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC7C,IAAI,MAAM;QAAE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;AAC3D,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sumi/plugins-precedent",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.5",
|
|
4
4
|
"description": "判例插件",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -13,10 +13,10 @@
|
|
|
13
13
|
"./package.json": "./package.json"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@sumi/plugin-sdk": "0.7.
|
|
16
|
+
"@sumi/plugin-sdk": "0.7.5",
|
|
17
17
|
"yaml": "2.9.1",
|
|
18
18
|
"picomatch": "4.0.7",
|
|
19
|
-
"@sumi/plugins-governance": "0.7.
|
|
19
|
+
"@sumi/plugins-governance": "0.7.5"
|
|
20
20
|
},
|
|
21
21
|
"files": [
|
|
22
22
|
"dist",
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
# 判例插件:判例 = 一句约束 + 执行者 + 来源。规划器把命中的判例接线成执行义务,自检保证登记了就可执行。
|
|
2
|
+
pathHints:
|
|
3
|
+
testNeutral: ['precedents/**']
|
|
2
4
|
plugins:
|
|
3
5
|
- id: prec/planner
|
|
4
6
|
version: 0.1.0
|
|
@@ -7,8 +9,11 @@ plugins:
|
|
|
7
9
|
command: [node, ./dist/plugins/planner.js]
|
|
8
10
|
timeout: 60
|
|
9
11
|
context: context-precedents
|
|
12
|
+
hooks:
|
|
13
|
+
agent: { afterEdit: context-after-edit }
|
|
10
14
|
commands:
|
|
11
15
|
- { name: context-precedents, argv: [node, ./dist/commands/context.js], description: 列出给定路径上生效的判例 }
|
|
16
|
+
- { name: context-after-edit, argv: [node, ./dist/commands/after-edit-context.js], description: 编辑后提示新命中的约束 }
|
|
12
17
|
- id: prec/checker
|
|
13
18
|
version: 0.1.0
|
|
14
19
|
description: 运行判例的检查器
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sumi/plugins-review",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.5",
|
|
4
4
|
"description": "评审插件",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -13,10 +13,10 @@
|
|
|
13
13
|
"./package.json": "./package.json"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@sumi/plugin-sdk": "0.7.
|
|
16
|
+
"@sumi/plugin-sdk": "0.7.5",
|
|
17
17
|
"yaml": "2.9.1",
|
|
18
18
|
"picomatch": "4.0.7",
|
|
19
|
-
"@sumi/plugins-governance": "0.7.
|
|
19
|
+
"@sumi/plugins-governance": "0.7.5"
|
|
20
20
|
},
|
|
21
21
|
"files": [
|
|
22
22
|
"dist",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fantasticit/sumi",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.5",
|
|
4
4
|
"description": "sumi 命令行",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -13,14 +13,14 @@
|
|
|
13
13
|
"./package.json": "./package.json"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@sumi/create": "0.7.
|
|
17
|
-
"@sumi/kernel": "0.7.
|
|
18
|
-
"@sumi/plugin-sdk": "0.7.
|
|
19
|
-
"@sumi/plugins-core": "0.7.
|
|
20
|
-
"@sumi/plugins-governance": "0.7.
|
|
21
|
-
"@sumi/plugins-openspec": "0.7.
|
|
22
|
-
"@sumi/plugins-precedent": "0.7.
|
|
23
|
-
"@sumi/plugins-review": "0.7.
|
|
16
|
+
"@sumi/create": "0.7.5",
|
|
17
|
+
"@sumi/kernel": "0.7.5",
|
|
18
|
+
"@sumi/plugin-sdk": "0.7.5",
|
|
19
|
+
"@sumi/plugins-core": "0.7.5",
|
|
20
|
+
"@sumi/plugins-governance": "0.7.5",
|
|
21
|
+
"@sumi/plugins-openspec": "0.7.5",
|
|
22
|
+
"@sumi/plugins-precedent": "0.7.5",
|
|
23
|
+
"@sumi/plugins-review": "0.7.5",
|
|
24
24
|
"tar": "7.5.22",
|
|
25
25
|
"yaml": "2.9.1"
|
|
26
26
|
},
|
|
@@ -42,5 +42,5 @@
|
|
|
42
42
|
"tar",
|
|
43
43
|
"yaml"
|
|
44
44
|
],
|
|
45
|
-
"sumiBuild": "sha256:
|
|
45
|
+
"sumiBuild": "sha256:1ca7ee9572526f5e6bf9dfaedc8544a0c34dbc8b16e6b28676f12cbe80678328"
|
|
46
46
|
}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
// 测试用插件:行为由步骤配置 with 决定。
|
|
2
|
-
import { spawn } from 'node:child_process';
|
|
3
|
-
import { writeFileSync } from 'node:fs';
|
|
4
|
-
|
|
5
|
-
let input = '';
|
|
6
|
-
for await (const chunk of process.stdin) input += chunk;
|
|
7
|
-
const ctx = JSON.parse(input);
|
|
8
|
-
const c = ctx.config;
|
|
9
|
-
if (c.touch) writeFileSync(`${ctx.repoRoot}/${c.touch}`, String(Date.now()));
|
|
10
|
-
if (c.assertNoGitEnv) {
|
|
11
|
-
// hook 中 git 导出的变量指向当前仓库,插件看到它们就可能把操作写进错误的仓库。
|
|
12
|
-
const leaked = ['GIT_DIR', 'GIT_INDEX_FILE', 'GIT_WORK_TREE'].filter((v) => process.env[v] !== undefined);
|
|
13
|
-
if (leaked.length) {
|
|
14
|
-
c.status = 'fail';
|
|
15
|
-
c.summary = `泄漏:${leaked.join(',')}`;
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
if (c.orphan) {
|
|
19
|
-
const child = spawn(process.execPath, ['-e', 'setTimeout(() => {}, 30000)'], { stdio: 'ignore' });
|
|
20
|
-
writeFileSync(`${ctx.evidenceDir}/orphan.pid`, String(child.pid));
|
|
21
|
-
child.unref();
|
|
22
|
-
}
|
|
23
|
-
if (c.sleep) await new Promise((r) => setTimeout(r, c.sleep * 1000));
|
|
24
|
-
if (c.raw !== undefined) {
|
|
25
|
-
process.stdout.write(c.raw);
|
|
26
|
-
process.exit(c.exit ?? 0);
|
|
27
|
-
}
|
|
28
|
-
const status = c.status ?? 'pass';
|
|
29
|
-
const result = {
|
|
30
|
-
status,
|
|
31
|
-
summary: c.summary ?? `${ctx.stepId} ${status}`,
|
|
32
|
-
findings: c.findings ?? [],
|
|
33
|
-
checked: ctx.files,
|
|
34
|
-
evidence: [],
|
|
35
|
-
next: c.next,
|
|
36
|
-
metrics: c.metrics,
|
|
37
|
-
plan: c.plan,
|
|
38
|
-
report: c.report,
|
|
39
|
-
obligations: ctx.obligations.map((o) => ({ id: o.id, outcome: (c.receipts ?? {})[o.id] ?? 'passed' })),
|
|
40
|
-
};
|
|
41
|
-
if (c.echoFiles) result.summary = ctx.files.join(',');
|
|
42
|
-
process.stdout.write(JSON.stringify(result));
|
|
43
|
-
process.exitCode = c.exit ?? (status === 'pass' ? 0 : status === 'fail' ? 1 : 2);
|
|
44
|
-
if (c.signal) process.kill(process.pid, c.signal);
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 各包 vitest 配置共用的 setupFiles:每个测试文件运行前把系统临时目录(TMPDIR,Windows 为 TEMP/TMP)指向
|
|
3
|
-
* 一个专用目录,测试文件结束后整体删除。
|
|
4
|
-
*
|
|
5
|
-
* 测试创建的仓库、门禁检出(失败时会保留)、自检与命令的临时文件都经 os.tmpdir() 落在这里;
|
|
6
|
-
* 测试启动的子进程(sumi、git hook、门禁)继承该环境,同样写入这里。直接用 vitest CLI、`pnpm test`,
|
|
7
|
-
* 或由 core/test-affected(vitest Node API)与 core/coverage 经根配置的 projects 运行时都会加载本文件。
|
|
8
|
-
*/
|
|
9
|
-
import { mkdtempSync, realpathSync, rmSync } from 'node:fs';
|
|
10
|
-
import { tmpdir } from 'node:os';
|
|
11
|
-
import { join } from 'node:path';
|
|
12
|
-
import { afterAll } from 'vitest';
|
|
13
|
-
|
|
14
|
-
const NAMES = ['TMPDIR', 'TMP', 'TEMP'] as const;
|
|
15
|
-
const saved = Object.fromEntries(NAMES.map((name) => [name, process.env[name]]));
|
|
16
|
-
// 取真实路径:macOS 的 /var 是 /private/var 的符号链接,git 与子进程报告的路径是后者
|
|
17
|
-
const dir = realpathSync(mkdtempSync(join(tmpdir(), 'sumi-test-')));
|
|
18
|
-
for (const name of NAMES) process.env[name] = dir;
|
|
19
|
-
|
|
20
|
-
// 本文件的 afterAll 先于测试文件注册,按 vitest 默认的 stack 顺序最后运行,测试文件自己的清理先完成
|
|
21
|
-
afterAll(() => {
|
|
22
|
-
for (const name of NAMES) {
|
|
23
|
-
if (saved[name] === undefined) delete process.env[name];
|
|
24
|
-
else process.env[name] = saved[name];
|
|
25
|
-
}
|
|
26
|
-
rmSync(dir, { recursive: true, force: true, maxRetries: 5, retryDelay: 200 });
|
|
27
|
-
});
|