@omne-harness/repo-toolchain 0.0.18 → 0.0.19
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/README.md +17 -11
- package/README_ZH.md +52 -44
- package/dist/arch/conformance-model.d.ts +0 -17
- package/dist/arch/conformance-model.d.ts.map +1 -1
- package/dist/arch/conformance-model.js.map +1 -1
- package/dist/arch/conformance.d.ts +14 -2
- package/dist/arch/conformance.d.ts.map +1 -1
- package/dist/arch/conformance.js +22 -14
- package/dist/arch/conformance.js.map +1 -1
- package/dist/arch/constraints.d.ts.map +1 -1
- package/dist/arch/constraints.js +6 -78
- package/dist/arch/constraints.js.map +1 -1
- package/dist/arch/extract.d.ts +6 -0
- package/dist/arch/extract.d.ts.map +1 -1
- package/dist/arch/extract.js +6 -1
- package/dist/arch/extract.js.map +1 -1
- package/dist/core/subject.d.ts +0 -2
- package/dist/core/subject.d.ts.map +1 -1
- package/dist/core/subject.js +0 -4
- package/dist/core/subject.js.map +1 -1
- package/dist/declarations/api-baseline.d.ts +2 -2
- package/dist/declarations/api-baseline.js +2 -2
- package/dist/declarations/contract-api.d.ts +4 -4
- package/dist/declarations/contract-api.d.ts.map +1 -1
- package/dist/declarations/contract-api.js +7 -7
- package/dist/declarations/contract-api.js.map +1 -1
- package/dist/deps/cli.js +4 -15
- package/dist/deps/cli.js.map +1 -1
- package/dist/deps/graph.d.ts +4 -10
- package/dist/deps/graph.d.ts.map +1 -1
- package/dist/deps/graph.js +2 -31
- package/dist/deps/graph.js.map +1 -1
- package/dist/loop/baseline-cache.d.ts +21 -0
- package/dist/loop/baseline-cache.d.ts.map +1 -0
- package/dist/loop/baseline-cache.js +135 -0
- package/dist/loop/baseline-cache.js.map +1 -0
- package/dist/loop/hook-child.d.ts +2 -0
- package/dist/loop/hook-child.d.ts.map +1 -0
- package/dist/loop/hook-child.js +13 -0
- package/dist/loop/hook-child.js.map +1 -0
- package/dist/loop/hook-graph.d.ts +36 -0
- package/dist/loop/hook-graph.d.ts.map +1 -0
- package/dist/loop/hook-graph.js +200 -0
- package/dist/loop/hook-graph.js.map +1 -0
- package/dist/loop/hook-job.d.ts +8 -0
- package/dist/loop/hook-job.d.ts.map +1 -0
- package/dist/loop/hook-job.js +31 -0
- package/dist/loop/hook-job.js.map +1 -0
- package/dist/loop/hook-measure.d.ts +8 -1
- package/dist/loop/hook-measure.d.ts.map +1 -1
- package/dist/loop/hook-measure.js +28 -11
- package/dist/loop/hook-measure.js.map +1 -1
- package/dist/loop/hook-process.d.ts +34 -0
- package/dist/loop/hook-process.d.ts.map +1 -0
- package/dist/loop/hook-process.js +91 -0
- package/dist/loop/hook-process.js.map +1 -0
- package/dist/loop/hook.d.ts +39 -14
- package/dist/loop/hook.d.ts.map +1 -1
- package/dist/loop/hook.js +104 -51
- package/dist/loop/hook.js.map +1 -1
- package/dist/loop/proposals.js +1 -1
- package/dist/loop/proposals.js.map +1 -1
- package/dist/loop/run.d.ts +3 -14
- package/dist/loop/run.d.ts.map +1 -1
- package/dist/loop/run.js +6 -26
- package/dist/loop/run.js.map +1 -1
- package/dist/loop/sensors/conformance.d.ts +7 -1
- package/dist/loop/sensors/conformance.d.ts.map +1 -1
- package/dist/loop/sensors/conformance.js +20 -9
- package/dist/loop/sensors/conformance.js.map +1 -1
- package/dist/loop/status.d.ts +2 -5
- package/dist/loop/status.d.ts.map +1 -1
- package/dist/loop/status.js +0 -2
- package/dist/loop/status.js.map +1 -1
- package/dist/loop/stop-hook.js +21 -5
- package/dist/loop/stop-hook.js.map +1 -1
- package/dist/loop/tool-root.d.ts +6 -0
- package/dist/loop/tool-root.d.ts.map +1 -0
- package/dist/loop/tool-root.js +18 -0
- package/dist/loop/tool-root.js.map +1 -0
- package/package.json +1 -1
- package/dist/arch/group-cycles.d.ts +0 -32
- package/dist/arch/group-cycles.d.ts.map +0 -1
- package/dist/arch/group-cycles.js +0 -69
- package/dist/arch/group-cycles.js.map +0 -1
- package/dist/loop/hook-thread.d.ts +0 -11
- package/dist/loop/hook-thread.d.ts.map +0 -1
- package/dist/loop/hook-thread.js +0 -31
- package/dist/loop/hook-thread.js.map +0 -1
- package/dist/loop/hook-worker.d.ts +0 -2
- package/dist/loop/hook-worker.d.ts.map +0 -1
- package/dist/loop/hook-worker.js +0 -23
- package/dist/loop/hook-worker.js.map +0 -1
package/README.md
CHANGED
|
@@ -80,16 +80,9 @@ Version 0.0.12 is the first version in which `omne-deps` checks the direction ro
|
|
|
80
80
|
- No direction rows: when the runner has no `constraints.json`, the command prints that it did not check directions, and the exit code comes from the other findings. A schema 1 or 2 file, or a schema 3 file without `directions`, prints that there are no direction rows.
|
|
81
81
|
- Exit 2: `constraints.json` does not parse, fails validation, fails the check of its cited sources, or `docs/architecture/constraints.json` and `.meta_harness/design/architecture/constraints.json` both exist. The command reads the file before it runs dependency-cruiser.
|
|
82
82
|
|
|
83
|
-
##
|
|
83
|
+
## Cycles
|
|
84
84
|
|
|
85
|
-
A cycle between
|
|
86
|
-
|
|
87
|
-
- A group cycle is allowed only when every cross-group member edge in it is listed by an exception. The command then prints one `excepted` line with the groups, the exception id, the ruling link, the allowed edges and the reason, and the cycle does not fail. If one edge is not listed, the cycle fails as before. The message ends with the edges that are not listed, and the machine-readable `edges` of the finding stay the full list of edges in the cycle. A new member edge between the same groups, which no exception lists, therefore always makes the cycle fail.
|
|
88
|
-
- Each listed edge must appear in a group cycle, whether or not that cycle is allowed. An exception with an edge that does not appear (the edge was removed, the cycle is gone, or the edge is not in the cycle) is an `unused-group-cycle-exception` finding and exits 1. The `edges` of that finding are the edges that did not appear. This is judged only when the checked tree is the runner repository itself (both roots resolve to the same directory). When the checked tree is another tree (`OMNE_RUNNER_ROOT` points elsewhere), exceptions still allow the cycles they list, but an unused exception is not reported: the exception is recorded in the runner tree, so the cycles of the checked tree cannot show that it is out of date. `omne-deps`, `omne-loop-status` and the stop hook use the same judgement.
|
|
89
|
-
- Exceptions do not apply to cycles between members, to file cycles, or to other rules.
|
|
90
|
-
- When at least one group cycle is allowed, the last line of the summary ends with `<n> 个组环按具名例外放行` (`<n>` group cycles allowed by named exceptions).
|
|
91
|
-
- The hard lines of `omne-loop-status` and of the stop hook read the same exceptions. An excepted group cycle is not a hard line. The status lists it under the cycle line and keeps it in `hardLines.exceptedCycles` of `status.json`. An unused exception is a cycle hard line. When the `constraints.json` of the runner is not valid, `omne-loop-status` exits 2 as a tool error.
|
|
92
|
-
- `omne-metrics` and the architecture report do not read exceptions. They still list an excepted group cycle as a cycle.
|
|
85
|
+
A cycle between members makes `omne-deps` exit 1 and is a hard line of `omne-loop-status`. A cycle that exists only at the level of groups, with no cycle between members, is not a finding.
|
|
93
86
|
|
|
94
87
|
## Contract API snapshots
|
|
95
88
|
|
|
@@ -108,7 +101,7 @@ The class is a whitelist gate. Differences fall into two buckets. Any difference
|
|
|
108
101
|
|
|
109
102
|
The tool does not use API Extractor, because API Extractor does not analyze ambient declarations. It drops every `declare module` and `declare global` augmentation, and the public surface of 8 of the 27 contract members contains such augmentations.
|
|
110
103
|
|
|
111
|
-
The `contractApi` configuration section has two keys. `members` is the path of the
|
|
104
|
+
The `contractApi` configuration section has two keys. `members` is the path of the contract member table. `snapshot` is the snapshot path template. It ends with `.md` and contains `{member}` or `{package}`. Any other key, a missing key or a bad value is an error.
|
|
112
105
|
|
|
113
106
|
`review` means that a person must decide. It includes changes that break the writer, the reader or both. It also includes changes that the additive-change table allows but that are outside the whitelist. Examples are a new member of a union that the contract declares open, and a new default for a type parameter. `review` is not a level for the "契约变化" section of a PR. A person decides that level (none, additive or breaking) from the additive-change table in `docs/engineering/integration.md`.
|
|
114
107
|
|
|
@@ -121,12 +114,25 @@ A card that changes the public surface of a contract member runs `--write` in th
|
|
|
121
114
|
The Stop hook recalculates its baseline on each invocation. With a task context it uses `taskBase`. Without one it uses the nearest merge base among `primaryBranch` and the active tracks in `integration-policy.json`. See the Chinese README section "收工钩子" for the exact rules.
|
|
122
115
|
The global architecture reader resolves that base to a fixed commit and batches its selected source and intent blobs.
|
|
123
116
|
They use byte lengths for UTF-8 content and preserve literal paths, empty files and read failures.
|
|
124
|
-
|
|
117
|
+
Source ownership uses the longest member prefix and one inventory traversal.
|
|
118
|
+
The base side of the architecture readings (the base constraints, the actual extraction and its deviation rows) is calculated once per commit and stored in `hook-baseline/` in the loop directory. Later stops only read it.
|
|
119
|
+
The cache key is the base commit, the `sensors.architecture` section of the configuration, a digest of the tool code (every file in the package code directory, and the TypeScript version) and the storage format version. When the key does not match or the file is damaged, the hook calculates the base side again and replaces the file. It never uses an old reading for a different key.
|
|
120
|
+
The hook prepares the base side first. Thus, when the first measurement on a new base goes over the time limit, the base side is stored, and the warning says that the next stop will not calculate it again.
|
|
121
|
+
The working-tree side is calculated on each stop.
|
|
122
|
+
The dependency findings use only the edges of the changed files (`src/loop/hook-graph.ts`). The hook does not calculate the full working-tree dependency graph. An edge belongs to the file that has the import, so a new edge can only come from a changed file, and each new cycle or direction violation contains a new edge.
|
|
123
|
+
The hook reads the per-commit dependency graph of the base (the same cache in `<git-common-dir>/omne-dep-graph/` that `loop:status` uses). It runs dependency-cruiser only on the changed source files that still exist, with the rules and resolution options of `lint:deps`, and it does not follow their import targets. Then it replaces the dependencies and violations of those files in the base graph. It calculates the member edges, member cycles and group cycles again on the result. The time follows the number of changed files, not the size of the repository.
|
|
124
|
+
When the base graph is not in its cache, the hook calculates it first, as it does for the base side of the architecture readings. When that measurement goes over the time limit, the warning says that the base readings are stored and that the next stop will not calculate them again.
|
|
125
|
+
When the resolution configuration changed, the hook does not measure the dependency findings. It adds only the line "本次改了解析配置,依赖项看 pnpm run lint:deps". It does not fall back to the full graph. The resolution configuration changed when the content of the root `.dependency-cruiser.cjs` or a root `tsconfig*.json` changed, or when `name`, `exports`, `main`, `module`, `types`, `typings` or `imports` changed in the `package.json` of a member. The hook compares only files that exist on both sides. `pnpm-lock.yaml`, member tsconfig files and other manifest fields do not count.
|
|
126
|
+
Two cases are not covered: a file cycle inside one member (the base graph keeps only cross-member dependencies), and an old edge from an unchanged file to a deleted file. `pnpm run lint:deps` finds both.
|
|
127
|
+
The measurement runs in a child process. At the time limit the hook stops that process together with the processes it started (dependency-cruiser), and then it shows the user a warning. See the Chinese README for the measured times.
|
|
125
128
|
|
|
126
129
|
Synchronizing the primary branch can remove delivered changes from the current difference.
|
|
127
130
|
For a task-wide report, run `pnpm run loop:status --base <task-start-commit>` with a fixed task anchor.
|
|
128
131
|
That explicit base does not change the automatic hook's base. The internal 40-second limit and host error protocol remain unchanged.
|
|
129
132
|
|
|
133
|
+
The hook reports only the findings that are new or worse since the last reading of the same worktree and branch. It keeps that reading in `hook-readings.json` in the loop directory. When the running script is not in the measured checkout and `OMNE_RUNNER_ROOT` is not set, the hook does not measure. It shows the user a warning that it cannot measure, because the tool in the other checkout can be out of date.
|
|
134
|
+
The host command runs only the script of the worktree where the session is. It does not use the script of another checkout. When the worktree does not have the script, the command exits 0 and writes nothing. When the worktree does not have its dependencies installed, the script shows the user a warning that it cannot measure.
|
|
135
|
+
|
|
130
136
|
## Actual assembly observations
|
|
131
137
|
|
|
132
138
|
The clean loop reads complete current and BASE sources through `sensors.architecture`.
|
package/README_ZH.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
- [dev-flow](../dev-flow/README_ZH.md):开工准入、任务绑定、Issue 与看板读取、包模板。
|
|
10
10
|
- [product-checks](../product-checks/README_ZH.md):本仓库的产品规则、验收覆盖声明与场景状态。
|
|
11
|
-
- [test-runner](../test-runner/README_ZH.md)
|
|
11
|
+
- [test-runner](../test-runner/README_ZH.md):影响面计划、成员测试与耗时账本;差分变异经 [pqw-adapter](../pqw-adapter/README_ZH.md)。
|
|
12
12
|
|
|
13
13
|
## 仓库根与配置
|
|
14
14
|
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
|
|
30
30
|
| 命令 | 源码入口 | 作用 |
|
|
31
31
|
| --- | --- | --- |
|
|
32
|
-
| `omne-deps` | `src/deps/cli.ts` | 依赖规则、`constraints.json`
|
|
32
|
+
| `omne-deps` | `src/deps/cli.ts` | 依赖规则、`constraints.json` 的方向行,与成员之间的环 |
|
|
33
33
|
| `omne-declarations` | `src/declarations/cli.ts` | 用 TypeScript 6 读成员 dist 里的声明 |
|
|
34
34
|
| `omne-contract-api` | `src/declarations/api-cli.ts` | 契约成员的 API 快照:写、核对与相对基线的粗分类 |
|
|
35
35
|
| `omne-metrics` | `src/metrics/cli.ts` | 结构度量与审讯页 |
|
|
@@ -61,7 +61,7 @@ pnpm --filter @omne-harness/repo-toolchain test
|
|
|
61
61
|
|
|
62
62
|
## Git 环境隔离
|
|
63
63
|
|
|
64
|
-
显式仓库的 Git 子进程由 [git-environment.ts](src/core/git-environment.ts) 隔离八项仓库定位变量。认证、Git 配置、OMNE runner/subject 与测试控制参数继续继承。Vitest 在加载测试文件前另清两个 OMNE root,防止普通 fixture 读写外部仓库;污染回归在被测入口显式注入环境。持续验证见 [repository-environment.spec.ts](tests/repository-environment.spec.ts)
|
|
64
|
+
显式仓库的 Git 子进程由 [git-environment.ts](src/core/git-environment.ts) 隔离八项仓库定位变量。认证、Git 配置、OMNE runner/subject 与测试控制参数继续继承。Vitest 在加载测试文件前另清两个 OMNE root,防止普通 fixture 读写外部仓库;污染回归在被测入口显式注入环境。持续验证见 [repository-environment.spec.ts](tests/repository-environment.spec.ts)。
|
|
65
65
|
|
|
66
66
|
## 依赖图与依赖规则
|
|
67
67
|
|
|
@@ -69,8 +69,7 @@ pnpm --filter @omne-harness/repo-toolchain test
|
|
|
69
69
|
|
|
70
70
|
- 规则:无法解析的导入、文件级运行时循环、legacy 引用,以及按[产品包组织](../../docs/package-organization.md#依赖方向与cordis集成)与[系统分层](../../docs/architecture/layers-and-dependencies.md#依赖关系与禁止方向)写成成员路径的方向规则(SDK 与 server-entry 互不导入、公开契约不依赖两端实现、业务不依赖 SDK 与装配入口、common 与 util 不依赖领域成员、产品包不依赖应用与工具)。每条规则的 `comment` 指回出处。要按角色判断的规则(契约不依赖提供者等)还没有机读的角色,没有写。
|
|
71
71
|
- 方向行:`docs/architecture/constraints.json` schema 3 的 `directions`,格式与校验见[符合性契约](src/arch/CONFORMANCE.md#方向行);`omne-deps` 怎样用它见下面[依赖方向](#依赖方向)一节。
|
|
72
|
-
-
|
|
73
|
-
- 成员边:产品源码(不含测试)解析到另一个成员的依赖,类型导入也算。成员与组之间的环由这些边算出。导入处的行号按说明符在文件里第一次出现的位置找。图里另保留成员里 dependency-cruiser 走到的模块清单(`modules`)与跨成员的文件级依赖事实(`dependencies`,含测试与 `src` 下的 testing 入口,不含 Node 内建模块),方向行的判定与架构符合性报告的方向行都只从这两项判断,不另解析导入。
|
|
72
|
+
- 成员边:产品源码(不含测试)解析到另一个成员的依赖,类型导入也算。成员之间的环由这些边算出,有环即失败。只在组的层面成环、成员之间不成环的不算:一个组里的不同成员可以分别依赖另一个组。导入处的行号按说明符在文件里第一次出现的位置找。图里另保留成员里 dependency-cruiser 走到的模块清单(`modules`)与跨成员的文件级依赖事实(`dependencies`,含测试与 `src` 下的 testing 入口,不含 Node 内建模块),方向行的判定与架构符合性报告的方向行都只从这两项判断,不另解析导入。
|
|
74
73
|
- 工作树的图不含被 Git 忽略且未跟踪的目录里的模块与它们的违规(本地产物,理由同[实际架构](#全局实际架构视图)的成员规则);不在 Git 仓库里的目录没有忽略规则,照常出图。
|
|
75
74
|
- 规则与解析选项(`tsconfig.base.json` 的 `source` 条件)只从运行检查器的仓库读,被检查的检出改不了。
|
|
76
75
|
- 基线图:把那个提交的源码导出到 git 公共目录下的临时树,按成员包名补上 `node_modules/@omne-harness/*` 链接后跑;结果按提交、规则文件摘要与图的格式版本缓存在 `<git-common-dir>/omne-dep-graph/`,同一基线只算一次,不写工作树。
|
|
@@ -98,9 +97,9 @@ pnpm --filter @omne-harness/repo-toolchain test
|
|
|
98
97
|
|
|
99
98
|
做法借鉴 ub-mode 列出的 crapper 复用已有覆盖报告(`--use-existing-coverage`)与 mutator 的差分快照:先按输入指纹判没变,没变就不重算。
|
|
100
99
|
- 耗时(Windows 宿主,24 核):全仓一次 dependency-cruiser 约 14 秒,工作树指纹约 0.7 秒,`lint:deps` 命中缓存约 1.2 秒;基线命中缓存约 10 毫秒。
|
|
101
|
-
- 回路状态的硬线是依赖违规与环;方向命中只让 `lint:deps` 退出 1
|
|
100
|
+
- 回路状态的硬线是依赖违规与环;方向命中只让 `lint:deps` 退出 1,回路里只报告。
|
|
102
101
|
|
|
103
|
-
自测:`tests/deps-graph.spec.ts`、`tests/deps-graph-cache.spec.ts`(指纹逐类失效,含扫描根之外的未提交文件与被忽略的路径;命中、坏文件、开关、留份、算图期间输入变了不写缓存)、`tests/deps-graph-trees.spec.ts`(过期临时树的清理)、`tests/direction-rules.spec.ts`、`tests/
|
|
102
|
+
自测:`tests/deps-graph.spec.ts`、`tests/deps-graph-cache.spec.ts`(指纹逐类失效,含扫描根之外的未提交文件与被忽略的路径;命中、坏文件、开关、留份、算图期间输入变了不写缓存)、`tests/deps-graph-trees.spec.ts`(过期临时树的清理)、`tests/direction-rules.spec.ts`、`tests/deps-cycles.spec.ts`(成员成环失败;只在组的层面成环不是发现);回路金丝雀种了一处 `shared-stays-pure` 违规与一对成环的成员。
|
|
104
103
|
|
|
105
104
|
### 依赖方向
|
|
106
105
|
|
|
@@ -113,17 +112,6 @@ pnpm --filter @omne-harness/repo-toolchain test
|
|
|
113
112
|
- 没有方向行:运行检查器的仓库没有 `constraints.json` 时不检查方向,写「runner 没有 docs/architecture/constraints.json,未检查」,退出码只由其他发现决定;文件是 schema 1、2,或 schema 3 缺省 `directions`,写「没有方向行」。
|
|
114
113
|
- 退出 2:`constraints.json` 解析失败、校验失败、来源核对失败,或 `docs/architecture/constraints.json` 与 `.meta_harness/design/architecture/constraints.json` 两份并存。先读它再运行 dependency-cruiser,所以文件坏了不出依赖图。
|
|
115
114
|
|
|
116
|
-
### 组环例外
|
|
117
|
-
|
|
118
|
-
组之间成环默认失败。负责人裁定某条具体的依赖链在架构上成立时,在运行检查器的仓库的 `constraints.json` 里登记一条 `groupCycleExceptions`,写明成员边(`from`、`to` 是成员路径)、裁定链接和一句理由。例外只放行登记的那几条边。例外与方向行一样只从运行检查器的仓库读,被检查的树登记的例外不生效。例外从 repo-toolchain 0.0.16 起执行。
|
|
119
|
-
|
|
120
|
-
- 放行:一个组环的每一条跨组成员边都登记了,`omne-deps` 才放行它,另写一行 `excepted 组环 <组>、<组> 按例外 <id>(裁定 <链接>)放行 <from> → <to>、…:<理由>`。环上有一条边没登记,就照常报 `组之间成环` 并失败,消息末尾列出没登记的边;机读的 `edges` 仍是环上的全部边。因此两个组之间以后新增的任何没有登记的成员边,都会让组环失败。
|
|
121
|
-
- 没用上:登记的边必须出现在某个组环里,不论那个组环最后是否放行。边被删、组环已消失或边不在环上时,这条例外报一条 `unused-group-cycle-exception`,写明 id、没用上的边和裁定链接,并退出 1。这条发现的机读 `edges` 是没用上的边。要删掉或改写这条例外。只有被检树就是运行检查器的仓库自己时才判这一条。跨树检查(`OMNE_RUNNER_ROOT` 指向另一个仓库)时,例外照常放行登记的组环,但不判没用上:登记它的是 runner 的树,被检树的组环说明不了它有没有过期。`omne-deps`、回路状态与收工钩子的判断一致。
|
|
122
|
-
- 成员环:成员之间的环不受例外影响,照常失败。文件环与其他规则也一样。
|
|
123
|
-
- 汇总行:有放行的组环时,末行写「<n> 个组环按具名例外放行」。
|
|
124
|
-
- 回路状态:硬线读同一份例外。放行的组环不算硬线,在 `status.md` 硬线一段的「环」下面列出例外、裁定链接与放行的边,在 `status.json` 的 `hardLines.exceptedCycles` 里保留。没用上的例外算进「环」这条硬线。runner 的 `constraints.json` 坏了时,回路状态按工具错误退出 2。收工钩子的硬线同样按例外判。
|
|
125
|
-
- 结构度量与实际架构的报告不读例外:它们照旧把放行的组环列为环。
|
|
126
|
-
|
|
127
115
|
## 提交署名
|
|
128
116
|
|
|
129
117
|
`commit-attribution`(`src/commits.ts`)随 `pnpm run lint:rules` 执行,有违反即退出 1。它查的不是源码,
|
|
@@ -369,10 +357,10 @@ omne-metrics --plan <计划文件> --coverage --coverage-parallel 3x5 # 覆盖
|
|
|
369
357
|
pnpm run loop:status # 全仓现状
|
|
370
358
|
pnpm run loop:status --base <任务基线> # 另列这次变更里要解释的红项,并核验收锁
|
|
371
359
|
pnpm run loop:status --snapshot # 干净的工作树上追加一条趋势快照
|
|
372
|
-
pnpm run loop:status --base <基线> --strict --out <目录> # 严格模式,
|
|
360
|
+
pnpm run loop:status --base <基线> --strict --out <目录> # 严格模式,mainline 提升 main 时的整仓健康读数
|
|
373
361
|
```
|
|
374
362
|
|
|
375
|
-
**除硬线外一切只报告。**退出码 1 只在硬线被破时:依赖违规或环(与 `pnpm run metrics`、`lint:deps` 读[同一张依赖图](#依赖图与依赖规则);无法解析的导入归 `lint:deps
|
|
363
|
+
**除硬线外一切只报告。**退出码 1 只在硬线被破时:依赖违规或环(与 `pnpm run metrics`、`lint:deps` 读[同一张依赖图](#依赖图与依赖规则);无法解析的导入归 `lint:deps`,不算硬线),
|
|
376
364
|
或给了 `--base` 且[验收锁](#验收锁)被破,或严格模式下有开着的传感器没数据;
|
|
377
365
|
2 是工具自己出错(参数、配置、git);其余报告项再多也是 0。
|
|
378
366
|
|
|
@@ -380,9 +368,9 @@ pnpm run loop:status --base <基线> --strict --out <目录> # 严格模式,
|
|
|
380
368
|
有哪个报「没数据」,「硬线」一段列出是哪几个、原因是什么,退出 1;配置里关掉的不算,照旧写明是关掉的。
|
|
381
369
|
对照表那一项没有开关、也不进指标,不在此列。「没有基线快照,与基线比未判」是趋势的事,不算传感器没数据。
|
|
382
370
|
它要求给 `--base` 与 `--out`(缺了按用法错退出 2),草稿写进 `--out` 目录下的 `proposals/`,不写趋势快照(与 `--snapshot` 同用也是用法错)——
|
|
383
|
-
|
|
371
|
+
回路目录里一个字节都不动。它不在 `pnpm run check` 里:mainline 提升 main 的 PR 开出后跑一次,摘要贴在提升 PR 上,只报告不挡(做法归 `omne-card` 技能的「提升与发行」)。
|
|
384
372
|
|
|
385
|
-
CLI 的范围只有 `all` 和 `engineering`,默认 `all`;工程范围必须与 strict
|
|
373
|
+
CLI 的范围只有 `all` 和 `engineering`,默认 `all`;工程范围必须与 strict 同用。提升 main 时的整仓健康读数不传范围,使用默认 `all`。
|
|
386
374
|
工具复用当前传感器的源码清单,并枚举固定 targetBase、实际 merge-base、每个任务 taskBase 的 Git 树,按同一规则统计源码和测试。相同提交去重。没有 task context 的仓库使用有效显式 base 及其 merge-base。
|
|
387
375
|
只有当前与全部基线的两类计数均为零,duplication、assertions 启用但无数据时才列入 `hardLines.sensors.notApplicable`,原因码为 `engineering-without-product-inputs`。
|
|
388
376
|
`status.json` 的 `scope.evidence` 保存当前计数和各基线的精确提交、计数。原始 `sensors` 仍是 no-data;终端与 Markdown 点名工程范围不适用。关闭项仍列 `off`,其他启用的无数据项仍列 `silent` 并失败。
|
|
@@ -404,9 +392,9 @@ CLI 的范围只有 `all` 和 `engineering`,默认 `all`;工程范围必须
|
|
|
404
392
|
| ------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
405
393
|
| `status/<提交短号>[-dirty]/status.md` | 与终端打印相同的文字,分五段:抬头(含用的哪条基线快照)、硬线、各项指标的带位、要解释的红项、超预算的成员(含比基线变差的成员)与对照表条数;`--out` 可改目录 |
|
|
406
394
|
| `status/…/status.json` | 全量:每个传感器的原始结果(有数据/没数据及原因)、每个成员的四项预算、带位与各项与基线比的结果、要解释的红项全集(函数一类每条带与基线比的结果,没变差的另列在 `functionsNotWorse`) |
|
|
407
|
-
| `proposals/<成员路径斜杠换成 ->.md` | 超预算成员的清理草稿,同一成员覆盖旧稿;六个固定章节与[派发模板](
|
|
395
|
+
| `proposals/<成员路径斜杠换成 ->.md` | 超预算成员的清理草稿,同一成员覆盖旧稿;六个固定章节与[派发模板](../../docs/clean-loop-cleanup-task.md)同名同序(常量 `CLEANUP_SECTIONS`) |
|
|
408
396
|
| `trend.jsonl` | 趋势快照,一行一条:提交、各指标的值与带位、各成员的预算值与带位 |
|
|
409
|
-
| `hook-
|
|
397
|
+
| `hook-readings.json`、`hook.log` | [收工钩子](#收工钩子)每棵工作树、每条分支上一次量到的读数(类别、位置与函数的圈复杂度),与它自己出错的原因,一行一次 |
|
|
410
398
|
|
|
411
399
|
**三条带**:每个指标与每项成员预算都有提醒线、处置线、解除线(数值越大越差,`release ≤ warn ≤ act`)。值到处置线进入处置;
|
|
412
400
|
进入之后要回落到解除线及以下才解除,低于处置线但高于解除线仍是处置,这样一个值在线附近摆动时带位不跟着来回翻。
|
|
@@ -576,7 +564,7 @@ rev 翻动只数改了 `revision:` 行的提交,不看改了什么。自测:
|
|
|
576
564
|
## 收工钩子
|
|
577
565
|
|
|
578
566
|
`src/loop/stop-hook.ts` 由宿主(Claude Code、Codex)在 agent 收工时调用(`Stop` 与 `SubagentStop`),
|
|
579
|
-
|
|
567
|
+
把「这次变更里要解释的红项」里**比上一次新出现或变差的**作为**事实**反馈给 agent:只陈述位置与数值,不写该怎么改。
|
|
580
568
|
宿主配置由 `.meta_harness/agents/hooks/hooks.yaml` 生成,怎么生效、怎么关见那里的 README。
|
|
581
569
|
|
|
582
570
|
标准输入是宿主给的 JSON 对象。要反馈时向标准输出写**恰好一个** `{"decision":"block","reason":"…"}`(两端在这两个事件上都接受这个最小形状,
|
|
@@ -586,7 +574,10 @@ rev 翻动只数改了 `revision:` 行的提交,不看改了什么。自测:
|
|
|
586
574
|
|
|
587
575
|
1. `OMNE_LOOP_HOOK=off` → 什么都不做;输入解析不了、不是对象 → 不反馈。
|
|
588
576
|
2. `stop_hook_active` 为 `true`(这次收工已经因钩子续跑过)→ 不反馈。**每次收工至多拦一次。**
|
|
589
|
-
3. 工作目录取输入的 `cwd`,没有就用进程的当前目录;不在 git 仓库里 →
|
|
577
|
+
3. 工作目录取输入的 `cwd`,没有就用进程的当前目录;不在 git 仓库里 → 不反馈。
|
|
578
|
+
跑的这份脚本不在被量的仓库里(例如手工从别的检出调它),且没给 `OMNE_RUNNER_ROOT` → 不量,按下面「出错」的路径给用户一句「量不了」:
|
|
579
|
+
别的检出里的工具可能落后,量出来的会是旧代码的读数。`loop` 配置(从被量的仓库读)的 `hook.enabled` 为 `false` → 不反馈。
|
|
580
|
+
本检出没装依赖(从脚本所在处解析不到 TypeScript 解析器)→ 不起量读数的线程,同样只给用户一句「量不了」;主线程本来就不加载解析器。
|
|
590
581
|
4. 这次变更(相对下面的基线;已提交、未提交、未跟踪都算)没碰产品源码、全局 `constraints.json` 或其引用的Markdown源 → 不反馈。
|
|
591
582
|
**基线**这样取:
|
|
592
583
|
- 有 task context:取它的 `taskBase`(没有 ownerTask 时取 `targetBase`),不看轨道登记。
|
|
@@ -597,39 +588,56 @@ rev 翻动只数改了 `revision:` 行的提交,不看改了什么。自测:
|
|
|
597
588
|
policy 读不到或读不懂时没有轨道候选,只用 `primaryBranch`(位置按 `origin`)。一个候选也求不出时基线是 `HEAD`,只看未提交的改动。
|
|
598
589
|
- 直接在轨道分支上工作时,HEAD 就是轨道尖端,基线也是它,只看未提交的改动;要看相对 `primaryBranch` 的全部变更,手给 `pnpm run loop:status --base main`。
|
|
599
590
|
5. 量**静态那部分**读数:变更函数里超 alert、且比基线涨了或新出现的(与 `pnpm run loop:status` 同一个判法,见上「要解释的函数与基线比」,基线是这里的合并点;
|
|
600
|
-
反馈的那一行末尾补「原 N
|
|
601
|
-
不跑重复代码(全仓二十多秒)、覆盖率、工作树与 topic
|
|
591
|
+
反馈的那一行末尾补「原 N」「新出现」或拿不准的原因,原来就超线、这次没变差的不反馈)、新增的跨成员依赖、其中稳定依赖不稳定的、改动过的测试文件里没有断言的用例,加依赖违规与环两条硬线。
|
|
592
|
+
不跑重复代码(全仓二十多秒)、覆盖率、工作树与 topic 那几项。量在一个子进程里跑,超过 `hook.timeoutSeconds`(初值 40;宿主那侧另配 60)就放弃,
|
|
593
|
+
连同它起的进程(dependency-cruiser)整组杀掉。不用 worker 线程:线程卡在同步的子进程调用里时,终止它与主进程退出都要等那次调用返回,宿主那侧的时限会先到。
|
|
594
|
+
**依赖项只看改动文件的边**([`hook-graph.ts`](src/loop/hook-graph.ts)),不算整张工作树依赖图:一条依赖边属于发出导入的文件,新增的边只可能出自改过的文件,
|
|
595
|
+
新的环或方向违规一定含一条新边。所以钩子取基线合并点上按提交缓存的依赖图(`<git-common-dir>/omne-dep-graph/`,与 `loop:status` 的基线图同一份),
|
|
596
|
+
只对这次改过且还在的源文件(`packages`、`apps`、`examples`、`tools`、`scripts` 下,含未跟踪的)跑一层 dependency-cruiser,规则与解析选项同 `lint:deps`,
|
|
597
|
+
只往下走这些文件,不走它们的导入目标;再把基线图里这些文件发出的依赖与违规换成现算的。成员边与成员环在换过的依赖上重算,
|
|
598
|
+
新增跨成员依赖、稳定依赖不稳定(成员的不稳定度按换过的成员图算)、dependency-cruiser 的方向规则与全局预期的方向行都读这张图。耗时随改动的文件数走,不随仓库大小走。
|
|
599
|
+
基线图这次没有缓存时现算(全仓一次 dependency-cruiser),与下面 BASE 架构读数一样最先做:这次超时,超时的那句警告同样写明「基线的读数这次已备好存下,下次收工不再重算」。
|
|
600
|
+
**解析配置变了时依赖项不量**,读数里只多一句「本次改了解析配置,依赖项看 pnpm run lint:deps」,不退回全量:没改的文件的导入可能换了落点,基线图里它们的边不再可信。
|
|
601
|
+
算「变了」的是:根上的 `.dependency-cruiser.cjs` 或 `tsconfig*.json` 内容变了,或某个成员的 `package.json` 里 `name`、`exports`、`main`、`module`、`types`、`typings`、`imports` 变了。
|
|
602
|
+
两边都在才比:新加、删掉的不算,导入新成员的文件本身就在改动里。`pnpm-lock.yaml` 只管第三方包,成员里的 tsconfig 不进 dependency-cruiser,版本号、脚本这些字段不影响落点,都不算。
|
|
603
|
+
不覆盖、留给 `pnpm run lint:deps` 的:同一成员里的文件环(基线图只留跨成员的依赖),没改的文件指向已删文件的旧边。
|
|
602
604
|
同时按 BASE 的架构预期判断新增偏离,分别报告全局及原节点预期的语义改动;机械范围见 [CONFORMANCE](src/arch/CONFORMANCE.md)。仅修改预期也可产生反馈,未发布新全局预期的节点继续由原声明传感器消费。
|
|
603
|
-
|
|
604
|
-
|
|
605
|
+
架构读数 BASE 那一侧(BASE 的架构预期、实际抽取、其中的偏离行)按提交算一次,存进回路目录的 `hook-baseline/`([`baseline-cache.ts`](src/loop/baseline-cache.ts)),之后只读。
|
|
606
|
+
键是 BASE 提交、配置里 `sensors.architecture` 那一段、检查器代码的摘要(本包代码目录里每个文件的路径与内容,加 TypeScript 版本)与存储格式版本;
|
|
607
|
+
键对不上、文件坏了都重算并覆盖,不给旧数;最多留 10 份。同一仓库的工作树共用这些文件,读出来的 BASE 坐标换成当前的根。
|
|
608
|
+
这一步在量读数里最先做:BASE 刚换、还没有缓存时,即使这次超时,基线读数也已存下,超时的那句警告会写明「下次收工不再重算」。
|
|
609
|
+
当前工作树那一侧每次都重算,抽取与判偏离共用一个 TypeScript 程序。方向行读运行检查器那棵树的预期与依赖图,不进这份缓存。
|
|
610
|
+
6. 只反馈比上一次新出现或变差的:每条取「类别+位置(路径与函数名、或成员对)」,**不含行号**;函数另记圈复杂度。
|
|
611
|
+
上一次是这棵工作树、这条分支最近一次量出的读数,记在回路目录的 `hook-readings.json`,每棵工作树每条分支一条,最多 `hook.stateLimit`(初值 200)条,超了丢最旧的;读数变了才重写。
|
|
612
|
+
上一次没有的类别与位置算新出现,同一个函数圈复杂度比上一次大算变差;一条都没有 → 不反馈。修掉之后又改回来的,中间那次读数里没有它,改回来再报一次。
|
|
613
|
+
没有上一次(这棵树这条分支第一次量)时全部算新。旧版的 `hook-state.json` 不读。
|
|
605
614
|
7. 反馈的文字列前 `hook.maxItems`(初值 12)条,多的写「另有 N 条」,整段不超过 `hook.maxChars`(初值 4000)个字符;硬线排最前,截断时截掉的是报告项。
|
|
606
615
|
|
|
607
616
|
第 3 步找到仓库之后任何一步抛错或超时 → 不反馈给 agent,往回路目录的 `hook.log` 追加一行原因(写日志失败也吞掉),
|
|
608
617
|
并用 `systemMessage` 给用户一句警告:没量出读数、原因的前 300 个字符、日志在哪。**钩子自己出错从不拦住 agent,但不闷声**——
|
|
609
618
|
不出这一句,「钩子坏了」与「没有红项」在会话里看起来一模一样。
|
|
610
619
|
|
|
611
|
-
**跑的是哪一份脚本**由宿主配置里的命令定(`hooks.yaml
|
|
612
|
-
|
|
613
|
-
2026-10-02 第一次在真实会话里触发时正是栽在这里:脚本在新工作树里加载不了解析器,只记了日志。主检出自己也没装依赖时,结果是上面那句警告。
|
|
620
|
+
**跑的是哪一份脚本**由宿主配置里的命令定(`hooks.yaml`):只跑会话所在那棵工作树自己的,不借别的检出。
|
|
621
|
+
这棵树没有这份脚本(停在旧提交上)→ 命令退出 0,什么都不说;刚 `git worktree add` 出来、还没装依赖的 → 按第 3 步只报「量不了」,装好依赖之后才量。
|
|
614
622
|
|
|
615
623
|
每次调用都重新计算 `git merge-base <primaryBranch> HEAD`,不沿用上一次的基线。
|
|
616
|
-
架构读取先把基线解析成固定 commit,再按该树的 blob ID
|
|
624
|
+
架构读取先把基线解析成固定 commit,再按该树的 blob ID 批量读取文件,不逐文件启动 Git;缓存按这个 commit 存(见第 5 步),不跨提交沿用。
|
|
617
625
|
成员源码与数据文件按最长成员路径前缀分配,文件清单只遍历一次。读取失败仍报错,不以当前工作树补齐旧提交的缺失文件。
|
|
618
626
|
同步主线可能让已交付的改动退出本次差分。需要核对整个任务时,用固定的任务起点运行
|
|
619
627
|
`pnpm run loop:status --base <任务起点commit>`;这个显式基线不改变自动钩子的基线。
|
|
620
628
|
没有输出时还需区分没有新红项、已反馈、递归 Stop 和测量错误,不能仅凭同步发生在先就认定基线损坏。
|
|
621
629
|
|
|
622
|
-
实测(本仓库全量,2026-10
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
加一个分支、反馈一条的 2.5 秒;多出的一次 `git diff -M --name-status` 与每个文件一次 `git show` 合计十几毫秒,再加只解析那几个文件的基线文本。
|
|
630
|
+
实测(本仓库全量,2026-11-10,8 核 Linux):从基线起改过的源文件 75 个、两份基线都已缓存时,依赖项约 2.5 秒(一层 dependency-cruiser 约 2 秒),
|
|
631
|
+
一次收工 23 到 33 秒(1 分钟负载 5 到 17);其余大头是当前工作树的架构抽取(16 到 24 秒,一个 TypeScript 程序加遍历全部产品源码)与度量报告(4 到 7 秒),这两项随仓库大小走。
|
|
632
|
+
再多改 60 个文件(共 135 个)时依赖项约 6 秒,一次收工 23.8 到 28.9 秒(负载 5 到 6)。两份基线都没有缓存的第一次(基线刚换)超过 40 秒,只给用户一句「已备好」的警告,下一次照常给读数。
|
|
626
633
|
|
|
627
|
-
|
|
634
|
+
**不能声称**:反馈过的读数被处理了——它只在新出现或变差时提醒,交代与否由交付说明与接受的人核对;没被反馈等于没有红项——
|
|
628
635
|
没碰产品源码、全局约束或原节点声明,或者钩子关了、出错或超时、`stop_hook_active` 为真时都不反馈,重复代码与覆盖率不在其中,
|
|
629
636
|
**改动落在会话当前目录之外的另一棵工作树里时也不反馈**(hook只量payload的 `cwd` 所在检出;每个写者须显式进入自己的检出,不能只给exec设置workdir就声称宿主cwd已迁移。shell脚本可用当前目录回退,但配置选择依脚本位置;真实host cwd未经验证仍是未覆盖。协作交接见[责任与协作交接](../../docs/engineering/workflow.md#责任与协作交接));宿主真的调用了它——
|
|
630
637
|
生成配置不等于宿主已加载、已信任,要在真实会话里另行核实(Claude Code 一端 2026-10-02 见过一次真实调用;Codex 一端还没有);
|
|
631
638
|
警告一定到了用户眼前——`systemMessage` 怎样显示由宿主定,两端都只按文档核对过,没有在真实会话里看过它显示出来的样子。
|
|
632
|
-
自测:`tests/loop-hook.spec.ts`(判断,外部动作用替身)、`tests/loop-stop-hook.spec.ts
|
|
639
|
+
自测:`tests/loop-hook.spec.ts`(判断,外部动作用替身)、`tests/loop-stop-hook.spec.ts`(入口与线程,用临时仓库与子进程)、
|
|
640
|
+
`tests/loop-hook-graph.spec.ts`(依赖项只换改动文件的边,以整张工作树图对照;解析配置变了只出那一句);
|
|
633
641
|
命令选哪一份脚本由 `.meta_harness/tooling/tests/test_compile_hooks.py` 拿真的工作树跑。
|
|
634
642
|
|
|
635
643
|
## 流程体检页
|
|
@@ -673,7 +681,7 @@ pnpm run loop:health # --out 可改产物目录
|
|
|
673
681
|
|
|
674
682
|
## 契约 API 快照
|
|
675
683
|
|
|
676
|
-
契约成员是[
|
|
684
|
+
契约成员是[契约成员表](../../docs/engineering/delivery-lines.json)各组 `contracts` 列出的成员。卡对它们缺省只做可加改动,规则见[可加改动](../../docs/engineering/delivery.md#可加改动)。本命令给每个契约成员一份入库的 API 快照,并把两份快照之间的差异粗分为三类:`none` 表示没有变化;`additive` 表示改动对已有的读方与写方都不破坏;`review` 表示其余一切改动,需要人判断。它只报告,不拦截。行为契约(输入、快照内容、确定性、分类规则、已知限制、退出码与配置校验)见 [SPEC](src/declarations/SPEC.md)。
|
|
677
685
|
|
|
678
686
|
```sh
|
|
679
687
|
omne-contract-api --write # 从 dist 重写快照(先构建)
|
|
@@ -687,7 +695,7 @@ omne-contract-api --baseline <区块文件> # 逐成员从登记的提交比
|
|
|
687
695
|
|
|
688
696
|
配置在 `repo-toolchain.config.json` 的 `contractApi` 一节,有两个键:
|
|
689
697
|
|
|
690
|
-
- `members
|
|
698
|
+
- `members`:契约成员表的路径。
|
|
691
699
|
- `snapshot`:快照路径模板,以 `.md` 结尾,至少含 `{member}`(成员目录)或 `{package}`(不带 scope 的包名)之一。
|
|
692
700
|
|
|
693
701
|
这一节有别的键、缺键或值不合条件时,命令报错退出。两个成员算出同一个快照路径时,命令也报错退出。
|
|
@@ -704,12 +712,12 @@ omne-contract-api --baseline <区块文件> # 逐成员从登记的提交比
|
|
|
704
712
|
|
|
705
713
|
- 改了契约成员公开面的卡,在同一个 PR 里构建并运行 `--write`,把快照的变化一起提交。`--check` 报不一致时,先判断改动是否有意。
|
|
706
714
|
- 本工具改了快照格式(格式版本变了)时,全部快照要重新生成。
|
|
707
|
-
- 谁写首份快照、格式变化时谁重新生成,规则见[里程碑内的规则](../../docs/engineering/
|
|
715
|
+
- 谁写首份快照、格式变化时谁重新生成,规则见[里程碑内的规则](../../docs/engineering/delivery.md#破坏性契约改动)。
|
|
708
716
|
|
|
709
717
|
`--diff` 的前提:
|
|
710
718
|
|
|
711
719
|
- 它只比快照文件,不读 dist。先用 `--check` 确认工作树的快照与 dist 一致,或先运行 `--write`。
|
|
712
|
-
-
|
|
720
|
+
- 成员取基线与当前两份契约成员表的并集,每侧的快照路径按那一侧的包名算。基线上没有快照的成员整份算 `additive`。
|
|
713
721
|
- 判断改动是否可加时,传里程碑登记的基线提交。
|
|
714
722
|
|
|
715
723
|
快照摘要是快照文件字节的 SHA-256。`--check --json` 对每个有快照文件的成员给出 `sha256`。
|
|
@@ -26,28 +26,11 @@ export interface ArchitectureDirection {
|
|
|
26
26
|
readonly to: readonly [string, ...string[]];
|
|
27
27
|
readonly source: string;
|
|
28
28
|
}
|
|
29
|
-
/** 例外登记的一条成员边:`from`、`to` 是成员路径(依赖图 `edges` 的键),两端在不同的组。 */
|
|
30
|
-
export interface ArchitectureGroupCycleEdge {
|
|
31
|
-
readonly from: string;
|
|
32
|
-
readonly to: string;
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* schema 3 的具名组环例外:放行裁定过的那几条成员边。依赖图的组环的每条跨组成员边都登记了才放行;
|
|
36
|
-
* `ruling` 是裁定的 https 链接,`reason` 是一句理由。一条边在全部例外里只出现一次。
|
|
37
|
-
*/
|
|
38
|
-
export interface ArchitectureGroupCycleException {
|
|
39
|
-
readonly id: string;
|
|
40
|
-
readonly edges: readonly [ArchitectureGroupCycleEdge, ...ArchitectureGroupCycleEdge[]];
|
|
41
|
-
readonly ruling: string;
|
|
42
|
-
readonly reason: string;
|
|
43
|
-
}
|
|
44
29
|
export interface ArchitectureConstraints {
|
|
45
30
|
readonly schemaVersion: 1 | 2 | 3;
|
|
46
31
|
readonly importExceptions?: readonly ArchitectureImportException[];
|
|
47
32
|
/** 只有 schema 3 可以声明;schema 1、2 的文档没有这个字段。 */
|
|
48
33
|
readonly directions?: readonly ArchitectureDirection[];
|
|
49
|
-
/** 只有 schema 3 可以声明;schema 1、2 的文档没有这个字段。 */
|
|
50
|
-
readonly groupCycleExceptions?: readonly ArchitectureGroupCycleException[];
|
|
51
34
|
readonly domains: readonly {
|
|
52
35
|
readonly id: string;
|
|
53
36
|
readonly label: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conformance-model.d.ts","sourceRoot":"","sources":["../../src/arch/conformance-model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAC5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAEpD,eAAO,MAAM,QAAQ,YACnB,aAAa,EACb,WAAW,EACX,MAAM,EACN,MAAM,EACN,MAAM,EACN,MAAM,EACN,MAAM,EACN,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,EACnB,2BAA2B,CACnB,CAAA;AACV,MAAM,MAAM,MAAM,GAAG,CAAC,OAAO,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAA;AAC9C,MAAM,MAAM,KAAK,GACb,aAAa,GACb,QAAQ,GACR,UAAU,GACV,cAAc,GACd,iBAAiB,GACjB,UAAU,GACV,SAAS,CAAA;AACb,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;IACjC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;IACnC,QAAQ,CAAC,MAAM,EAAE,SAAS,GAAG,WAAW,GAAG,SAAS,CAAA;IACpD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB;AACD,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;IACnC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB;AACD,yEAAyE;AACzE,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,CAAA;IAC7C,QAAQ,CAAC,EAAE,EAAE,SAAS,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,CAAA;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB;AACD,
|
|
1
|
+
{"version":3,"file":"conformance-model.d.ts","sourceRoot":"","sources":["../../src/arch/conformance-model.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conformance-model.js","sourceRoot":"","sources":["../../src/arch/conformance-model.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,aAAa;IACb,WAAW;IACX,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,kBAAkB;IAClB,qBAAqB;IACrB,mBAAmB;IACnB,2BAA2B;CACnB,CAAA;
|
|
1
|
+
{"version":3,"file":"conformance-model.js","sourceRoot":"","sources":["../../src/arch/conformance-model.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,aAAa;IACb,WAAW;IACX,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,MAAM;IACN,kBAAkB;IAClB,qBAAqB;IACrB,mBAAmB;IACnB,2BAA2B;CACnB,CAAA;AAsDV,MAAM,UAAU,WAAW,CAAC,KAAsB;IAChD,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,cAAc,IAAI,EAAE,CAAC,CAAA;IACnD,OAAO,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;AACvE,CAAC"}
|
|
@@ -2,14 +2,26 @@ import { type ArchitectureSource } from './source.ts';
|
|
|
2
2
|
import type { ActualExtraction } from './actual-model.ts';
|
|
3
3
|
import type { ActualArchitectureInput } from './actual.ts';
|
|
4
4
|
import type { DependencyGraph } from '../deps/graph.ts';
|
|
5
|
-
import type { Conformance } from './conformance-model.ts';
|
|
5
|
+
import type { Conformance, ConstraintInput } from './conformance-model.ts';
|
|
6
6
|
export declare function conformanceOf(root: string, current: ArchitectureSource, baseline?: ArchitectureSource, graph?: DependencyGraph): Conformance;
|
|
7
|
+
/**
|
|
8
|
+
* BASE 一侧的全部观测:BASE 的架构预期、实际抽取,与按 BASE 预期判出的偏离行 id。
|
|
9
|
+
* 只取决于 BASE 提交与检查器代码,可以按提交算一次存下(收工钩子的缓存见 loop/baseline-cache.ts)。
|
|
10
|
+
* 方向行不在这里:它读运行检查器那棵树的预期,见 arch/directions.ts。
|
|
11
|
+
*/
|
|
12
|
+
export interface BaselineObservation {
|
|
13
|
+
readonly constraints: ConstraintInput;
|
|
14
|
+
readonly actual: ActualExtraction;
|
|
15
|
+
readonly stock: readonly string[];
|
|
16
|
+
}
|
|
17
|
+
export declare function observeBaseline(root: string, baseline: ArchitectureSource): BaselineObservation;
|
|
7
18
|
/**
|
|
8
19
|
* One extraction per source version for constraints and actual assembly observations.
|
|
20
|
+
* BASE 一侧由调用方观测好传进来(`observeBaseline`);当前版本的抽取与偏离判定共用一个解析器。
|
|
9
21
|
* 方向行一节另从可信 runner 读(arch/directions.ts);调用方已经算过当前版本的依赖图时传进来,
|
|
10
22
|
* 免得再跑一次 dependency-cruiser;没传就按版本自己取,而且只在 runner 有方向行时才取。
|
|
11
23
|
*/
|
|
12
|
-
export declare function analyzeConformance(root: string, current: ArchitectureSource, baseline?:
|
|
24
|
+
export declare function analyzeConformance(root: string, current: ArchitectureSource, baseline?: BaselineObservation, graph?: DependencyGraph): {
|
|
13
25
|
conformance: Conformance;
|
|
14
26
|
headActual: ActualExtraction;
|
|
15
27
|
baseActual: ActualExtraction | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conformance.d.ts","sourceRoot":"","sources":["../../src/arch/conformance.ts"],"names":[],"mappings":"AACA,OAAO,EAA0B,KAAK,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAQ7E,OAAO,KAAK,EAAE,gBAAgB,EAAuB,MAAM,mBAAmB,CAAA;AAC9E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AAI1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,KAAK,EAEV,WAAW,
|
|
1
|
+
{"version":3,"file":"conformance.d.ts","sourceRoot":"","sources":["../../src/arch/conformance.ts"],"names":[],"mappings":"AACA,OAAO,EAA0B,KAAK,kBAAkB,EAAE,MAAM,aAAa,CAAA;AAQ7E,OAAO,KAAK,EAAE,gBAAgB,EAAuB,MAAM,mBAAmB,CAAA;AAC9E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAA;AAI1D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,KAAK,EAEV,WAAW,EAGX,eAAe,EAEhB,MAAM,wBAAwB,CAAA;AAye/B,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,kBAAkB,EAC3B,QAAQ,CAAC,EAAE,kBAAkB,EAC7B,KAAK,CAAC,EAAE,eAAe,GACtB,WAAW,CAOb;AACD;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,WAAW,EAAE,eAAe,CAAA;IACrC,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAA;IACjC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;CAClC;AACD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,kBAAkB,GAAG,mBAAmB,CAU/F;AACD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,kBAAkB,EAC3B,QAAQ,CAAC,EAAE,mBAAmB,EAC9B,KAAK,CAAC,EAAE,eAAe;;;;EAuExB;AACD,wBAAgB,eAAe,CAC7B,KAAK,EAAE,uBAAuB,GAAG;IAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,eAAe,CAAA;CAAE,GAC9F,WAAW,CAWb;AACD,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,SAAS,MAAM,EAAE,GACzB,WAAW,CAMb"}
|
package/dist/arch/conformance.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { extractWithResolver } from './extract.js';
|
|
2
2
|
import { readArchitectureSource } from './source.js';
|
|
3
3
|
import { readBaselineConstraints, readConstraints, roleAt, semanticConstraints, } from './constraints.js';
|
|
4
4
|
import { activeRoles } from './conformance-model.js';
|
|
5
|
-
import { publicEntries
|
|
5
|
+
import { publicEntries } from './resolve.js';
|
|
6
6
|
import { directionConformance } from './directions.js';
|
|
7
7
|
const coverage = [
|
|
8
8
|
...['LAYER-ENTRY', 'LAYER-DIP', 'IC-1', 'IC-2', 'IC-3', 'IC-4', 'IC-5'].map(id => ({
|
|
@@ -68,7 +68,8 @@ function exceptionAt(edge, input, extraction) {
|
|
|
68
68
|
members.has(item.target));
|
|
69
69
|
return exception === undefined ? undefined : { ...exception, path: input.path };
|
|
70
70
|
}
|
|
71
|
-
|
|
71
|
+
/** `resolver` 是抽取 `extraction` 时用的那一个,建在同一份 `snapshot` 上。 */
|
|
72
|
+
function rowsOf(extraction, input, snapshot, resolver) {
|
|
72
73
|
const rows = [], intent = input.value === null ? null : { ...input.value, roles: activeRoles(input) };
|
|
73
74
|
const rules = new Map(intent?.rules.map(rule => [rule.id, rule]) ?? []);
|
|
74
75
|
const entries = publicEntries(snapshot);
|
|
@@ -235,7 +236,6 @@ function rowsOf(extraction, input, snapshot) {
|
|
|
235
236
|
item.serviceDefinition?.symbol === fact.serviceDefinition?.symbol)
|
|
236
237
|
: undefined;
|
|
237
238
|
const declarations = definitions.filter(fact => serviceDefinition(fact) === undefined);
|
|
238
|
-
const resolver = new StaticResolver(snapshot);
|
|
239
239
|
const publicDeclarations = entries.flatMap(entry => entry.sourcePath === undefined
|
|
240
240
|
? []
|
|
241
241
|
: resolver
|
|
@@ -344,17 +344,29 @@ function checkRoots(extraction, add, entries, snapshot) {
|
|
|
344
344
|
}
|
|
345
345
|
}
|
|
346
346
|
export function conformanceOf(root, current, baseline, graph) {
|
|
347
|
-
return analyzeConformance(root, current, baseline, graph).conformance;
|
|
347
|
+
return analyzeConformance(root, current, baseline === undefined ? undefined : observeBaseline(root, baseline), graph).conformance;
|
|
348
|
+
}
|
|
349
|
+
export function observeBaseline(root, baseline) {
|
|
350
|
+
const constraints = readBaselineConstraints(root, baseline);
|
|
351
|
+
const { extraction, resolver } = extractWithResolver(baseline.snapshot);
|
|
352
|
+
return {
|
|
353
|
+
constraints,
|
|
354
|
+
actual: extraction,
|
|
355
|
+
stock: rowsOf(extraction, constraints, baseline.snapshot, resolver)
|
|
356
|
+
.filter(row => row.state === 'deviation')
|
|
357
|
+
.map(row => row.id),
|
|
358
|
+
};
|
|
348
359
|
}
|
|
349
360
|
/**
|
|
350
361
|
* One extraction per source version for constraints and actual assembly observations.
|
|
362
|
+
* BASE 一侧由调用方观测好传进来(`observeBaseline`);当前版本的抽取与偏离判定共用一个解析器。
|
|
351
363
|
* 方向行一节另从可信 runner 读(arch/directions.ts);调用方已经算过当前版本的依赖图时传进来,
|
|
352
364
|
* 免得再跑一次 dependency-cruiser;没传就按版本自己取,而且只在 runner 有方向行时才取。
|
|
353
365
|
*/
|
|
354
366
|
export function analyzeConformance(root, current, baseline, graph) {
|
|
355
|
-
const head = readConstraints(root, current.source), base = baseline
|
|
356
|
-
const headActual =
|
|
357
|
-
const rows = rowsOf(headActual, base ?? head, current.snapshot);
|
|
367
|
+
const head = readConstraints(root, current.source), base = baseline?.constraints;
|
|
368
|
+
const { extraction: headActual, resolver } = extractWithResolver(current.snapshot), baseActual = baseline?.actual;
|
|
369
|
+
const rows = rowsOf(headActual, base ?? head, current.snapshot, resolver);
|
|
358
370
|
for (const [version, input] of [
|
|
359
371
|
['current', head],
|
|
360
372
|
['baseline', base],
|
|
@@ -372,11 +384,7 @@ export function analyzeConformance(root, current, baseline, graph) {
|
|
|
372
384
|
sites: [{ path: input.path, line: 1 }],
|
|
373
385
|
});
|
|
374
386
|
}
|
|
375
|
-
const stock = new Set(
|
|
376
|
-
? []
|
|
377
|
-
: rowsOf(baseActual, base ?? head, baseline?.snapshot ?? current.snapshot)
|
|
378
|
-
.filter(row => row.state === 'deviation')
|
|
379
|
-
.map(row => row.id));
|
|
387
|
+
const stock = new Set(baseline?.stock ?? []);
|
|
380
388
|
const changes = [];
|
|
381
389
|
const before = semanticConstraints(base?.value ?? null), after = semanticConstraints(head.value);
|
|
382
390
|
if (base !== undefined && before !== after)
|
|
@@ -411,7 +419,7 @@ export function analyzeConformance(root, current, baseline, graph) {
|
|
|
411
419
|
? 'stock'
|
|
412
420
|
: 'new',
|
|
413
421
|
})),
|
|
414
|
-
...directionConformance({ root, current: current.source, baseline:
|
|
422
|
+
...directionConformance({ root, current: current.source, baseline: base?.source, graph }),
|
|
415
423
|
],
|
|
416
424
|
changes,
|
|
417
425
|
sourceChanges,
|