codeharness 0.22.2 → 0.24.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/dist/index.js +1799 -1968
- package/package.json +3 -1
- package/patches/dev/enforcement.md +10 -0
- package/patches/infra/dockerfile-rules.md +62 -0
- package/patches/observability/AGENTS.md +20 -0
- package/patches/observability/rust-catch-without-tracing.rs +65 -0
- package/patches/observability/rust-catch-without-tracing.yaml +19 -0
- package/patches/observability/rust-error-path-no-tracing.rs +79 -0
- package/patches/observability/rust-error-path-no-tracing.yaml +62 -0
- package/patches/observability/rust-function-no-tracing.rs +119 -0
- package/patches/observability/rust-function-no-tracing.yaml +282 -0
- package/patches/review/enforcement.md +9 -0
- package/patches/verify/story-verification.md +23 -0
- package/templates/Dockerfile.verify.generic +27 -0
- package/templates/Dockerfile.verify.rust +39 -0
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
rules:
|
|
2
|
+
- id: rust-function-no-tracing
|
|
3
|
+
patterns:
|
|
4
|
+
- pattern-either:
|
|
5
|
+
- pattern: |
|
|
6
|
+
fn $FUNC(...) { ... }
|
|
7
|
+
- pattern: |
|
|
8
|
+
pub fn $FUNC(...) { ... }
|
|
9
|
+
- pattern: |
|
|
10
|
+
async fn $FUNC(...) { ... }
|
|
11
|
+
- pattern: |
|
|
12
|
+
pub async fn $FUNC(...) { ... }
|
|
13
|
+
- pattern-not: |
|
|
14
|
+
#[tracing::instrument]
|
|
15
|
+
fn $FUNC(...) { ... }
|
|
16
|
+
- pattern-not: |
|
|
17
|
+
#[tracing::instrument]
|
|
18
|
+
pub fn $FUNC(...) { ... }
|
|
19
|
+
- pattern-not: |
|
|
20
|
+
#[tracing::instrument]
|
|
21
|
+
async fn $FUNC(...) { ... }
|
|
22
|
+
- pattern-not: |
|
|
23
|
+
#[tracing::instrument]
|
|
24
|
+
pub async fn $FUNC(...) { ... }
|
|
25
|
+
- pattern-not: |
|
|
26
|
+
#[instrument]
|
|
27
|
+
fn $FUNC(...) { ... }
|
|
28
|
+
- pattern-not: |
|
|
29
|
+
#[instrument]
|
|
30
|
+
pub fn $FUNC(...) { ... }
|
|
31
|
+
- pattern-not: |
|
|
32
|
+
#[instrument]
|
|
33
|
+
async fn $FUNC(...) { ... }
|
|
34
|
+
- pattern-not: |
|
|
35
|
+
#[instrument]
|
|
36
|
+
pub async fn $FUNC(...) { ... }
|
|
37
|
+
- pattern-not: |
|
|
38
|
+
fn $FUNC(...) {
|
|
39
|
+
...
|
|
40
|
+
tracing::debug!(...);
|
|
41
|
+
...
|
|
42
|
+
}
|
|
43
|
+
- pattern-not: |
|
|
44
|
+
fn $FUNC(...) {
|
|
45
|
+
...
|
|
46
|
+
tracing::info!(...);
|
|
47
|
+
...
|
|
48
|
+
}
|
|
49
|
+
- pattern-not: |
|
|
50
|
+
fn $FUNC(...) {
|
|
51
|
+
...
|
|
52
|
+
tracing::warn!(...);
|
|
53
|
+
...
|
|
54
|
+
}
|
|
55
|
+
- pattern-not: |
|
|
56
|
+
fn $FUNC(...) {
|
|
57
|
+
...
|
|
58
|
+
tracing::error!(...);
|
|
59
|
+
...
|
|
60
|
+
}
|
|
61
|
+
- pattern-not: |
|
|
62
|
+
fn $FUNC(...) {
|
|
63
|
+
...
|
|
64
|
+
tracing::trace!(...);
|
|
65
|
+
...
|
|
66
|
+
}
|
|
67
|
+
- pattern-not: |
|
|
68
|
+
fn $FUNC(...) {
|
|
69
|
+
...
|
|
70
|
+
debug!(...);
|
|
71
|
+
...
|
|
72
|
+
}
|
|
73
|
+
- pattern-not: |
|
|
74
|
+
fn $FUNC(...) {
|
|
75
|
+
...
|
|
76
|
+
info!(...);
|
|
77
|
+
...
|
|
78
|
+
}
|
|
79
|
+
- pattern-not: |
|
|
80
|
+
fn $FUNC(...) {
|
|
81
|
+
...
|
|
82
|
+
warn!(...);
|
|
83
|
+
...
|
|
84
|
+
}
|
|
85
|
+
- pattern-not: |
|
|
86
|
+
fn $FUNC(...) {
|
|
87
|
+
...
|
|
88
|
+
error!(...);
|
|
89
|
+
...
|
|
90
|
+
}
|
|
91
|
+
- pattern-not: |
|
|
92
|
+
fn $FUNC(...) {
|
|
93
|
+
...
|
|
94
|
+
trace!(...);
|
|
95
|
+
...
|
|
96
|
+
}
|
|
97
|
+
- pattern-not: |
|
|
98
|
+
pub fn $FUNC(...) {
|
|
99
|
+
...
|
|
100
|
+
tracing::debug!(...);
|
|
101
|
+
...
|
|
102
|
+
}
|
|
103
|
+
- pattern-not: |
|
|
104
|
+
pub fn $FUNC(...) {
|
|
105
|
+
...
|
|
106
|
+
tracing::info!(...);
|
|
107
|
+
...
|
|
108
|
+
}
|
|
109
|
+
- pattern-not: |
|
|
110
|
+
pub fn $FUNC(...) {
|
|
111
|
+
...
|
|
112
|
+
tracing::warn!(...);
|
|
113
|
+
...
|
|
114
|
+
}
|
|
115
|
+
- pattern-not: |
|
|
116
|
+
pub fn $FUNC(...) {
|
|
117
|
+
...
|
|
118
|
+
tracing::error!(...);
|
|
119
|
+
...
|
|
120
|
+
}
|
|
121
|
+
- pattern-not: |
|
|
122
|
+
pub fn $FUNC(...) {
|
|
123
|
+
...
|
|
124
|
+
tracing::trace!(...);
|
|
125
|
+
...
|
|
126
|
+
}
|
|
127
|
+
- pattern-not: |
|
|
128
|
+
pub fn $FUNC(...) {
|
|
129
|
+
...
|
|
130
|
+
debug!(...);
|
|
131
|
+
...
|
|
132
|
+
}
|
|
133
|
+
- pattern-not: |
|
|
134
|
+
pub fn $FUNC(...) {
|
|
135
|
+
...
|
|
136
|
+
info!(...);
|
|
137
|
+
...
|
|
138
|
+
}
|
|
139
|
+
- pattern-not: |
|
|
140
|
+
pub fn $FUNC(...) {
|
|
141
|
+
...
|
|
142
|
+
warn!(...);
|
|
143
|
+
...
|
|
144
|
+
}
|
|
145
|
+
- pattern-not: |
|
|
146
|
+
pub fn $FUNC(...) {
|
|
147
|
+
...
|
|
148
|
+
error!(...);
|
|
149
|
+
...
|
|
150
|
+
}
|
|
151
|
+
- pattern-not: |
|
|
152
|
+
pub fn $FUNC(...) {
|
|
153
|
+
...
|
|
154
|
+
trace!(...);
|
|
155
|
+
...
|
|
156
|
+
}
|
|
157
|
+
- pattern-not: |
|
|
158
|
+
async fn $FUNC(...) {
|
|
159
|
+
...
|
|
160
|
+
tracing::debug!(...);
|
|
161
|
+
...
|
|
162
|
+
}
|
|
163
|
+
- pattern-not: |
|
|
164
|
+
async fn $FUNC(...) {
|
|
165
|
+
...
|
|
166
|
+
tracing::info!(...);
|
|
167
|
+
...
|
|
168
|
+
}
|
|
169
|
+
- pattern-not: |
|
|
170
|
+
async fn $FUNC(...) {
|
|
171
|
+
...
|
|
172
|
+
tracing::warn!(...);
|
|
173
|
+
...
|
|
174
|
+
}
|
|
175
|
+
- pattern-not: |
|
|
176
|
+
async fn $FUNC(...) {
|
|
177
|
+
...
|
|
178
|
+
tracing::error!(...);
|
|
179
|
+
...
|
|
180
|
+
}
|
|
181
|
+
- pattern-not: |
|
|
182
|
+
async fn $FUNC(...) {
|
|
183
|
+
...
|
|
184
|
+
tracing::trace!(...);
|
|
185
|
+
...
|
|
186
|
+
}
|
|
187
|
+
- pattern-not: |
|
|
188
|
+
async fn $FUNC(...) {
|
|
189
|
+
...
|
|
190
|
+
debug!(...);
|
|
191
|
+
...
|
|
192
|
+
}
|
|
193
|
+
- pattern-not: |
|
|
194
|
+
async fn $FUNC(...) {
|
|
195
|
+
...
|
|
196
|
+
info!(...);
|
|
197
|
+
...
|
|
198
|
+
}
|
|
199
|
+
- pattern-not: |
|
|
200
|
+
async fn $FUNC(...) {
|
|
201
|
+
...
|
|
202
|
+
warn!(...);
|
|
203
|
+
...
|
|
204
|
+
}
|
|
205
|
+
- pattern-not: |
|
|
206
|
+
async fn $FUNC(...) {
|
|
207
|
+
...
|
|
208
|
+
error!(...);
|
|
209
|
+
...
|
|
210
|
+
}
|
|
211
|
+
- pattern-not: |
|
|
212
|
+
async fn $FUNC(...) {
|
|
213
|
+
...
|
|
214
|
+
trace!(...);
|
|
215
|
+
...
|
|
216
|
+
}
|
|
217
|
+
- pattern-not: |
|
|
218
|
+
pub async fn $FUNC(...) {
|
|
219
|
+
...
|
|
220
|
+
tracing::debug!(...);
|
|
221
|
+
...
|
|
222
|
+
}
|
|
223
|
+
- pattern-not: |
|
|
224
|
+
pub async fn $FUNC(...) {
|
|
225
|
+
...
|
|
226
|
+
tracing::info!(...);
|
|
227
|
+
...
|
|
228
|
+
}
|
|
229
|
+
- pattern-not: |
|
|
230
|
+
pub async fn $FUNC(...) {
|
|
231
|
+
...
|
|
232
|
+
tracing::warn!(...);
|
|
233
|
+
...
|
|
234
|
+
}
|
|
235
|
+
- pattern-not: |
|
|
236
|
+
pub async fn $FUNC(...) {
|
|
237
|
+
...
|
|
238
|
+
tracing::error!(...);
|
|
239
|
+
...
|
|
240
|
+
}
|
|
241
|
+
- pattern-not: |
|
|
242
|
+
pub async fn $FUNC(...) {
|
|
243
|
+
...
|
|
244
|
+
tracing::trace!(...);
|
|
245
|
+
...
|
|
246
|
+
}
|
|
247
|
+
- pattern-not: |
|
|
248
|
+
pub async fn $FUNC(...) {
|
|
249
|
+
...
|
|
250
|
+
debug!(...);
|
|
251
|
+
...
|
|
252
|
+
}
|
|
253
|
+
- pattern-not: |
|
|
254
|
+
pub async fn $FUNC(...) {
|
|
255
|
+
...
|
|
256
|
+
info!(...);
|
|
257
|
+
...
|
|
258
|
+
}
|
|
259
|
+
- pattern-not: |
|
|
260
|
+
pub async fn $FUNC(...) {
|
|
261
|
+
...
|
|
262
|
+
warn!(...);
|
|
263
|
+
...
|
|
264
|
+
}
|
|
265
|
+
- pattern-not: |
|
|
266
|
+
pub async fn $FUNC(...) {
|
|
267
|
+
...
|
|
268
|
+
error!(...);
|
|
269
|
+
...
|
|
270
|
+
}
|
|
271
|
+
- pattern-not: |
|
|
272
|
+
pub async fn $FUNC(...) {
|
|
273
|
+
...
|
|
274
|
+
trace!(...);
|
|
275
|
+
...
|
|
276
|
+
}
|
|
277
|
+
message: "Rust function without tracing instrumentation — observability gap"
|
|
278
|
+
languages: [rust]
|
|
279
|
+
severity: INFO
|
|
280
|
+
metadata:
|
|
281
|
+
category: observability
|
|
282
|
+
cwe: "CWE-778: Insufficient Logging"
|
|
@@ -25,6 +25,15 @@ The proof must pass black-box enforcement:
|
|
|
25
25
|
- `[FAIL]` verdicts outside code blocks cause the proof to fail
|
|
26
26
|
- `[ESCALATE]` is acceptable only when all automated approaches are exhausted
|
|
27
27
|
|
|
28
|
+
### Observability
|
|
29
|
+
|
|
30
|
+
Run `semgrep scan --config patches/observability/ --json` against changed files and report gaps.
|
|
31
|
+
|
|
32
|
+
- For each gap found, list it as a review issue: file path, line number, and description (e.g., "src/lib/docker.ts:42 — catch block without logging")
|
|
33
|
+
- Semgrep JSON output fields to extract: `check_id`, `path`, `start.line`, `extra.message`
|
|
34
|
+
- If zero observability gaps are found, this check passes silently — do not emit warnings
|
|
35
|
+
- If Semgrep is not installed, report "static analysis skipped — install semgrep" as a warning and do NOT fail the review
|
|
36
|
+
|
|
28
37
|
### Code Quality
|
|
29
38
|
|
|
30
39
|
- Coverage delta reported (before vs after)
|
|
@@ -27,6 +27,29 @@ For each AC, append a tag indicating verification approach:
|
|
|
27
27
|
|
|
28
28
|
**Do not over-tag.** Workflows, sprint planning, user sessions, slash commands, and agent behavior are all verifiable via `docker exec ... claude --print`. Only tag `integration-required` when there is genuinely no automated path.
|
|
29
29
|
|
|
30
|
+
### Observability Evidence
|
|
31
|
+
|
|
32
|
+
After each `docker exec` command, query the observability backend for log events from the last 30 seconds.
|
|
33
|
+
Use the configured VictoriaLogs endpoint (default: `http://localhost:9428`):
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
curl 'http://localhost:9428/select/logsql/query?query=_stream_id:*&start=-30s&limit=100'
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
- If log entries are returned, note the count in the AC section as runtime observability evidence.
|
|
40
|
+
- If **zero events** are returned, include `[OBSERVABILITY GAP]` in the AC section:
|
|
41
|
+
`[OBSERVABILITY GAP] No log events detected for this user interaction`
|
|
42
|
+
- Every AC should produce at least one log entry when exercised. Gaps indicate silent code paths.
|
|
43
|
+
- If the observability backend is **not reachable** (connection refused, timeout), report
|
|
44
|
+
"observability check skipped — backend not reachable" as a warning and do NOT fail the verification.
|
|
45
|
+
The functional verification result stands on its own.
|
|
46
|
+
|
|
47
|
+
This ensures proof documents include both functional evidence (`docker exec` output) and
|
|
48
|
+
observability evidence (log query results or `[OBSERVABILITY GAP]` tags) for each AC.
|
|
49
|
+
|
|
50
|
+
The VictoriaLogs query pattern matches `verify-prompt.ts` Step 3.5 — see that template for
|
|
51
|
+
the full observability check instructions used by the automated verifier agent.
|
|
52
|
+
|
|
30
53
|
### Testing Requirements
|
|
31
54
|
|
|
32
55
|
- Unit tests for all new/changed code
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Generic black-box verification environment
|
|
2
|
+
# Minimal image with basic tools for projects with unrecognized stacks.
|
|
3
|
+
# NO source code enters the image — only project metadata and basic utilities.
|
|
4
|
+
FROM node:20-slim
|
|
5
|
+
|
|
6
|
+
# System utilities for generic verification
|
|
7
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
8
|
+
bash \
|
|
9
|
+
curl \
|
|
10
|
+
jq \
|
|
11
|
+
git \
|
|
12
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
13
|
+
|
|
14
|
+
# Verification tools + Claude Code CLI
|
|
15
|
+
RUN npm install -g showboat @anthropic-ai/claude-code
|
|
16
|
+
|
|
17
|
+
# OTEL environment pointing to host observability stack
|
|
18
|
+
ENV OTEL_EXPORTER_OTLP_ENDPOINT=http://host.docker.internal:4318
|
|
19
|
+
ENV OTEL_SERVICE_NAME=codeharness-verify
|
|
20
|
+
ENV OTEL_TRACES_EXPORTER=otlp
|
|
21
|
+
ENV OTEL_METRICS_EXPORTER=otlp
|
|
22
|
+
ENV OTEL_LOGS_EXPORTER=otlp
|
|
23
|
+
|
|
24
|
+
WORKDIR /workspace
|
|
25
|
+
|
|
26
|
+
# Copy any build context files into the workspace
|
|
27
|
+
COPY . /workspace/
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Rust black-box verification environment
|
|
2
|
+
# Provides Rust tooling, Semgrep, showboat, and cargo-tarpaulin for automated verification.
|
|
3
|
+
# NO project source enters the image — the project is mounted at runtime.
|
|
4
|
+
FROM rust:1.82-slim
|
|
5
|
+
|
|
6
|
+
# System utilities + Python for Semgrep
|
|
7
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
8
|
+
python3 \
|
|
9
|
+
python3-pip \
|
|
10
|
+
python3-venv \
|
|
11
|
+
pipx \
|
|
12
|
+
curl \
|
|
13
|
+
jq \
|
|
14
|
+
git \
|
|
15
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
16
|
+
|
|
17
|
+
# Semgrep for static analysis verification
|
|
18
|
+
RUN pipx install semgrep && pipx ensurepath
|
|
19
|
+
ENV PATH="/root/.local/bin:${PATH}"
|
|
20
|
+
|
|
21
|
+
# Node.js 20 LTS (needed for showboat and claude-code npm packages)
|
|
22
|
+
RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && \
|
|
23
|
+
apt-get install -y nodejs && \
|
|
24
|
+
rm -rf /var/lib/apt/lists/*
|
|
25
|
+
|
|
26
|
+
# Verification tools + Claude Code CLI
|
|
27
|
+
RUN npm install -g showboat @anthropic-ai/claude-code
|
|
28
|
+
|
|
29
|
+
# Rust coverage tool
|
|
30
|
+
RUN cargo install cargo-tarpaulin
|
|
31
|
+
|
|
32
|
+
# OTEL environment pointing to host observability stack
|
|
33
|
+
ENV OTEL_EXPORTER_OTLP_ENDPOINT=http://host.docker.internal:4318
|
|
34
|
+
ENV OTEL_SERVICE_NAME=codeharness-verify
|
|
35
|
+
ENV OTEL_TRACES_EXPORTER=otlp
|
|
36
|
+
ENV OTEL_METRICS_EXPORTER=otlp
|
|
37
|
+
ENV OTEL_LOGS_EXPORTER=otlp
|
|
38
|
+
|
|
39
|
+
WORKDIR /workspace
|