euthyna 0.1.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/LICENSE ADDED
@@ -0,0 +1,202 @@
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright 2026 euthyna contributors
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
package/NOTICE.md ADDED
@@ -0,0 +1,119 @@
1
+ # 第三方来源与许可
2
+
3
+ ## 本项目许可
4
+
5
+ **Apache License 2.0**,全文见 `LICENSE`。
6
+ Copyright 2026 euthyna contributors。
7
+
8
+ ## 本仓库**不分发**任何第三方文件
9
+
10
+ 这是有意设计的,不是遗漏。
11
+
12
+ 本项目的调研需要反复阅读上游原文。但把上游原文**拷进仓库**会带来两个问题:
13
+ 它让本仓库的许可证变得含糊(上游中有一份是 CC-BY-SA-4.0),
14
+ 而且那份快照会悄悄与上游脱节。
15
+
16
+ 所以原文改为**按需拉取**:
17
+
18
+ ```powershell
19
+ node tools/fetch-references.js # 全部拉取
20
+ node tools/fetch-references.js --list # 只看清单,不下载
21
+ node tools/fetch-references.js competitors # 只拉某一份
22
+ ```
23
+
24
+ 文件落到 `.refs/`(已 gitignore),并在同目录生成 `PROVENANCE.txt` 记录来源、分支、许可与拉取时间。
25
+ **这些文件不属于本项目,也不受本项目许可覆盖。**
26
+
27
+ 已验证:拉取回来的 30 个文件与原先入库的副本**逐字节一致**(SHA-256 比对)。
28
+
29
+ ## 上游来源与致谢
30
+
31
+ 本项目的**方法论**主要借鉴以下两处公开工作。思想与方法不受版权保护,
32
+ 本项目据此**自行实现**(包括代码与技能文本),并按学术惯例署名。
33
+
34
+ ### Trail of Bits — `skills`
35
+
36
+ - 仓库:https://github.com/trailofbits/skills
37
+ - 许可:**CC-BY-SA-4.0**,Copyright Trail of Bits
38
+ - 借鉴内容:变更面安全审查(`differential-review`)、误报验证(`fp-check`,
39
+ 含 6 门禁、误报清单、恶魔代言人提问)、依赖供应链审计(`supply-chain-risk-auditor`)
40
+
41
+ 他们选择 CC-BY-SA 而不是「保留所有权利」,本身就是一份**允许他人复用**的邀请。
42
+ 本项目感谢这份公开工作,并**不把他们的文本重新授权**。
43
+
44
+ ### dsh-skill-pack-security
45
+
46
+ - 仓库:https://github.com/PerryLink/dsh-skill-pack-security
47
+ - 许可:**Apache-2.0**,dsh-skill-pack-security contributors
48
+ - 借鉴内容:竞品能力边界分析;技能包型插件的 provider 骨架结构
49
+
50
+ ## 上游原文**没有被改写进本仓库**
51
+
52
+ 本仓库中的方法论与技能文本是**自行撰写的表述**,不是上游文档的翻译或逐句改写。
53
+ 判断依据见下节。
54
+
55
+ ### 为什么这一点需要单独说明
56
+
57
+ CC BY-SA 4.0 对 `Adapted Material` 的定义**明确包含 "translated"**
58
+ (CC 官方 legalcode 原文):
59
+
60
+ > …material … derived from or based upon the Licensed Material and in which the
61
+ > Licensed Material is **translated**, altered, arranged, transformed, or otherwise modified…
62
+
63
+ 也就是说:**翻译或逐句改写会构成改编物**,而 ShareAlike(§3(b))要求改编物以相同许可分发。
64
+ 本项目希望整体采用 Apache-2.0,因此**不能**包含对上游文本的改编。
65
+
66
+ 同行的两种做法都印证了这条边界:
67
+
68
+ - `solanabr/auditor-skill`(MIT)在 `ATTRIBUTION.md` 中写明:上游以 git submodule 方式引用,
69
+ 「**A submodule is a reference (gitlink), not a copy, so no CC-BY-SA ShareAlike obligation
70
+ attaches**」,方法论则「**re-implemented natively, in our own words (not copied)**」
71
+ - `dsh-skill-pack-security`(Apache-2.0)在 `THIRD_PARTY_NOTICES.md` 中声明技能与引擎
72
+ **全部为原创**,未移植第三方代码
73
+
74
+ ### ✅ 已解决:仓库内不含任何改编物
75
+
76
+ 早期有一份 `docs/methodology-zh.md` 是按「逐条对照改写」写的,属于上述改编物候选。
77
+ 它**已从仓库移除**。其中的内容改为**用自己的结构重新撰写**,落在技能里:
78
+
79
+ ```
80
+ .agents/skills/euthyna/references/
81
+ ├── meta-mechanisms.md 让流程不退化成走过场的机制
82
+ ├── change-audit.md 变更面审计
83
+ ├── dependency-audit.md 依赖面审计
84
+ ├── bug-classes.md 缺陷类别与默认假设方向
85
+ ├── verification-gates.md 结论面验证
86
+ ├── fact-producers.md 两个确定性测量的操作手册
87
+ └── fact-contract.md 事实的读法
88
+ ```
89
+
90
+ 这些文件是**原创表述**,不是上游文档的翻译。**本仓库现在整体适用 Apache-2.0,无例外。**
91
+
92
+ ### 边界在哪
93
+
94
+ 判据不是「有没有改代码」,而是**「你的文字是不是从人家的文字长出来的」**:
95
+
96
+ | 做了什么 | 是否需要相同许可 |
97
+ |---|---|
98
+ | 读它、理解方法、**用自己的结构重新表述** | ❌ 不需要 |
99
+ | **翻译它**,或照着它的段落逐句改写 | ✅ 需要 |
100
+ | 把原文件拷进仓库 | ✅ 需要 |
101
+
102
+ 上表第二行是本项目早期踩到的点——**它和「改代码」无关**。
103
+
104
+ ## DSH 插件目录快照
105
+
106
+ `data/dsh-plugins.json` 是公开插件目录 https://awesome-dsh-plugin.com/plugins.json 的快照
107
+ (`updated` 字段:2026-09-18,共 3931 条),仅用于生态调研。
108
+ 其中各插件的名称、描述与链接归各自作者所有。
109
+
110
+ ## DeepSeek Harness
111
+
112
+ 本仓库中关于宿主能力的描述(技能 frontmatter 契约、hook 协议、技能发现路径等)
113
+ 来自对本机安装的 DeepSeek Harness 源码的阅读与**运行验证**,属于对软件行为的**事实性描述**,
114
+ 不复制其代码。
115
+
116
+ `tools/check-stop-gate.mjs` 会 `import` 本机 DSH 安装中的两个包
117
+ (`dsh-hook-protocol`、`dsh-hooks-claude-code`)以验证协议行为——它**引用**而非**分发**这些包。
118
+
119
+ DeepSeek Harness 及其相关包归其各自权利人所有。本项目与 DeepSeek 官方无隶属关系。
package/README.md ADDED
@@ -0,0 +1,246 @@
1
+ <p align="center">
2
+ <img src="assets/euthyna.png" width="150" alt="euthyna logo">
3
+ </p>
4
+
5
+ <h1 align="center">euthyna</h1>
6
+
7
+ > **εὔθυνα** — in classical Athens, the audit every outgoing official had to submit.
8
+ > You did not get to simply walk away from office. You handed over your accounts and they
9
+ > were examined. Pass, and you left with your standing intact. Fail, and you faced trial.
10
+
11
+ <p align="center">
12
+ <a href="https://github.com/slow-stack/euthyna/actions/workflows/ci.yml"><img src="https://github.com/slow-stack/euthyna/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
13
+ </p>
14
+
15
+ **euthyna is a code security audit framework for AI coding agents.** It is not another
16
+ scanner. It does two things: it **produces the facts an agent cannot compute by reading
17
+ code**, and it **forces every security claim the agent makes through gates before it
18
+ counts as a finding**.
19
+
20
+ ---
21
+
22
+ ## 📖 The problem, in plain words
23
+
24
+ When an AI coding agent touches security, it fails in two specific ways:
25
+
26
+ 1. **It reports things that are not real.** Code that *looks* dangerous gets called a
27
+ vulnerability, without tracing the data. In validation runs on real codebases — a
28
+ JavaScript one and a Python one — the pattern-matched "vulnerabilities" were mostly
29
+ false: **5 out of 5** refuted at the gates on the first run; **2 out of 3** refuted,
30
+ the third unresolved (INCONCLUSIVE, supply-chain-dependent) on the second. See the
31
+ [case studies](https://github.com/slow-stack/euthyna/blob/main/docs/case-study-crewai.md)
32
+ ([Python/crewAI](https://github.com/slow-stack/euthyna/blob/main/docs/case-study-crewai.md),
33
+ [JavaScript/axe-core](https://github.com/slow-stack/euthyna/blob/main/docs/case-study-axe-core.md)).
34
+ 2. **Its reassurances cannot be checked.** "I'm done." "The tests cover this." "It's
35
+ safe now." These are assertions. You cannot tell a done-claim from a done-deal.
36
+
37
+ Neither is fixed by telling the agent to be more careful. euthyna changes the handshake
38
+ between you and the agent:
39
+
40
+ > **The agent saying "I'm done" does not count. The accounts get handed over, and the
41
+ > gates decide.**
42
+
43
+ ---
44
+
45
+ ## ⚖️ The two things it does
46
+
47
+ ### 1. It measures what a model cannot
48
+
49
+ Two fact producers — a zero-dependency Node CLI:
50
+
51
+ - **`history`** — for every line a change deletes, it finds the commit that introduced
52
+ that line and classifies that commit from its own message. If the deleted code came
53
+ from a security fix, that is flagged. This is git archaeology no model can do from
54
+ reading a diff.
55
+ - **`coverage`** — was this symbol *ever actually invoked* by a test? It has exactly two
56
+ answers: never invoked (established), or entered but that proves nothing about any
57
+ specific call site (unknown). **It never reports "executed"** — V8 coverage marks
58
+ unreachable code as covered, and "line covered → call ran" is wrong in exactly the
59
+ direction an audit cannot afford. The reasoning is in
60
+ [`docs/fact-contract.md`](https://github.com/slow-stack/euthyna/blob/main/docs/fact-contract.md) §6.2.
61
+
62
+ ### 2. It gates what the agent claims
63
+
64
+ The [skill](https://github.com/slow-stack/euthyna/tree/main/.agents/skills/euthyna/) is the audit discipline itself, as loadable
65
+ Markdown. Every security claim must pass six gates — reachability, trust boundary, real
66
+ impact, and their counterparts. A claim that cannot produce evidence is **downgraded to
67
+ an observation**, not reported as a finding. "I'm done" becomes a package: claims,
68
+ evidence, and the commands that reproduce both.
69
+
70
+ ---
71
+
72
+ ## 🖥️ Which tools it works in, and how to install
73
+
74
+ **Prerequisite for everything**: Node >= 20 and git. There is nothing else to install —
75
+ the project is deliberately zero-dependency.
76
+
77
+ | Host | The skill (audit discipline) | The CLI (fact producers) |
78
+ |---|---|---|
79
+ | **DSH** | Copy `.agents/skills/euthyna/` into `~/.agents/skills/` (user-wide) or `<project>/.agents/skills/`. Markdown hot-reloads; no restart needed. | `npm install -g euthyna` — runs in any terminal |
80
+ | **Claude Code** | Copy the same folder into `~/.claude/skills/` | Same |
81
+ | **Codex** | The same Markdown layer works; packaging goes through Codex's plugin/marketplace format | Same |
82
+ | **Any terminal** | — | `npm install -g euthyna`, then `euthyna …` |
83
+
84
+ Two honest notes:
85
+
86
+ - **The skill is the instructions; the CLI is the measurement.** The skill directory
87
+ does **not** contain the CLI. Install the CLI from npm (`npm install -g euthyna`) or
88
+ keep this repository checked out; on a host without the CLI, the skill requires the
89
+ unmeasurable criteria to be recorded as *not evaluated* rather than guessed at — that
90
+ fallback is the design, not a gap.
91
+ - **The skill text and the CLI's reports are currently written in Chinese.** The
92
+ discipline is host-agnostic Markdown, but an English reader should expect Chinese
93
+ output from the tool itself.
94
+
95
+ ---
96
+
97
+ ## 🚀 Quick start
98
+
99
+ ```sh
100
+ npm install -g euthyna
101
+ euthyna history --repo <path> --base main --head HEAD
102
+ euthyna coverage --coverage coverage/coverage-final.json --symbol <name>
103
+ ```
104
+
105
+ Or without a global install: `npx euthyna history --repo <path> --base main`.
106
+
107
+ From a checkout instead (development):
108
+
109
+ ```sh
110
+ git clone https://github.com/slow-stack/euthyna
111
+ cd euthyna && npm test # 92 tests; no install step exists
112
+ node bin/euthyna.js history --repo <path> --base main --head HEAD
113
+ ```
114
+
115
+ What `history` reports looks like this:
116
+
117
+ ```
118
+ 已确证 (7)
119
+ • 本次变更删除了 4 行来自提交 ab877f9d70 的代码,分布在 2 个文件。
120
+ 提交信息:"fix(link-in-text-block): don't match style or script text (#3775)",分类:fix
121
+ 证据: lib/checks/color/link-in-text-block-evaluate.js (ab877f9d70)
122
+ 复现: git blame --porcelain -L 104,104 -L 114,114 <base> -- lib/checks/.../evaluate.js
123
+ ```
124
+
125
+ Every deleted line is blamed back to the commit that introduced it, and the `复现`
126
+ (Reproduce) command lets you re-derive the claim yourself without trusting the report.
127
+ Add `--json` for the structured fact report, and `--pickaxe` to detect lines that were
128
+ removed and are now being added back.
129
+
130
+ ### Exit codes are part of the contract
131
+
132
+ Surveying eight measurement plugins in this ecosystem found **none of them publishes a
133
+ process exit code**, which makes their output unusable as a CI gate. This one does:
134
+
135
+ | Code | Meaning |
136
+ |---|---|
137
+ | `0` | Measured; nothing security-classified found |
138
+ | `10` | Measured; at least one `security`-classified fact exists |
139
+ | `1` | Usage error |
140
+ | `2` | **Could not measure at all** — must not be read as clean |
141
+
142
+ `2` being distinct from `0` is the whole point: *failing to measure* and *measuring and
143
+ finding nothing* are different things.
144
+
145
+ ---
146
+
147
+ ## 🧱 What is actually built
148
+
149
+ | Piece | What it is | Status |
150
+ |---|---|---|
151
+ | **Fact producers** | A zero-dependency Node CLI that answers two questions deterministically | Working, tested |
152
+ | **The skill** | The audit discipline itself, as loadable Markdown | Working, loadable |
153
+ | **The benchmark** | A blind recall measurement for the adjudication layer | Four rounds complete |
154
+
155
+ ---
156
+
157
+ ## ✅ What has been verified, and what has not
158
+
159
+ This project tries to be explicit about the difference. Current state:
160
+
161
+ ### Verified
162
+
163
+ - **`history` attribution against real repositories — in two languages.** Run against
164
+ [axe-core](https://github.com/dequelabs/axe-core) (JavaScript) and
165
+ [crewAI](https://github.com/crewAIInc/crewAI) (Python); deleted lines attributed to the
166
+ commits that introduced them, then checked **by hand** against `git blame`. The checks
167
+ developed for that comparison now run as regression tests in the suite.
168
+ - **`coverage` on real output in two formats** — c8/V8 JSON and coverage.py JSON (format 3) —
169
+ distinguishing all three states correctly.
170
+ - **Adjudication recall and specificity**, measured blind: **10/10 cases**, 4 real
171
+ vulnerabilities all caught, 6 non-vulnerabilities all correctly cleared, no abstentions.
172
+ Round 2 repeated every case three times — **30 adjudications, zero flips**, four of them
173
+ on a different model. Round 3 expanded the set to **18 cases** (8 real, 10 not) and
174
+ reshuffled the blind ids every round: **54 adjudications**, 24/24 real-bug claims caught
175
+ with no misses and no abstentions, 29/30 non-vulnerabilities correctly cleared — and the
176
+ single "false alarm" was the round's finding, not noise: the adjudicator caught a defect
177
+ in a fixture's guard, confirmed by reproduction and fixed. Every case is a *near-neighbour
178
+ pair* — same pattern, one guard apart — so the verdicts had to come from reading the guard
179
+ rather than recognising the shape. Round 4 re-ran the full set under fresh id shuffles, with
180
+ the twice-defeated guard — rebuilt as a bare-name allow-list — facing its first blind
181
+ adjudication: **54/54 correct**, all 8 pairs separated, and a third run on a second model
182
+ family agreed with the first two on every case.
183
+ See [`bench/RESULTS.md`](https://github.com/slow-stack/euthyna/blob/main/bench/RESULTS.md),
184
+ [`bench/RESULTS-round2.md`](https://github.com/slow-stack/euthyna/blob/main/bench/RESULTS-round2.md),
185
+ [`bench/RESULTS-round3.md`](https://github.com/slow-stack/euthyna/blob/main/bench/RESULTS-round3.md),
186
+ and [`bench/RESULTS-round4.md`](https://github.com/slow-stack/euthyna/blob/main/bench/RESULTS-round4.md).
187
+ - **The delivery-gate mechanism**, by running the real host plugin: blocking works, and the two
188
+ documented ways of getting it wrong do not. See [`docs/dsh-stop-gate.md`](https://github.com/slow-stack/euthyna/blob/main/docs/dsh-stop-gate.md).
189
+
190
+ ### Not verified
191
+
192
+ - **Whether the method finds vulnerabilities in real code.** The benchmark measures whether the
193
+ discipline reaches the right verdict *on a claim*. It does not measure whether the claims would
194
+ be found in the first place. The cases are deliberately constructed. The crewAI case study
195
+ surfaced one INCONCLUSIVE (pickle deserialization, supply-chain-dependent) and refuted the
196
+ rest — a directional signal, not a rate.
197
+ - **Recall in the field.** The benchmark's real-bug cases are constructed; whether the
198
+ discipline helps on code nobody staged for it is unmeasured.
199
+ - **Source maps, bundlers, monorepos** for the coverage producer. Untested.
200
+ - **Anything about the case-study targets' security** — the runs found nothing to endorse or
201
+ condemn; that is not a statement about either project. See
202
+ [`docs/case-study-crewai.md`](https://github.com/slow-stack/euthyna/blob/main/docs/case-study-crewai.md) and
203
+ [`docs/case-study-axe-core.md`](https://github.com/slow-stack/euthyna/blob/main/docs/case-study-axe-core.md).
204
+
205
+ ---
206
+
207
+ ## 📂 Repository layout
208
+
209
+ ```
210
+ euthyna/
211
+ ├── bin/ src/ test/ Fact producers (zero dependencies, Node >= 20)
212
+ ├── .agents/skills/euthyna/ The audit discipline, as a portable skill
213
+ ├── bench/ Blind recall benchmark + results
214
+ ├── docs/ Design notes and case studies (English and Chinese)
215
+ ├── tools/ Research and verification scripts
216
+ └── data/ DSH plugin catalog snapshot
217
+ ```
218
+
219
+ `tools/fetch-references.js` downloads the upstream sources this project reads into `.refs/`
220
+ (gitignored). **No third-party files are distributed in this repository** — see
221
+ [`NOTICE.md`](NOTICE.md) for why, and for what is owed to whom.
222
+
223
+ ---
224
+
225
+ ## 🧭 Status
226
+
227
+ Early, and honest about it. Working: the two fact producers, the skill, the benchmark harness.
228
+ Not yet built: wiring the skill to the CLI so an agent uses them without being told, and the
229
+ git-history / coverage work needed to close the remaining recall gap.
230
+
231
+ The design notes are available in English and Chinese; the `-zh` files are the originals.
232
+
233
+ ## 🤝 Contributing
234
+
235
+ Read [`CONTRIBUTING.md`](CONTRIBUTING.md). The short version: no AI attribution in commits,
236
+ one change per commit, and do not claim something works until you have run it.
237
+
238
+ ## 🔒 Security
239
+
240
+ The fact producers execute `git` and parse coverage output; their integrity is the product.
241
+ What is in scope, and how to report privately: [`SECURITY.md`](SECURITY.md). Note that the
242
+ benchmark fixtures in `bench/cases/` are vulnerable by construction and are not vulnerabilities.
243
+
244
+ ## 📜 License
245
+
246
+ **Apache License 2.0** — see [`LICENSE`](LICENSE).
Binary file
package/bin/euthyna.js ADDED
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * euthyna CLI entry point.
4
+ *
5
+ * Kept trivial on purpose: argument handling and exit codes live in src/cli.js
6
+ * so they can be exercised by tests without spawning a process.
7
+ */
8
+ import process from 'node:process';
9
+ import { main } from '../src/cli.js';
10
+ import { safeTextLines } from '../src/contract.js';
11
+
12
+ try {
13
+ process.exitCode = await main(process.argv.slice(2));
14
+ } catch (error) {
15
+ // An unexpected throw is a measurement failure, not a clean result. Saying so
16
+ // is the whole point of having a distinct exit code for it.
17
+ //
18
+ // stderr boundary: an error message inherits repo-controlled text (git embeds
19
+ // filenames and refs in its stderr), so the stack is made terminal-safe at
20
+ // this write, exactly once, like the report channel at its render boundary.
21
+ process.stderr.write(
22
+ safeTextLines(`euthyna: 测量过程抛出异常,结果不可用\n${error?.stack ?? error}\n`)
23
+ );
24
+ process.exitCode = 2;
25
+ }
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "euthyna",
3
+ "version": "0.1.0",
4
+ "description": "Deterministic fact producers for security auditing: which deleted code came from a security fix, and which changed symbols no test ever executed.",
5
+ "type": "module",
6
+ "bin": {
7
+ "euthyna": "./bin/euthyna.js"
8
+ },
9
+ "files": [
10
+ "bin/",
11
+ "src/",
12
+ "assets/euthyna.png",
13
+ "NOTICE.md"
14
+ ],
15
+ "engines": {
16
+ "node": ">=20"
17
+ },
18
+ "scripts": {
19
+ "test": "node --test",
20
+ "check:license": "node tools/check-license-text.mjs"
21
+ },
22
+ "keywords": [
23
+ "security-audit",
24
+ "git",
25
+ "code-review",
26
+ "coverage",
27
+ "ai-agents",
28
+ "ai-coding-agents"
29
+ ],
30
+ "author": "modusensus",
31
+ "license": "Apache-2.0",
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "git+https://github.com/slow-stack/euthyna.git"
35
+ },
36
+ "bugs": {
37
+ "url": "https://github.com/slow-stack/euthyna/issues"
38
+ },
39
+ "homepage": "https://github.com/slow-stack/euthyna#readme"
40
+ }