@dommaker/harness 1.2.3 → 1.3.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.
- package/CHANGELOG.md +7 -0
- package/dist/cli/commands/definitions.js +1 -1
- package/dist/cli/commands/definitions.js.map +1 -1
- package/dist/cli/commands/failure.d.ts.map +1 -1
- package/dist/cli/commands/failure.js +2 -1
- package/dist/cli/commands/failure.js.map +1 -1
- package/dist/cli/commands/knowledge.d.ts.map +1 -1
- package/dist/cli/commands/knowledge.js +24 -1
- package/dist/cli/commands/knowledge.js.map +1 -1
- package/dist/cli/commands/release.d.ts.map +1 -1
- package/dist/cli/commands/release.js +6 -20
- package/dist/cli/commands/release.js.map +1 -1
- package/dist/cli/commands/sync-docs/agents-syncer.js +26 -14
- package/dist/cli/commands/sync-docs/agents-syncer.js.map +1 -1
- package/dist/completion-checkers/index.d.ts +3 -3
- package/dist/completion-checkers/index.js +3 -3
- package/dist/completion-checkers/phase-format.d.ts +1 -1
- package/dist/completion-checkers/phase-format.js +2 -2
- package/dist/completion-checkers/phase-format.js.map +1 -1
- package/dist/completion-checkers/tdd-chain.d.ts +1 -1
- package/dist/completion-checkers/tdd-chain.js +2 -2
- package/dist/completion-checkers/tdd-chain.js.map +1 -1
- package/dist/completion-checkers/types.d.ts +5 -5
- package/dist/completion-checkers/types.d.ts.map +1 -1
- package/dist/completion-checkers/types.js +2 -2
- package/dist/failure/recorder.d.ts +1 -1
- package/dist/failure/recorder.js +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -4
- package/dist/index.js.map +1 -1
- package/dist/knowledge/index-generator.js +1 -1
- package/dist/knowledge/index-generator.js.map +1 -1
- package/dist/release/index.d.ts +3 -0
- package/dist/release/index.d.ts.map +1 -0
- package/dist/release/index.js +11 -0
- package/dist/release/index.js.map +1 -0
- package/dist/release/integrity.d.ts +65 -0
- package/dist/release/integrity.d.ts.map +1 -0
- package/dist/release/integrity.js +151 -0
- package/dist/release/integrity.js.map +1 -0
- package/dist/types/failure.d.ts +7 -0
- package/dist/types/failure.d.ts.map +1 -1
- package/dist/types/failure.js +8 -1
- package/dist/types/failure.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/failure-recorder.test.ts +9 -0
- package/src/__tests__/public-exports.test.ts +3 -0
- package/src/cli/commands/__tests__/knowledge.test.ts +35 -3
- package/src/cli/commands/__tests__/release.test.ts +22 -1
- package/src/cli/commands/__tests__/sync-docs-agents.test.ts +33 -10
- package/src/cli/commands/definitions.ts +1 -1
- package/src/cli/commands/failure.ts +2 -1
- package/src/cli/commands/knowledge.ts +26 -1
- package/src/cli/commands/release.ts +6 -20
- package/src/cli/commands/sync-docs/agents-syncer.ts +26 -13
- package/src/completion-checkers/CONTEXT.md +1 -1
- package/src/completion-checkers/__tests__/contract-presence.test.ts +1 -1
- package/src/completion-checkers/__tests__/phase-format.test.ts +1 -1
- package/src/completion-checkers/__tests__/tdd-chain.test.ts +2 -2
- package/src/completion-checkers/index.ts +3 -3
- package/src/completion-checkers/phase-format.ts +2 -2
- package/src/completion-checkers/tdd-chain.ts +2 -2
- package/src/completion-checkers/types.ts +5 -5
- package/src/failure/recorder.ts +1 -1
- package/src/index.ts +11 -2
- package/src/knowledge/__tests__/index-generator.test.ts +2 -2
- package/src/knowledge/index-generator.ts +1 -1
- package/src/release/CONTEXT.md +23 -0
- package/src/release/__tests__/integrity.test.ts +157 -0
- package/src/release/index.ts +13 -0
- package/src/release/integrity.ts +141 -0
- package/src/types/failure.ts +8 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# release/
|
|
2
|
+
|
|
3
|
+
## 职责
|
|
4
|
+
发布物完整性自检:harness 自己声明并校验自己发布了什么。关键发布物清单的单一来源,替代外部(studio publishPackage)与本仓 release 命令各自的 dist 文件硬编码(harness#77,#75 N4 收编)。
|
|
5
|
+
|
|
6
|
+
## 核心导出
|
|
7
|
+
- `deriveCriticalArtifacts(manifest)`(`integrity.ts`)——从包声明面(package.json `main`/`exports`/`bin`)推导脚本入口清单(.js/.cjs/.mjs/.d.ts,去 `./` 前缀、剔除非脚本叶子、去重排序);纯函数
|
|
8
|
+
- `EXTRA_CRITICAL_ARTIFACTS`——声明面推导之外的运行时关键发布物(bin/harness.js 引导期 require 的命令/门禁定义表、`dist/tools/definitions` 数据目录);与其描述的文件同仓同评审,删改须同步
|
|
9
|
+
- `resolvePackageRoot(fromDir?)`——从模块位置向上按包名解析本包根(源码仓与 node_modules 安装态均可达)
|
|
10
|
+
- `getCriticalArtifacts(pkgRoot?)` / `verifyReleaseArtifacts(pkgRoot?)`——公开 API;pkgRoot 缺省自动解析,外部消费者零参数即自检已安装的 harness
|
|
11
|
+
|
|
12
|
+
## 依赖关系
|
|
13
|
+
- 无内部依赖(只依赖 node fs/path)
|
|
14
|
+
|
|
15
|
+
## 约定
|
|
16
|
+
- 清单维护模型:声明面推导为主(目录重构动到 package.json 时清单自动跟随)+ extras 随源码维护;**不新增第三处硬编码清单**
|
|
17
|
+
- 覆盖口径(有意裁决,#77):深度内部文件(tsc 产出的 dist/knowledge/*、core/constraints/checker.js 等)**不在清单**——非公开契约,存在性由 tsc 构建成功保证;历史上外部硬编码它们正是重构误判(studio 6cf3c329)的根因。旧 studio 清单 checker.js/doctor.js、旧 release 清单 13 项均被本清单取代,覆盖收窄是裁决而非遗漏
|
|
18
|
+
- `__tests__/integrity.test.ts` 的「真实包根清单同步闸门」是重构同步闸门:动 exports/main/bin 或 extras 时该测试强制同步
|
|
19
|
+
- bin 新增引导期 require 的 dist 文件 → extras 加一条 + 测试同步
|
|
20
|
+
|
|
21
|
+
## 注意事项
|
|
22
|
+
- 挂载点:`harness release` 命令第 4 步(tsc 后校验 dist);studio publishPackage dist 校验改调本能力(studio#425 配套切换)
|
|
23
|
+
- 公开面只收 `getCriticalArtifacts` / `verifyReleaseArtifacts` + `ArtifactIntegrityResult`(ADR-0003);derive/resolve 属内部 seam
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 发布物完整性自检测试(harness#77,#75 N4 收编)
|
|
3
|
+
*
|
|
4
|
+
* 覆盖:声明面推导(main/exports/bin)、extras 清单守卫、包根向上解析、
|
|
5
|
+
* 存在性校验、真实包根清单同步闸门。
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { describe, it, expect } from '@jest/globals';
|
|
9
|
+
import * as fs from 'fs';
|
|
10
|
+
import * as os from 'os';
|
|
11
|
+
import * as path from 'path';
|
|
12
|
+
import {
|
|
13
|
+
HARNESS_PACKAGE_NAME,
|
|
14
|
+
EXTRA_CRITICAL_ARTIFACTS,
|
|
15
|
+
deriveCriticalArtifacts,
|
|
16
|
+
resolvePackageRoot,
|
|
17
|
+
getCriticalArtifacts,
|
|
18
|
+
verifyReleaseArtifacts,
|
|
19
|
+
} from '../integrity';
|
|
20
|
+
import type { PackagePublishManifest } from '../integrity';
|
|
21
|
+
|
|
22
|
+
/** 建临时 fixture 包根:写 package.json + 按清单造文件/目录 */
|
|
23
|
+
function makeFixture(manifest: PackagePublishManifest, artifacts: string[]): string {
|
|
24
|
+
const root = fs.mkdtempSync(path.join(os.tmpdir(), 'harness-release-integrity-'));
|
|
25
|
+
fs.writeFileSync(path.join(root, 'package.json'), JSON.stringify(manifest));
|
|
26
|
+
for (const artifact of artifacts) {
|
|
27
|
+
const abs = path.join(root, artifact);
|
|
28
|
+
if (/\.[cm]?js$|\.d\.ts$/.test(artifact)) {
|
|
29
|
+
fs.mkdirSync(path.dirname(abs), { recursive: true });
|
|
30
|
+
fs.writeFileSync(abs, '');
|
|
31
|
+
} else {
|
|
32
|
+
fs.mkdirSync(abs, { recursive: true });
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return root;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
describe('deriveCriticalArtifacts', () => {
|
|
39
|
+
it('收集 main/exports/bin 声明的脚本入口,去 ./ 前缀、去重、排序,非脚本叶子剔除', () => {
|
|
40
|
+
const manifest: PackagePublishManifest = {
|
|
41
|
+
name: HARNESS_PACKAGE_NAME,
|
|
42
|
+
main: './dist/index.js',
|
|
43
|
+
bin: { harness: './bin/harness.js' },
|
|
44
|
+
exports: {
|
|
45
|
+
'.': {
|
|
46
|
+
types: './dist/index.d.ts',
|
|
47
|
+
require: './dist/index.js',
|
|
48
|
+
import: './dist/index.js',
|
|
49
|
+
},
|
|
50
|
+
'./core': './dist/core/index.js',
|
|
51
|
+
'./package.json': './package.json',
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
expect(deriveCriticalArtifacts(manifest)).toEqual([
|
|
55
|
+
'bin/harness.js',
|
|
56
|
+
'dist/core/index.js',
|
|
57
|
+
'dist/index.d.ts',
|
|
58
|
+
'dist/index.js',
|
|
59
|
+
]);
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('exports 为字符串、bin 为字符串、null 条目(兜底禁用)安全', () => {
|
|
63
|
+
const manifest: PackagePublishManifest = {
|
|
64
|
+
name: HARNESS_PACKAGE_NAME,
|
|
65
|
+
main: 'dist/index.js',
|
|
66
|
+
bin: 'bin/harness.js',
|
|
67
|
+
exports: { '.': './dist/index.js', './forbidden': null },
|
|
68
|
+
};
|
|
69
|
+
expect(deriveCriticalArtifacts(manifest)).toEqual(['bin/harness.js', 'dist/index.js']);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('无声明字段返回空清单', () => {
|
|
73
|
+
expect(deriveCriticalArtifacts({ name: HARNESS_PACKAGE_NAME })).toEqual([]);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
describe('EXTRA_CRITICAL_ARTIFACTS', () => {
|
|
78
|
+
it('覆盖 bin 引导定义表与 tools 运行时数据目录(随源码维护,删改须同评审)', () => {
|
|
79
|
+
expect(EXTRA_CRITICAL_ARTIFACTS).toEqual([
|
|
80
|
+
'dist/cli/commands/definitions.js',
|
|
81
|
+
'dist/gates/definitions.js',
|
|
82
|
+
'dist/tools/definitions',
|
|
83
|
+
]);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
describe('resolvePackageRoot', () => {
|
|
88
|
+
it('从源码位置向上解析到本仓包根', () => {
|
|
89
|
+
const root = resolvePackageRoot(__dirname);
|
|
90
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf-8'));
|
|
91
|
+
expect(pkg.name).toBe(HARNESS_PACKAGE_NAME);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('无匹配包根时抛错并提示显式传入 pkgRoot', () => {
|
|
95
|
+
const bare = fs.mkdtempSync(path.join(os.tmpdir(), 'harness-no-pkg-root-'));
|
|
96
|
+
const nested = path.join(bare, 'deep', 'nested');
|
|
97
|
+
fs.mkdirSync(nested, { recursive: true });
|
|
98
|
+
expect(() => resolvePackageRoot(nested)).toThrow(/pkgRoot/);
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
describe('getCriticalArtifacts / verifyReleaseArtifacts(fixture 包根)', () => {
|
|
103
|
+
const FIXTURE_MANIFEST: PackagePublishManifest = {
|
|
104
|
+
name: HARNESS_PACKAGE_NAME,
|
|
105
|
+
main: './dist/index.js',
|
|
106
|
+
bin: './bin/harness.js',
|
|
107
|
+
exports: { '.': './dist/index.js' },
|
|
108
|
+
};
|
|
109
|
+
const FIXTURE_ARTIFACTS = [
|
|
110
|
+
'dist/index.js',
|
|
111
|
+
'bin/harness.js',
|
|
112
|
+
...EXTRA_CRITICAL_ARTIFACTS,
|
|
113
|
+
];
|
|
114
|
+
|
|
115
|
+
it('清单 = 声明面推导 + extras', () => {
|
|
116
|
+
const root = makeFixture(FIXTURE_MANIFEST, FIXTURE_ARTIFACTS);
|
|
117
|
+
expect(getCriticalArtifacts(root)).toEqual([
|
|
118
|
+
'bin/harness.js',
|
|
119
|
+
'dist/cli/commands/definitions.js',
|
|
120
|
+
'dist/gates/definitions.js',
|
|
121
|
+
'dist/index.js',
|
|
122
|
+
'dist/tools/definitions',
|
|
123
|
+
]);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('全部就位 → ok:true', () => {
|
|
127
|
+
const root = makeFixture(FIXTURE_MANIFEST, FIXTURE_ARTIFACTS);
|
|
128
|
+
const result = verifyReleaseArtifacts(root);
|
|
129
|
+
expect(result).toMatchObject({ ok: true, pkgRoot: root, missing: [] });
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('缺文件 → ok:false 且 missing 指名', () => {
|
|
133
|
+
const root = makeFixture(FIXTURE_MANIFEST, FIXTURE_ARTIFACTS);
|
|
134
|
+
fs.rmSync(path.join(root, 'dist', 'tools', 'definitions'), { recursive: true, force: true });
|
|
135
|
+
const result = verifyReleaseArtifacts(root);
|
|
136
|
+
expect(result.ok).toBe(false);
|
|
137
|
+
expect(result.missing).toEqual(['dist/tools/definitions']);
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
describe('真实包根清单同步闸门', () => {
|
|
142
|
+
it('真实 package.json 推导覆盖全部声明入口 + extras(重构动声明面时本测试强制同步)', () => {
|
|
143
|
+
const root = resolvePackageRoot(__dirname);
|
|
144
|
+
const artifacts = getCriticalArtifacts(root);
|
|
145
|
+
for (const required of [
|
|
146
|
+
'dist/index.js',
|
|
147
|
+
'dist/core/index.js',
|
|
148
|
+
'dist/presets/index.js',
|
|
149
|
+
'dist/context/index.js',
|
|
150
|
+
'dist/gates/index.js',
|
|
151
|
+
'bin/harness.js',
|
|
152
|
+
...EXTRA_CRITICAL_ARTIFACTS,
|
|
153
|
+
]) {
|
|
154
|
+
expect(artifacts).toContain(required);
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export {
|
|
2
|
+
HARNESS_PACKAGE_NAME,
|
|
3
|
+
EXTRA_CRITICAL_ARTIFACTS,
|
|
4
|
+
deriveCriticalArtifacts,
|
|
5
|
+
resolvePackageRoot,
|
|
6
|
+
getCriticalArtifacts,
|
|
7
|
+
verifyReleaseArtifacts,
|
|
8
|
+
} from './integrity';
|
|
9
|
+
export type {
|
|
10
|
+
PackagePublishManifest,
|
|
11
|
+
PackageExports,
|
|
12
|
+
ArtifactIntegrityResult,
|
|
13
|
+
} from './integrity';
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 发布物完整性自检(harness#77,#75 N4 收编)
|
|
3
|
+
*
|
|
4
|
+
* harness 自己最知道自己发了什么:关键发布物清单不再由外部(studio publishPackage)
|
|
5
|
+
* 或本仓 release 命令各自硬编码 dist 内部文件,而是从包声明面(package.json
|
|
6
|
+
* main/exports/bin)运行时推导 + 少量运行时 extras 随源码维护——目录重构动到
|
|
7
|
+
* 声明面时清单自动跟随,extras 与其描述的文件同仓同评审。
|
|
8
|
+
*
|
|
9
|
+
* 公开面(barrel):getCriticalArtifacts / verifyReleaseArtifacts。
|
|
10
|
+
* studio publishPackage 的 dist 校验改调本能力,替换硬编码清单(studio#425 配套切换)。
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import * as fs from 'fs';
|
|
14
|
+
import * as path from 'path';
|
|
15
|
+
|
|
16
|
+
/** 本包名(包根向上解析的身份锚点,同 bin 名同源) */
|
|
17
|
+
export const HARNESS_PACKAGE_NAME = '@dommaker/harness';
|
|
18
|
+
|
|
19
|
+
/** package.json 发布面形状(只关心与发布物定位相关字段) */
|
|
20
|
+
export interface PackagePublishManifest {
|
|
21
|
+
name?: string;
|
|
22
|
+
main?: string;
|
|
23
|
+
bin?: string | Record<string, string>;
|
|
24
|
+
exports?: PackageExports;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/** exports 字段形状:字符串叶子 / null(兜底禁用)/ 条件对象递归 */
|
|
28
|
+
export type PackageExports = string | null | { [key: string]: PackageExports };
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* 推导之外、随源码维护的运行时关键发布物。
|
|
32
|
+
* 声明面推导只覆盖入口文件;以下入口的运行时依赖由本清单兜底。
|
|
33
|
+
*/
|
|
34
|
+
export const EXTRA_CRITICAL_ARTIFACTS: readonly string[] = [
|
|
35
|
+
// bin/harness.js 引导期 require 的命令/门禁定义表
|
|
36
|
+
'dist/cli/commands/definitions.js',
|
|
37
|
+
'dist/gates/definitions.js',
|
|
38
|
+
// getToolsDir/getRegistryPath 运行时数据目录(build 脚本 cp -r,tsc 不产出)
|
|
39
|
+
'dist/tools/definitions',
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
const CRITICAL_SUFFIXES = ['.js', '.cjs', '.mjs', '.d.ts'];
|
|
43
|
+
|
|
44
|
+
function collectExportsLeaves(exportsField: PackageExports | undefined, out: string[]): void {
|
|
45
|
+
if (typeof exportsField === 'string') {
|
|
46
|
+
out.push(exportsField);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (!exportsField || typeof exportsField !== 'object') return;
|
|
50
|
+
for (const value of Object.values(exportsField)) {
|
|
51
|
+
collectExportsLeaves(value, out);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* 从包声明面推导关键发布物清单:main + bin + exports 全部脚本入口。
|
|
57
|
+
* 去 ./ 前缀,剔除非脚本叶子(如 ./package.json 自导出),去重排序。
|
|
58
|
+
*/
|
|
59
|
+
export function deriveCriticalArtifacts(manifest: PackagePublishManifest): string[] {
|
|
60
|
+
const collected: string[] = [];
|
|
61
|
+
if (manifest.main) collected.push(manifest.main);
|
|
62
|
+
if (typeof manifest.bin === 'string') collected.push(manifest.bin);
|
|
63
|
+
else if (manifest.bin && typeof manifest.bin === 'object') {
|
|
64
|
+
collected.push(...Object.values(manifest.bin));
|
|
65
|
+
}
|
|
66
|
+
collectExportsLeaves(manifest.exports, collected);
|
|
67
|
+
return [...new Set(
|
|
68
|
+
collected
|
|
69
|
+
.map(p => p.replace(/^\.\//, ''))
|
|
70
|
+
.filter(p => CRITICAL_SUFFIXES.some(suffix => p.endsWith(suffix)))
|
|
71
|
+
)].sort();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function isHarnessPackageRoot(dir: string): boolean {
|
|
75
|
+
try {
|
|
76
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(dir, 'package.json'), 'utf-8'));
|
|
77
|
+
return pkg?.name === HARNESS_PACKAGE_NAME;
|
|
78
|
+
} catch {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* 从 fromDir(缺省本模块编译位置)向上解析本包根。
|
|
85
|
+
* 源码仓(src/release → 仓根)与发布包(node_modules/@dommaker/harness/dist/release
|
|
86
|
+
* → 包根)均可达;到文件系统根仍无匹配则抛错。
|
|
87
|
+
*/
|
|
88
|
+
export function resolvePackageRoot(fromDir: string = __dirname): string {
|
|
89
|
+
let dir = path.resolve(fromDir);
|
|
90
|
+
for (;;) {
|
|
91
|
+
if (isHarnessPackageRoot(dir)) return dir;
|
|
92
|
+
const parent = path.dirname(dir);
|
|
93
|
+
if (parent === dir) break;
|
|
94
|
+
dir = parent;
|
|
95
|
+
}
|
|
96
|
+
throw new Error(
|
|
97
|
+
`[harness] 无法从 ${fromDir} 向上定位 ${HARNESS_PACKAGE_NAME} 包根;请显式传入 pkgRoot。`
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function resolveRoot(pkgRoot?: string): string {
|
|
102
|
+
return pkgRoot ? path.resolve(pkgRoot) : resolvePackageRoot();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* 关键发布物清单(相对包根路径,排序去重)。
|
|
107
|
+
* pkgRoot 缺省时自动解析本包根——外部消费者(studio)零参数即自检已安装的 harness。
|
|
108
|
+
*/
|
|
109
|
+
export function getCriticalArtifacts(pkgRoot?: string): string[] {
|
|
110
|
+
const root = resolveRoot(pkgRoot);
|
|
111
|
+
const manifest: PackagePublishManifest = JSON.parse(
|
|
112
|
+
fs.readFileSync(path.join(root, 'package.json'), 'utf-8')
|
|
113
|
+
);
|
|
114
|
+
return [...new Set([...deriveCriticalArtifacts(manifest), ...EXTRA_CRITICAL_ARTIFACTS])].sort();
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export interface ArtifactIntegrityResult {
|
|
118
|
+
ok: boolean;
|
|
119
|
+
pkgRoot: string;
|
|
120
|
+
/** 清单全量(相对包根路径) */
|
|
121
|
+
checked: string[];
|
|
122
|
+
/** 缺失项(相对包根路径) */
|
|
123
|
+
missing: string[];
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* 发布物完整性自检:逐项存在性校验(目录/文件均可)。
|
|
128
|
+
*
|
|
129
|
+
* 覆盖口径(有意裁决,#77):清单只锚定声明面及其运行时依赖;深度内部文件
|
|
130
|
+
* (tsc 产出的 dist/knowledge/*、core/constraints/checker.js 等)不在清单——
|
|
131
|
+
* 它们非公开契约,存在性由 tsc 构建成功保证,历史上外部硬编码它们正是
|
|
132
|
+
* 重构误判(6cf3c329)的根因。
|
|
133
|
+
*
|
|
134
|
+
* 挂载点:harness release 命令第 4 步;studio publishPackage dist 校验(配套切换 studio#425)。
|
|
135
|
+
*/
|
|
136
|
+
export function verifyReleaseArtifacts(pkgRoot?: string): ArtifactIntegrityResult {
|
|
137
|
+
const root = resolveRoot(pkgRoot);
|
|
138
|
+
const checked = getCriticalArtifacts(root);
|
|
139
|
+
const missing = checked.filter(f => !fs.existsSync(path.join(root, f)));
|
|
140
|
+
return { ok: missing.length === 0, pkgRoot: root, checked, missing };
|
|
141
|
+
}
|
package/src/types/failure.ts
CHANGED
|
@@ -5,6 +5,14 @@
|
|
|
5
5
|
* 不包含业务逻辑,只定义数据结构
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* 默认 failure 日志路径(相对项目根目录)
|
|
10
|
+
*
|
|
11
|
+
* 读写双方必须统一引用此常量(DEFAULT_TRACE_FILE 同款先例);
|
|
12
|
+
* 自定义路径时向 FailureRecorder 传入自定 logFile
|
|
13
|
+
*/
|
|
14
|
+
export const DEFAULT_FAILURE_LOG_FILE = '.harness/logs/failures.log';
|
|
15
|
+
|
|
8
16
|
/**
|
|
9
17
|
* 错误类型枚举
|
|
10
18
|
*/
|