agent-hitch 0.2.0 → 0.2.2
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 +88 -250
- package/README.zh-CN.md +84 -230
- package/dist/bin/hitch.js +1 -1
- package/dist/bin/hitch.js.map +1 -1
- package/dist/scripts/check-architecture.js +159 -0
- package/dist/scripts/check-architecture.js.map +1 -0
- package/dist/scripts/check-release.js +1 -1
- package/dist/scripts/check-release.js.map +1 -1
- package/dist/src/adapters/catalog.js +55 -0
- package/dist/src/adapters/catalog.js.map +1 -0
- package/dist/src/adapters/contract.js +2 -0
- package/dist/src/adapters/contract.js.map +1 -0
- package/dist/src/adapters/discovery.js +22 -0
- package/dist/src/adapters/discovery.js.map +1 -0
- package/dist/src/adapters/index.js +3 -0
- package/dist/src/adapters/index.js.map +1 -0
- package/dist/src/adapters/providers/claude.js +69 -0
- package/dist/src/adapters/providers/claude.js.map +1 -0
- package/dist/src/adapters/providers/codex.js +74 -0
- package/dist/src/adapters/providers/codex.js.map +1 -0
- package/dist/src/adapters/providers/deepseek.js +51 -0
- package/dist/src/adapters/providers/deepseek.js.map +1 -0
- package/dist/src/adapters/providers/opencode.js +73 -0
- package/dist/src/adapters/providers/opencode.js.map +1 -0
- package/dist/src/adapters/providers/pi.js +82 -0
- package/dist/src/adapters/providers/pi.js.map +1 -0
- package/dist/src/adapters/providers/shared.js +82 -0
- package/dist/src/adapters/providers/shared.js.map +1 -0
- package/dist/src/artifacts/handoff.js +12 -0
- package/dist/src/artifacts/handoff.js.map +1 -0
- package/dist/src/artifacts/index.js +5 -0
- package/dist/src/artifacts/index.js.map +1 -0
- package/dist/src/artifacts/integrity.js +188 -0
- package/dist/src/artifacts/integrity.js.map +1 -0
- package/dist/src/artifacts/preparer.js +379 -0
- package/dist/src/artifacts/preparer.js.map +1 -0
- package/dist/src/artifacts/store.js +157 -0
- package/dist/src/artifacts/store.js.map +1 -0
- package/dist/src/artifacts/types.js +2 -0
- package/dist/src/artifacts/types.js.map +1 -0
- package/dist/src/backends/contract.js +2 -0
- package/dist/src/backends/contract.js.map +1 -0
- package/dist/src/{harbor-backend.js → backends/harbor/backend.js} +52 -14
- package/dist/src/backends/harbor/backend.js.map +1 -0
- package/dist/src/backends/harbor/index.js +4 -0
- package/dist/src/backends/harbor/index.js.map +1 -0
- package/dist/src/backends/harbor/local-git-transport.js +447 -0
- package/dist/src/backends/harbor/local-git-transport.js.map +1 -0
- package/dist/src/{eval-tools.js → backends/harbor/tools.js} +2 -6
- package/dist/src/backends/harbor/tools.js.map +1 -0
- package/dist/src/backends/index.js +4 -0
- package/dist/src/backends/index.js.map +1 -0
- package/dist/src/cli/arguments.js +123 -0
- package/dist/src/cli/arguments.js.map +1 -0
- package/dist/src/cli/commands/compare.js +55 -0
- package/dist/src/cli/commands/compare.js.map +1 -0
- package/dist/src/cli/commands/daemon.js +106 -0
- package/dist/src/cli/commands/daemon.js.map +1 -0
- package/dist/src/cli/commands/eval.js +126 -0
- package/dist/src/cli/commands/eval.js.map +1 -0
- package/dist/src/cli/commands/feedback.js +84 -0
- package/dist/src/cli/commands/feedback.js.map +1 -0
- package/dist/src/cli/commands/inspect.js +20 -0
- package/dist/src/cli/commands/inspect.js.map +1 -0
- package/dist/src/cli/commands/list.js +17 -0
- package/dist/src/cli/commands/list.js.map +1 -0
- package/dist/src/cli/commands/prepare.js +21 -0
- package/dist/src/cli/commands/prepare.js.map +1 -0
- package/dist/src/cli/commands/resolve.js +17 -0
- package/dist/src/cli/commands/resolve.js.map +1 -0
- package/dist/src/cli/commands/run.js +145 -0
- package/dist/src/cli/commands/run.js.map +1 -0
- package/dist/src/cli/commands/runs.js +45 -0
- package/dist/src/cli/commands/runs.js.map +1 -0
- package/dist/src/cli/commands/trajectory.js +31 -0
- package/dist/src/cli/commands/trajectory.js.map +1 -0
- package/dist/src/cli/commands/workspace.js +44 -0
- package/dist/src/cli/commands/workspace.js.map +1 -0
- package/dist/src/cli/index.js +2 -0
- package/dist/src/cli/index.js.map +1 -0
- package/dist/src/cli/main.js +48 -0
- package/dist/src/cli/main.js.map +1 -0
- package/dist/src/cli/output.js +96 -0
- package/dist/src/cli/output.js.map +1 -0
- package/dist/src/controller-runtime/index.js +3 -0
- package/dist/src/controller-runtime/index.js.map +1 -0
- package/dist/src/controller-runtime/store.js +2 -7
- package/dist/src/controller-runtime/store.js.map +1 -1
- package/dist/src/daemon/auth.js +108 -0
- package/dist/src/daemon/auth.js.map +1 -0
- package/dist/src/daemon/client.js +76 -0
- package/dist/src/daemon/client.js.map +1 -0
- package/dist/src/daemon/index.js +5 -0
- package/dist/src/daemon/index.js.map +1 -0
- package/dist/src/daemon/launcher.js +24 -0
- package/dist/src/daemon/launcher.js.map +1 -0
- package/dist/src/{scheduler.js → daemon/scheduler.js} +6 -7
- package/dist/src/daemon/scheduler.js.map +1 -0
- package/dist/src/{daemon.js → daemon/server.js} +10 -155
- package/dist/src/daemon/server.js.map +1 -0
- package/dist/src/domain/artifacts.js +2 -0
- package/dist/src/domain/artifacts.js.map +1 -0
- package/dist/src/domain/controller-runtime.js +2 -0
- package/dist/src/domain/controller-runtime.js.map +1 -0
- package/dist/src/domain/eval-records.js +2 -0
- package/dist/src/domain/eval-records.js.map +1 -0
- package/dist/src/domain/evals.js +2 -0
- package/dist/src/domain/evals.js.map +1 -0
- package/dist/src/domain/feedback.js +2 -0
- package/dist/src/domain/feedback.js.map +1 -0
- package/dist/src/domain/{types.js → ids.js} +1 -1
- package/dist/src/domain/ids.js.map +1 -0
- package/dist/src/domain/index.js +11 -0
- package/dist/src/domain/index.js.map +1 -0
- package/dist/src/domain/revisions.js +2 -0
- package/dist/src/domain/revisions.js.map +1 -0
- package/dist/src/domain/runs.js +3 -0
- package/dist/src/domain/runs.js.map +1 -0
- package/dist/src/domain/trajectories.js +2 -0
- package/dist/src/domain/trajectories.js.map +1 -0
- package/dist/src/domain/{validate.js → validation.js} +194 -5
- package/dist/src/domain/validation.js.map +1 -0
- package/dist/src/domain/workspaces.js +2 -0
- package/dist/src/domain/workspaces.js.map +1 -0
- package/dist/src/evals/events.js +67 -0
- package/dist/src/evals/events.js.map +1 -0
- package/dist/src/evals/index.js +5 -0
- package/dist/src/evals/index.js.map +1 -0
- package/dist/src/evals/records.js +55 -0
- package/dist/src/evals/records.js.map +1 -0
- package/dist/src/evals/request.js +109 -0
- package/dist/src/evals/request.js.map +1 -0
- package/dist/src/evals/service.js +280 -0
- package/dist/src/evals/service.js.map +1 -0
- package/dist/src/evals/trial-import.js +394 -0
- package/dist/src/evals/trial-import.js.map +1 -0
- package/dist/src/feedback/index.js +2 -0
- package/dist/src/feedback/index.js.map +1 -0
- package/dist/src/feedback/service.js +3 -4
- package/dist/src/feedback/service.js.map +1 -1
- package/dist/src/{config.js → foundation/config.js} +1 -0
- package/dist/src/foundation/config.js.map +1 -0
- package/dist/src/foundation/errors.js.map +1 -0
- package/dist/src/foundation/executable.js +135 -0
- package/dist/src/foundation/executable.js.map +1 -0
- package/dist/src/foundation/fs.js.map +1 -0
- package/dist/src/foundation/hash.js +24 -0
- package/dist/src/foundation/hash.js.map +1 -0
- package/dist/src/foundation/index.js +11 -0
- package/dist/src/foundation/index.js.map +1 -0
- package/dist/src/foundation/line-stream.js.map +1 -0
- package/dist/src/foundation/locks.js +114 -0
- package/dist/src/foundation/locks.js.map +1 -0
- package/dist/src/{package-root.js → foundation/package-root.js} +3 -2
- package/dist/src/foundation/package-root.js.map +1 -0
- package/dist/src/foundation/process.js.map +1 -0
- package/dist/src/revisions/index.js +4 -0
- package/dist/src/revisions/index.js.map +1 -0
- package/dist/src/{harness-reference.js → revisions/reference.js} +16 -2
- package/dist/src/revisions/reference.js.map +1 -0
- package/dist/src/revisions/resolver.js +25 -0
- package/dist/src/revisions/resolver.js.map +1 -0
- package/dist/src/revisions/sources/git.js +180 -0
- package/dist/src/revisions/sources/git.js.map +1 -0
- package/dist/src/revisions/sources/installed.js +45 -0
- package/dist/src/revisions/sources/installed.js.map +1 -0
- package/dist/src/revisions/sources/npm.js +97 -0
- package/dist/src/revisions/sources/npm.js.map +1 -0
- package/dist/src/runs/compare.js +132 -0
- package/dist/src/runs/compare.js.map +1 -0
- package/dist/src/{events.js → runs/events.js} +1 -2
- package/dist/src/runs/events.js.map +1 -0
- package/dist/src/{engine.js → runs/executor.js} +172 -151
- package/dist/src/runs/executor.js.map +1 -0
- package/dist/src/runs/finalizer.js +22 -0
- package/dist/src/runs/finalizer.js.map +1 -0
- package/dist/src/runs/identity.js +35 -0
- package/dist/src/runs/identity.js.map +1 -0
- package/dist/src/runs/index.js +11 -0
- package/dist/src/runs/index.js.map +1 -0
- package/dist/src/runs/manifest.js +70 -0
- package/dist/src/runs/manifest.js.map +1 -0
- package/dist/src/runs/outcome.js +49 -0
- package/dist/src/runs/outcome.js.map +1 -0
- package/dist/src/runs/query.js +104 -0
- package/dist/src/runs/query.js.map +1 -0
- package/dist/src/runs/queued.js +54 -0
- package/dist/src/runs/queued.js.map +1 -0
- package/dist/src/runs/records.js +288 -0
- package/dist/src/runs/records.js.map +1 -0
- package/dist/src/runs/request.js +169 -0
- package/dist/src/runs/request.js.map +1 -0
- package/dist/src/trajectories/format.js +1 -1
- package/dist/src/trajectories/format.js.map +1 -1
- package/dist/src/trajectories/index.js +7 -0
- package/dist/src/trajectories/index.js.map +1 -0
- package/dist/src/trajectories/projector.js +1 -1
- package/dist/src/trajectories/projector.js.map +1 -1
- package/dist/src/trajectories/provider-capture.js +133 -0
- package/dist/src/trajectories/provider-capture.js.map +1 -0
- package/dist/src/trajectories/providers/deepseek.js +179 -0
- package/dist/src/trajectories/providers/deepseek.js.map +1 -0
- package/dist/src/trajectories/store.js +148 -8
- package/dist/src/trajectories/store.js.map +1 -1
- package/dist/src/workspaces/copy.js +142 -0
- package/dist/src/workspaces/copy.js.map +1 -0
- package/dist/src/workspaces/digest.js +47 -0
- package/dist/src/workspaces/digest.js.map +1 -0
- package/dist/src/workspaces/git.js +164 -0
- package/dist/src/workspaces/git.js.map +1 -0
- package/dist/src/workspaces/index.js +6 -0
- package/dist/src/workspaces/index.js.map +1 -0
- package/dist/src/workspaces/lifecycle.js +313 -0
- package/dist/src/workspaces/lifecycle.js.map +1 -0
- package/dist/src/workspaces/planner.js +80 -0
- package/dist/src/workspaces/planner.js.map +1 -0
- package/dist/src/workspaces/store.js +25 -0
- package/dist/src/workspaces/store.js.map +1 -0
- package/dist/src/workspaces/types.js +4 -0
- package/dist/src/workspaces/types.js.map +1 -0
- package/dist/src/workspaces/utils.js +56 -0
- package/dist/src/workspaces/utils.js.map +1 -0
- package/docs/schemas/eval-request.schema.json +2 -0
- package/docs/schemas/eval-result.schema.json +50 -1
- package/docs/schemas/local-git-transport-manifest.schema.json +34 -0
- package/docs/schemas/result.schema.json +9 -0
- package/docs/schemas/run-context.schema.json +39 -0
- package/docs/schemas/run-manifest.schema.json +81 -0
- package/docs/schemas/run-request.schema.json +16 -1
- package/docs/schemas/trajectory-ref.schema.json +66 -23
- package/integrations/harbor/hitch_harbor_agent.py +482 -10
- package/package.json +21 -3
- package/dist/src/adapters.js +0 -461
- package/dist/src/adapters.js.map +0 -1
- package/dist/src/artifacts.js +0 -1081
- package/dist/src/artifacts.js.map +0 -1
- package/dist/src/cli.js +0 -699
- package/dist/src/cli.js.map +0 -1
- package/dist/src/config.js.map +0 -1
- package/dist/src/daemon.js.map +0 -1
- package/dist/src/domain/types.js.map +0 -1
- package/dist/src/domain/validate.js.map +0 -1
- package/dist/src/engine.js.map +0 -1
- package/dist/src/errors.js.map +0 -1
- package/dist/src/eval-tools.js.map +0 -1
- package/dist/src/evals.js +0 -313
- package/dist/src/evals.js.map +0 -1
- package/dist/src/events.js.map +0 -1
- package/dist/src/fs.js.map +0 -1
- package/dist/src/harbor-backend.js.map +0 -1
- package/dist/src/harness-reference.js.map +0 -1
- package/dist/src/line-stream.js.map +0 -1
- package/dist/src/locks.js +0 -38
- package/dist/src/locks.js.map +0 -1
- package/dist/src/package-root.js.map +0 -1
- package/dist/src/process.js.map +0 -1
- package/dist/src/registry.js +0 -81
- package/dist/src/registry.js.map +0 -1
- package/dist/src/scheduler.js.map +0 -1
- package/dist/src/workspaces.js +0 -858
- package/dist/src/workspaces.js.map +0 -1
- /package/dist/src/{errors.js → foundation/errors.js} +0 -0
- /package/dist/src/{fs.js → foundation/fs.js} +0 -0
- /package/dist/src/{line-stream.js → foundation/line-stream.js} +0 -0
- /package/dist/src/{process.js → foundation/process.js} +0 -0
package/README.zh-CN.md
CHANGED
|
@@ -6,168 +6,126 @@
|
|
|
6
6
|
|
|
7
7
|
[English](README.md) | [简体中文](README.zh-CN.md)
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
**让智能体 Harness 的每次运行都可复现。**
|
|
10
10
|
|
|
11
|
-
Hitch
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
Git 可以标识发生变化的 Harness 源代码,而 Hitch 将这个身份贯穿构建与
|
|
16
|
-
执行的全过程:
|
|
11
|
+
Hitch 可以从确定的软件版本或 Git 提交运行 Codex、Claude Code、Pi、OpenCode
|
|
12
|
+
和 DeepSeek Harness。每次运行都会关联 Harness 版本、不可变制品、工作区、
|
|
13
|
+
轨迹、日志和评测证据。
|
|
17
14
|
|
|
18
15
|
```text
|
|
19
|
-
|
|
20
|
-
-> 已解析版本
|
|
21
|
-
-> 已准备制品
|
|
22
|
-
-> 运行 / 评测
|
|
23
|
-
-> 轨迹
|
|
24
|
-
-> 反馈与评测证据
|
|
25
|
-
|
|
26
|
-
Hitch 控制器
|
|
27
|
-
-> 内容寻址的运行时包
|
|
28
|
-
-> 由容器化评测引用
|
|
16
|
+
版本或提交 -> 不可变制品 -> 运行或评测 -> 可验证证据
|
|
29
17
|
```
|
|
30
18
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
Hitch 的上层系统负责。
|
|
19
|
+
```bash
|
|
20
|
+
npm install --global agent-hitch
|
|
34
21
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
22
|
+
hitch run \
|
|
23
|
+
--harness codex@version:0.92.0 \
|
|
24
|
+
--prompt "Inspect this repository"
|
|
25
|
+
```
|
|
38
26
|
|
|
39
|
-
|
|
27
|
+
> **状态:** pre-alpha。核心运行、来源追踪、轨迹、反馈、守护进程和 Harbor
|
|
28
|
+
> 评测链路已经实现。
|
|
40
29
|
|
|
41
|
-
|
|
42
|
-
版本、构建产物、控制器代码、工作区模式、原生适配器,以及机器上可变的
|
|
43
|
-
已安装可执行文件。如果分数或记录没有关联这些身份,就很难审计,更难复现。
|
|
30
|
+
## 为什么使用 Hitch?
|
|
44
31
|
|
|
45
|
-
Hitch
|
|
32
|
+
Git 告诉你哪些源码发生了变化,Hitch 则告诉你究竟运行了什么,以及它产生了
|
|
33
|
+
哪些证据。
|
|
46
34
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
| 已准备制品 | 经过验证、采用内容寻址的可运行构建产物 |
|
|
52
|
-
| 控制器运行时 | 上传到容器化评测中的确切 Hitch 运行时 |
|
|
53
|
-
| 运行或评测记录 | 请求、工作区、生命周期、结果以及各身份之间的关联 |
|
|
54
|
-
| 规范化轨迹 | 采用稳定、兼容 DSH 格式记录的智能体消息与工具活动 |
|
|
55
|
-
| 反馈与评测证据 | 消息级反馈、验证器输出、奖励及后端记录 |
|
|
35
|
+
- **复现:** 从确定的软件包版本或源码提交重新运行。
|
|
36
|
+
- **比较:** 通过统一的执行契约比较不同 Harness 和模型。
|
|
37
|
+
- **审计:** 用不可变制品、原生事件、规范化轨迹、日志、反馈和评测记录验证
|
|
38
|
+
结果。
|
|
56
39
|
|
|
57
|
-
|
|
58
|
-
|
|
40
|
+
Hitch 适合构建智能体评测、Harness 实验、Coding Agent 基础设施和自动晋级
|
|
41
|
+
流水线的团队。
|
|
59
42
|
|
|
60
43
|
## 快速开始
|
|
61
44
|
|
|
62
|
-
Hitch 要求 Node.js 22
|
|
45
|
+
Hitch 要求 Node.js 22 或更高版本。
|
|
63
46
|
|
|
64
47
|
```bash
|
|
65
48
|
npm install --global agent-hitch
|
|
66
49
|
hitch --version
|
|
67
|
-
hitch list --json
|
|
68
50
|
```
|
|
69
51
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
```bash
|
|
73
|
-
hitch resolve codex@version:0.92.0 --json
|
|
74
|
-
hitch prepare codex@version:0.92.0 --json
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
在隔离的 Git worktree 中运行这个确定版本:
|
|
52
|
+
在隔离的 Git worktree 中运行一个确定的 Harness 版本:
|
|
78
53
|
|
|
79
54
|
```bash
|
|
80
55
|
hitch run \
|
|
81
56
|
--harness codex@version:0.92.0 \
|
|
82
|
-
--model gpt-5.6-terra \
|
|
83
|
-
--cwd /workspace/project \
|
|
84
57
|
--workspace-mode worktree \
|
|
85
|
-
--prompt
|
|
58
|
+
--prompt "Inspect this repository" \
|
|
86
59
|
--output jsonl
|
|
87
60
|
```
|
|
88
61
|
|
|
89
|
-
|
|
90
|
-
进程日志、规范化事件和规范化轨迹。可以通过 CLI 检查轨迹:
|
|
62
|
+
输出中包含 run ID,可以用它查看保存的轨迹:
|
|
91
63
|
|
|
92
64
|
```bash
|
|
93
|
-
hitch trajectory inspect RUN_ID
|
|
65
|
+
hitch trajectory inspect RUN_ID
|
|
94
66
|
```
|
|
95
67
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
```bash
|
|
99
|
-
npm install
|
|
100
|
-
npm run check
|
|
101
|
-
npm link
|
|
102
|
-
hitch list --json
|
|
103
|
-
```
|
|
68
|
+
每次运行的 manifest、结果、事件、日志和轨迹都会保存在
|
|
69
|
+
`~/.hitch/runs/RUN_ID` 下。
|
|
104
70
|
|
|
105
|
-
## Harness
|
|
71
|
+
## 固定任意 Harness 版本
|
|
106
72
|
|
|
107
|
-
|
|
108
|
-
不可变身份,并在 Hitch 的制品存储中完成准备。
|
|
73
|
+
每次运行都会显式选择 Harness:
|
|
109
74
|
|
|
110
75
|
```bash
|
|
111
|
-
#
|
|
76
|
+
# 对本机已经安装的可执行文件生成指纹并运行。
|
|
112
77
|
hitch run --harness codex@installed --prompt "Inspect this repository"
|
|
113
78
|
|
|
114
|
-
#
|
|
115
|
-
hitch resolve codex@version:0.92.0 --json
|
|
116
|
-
hitch prepare codex@version:0.92.0 --json
|
|
79
|
+
# 解析并运行一个确定的已发布版本。
|
|
117
80
|
hitch run --harness codex@version:0.92.0 --prompt "Inspect this repository"
|
|
118
81
|
|
|
119
|
-
#
|
|
82
|
+
# 从已注册的上游仓库构建并运行一个确定的提交。
|
|
120
83
|
hitch run --harness codex@commit:0123456789abcdef --prompt "Inspect this repository"
|
|
121
|
-
|
|
122
|
-
# 从本地 Harness 仓库构建一个干净的提交。
|
|
123
|
-
hitch run \
|
|
124
|
-
--harness 'pi@git+file:///workspace/pi#0123456789abcdef' \
|
|
125
|
-
--prompt "Inspect this repository"
|
|
126
84
|
```
|
|
127
85
|
|
|
128
|
-
|
|
129
|
-
|
|
86
|
+
| Harness | 已安装版本 | 确定的软件包版本 | 源码提交 |
|
|
87
|
+
| --- | :---: | :---: | :---: |
|
|
88
|
+
| Codex | ✓ | ✓ | ✓ |
|
|
89
|
+
| Claude Code | ✓ | ✓ | — |
|
|
90
|
+
| Pi | ✓ | ✓ | ✓ |
|
|
91
|
+
| OpenCode | ✓ | ✓ | — |
|
|
92
|
+
| DeepSeek Harness | ✓ | ✓ | ✓ |
|
|
130
93
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
与 OpenCode 目前支持已安装版本和确定的软件包版本。
|
|
94
|
+
确定的版本和提交会被准备为经过验证、采用内容寻址的制品,并从 Hitch 的本地
|
|
95
|
+
缓存中复用。已安装的可执行文件适合本地工作;需要可移植性时,应使用不可变
|
|
96
|
+
引用。
|
|
135
97
|
|
|
136
|
-
|
|
137
|
-
命令。内容寻址让制品可以审计和缓存,但不会让不可信的构建代码变得安全。
|
|
98
|
+
## 每次运行都会留下证据
|
|
138
99
|
|
|
139
|
-
|
|
100
|
+
Hitch 记录从请求到结果的完整链路:
|
|
140
101
|
|
|
141
|
-
|
|
102
|
+
- 请求的引用及解析后的不可变版本;
|
|
103
|
+
- 经过验证、采用内容寻址的可运行制品;
|
|
104
|
+
- 工作区、模型身份、生命周期与最终结果;
|
|
105
|
+
- 规范化控制面事件与原始进程日志;
|
|
106
|
+
- 支持场景下经过脱敏的 provider-native 事件;
|
|
107
|
+
- 采用 SHA-256 绑定文件、兼容 DSH 的规范化轨迹;
|
|
108
|
+
- 带版本的消息反馈与评测证据。
|
|
142
109
|
|
|
143
|
-
|
|
144
|
-
取消和最终状态;
|
|
145
|
-
- 兼容 DSH 的规范化轨迹以明确的保真度记录智能体会话、消息、工具调用与
|
|
146
|
-
工具结果;
|
|
147
|
-
- `trajectory.ref.json` 将运行与规范化轨迹及其 SHA-256 摘要绑定;
|
|
148
|
-
- 反馈 sidecar 可以为助手消息附加带版本的正向或负向评分与备注,而无需
|
|
149
|
-
改写不可变轨迹。
|
|
110
|
+
可以通过 CLI 查询运行,并在不改写轨迹的情况下附加反馈:
|
|
150
111
|
|
|
151
112
|
```bash
|
|
152
|
-
hitch
|
|
113
|
+
hitch runs list --json
|
|
153
114
|
hitch feedback list RUN_ID --json
|
|
154
115
|
hitch feedback put RUN_ID \
|
|
155
116
|
--message MESSAGE_ID \
|
|
156
117
|
--rating positive \
|
|
157
|
-
--note "修改保持了足够聚焦"
|
|
158
|
-
--json
|
|
118
|
+
--note "修改保持了足够聚焦"
|
|
159
119
|
```
|
|
160
120
|
|
|
161
|
-
带版本的机器接口 Schema 位于 [`docs/schemas`](docs/schemas)
|
|
162
|
-
拒绝未知的请求字段,并在守护进程 HTTP 边界两侧保留类型化错误。
|
|
121
|
+
带版本的机器接口 Schema 位于 [`docs/schemas`](docs/schemas)。
|
|
163
122
|
|
|
164
|
-
##
|
|
123
|
+
## 可复现的智能体评测
|
|
165
124
|
|
|
166
|
-
Hitch
|
|
167
|
-
|
|
125
|
+
Hitch 集成了 [Harbor](https://github.com/harbor-framework/harbor),可以在 Docker
|
|
126
|
+
中评测确定且可移植的 Harness 版本:
|
|
168
127
|
|
|
169
128
|
```bash
|
|
170
|
-
# 将固定版本的 Harbor 安装到 ~/.hitch/tools,不修改系统 Python。
|
|
171
129
|
hitch eval setup harbor
|
|
172
130
|
hitch eval doctor
|
|
173
131
|
|
|
@@ -175,155 +133,51 @@ hitch eval run \
|
|
|
175
133
|
--backend harbor \
|
|
176
134
|
--dataset terminal-bench@2.0 \
|
|
177
135
|
--harness codex@version:0.92.0 \
|
|
178
|
-
--model openai/gpt-5.6
|
|
179
|
-
--attempts 1 \
|
|
180
|
-
--max-concurrent 4
|
|
181
|
-
|
|
182
|
-
hitch eval list
|
|
183
|
-
hitch eval inspect EVAL_ID --json
|
|
136
|
+
--model openai/gpt-5.6
|
|
184
137
|
```
|
|
185
138
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
并在 `/app` 中执行选定的 Harness 版本。生成的评测记录会关联请求、已解析
|
|
189
|
-
版本、控制器运行时、后端配置与日志、规范化结果、奖励摘要和轨迹证据。
|
|
190
|
-
|
|
191
|
-
评测接受由已注册远端源码支持的确定 `version:` 引用和 `commit:` 引用。
|
|
192
|
-
已安装可执行文件与本地 `git+file://` 引用无法移植到 Harbor 容器,因此会被
|
|
193
|
-
拒绝。常用的模型供应商凭证通过环境变量引用转发;使用 `--pass-env NAME`
|
|
194
|
-
可以额外传入一个环境变量。
|
|
195
|
-
|
|
196
|
-
有关安装、可移植性规则和执行边界,请参阅
|
|
139
|
+
每次评测都会关联已解析的 Harness 版本、采用内容寻址的 Hitch 控制器运行时、
|
|
140
|
+
后端配置、奖励、日志和轨迹证据。安装方法和可移植性规则参见
|
|
197
141
|
[Harbor 智能体评测](docs/evals.md)。
|
|
198
142
|
|
|
199
|
-
##
|
|
143
|
+
## 为自动化而设计
|
|
200
144
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
145
|
+
- 提供 JSON 和 JSONL 输出、带版本的 Schema 与类型化错误
|
|
146
|
+
- 支持直接执行或具有并发上限的持久化守护进程
|
|
147
|
+
- 支持共享、detached Git worktree 和独立副本工作区
|
|
148
|
+
- 支持超时、取消、进程树清理和中断运行恢复
|
|
149
|
+
- 通过 `--root <path>` 或 `HITCH_ROOT` 隔离本地状态
|
|
204
150
|
|
|
205
|
-
|
|
206
|
-
调用方 -> Hitch CLI / 守护进程 -> 共享运行引擎 -> Codex CLI
|
|
207
|
-
\----> Claude Code
|
|
208
|
-
\----> Pi
|
|
209
|
-
\----> OpenCode
|
|
210
|
-
\----> DeepSeek Harness
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
直接 CLI 与持久化守护进程使用同一个运行引擎,因此版本解析、记录、超时、
|
|
214
|
-
取消和事件行为不会发生偏移。当前运行时提供:
|
|
215
|
-
|
|
216
|
-
- 可执行文件发现、版本探测和可执行文件指纹;
|
|
217
|
-
- 确定的软件包版本与 Git 提交解析;
|
|
218
|
-
- 带完整性校验缓存的不可变制品;
|
|
219
|
-
- 输出规范化 JSONL 事件的直接执行;
|
|
220
|
-
- 具备并发上限的持久化本地守护进程;
|
|
221
|
-
- 队列中及运行中任务的取消、超时与完整进程树清理;
|
|
222
|
-
- 受管理的共享、Git worktree 和独立副本工作区模式;
|
|
223
|
-
- 原子的 manifest 与结果,以及原始 stdout 和 stderr 日志;
|
|
224
|
-
- 守护进程重启后对中断记录的保守恢复。
|
|
225
|
-
|
|
226
|
-
需要长期运行的队列时,可以通过守护进程执行:
|
|
151
|
+
需要长期执行队列时,可以启动守护进程:
|
|
227
152
|
|
|
228
153
|
```bash
|
|
229
154
|
hitch daemon start --max-concurrent 4
|
|
230
|
-
|
|
231
|
-
hitch run \
|
|
232
|
-
--daemon \
|
|
233
|
-
--harness codex@version:0.92.0 \
|
|
234
|
-
--cwd /workspace/project \
|
|
235
|
-
--prompt-file task.md \
|
|
236
|
-
--output jsonl
|
|
237
|
-
|
|
238
|
-
hitch daemon status --json
|
|
239
|
-
hitch daemon stop
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
也可以异步提交并取消:
|
|
243
|
-
|
|
244
|
-
```bash
|
|
245
|
-
hitch daemon submit \
|
|
246
|
-
--harness claude@version:EXACT_VERSION \
|
|
247
|
-
--cwd /workspace/project \
|
|
248
|
-
--prompt-file task.md
|
|
249
|
-
|
|
250
|
-
hitch daemon cancel RUN_ID
|
|
155
|
+
hitch run --daemon --harness codex@version:0.92.0 --prompt-file task.md
|
|
251
156
|
```
|
|
252
157
|
|
|
253
|
-
## 状态与隔离
|
|
254
|
-
|
|
255
|
-
状态默认存储在 `~/.hitch` 下。可以使用 `--root <path>` 或 `HITCH_ROOT`
|
|
256
|
-
修改位置。每个 root 都拥有独立的制品存储、控制器运行时存储、运行与评测
|
|
257
|
-
记录、守护进程令牌和队列。
|
|
258
|
-
|
|
259
|
-
可以通过 `HITCH_CODEX_PATH`、`HITCH_CLAUDE_PATH`、`HITCH_PI_PATH`、
|
|
260
|
-
`HITCH_OPENCODE_PATH` 和 `HITCH_DEEPSEEK_PATH` 覆盖原生可执行文件路径。
|
|
261
|
-
|
|
262
|
-
工作区模式会明确数据修改的边界:
|
|
263
|
-
|
|
264
|
-
- `shared` 直接在源码目录中运行;
|
|
265
|
-
- `worktree` 从干净的 `HEAD` 创建 detached Git worktree;
|
|
266
|
-
- `copy` 创建独立的文件系统副本。
|
|
267
|
-
|
|
268
|
-
工作区隔离并不等同于进程安全沙箱。
|
|
269
|
-
|
|
270
|
-
## 设计原则
|
|
271
|
-
|
|
272
|
-
- **默认可追溯:** 每次运行都会关联请求的引用、已解析版本、可运行制品、
|
|
273
|
-
执行记录与证据。
|
|
274
|
-
- **不可变解析:** 在准备或执行前将可变输入解析为不可变身份,并记录该
|
|
275
|
-
身份。
|
|
276
|
-
- **内容寻址复用:** 通过摘要复用经过验证的制品与控制器运行时,而不是为
|
|
277
|
-
每次运行重复复制。
|
|
278
|
-
- **不以有损抽象换取证据统一:** 稳定的规范化记录与原始 Harness 输出并存,
|
|
279
|
-
并明确记录轨迹保真度。
|
|
280
|
-
- **机器优先的接口:** 结构化输出、带版本的 Schema 和类型化错误构成公共
|
|
281
|
-
接口。
|
|
282
|
-
- **策略位于 Hitch 之上:** 变更、排序、晋级与回滚都是调用方系统的显式
|
|
283
|
-
决策。
|
|
284
|
-
- **安全中断:** 取消操作覆盖完整子进程树,涉及工作区修改的中断运行绝不
|
|
285
|
-
隐式重放。
|
|
286
|
-
|
|
287
|
-
## 计划中的工作
|
|
288
|
-
|
|
289
|
-
- [ ] Harness 版本及其证据的比较原语
|
|
290
|
-
- [ ] 命名的候选与 champion 引用
|
|
291
|
-
- [ ] 不内嵌晋级策略的晋级与回滚记录
|
|
292
|
-
- [ ] 远端制品与证据同步
|
|
293
|
-
- [ ] 更多 Harness 适配器
|
|
294
|
-
- [ ] 更多 API 供应商支持
|
|
295
|
-
- [ ] 本地模型推理支持
|
|
296
|
-
|
|
297
|
-
## 动态
|
|
298
|
-
|
|
299
|
-
- **2026-08-20:** Hitch 0.2 开发版将项目迁移到编译为 ESM 的严格
|
|
300
|
-
TypeScript,加入共享 SHA-256 控制器运行时缓存,为每次运行记录兼容 DSH
|
|
301
|
-
的规范化轨迹,并引入与生命周期绑定的消息反馈。
|
|
302
|
-
- **2026-08-13:** Hitch 加入对 DeepSeek Harness 的支持。
|
|
303
|
-
|
|
304
158
|
## 文档
|
|
305
159
|
|
|
306
|
-
- [
|
|
307
|
-
- [设计文档](docs/design.md)
|
|
308
|
-
- [智能体守护进程分析与移植](docs/daemon.md)
|
|
309
|
-
- [工作区隔离](docs/workspaces.md)
|
|
160
|
+
- [设计与架构](docs/design.md)
|
|
310
161
|
- [Harbor 评测](docs/evals.md)
|
|
162
|
+
- [工作区隔离](docs/workspaces.md)
|
|
163
|
+
- [守护进程设计](docs/daemon.md)
|
|
164
|
+
- [Hitch 0.2 开发规范](docs/hitch-0.2-development-spec.md)
|
|
311
165
|
- [发布流程](docs/releasing.md)
|
|
312
166
|
|
|
313
|
-
##
|
|
167
|
+
## 项目状态
|
|
314
168
|
|
|
315
|
-
|
|
316
|
-
|
|
169
|
+
Hitch 是 pre-alpha 阶段的本地版本与证据层。它是 Git 的补充,目前不提供远端
|
|
170
|
+
制品注册表、分支、标签、候选晋级或回滚策略。
|
|
317
171
|
|
|
318
|
-
|
|
172
|
+
远端制品同步、命名候选、晋级记录和更多 Harness 适配器已列入计划。
|
|
319
173
|
|
|
320
|
-
|
|
321
|
-
使用 [Harbor](https://github.com/harbor-framework/harbor) 作为评测后端。感谢
|
|
322
|
-
这两个项目提供的基础。
|
|
174
|
+
## 社区
|
|
323
175
|
|
|
324
|
-
|
|
176
|
+
加入 [Hitch Discord 社区](https://discord.gg/cZ4NBbHDk),提问、分享反馈,
|
|
177
|
+
并讨论智能体 Harness 基础设施。
|
|
325
178
|
|
|
326
|
-
|
|
179
|
+
Hitch 的设计受到 [Multica](https://github.com/multica-ai/multica) 启发,并使用
|
|
180
|
+
[Harbor](https://github.com/harbor-framework/harbor) 作为评测后端。
|
|
327
181
|
|
|
328
182
|
## 许可证
|
|
329
183
|
|
package/dist/bin/hitch.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { main } from "../src/cli.js";
|
|
2
|
+
import { main } from "../src/cli/index.js";
|
|
3
3
|
main(process.argv.slice(2)).catch((error) => {
|
|
4
4
|
const message = error instanceof Error ? error.message : String(error);
|
|
5
5
|
process.stderr.write(`hitch: ${message}\n`);
|
package/dist/bin/hitch.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hitch.js","sourceRoot":"","sources":["../../bin/hitch.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"hitch.js","sourceRoot":"","sources":["../../bin/hitch.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAE3C,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;IACnD,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACvE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,OAAO,IAAI,CAAC,CAAC;IAC5C,MAAM,QAAQ,GAAI,KAAgC,CAAC,QAAQ,CAAC;IAC5D,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAkB,CAAC,CAAC,CAAC,EAAE,CAAC;AAC1E,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { readFile, readdir } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
const SRC_ROOT = path.resolve("src");
|
|
4
|
+
const MODULES = new Set([
|
|
5
|
+
"domain", "foundation", "adapters", "revisions", "artifacts", "controller-runtime",
|
|
6
|
+
"trajectories", "feedback", "workspaces", "runs", "backends", "evals", "daemon", "cli",
|
|
7
|
+
]);
|
|
8
|
+
const ALLOWED = new Map([
|
|
9
|
+
["domain", new Set()],
|
|
10
|
+
["foundation", new Set(["domain"])],
|
|
11
|
+
["adapters", new Set(["domain", "foundation"])],
|
|
12
|
+
["revisions", new Set(["domain", "foundation", "adapters"])],
|
|
13
|
+
["artifacts", new Set(["domain", "foundation", "adapters", "revisions"])],
|
|
14
|
+
["controller-runtime", new Set(["domain", "foundation"])],
|
|
15
|
+
["trajectories", new Set(["domain", "foundation", "adapters"])],
|
|
16
|
+
["feedback", new Set(["domain", "foundation", "trajectories"])],
|
|
17
|
+
["workspaces", new Set(["domain", "foundation"])],
|
|
18
|
+
["runs", new Set(["domain", "foundation", "adapters", "revisions", "artifacts", "workspaces", "trajectories"])],
|
|
19
|
+
["backends", new Set(["domain", "foundation"])],
|
|
20
|
+
["evals", new Set(["domain", "foundation", "backends", "runs", "artifacts", "revisions", "controller-runtime", "workspaces", "trajectories"])],
|
|
21
|
+
["daemon", new Set(["domain", "foundation", "runs", "workspaces"])],
|
|
22
|
+
["cli", new Set([...MODULES].filter((name) => name !== "cli"))],
|
|
23
|
+
]);
|
|
24
|
+
const violations = [];
|
|
25
|
+
const edges = [];
|
|
26
|
+
const files = await sourceFiles(SRC_ROOT);
|
|
27
|
+
for (const file of files) {
|
|
28
|
+
const relative = slash(path.relative(SRC_ROOT, file));
|
|
29
|
+
const content = await readFile(file, "utf8");
|
|
30
|
+
const lines = content.split(/\r?\n/);
|
|
31
|
+
const sourceModule = topModule(relative);
|
|
32
|
+
if (!relative.includes("/")) {
|
|
33
|
+
report(relative, 1, "root-source", "root-level source files are not allowed", "move the public API to the owning module facade");
|
|
34
|
+
}
|
|
35
|
+
if (lines.length - 1 > 500) {
|
|
36
|
+
report(relative, 501, "file-size", `implementation has ${lines.length - 1} lines (maximum 500)`, "split by responsibility before adding more behavior");
|
|
37
|
+
}
|
|
38
|
+
if (path.basename(file) === "index.ts")
|
|
39
|
+
checkFacade(relative, lines);
|
|
40
|
+
for (const imported of imports(content)) {
|
|
41
|
+
if (sourceModule === "domain" && imported.specifier.startsWith("node:")) {
|
|
42
|
+
report(relative, imported.line, "domain-purity", `domain imports Node.js builtin ${imported.specifier}`, "move I/O or runtime behavior to foundation");
|
|
43
|
+
}
|
|
44
|
+
if (relative.startsWith("cli/commands/") && imported.specifier.startsWith("node:fs")) {
|
|
45
|
+
report(relative, imported.line, "cli-command-io", `CLI command imports filesystem builtin ${imported.specifier}`, "move state access behind the owning module facade");
|
|
46
|
+
}
|
|
47
|
+
if (!imported.specifier.startsWith("."))
|
|
48
|
+
continue;
|
|
49
|
+
const targetFile = resolveSource(file, imported.specifier);
|
|
50
|
+
if (!targetFile.startsWith(`${SRC_ROOT}${path.sep}`))
|
|
51
|
+
continue;
|
|
52
|
+
const targetRelative = slash(path.relative(SRC_ROOT, targetFile));
|
|
53
|
+
const targetModule = topModule(targetRelative);
|
|
54
|
+
if (!targetModule)
|
|
55
|
+
continue;
|
|
56
|
+
if (sourceModule && targetModule && sourceModule !== targetModule) {
|
|
57
|
+
if (!ALLOWED.get(sourceModule)?.has(targetModule)) {
|
|
58
|
+
report(relative, imported.line, "dependency-direction", `${sourceModule} may not depend on ${targetModule}`, `move the contract down or call ${targetModule}/index.ts from an allowed owner`);
|
|
59
|
+
}
|
|
60
|
+
if (targetRelative !== `${targetModule}/index.ts`) {
|
|
61
|
+
report(relative, imported.line, "deep-import", `cross-module deep import targets ${targetRelative}`, `import from ${targetModule}/index.ts`);
|
|
62
|
+
}
|
|
63
|
+
edges.push({ sourceFile: relative, sourceModule, targetFile: targetRelative, targetModule, line: imported.line });
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
checkModuleCycles(edges);
|
|
68
|
+
if (violations.length > 0) {
|
|
69
|
+
for (const item of violations.sort((a, b) => a.file.localeCompare(b.file) || a.line - b.line || a.rule.localeCompare(b.rule))) {
|
|
70
|
+
process.stderr.write(`${item.file}:${item.line} [${item.rule}] ${item.message}; ${item.suggestion}\n`);
|
|
71
|
+
}
|
|
72
|
+
process.stderr.write(`architecture check failed with ${violations.length} violation(s)\n`);
|
|
73
|
+
process.exitCode = 1;
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
process.stdout.write(`architecture check passed (${files.length} source files, ${edges.length} cross-module edges)\n`);
|
|
77
|
+
}
|
|
78
|
+
async function sourceFiles(directory) {
|
|
79
|
+
const result = [];
|
|
80
|
+
for (const entry of await readdir(directory, { withFileTypes: true })) {
|
|
81
|
+
const candidate = path.join(directory, entry.name);
|
|
82
|
+
if (entry.isDirectory())
|
|
83
|
+
result.push(...await sourceFiles(candidate));
|
|
84
|
+
else if (entry.isFile() && entry.name.endsWith(".ts"))
|
|
85
|
+
result.push(candidate);
|
|
86
|
+
}
|
|
87
|
+
return result.sort();
|
|
88
|
+
}
|
|
89
|
+
function imports(content) {
|
|
90
|
+
const result = [];
|
|
91
|
+
const pattern = /(?:\bfrom\s+|\bimport\s*)["']([^"']+)["']/g;
|
|
92
|
+
for (const match of content.matchAll(pattern)) {
|
|
93
|
+
result.push({ specifier: match[1], line: 1 + content.slice(0, match.index).split("\n").length - 1 });
|
|
94
|
+
}
|
|
95
|
+
return result;
|
|
96
|
+
}
|
|
97
|
+
function resolveSource(sourceFile, specifier) {
|
|
98
|
+
const raw = path.resolve(path.dirname(sourceFile), specifier);
|
|
99
|
+
if (raw.endsWith(".js"))
|
|
100
|
+
return `${raw.slice(0, -3)}.ts`;
|
|
101
|
+
if (path.extname(raw))
|
|
102
|
+
return raw;
|
|
103
|
+
return path.join(raw, "index.ts");
|
|
104
|
+
}
|
|
105
|
+
function topModule(relative) {
|
|
106
|
+
const [first, second] = relative.split("/");
|
|
107
|
+
return second && first && MODULES.has(first) ? first : null;
|
|
108
|
+
}
|
|
109
|
+
function checkFacade(relative, lines) {
|
|
110
|
+
lines.forEach((line, index) => {
|
|
111
|
+
const trimmed = line.trim();
|
|
112
|
+
if (!trimmed || trimmed.startsWith("//") || trimmed.startsWith("/**") || trimmed.startsWith("*") || trimmed.startsWith("*/") || trimmed.startsWith("export "))
|
|
113
|
+
return;
|
|
114
|
+
report(relative, index + 1, "facade-logic", "index.ts contains non-export logic", "move logic to an implementation file and export its public symbol");
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
function checkModuleCycles(importEdges) {
|
|
118
|
+
const graph = new Map();
|
|
119
|
+
for (const edge of importEdges) {
|
|
120
|
+
const targets = graph.get(edge.sourceModule) || new Set();
|
|
121
|
+
targets.add(edge.targetModule);
|
|
122
|
+
graph.set(edge.sourceModule, targets);
|
|
123
|
+
}
|
|
124
|
+
const visiting = new Set();
|
|
125
|
+
const visited = new Set();
|
|
126
|
+
const stack = [];
|
|
127
|
+
const emitted = new Set();
|
|
128
|
+
const visit = (module) => {
|
|
129
|
+
if (visited.has(module))
|
|
130
|
+
return;
|
|
131
|
+
if (visiting.has(module)) {
|
|
132
|
+
const start = stack.indexOf(module);
|
|
133
|
+
const cycle = [...stack.slice(start), module];
|
|
134
|
+
const key = cycle.join(" -> ");
|
|
135
|
+
if (!emitted.has(key)) {
|
|
136
|
+
emitted.add(key);
|
|
137
|
+
const edge = importEdges.find((item) => item.sourceModule === cycle.at(-2) && item.targetModule === module);
|
|
138
|
+
report(edge?.sourceFile || `${module}/index.ts`, edge?.line || 1, "module-cycle", key, "invert the shared contract into domain or foundation");
|
|
139
|
+
}
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
visiting.add(module);
|
|
143
|
+
stack.push(module);
|
|
144
|
+
for (const target of graph.get(module) || [])
|
|
145
|
+
visit(target);
|
|
146
|
+
stack.pop();
|
|
147
|
+
visiting.delete(module);
|
|
148
|
+
visited.add(module);
|
|
149
|
+
};
|
|
150
|
+
for (const module of MODULES)
|
|
151
|
+
visit(module);
|
|
152
|
+
}
|
|
153
|
+
function report(file, line, rule, message, suggestion) {
|
|
154
|
+
violations.push({ file, line, rule, message, suggestion });
|
|
155
|
+
}
|
|
156
|
+
function slash(value) {
|
|
157
|
+
return value.split(path.sep).join("/");
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=check-architecture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-architecture.js","sourceRoot":"","sources":["../../scripts/check-architecture.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { packageVersion } from "../src/
|
|
2
|
+
import { packageVersion } from "../src/foundation/index.js";
|
|
3
3
|
const [tag, prereleaseValue] = process.argv.slice(2);
|
|
4
4
|
const version = packageVersion();
|
|
5
5
|
const expectedTag = `v${version}`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check-release.js","sourceRoot":"","sources":["../../scripts/check-release.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"check-release.js","sourceRoot":"","sources":["../../scripts/check-release.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAE5D,MAAM,CAAC,GAAG,EAAE,eAAe,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACrD,MAAM,OAAO,GAAG,cAAc,EAAE,CAAC;AACjC,MAAM,WAAW,GAAG,IAAI,OAAO,EAAE,CAAC;AAElC,IAAI,GAAG,KAAK,WAAW,EAAE,CAAC;IACxB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,GAAG,IAAI,WAAW,mCAAmC,OAAO,cAAc,WAAW,IAAI,CAAC,CAAC;IAC/H,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC;KAAM,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,eAAe,IAAI,EAAE,CAAC,EAAE,CAAC;IAClE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAAC;IACzE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC;KAAM,CAAC;IACN,MAAM,mBAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAClD,MAAM,mBAAmB,GAAG,eAAe,KAAK,MAAM,CAAC;IACvD,IAAI,mBAAmB,KAAK,mBAAmB,EAAE,CAAC;QAChD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB,OAAO,6CAA6C,CAAC,CAAC;QAC9F,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvB,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,GAAG,4BAA4B,OAAO,IAAI,CAAC,CAAC;IAC9E,CAAC;AACH,CAAC"}
|