clinescope 1.0.1__tar.gz
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.
- clinescope-1.0.1/.gitattributes +12 -0
- clinescope-1.0.1/.github/ISSUE_TEMPLATE/bug_report.yml +63 -0
- clinescope-1.0.1/.github/ISSUE_TEMPLATE/scorer_request.yml +48 -0
- clinescope-1.0.1/.github/PULL_REQUEST_TEMPLATE.md +19 -0
- clinescope-1.0.1/.github/SECURITY.md +24 -0
- clinescope-1.0.1/.github/dependabot.yml +9 -0
- clinescope-1.0.1/.github/workflows/ci.yml +37 -0
- clinescope-1.0.1/.github/workflows/release.yml +52 -0
- clinescope-1.0.1/.gitignore +40 -0
- clinescope-1.0.1/CLAUDE.md +82 -0
- clinescope-1.0.1/CODE_OF_CONDUCT.md +128 -0
- clinescope-1.0.1/CONTRIBUTING.md +100 -0
- clinescope-1.0.1/LICENSE +201 -0
- clinescope-1.0.1/PKG-INFO +150 -0
- clinescope-1.0.1/README.md +124 -0
- clinescope-1.0.1/docs/demo.png +0 -0
- clinescope-1.0.1/examples/apply-patch-trace.json +62 -0
- clinescope-1.0.1/examples/apply-recovery-trace.json +97 -0
- clinescope-1.0.1/examples/corpus/README.md +66 -0
- clinescope-1.0.1/examples/corpus/corpus.json +98 -0
- clinescope-1.0.1/examples/corpus/live-gpt-oss-add-file.json +187 -0
- clinescope-1.0.1/examples/corpus/live-gpt-oss-apply-fail.json +135 -0
- clinescope-1.0.1/examples/corpus/live-gpt-oss-trace.json +137 -0
- clinescope-1.0.1/examples/corpus/live-gpt-oss-update-2hunk.json +135 -0
- clinescope-1.0.1/examples/corpus/llama-code-dump.json +41 -0
- clinescope-1.0.1/examples/corpus/qwen-missing-tools.json +41 -0
- clinescope-1.0.1/examples/gate-regression-badpatch.json +35 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-01-py-retype-timeout-pair.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-02-js-retype-header-pair.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-03-go-retype-struct-fields.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-04-yaml-retype-resource-limits.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-05-py-settings-interleaved-retype.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-06-go-handler-interleaved-fields.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-07-yaml-ci-interleaved-steps.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-08-fix-timeout-constant.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-09-add-py-typed-marker.json +39 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-10-rename-util-module.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-11-add-nil-guard.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-12-bump-replicas-two-line.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-13-blind-retype-normalize-fn.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-14-blind-retype-js-retry-config.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-15-blind-retype-go-limits-mixed.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-16-blind-retype-yaml-ci-matrix.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-17-retype-normalize-body.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-18-retype-retry-config.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-19-retype-parse-args-go.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-20-retype-reducer-js.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-21-python-http-timeout-default.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-22-go-server-const-poolsize.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-23-yaml-deploy-image-tag.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-24-js-retry-max-attempts.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-25-py-retype-two-thresholds.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-26-ts-retype-two-flags.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-27-py-interleaved-defaults.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-28-go-interleaved-consts.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-29-fix-single-return.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-30-add-one-import.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-31-bump-single-version.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-32-add-newline-eof.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-33-py-timeout-in-big-block.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-34-yaml-image-in-pod.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-35-go-one-field-in-struct.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-36-js-one-option-in-object.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-37-py-split-compute.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-38-go-split-parse.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-39-js-split-reducer.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-40-py-split-validate.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-41-blind-retype-py-config-block.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-42-blind-retype-go-struct-literal.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-43-blind-retype-yaml-service.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-44-blind-retype-js-handlers.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-45-py-retype-pair-limits.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-46-go-interleaved-two.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-47-context-drag-py-single.json +63 -0
- clinescope-1.0.1/examples/gold/dm-hardcase-48-tight-add-guard-js.json +63 -0
- clinescope-1.0.1/examples/live-gpt-oss-add-file.json +187 -0
- clinescope-1.0.1/examples/live-gpt-oss-apply-fail.json +135 -0
- clinescope-1.0.1/examples/live-gpt-oss-trace.json +137 -0
- clinescope-1.0.1/examples/live-gpt-oss-update-2hunk.json +135 -0
- clinescope-1.0.1/examples/multi-op-trace.json +65 -0
- clinescope-1.0.1/examples/sample-trace.json +59 -0
- clinescope-1.0.1/gold/README.md +149 -0
- clinescope-1.0.1/gold/diff_minimality.gold.jsonl +50 -0
- clinescope-1.0.1/gold/diff_minimality.judge.jsonl +50 -0
- clinescope-1.0.1/pyproject.toml +76 -0
- clinescope-1.0.1/scripts/gen_hardcases_25_48.py +313 -0
- clinescope-1.0.1/src/clinescope/__init__.py +9 -0
- clinescope-1.0.1/src/clinescope/__main__.py +152 -0
- clinescope-1.0.1/src/clinescope/_datafiles.py +111 -0
- clinescope-1.0.1/src/clinescope/advice.py +120 -0
- clinescope-1.0.1/src/clinescope/agreement.py +270 -0
- clinescope-1.0.1/src/clinescope/agreement_multi.py +207 -0
- clinescope-1.0.1/src/clinescope/apply_recovery.py +514 -0
- clinescope-1.0.1/src/clinescope/compare.py +365 -0
- clinescope-1.0.1/src/clinescope/corpus.py +497 -0
- clinescope-1.0.1/src/clinescope/diff_coherence.py +352 -0
- clinescope-1.0.1/src/clinescope/diff_minimality.py +323 -0
- clinescope-1.0.1/src/clinescope/gate.py +317 -0
- clinescope-1.0.1/src/clinescope/gold.py +341 -0
- clinescope-1.0.1/src/clinescope/judge.py +351 -0
- clinescope-1.0.1/src/clinescope/judge_multidraw.py +444 -0
- clinescope-1.0.1/src/clinescope/judge_run.py +631 -0
- clinescope-1.0.1/src/clinescope/label_gold.py +263 -0
- clinescope-1.0.1/src/clinescope/labels.py +271 -0
- clinescope-1.0.1/src/clinescope/report.py +433 -0
- clinescope-1.0.1/src/clinescope/tool_selection.py +91 -0
- clinescope-1.0.1/src/clinescope/tool_vocab.py +69 -0
- clinescope-1.0.1/src/clinescope/world_a.py +210 -0
- clinescope-1.0.1/tests/test_advice.py +255 -0
- clinescope-1.0.1/tests/test_agreement.py +289 -0
- clinescope-1.0.1/tests/test_agreement_multi.py +122 -0
- clinescope-1.0.1/tests/test_apply_recovery.py +767 -0
- clinescope-1.0.1/tests/test_compare.py +358 -0
- clinescope-1.0.1/tests/test_corpus.py +353 -0
- clinescope-1.0.1/tests/test_datafiles.py +101 -0
- clinescope-1.0.1/tests/test_diff_coherence.py +527 -0
- clinescope-1.0.1/tests/test_diff_minimality.py +432 -0
- clinescope-1.0.1/tests/test_expected_input_guards.py +217 -0
- clinescope-1.0.1/tests/test_fixture_drift.py +76 -0
- clinescope-1.0.1/tests/test_gate.py +307 -0
- clinescope-1.0.1/tests/test_gold.py +416 -0
- clinescope-1.0.1/tests/test_gold_hardcases.py +187 -0
- clinescope-1.0.1/tests/test_judge_live.py +78 -0
- clinescope-1.0.1/tests/test_judge_multidraw.py +184 -0
- clinescope-1.0.1/tests/test_judge_run.py +414 -0
- clinescope-1.0.1/tests/test_label_gold.py +410 -0
- clinescope-1.0.1/tests/test_labels.py +218 -0
- clinescope-1.0.1/tests/test_live_capture.py +164 -0
- clinescope-1.0.1/tests/test_live_captures_day11.py +223 -0
- clinescope-1.0.1/tests/test_loader.py +294 -0
- clinescope-1.0.1/tests/test_report.py +414 -0
- clinescope-1.0.1/tests/test_tool_selection.py +115 -0
- clinescope-1.0.1/tests/test_tool_vocab.py +55 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Normalize line endings to LF for text so the checked-out form is identical on
|
|
2
|
+
# every platform. The gold set + example traces are a versioned contract read by a
|
|
3
|
+
# byte-preserving label writer (src/clinescope/label_gold.py); a mixed CRLF/LF
|
|
4
|
+
# checkout would make that writer's "leave other lines byte-identical" guarantee
|
|
5
|
+
# platform-dependent. Pinning LF makes it hold on Windows and Linux/CI alike.
|
|
6
|
+
* text=auto eol=lf
|
|
7
|
+
|
|
8
|
+
# Explicit for the contract files (belt-and-suspenders; the wildcard already covers them).
|
|
9
|
+
*.jsonl text eol=lf
|
|
10
|
+
*.json text eol=lf
|
|
11
|
+
*.py text eol=lf
|
|
12
|
+
*.md text eol=lf
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
name: Bug report
|
|
2
|
+
description: A scorer, the CLI, or the trace loader misbehaves on a real trace.
|
|
3
|
+
title: "[bug]: "
|
|
4
|
+
labels: ["bug"]
|
|
5
|
+
body:
|
|
6
|
+
- type: markdown
|
|
7
|
+
attributes:
|
|
8
|
+
value: |
|
|
9
|
+
Thanks for the report. clinescope scores a Cline `messages.json` trace, so a bug is usually
|
|
10
|
+
reproducible from a trace + the command you ran. Please include both.
|
|
11
|
+
- type: textarea
|
|
12
|
+
id: what-happened
|
|
13
|
+
attributes:
|
|
14
|
+
label: What happened
|
|
15
|
+
description: What did clinescope do, and what did you expect instead?
|
|
16
|
+
placeholder: "e.g. diff_coherence scored 0.0 on a patch that applies cleanly in Cline."
|
|
17
|
+
validations:
|
|
18
|
+
required: true
|
|
19
|
+
- type: input
|
|
20
|
+
id: command
|
|
21
|
+
attributes:
|
|
22
|
+
label: Command you ran
|
|
23
|
+
placeholder: "clinescope path/to/messages.json --expected read_files apply_patch"
|
|
24
|
+
validations:
|
|
25
|
+
required: true
|
|
26
|
+
- type: dropdown
|
|
27
|
+
id: trace-source
|
|
28
|
+
attributes:
|
|
29
|
+
label: Trace source
|
|
30
|
+
description: Where did the trace come from?
|
|
31
|
+
options:
|
|
32
|
+
- A real Cline CLI run
|
|
33
|
+
- A real Cline VS Code session
|
|
34
|
+
- A hand-authored / synthetic trace
|
|
35
|
+
- The bundled examples/
|
|
36
|
+
- Other (describe below)
|
|
37
|
+
validations:
|
|
38
|
+
required: true
|
|
39
|
+
- type: textarea
|
|
40
|
+
id: expected-vs-actual
|
|
41
|
+
attributes:
|
|
42
|
+
label: Expected vs actual score
|
|
43
|
+
description: Which scorer, the number you expected, and the number you got.
|
|
44
|
+
placeholder: "diff_coherence — expected 1.0, got 0.0."
|
|
45
|
+
validations:
|
|
46
|
+
required: true
|
|
47
|
+
- type: textarea
|
|
48
|
+
id: repro
|
|
49
|
+
attributes:
|
|
50
|
+
label: Minimal trace to reproduce
|
|
51
|
+
description: >
|
|
52
|
+
Paste the smallest trace that triggers it (a `messages.json` snippet). Do NOT paste secrets
|
|
53
|
+
or anything you can't share publicly. Never include Cline's own golden fixture.
|
|
54
|
+
render: json
|
|
55
|
+
validations:
|
|
56
|
+
required: false
|
|
57
|
+
- type: input
|
|
58
|
+
id: environment
|
|
59
|
+
attributes:
|
|
60
|
+
label: Environment
|
|
61
|
+
placeholder: "clinescope version (or commit), Python version, OS"
|
|
62
|
+
validations:
|
|
63
|
+
required: true
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
name: New scorer / metric request
|
|
2
|
+
description: Propose a new eval scorer or metric for clinescope to compute from a trace.
|
|
3
|
+
title: "[scorer]: "
|
|
4
|
+
labels: ["enhancement", "scorer"]
|
|
5
|
+
body:
|
|
6
|
+
- type: markdown
|
|
7
|
+
attributes:
|
|
8
|
+
value: |
|
|
9
|
+
clinescope scores a coding-agent run from its trace alone (no rerun, no repo). A new scorer
|
|
10
|
+
has to be computable from the `messages.json` trace and, ideally, verifiable against a known
|
|
11
|
+
expected number. Please open this before writing code so we can agree on the shape.
|
|
12
|
+
- type: textarea
|
|
13
|
+
id: signal
|
|
14
|
+
attributes:
|
|
15
|
+
label: What signal should it measure
|
|
16
|
+
description: What quality of the run would this scorer capture that the current ones don't?
|
|
17
|
+
placeholder: "e.g. how much unrelated context the agent read before editing."
|
|
18
|
+
validations:
|
|
19
|
+
required: true
|
|
20
|
+
- type: dropdown
|
|
21
|
+
id: llm
|
|
22
|
+
attributes:
|
|
23
|
+
label: Deterministic or judge-based?
|
|
24
|
+
description: >
|
|
25
|
+
clinescope prefers deterministic, zero-LLM scorers; an LLM judge must be validated against
|
|
26
|
+
human labels (Cohen's κ) before it counts.
|
|
27
|
+
options:
|
|
28
|
+
- Deterministic (zero-LLM) — computed from the trace text
|
|
29
|
+
- LLM-judge (would need κ validation vs human labels)
|
|
30
|
+
- Not sure
|
|
31
|
+
validations:
|
|
32
|
+
required: true
|
|
33
|
+
- type: textarea
|
|
34
|
+
id: definition
|
|
35
|
+
attributes:
|
|
36
|
+
label: How would you define / compute it
|
|
37
|
+
description: The rule, and what in the trace it reads (tool calls, patch text, results, verdicts).
|
|
38
|
+
validations:
|
|
39
|
+
required: true
|
|
40
|
+
- type: textarea
|
|
41
|
+
id: expected
|
|
42
|
+
attributes:
|
|
43
|
+
label: A trace + its expected score
|
|
44
|
+
description: >
|
|
45
|
+
A scorer is only reviewable with a trace that pins its output. Sketch one case (a trace shape)
|
|
46
|
+
and the number the scorer should produce on it.
|
|
47
|
+
validations:
|
|
48
|
+
required: false
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<!-- See CONTRIBUTING.md for dev setup, tests, and what a scorer change needs. -->
|
|
2
|
+
|
|
3
|
+
## Summary
|
|
4
|
+
|
|
5
|
+
<!-- What does this change and why? -->
|
|
6
|
+
|
|
7
|
+
## Linked issue
|
|
8
|
+
|
|
9
|
+
<!-- Closes #... — open an issue first for anything larger than a bug/doc fix. -->
|
|
10
|
+
|
|
11
|
+
## How verified
|
|
12
|
+
|
|
13
|
+
<!-- The command you ran and what it returned (e.g. `pytest -q`, and a `clinescope <trace>` run). -->
|
|
14
|
+
|
|
15
|
+
## Checklist
|
|
16
|
+
|
|
17
|
+
- [ ] Tests + linters pass (`pytest -q`, `ruff check .`, `ruff format --check .`, `mypy src`)
|
|
18
|
+
- [ ] A scorer change adds a trace + its expected score (see CONTRIBUTING.md)
|
|
19
|
+
- [ ] Cline's golden fixture was not modified or copied in
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Supported Versions
|
|
4
|
+
|
|
5
|
+
clinescope is at 1.x and maintained by a single author. Security fixes land on `main` and in the
|
|
6
|
+
latest tagged release only; older tags are not patched.
|
|
7
|
+
|
|
8
|
+
| Version | Supported |
|
|
9
|
+
| -------------------- | --------- |
|
|
10
|
+
| latest 1.x release | ✅ |
|
|
11
|
+
| `main` | ✅ |
|
|
12
|
+
| older tags (< latest)| ❌ |
|
|
13
|
+
|
|
14
|
+
## Reporting a Vulnerability
|
|
15
|
+
|
|
16
|
+
Please report security issues **privately**, not as a public issue.
|
|
17
|
+
|
|
18
|
+
- Preferred: open a private report from the repository's **Security** tab → **Report a vulnerability**
|
|
19
|
+
(GitHub private vulnerability reporting).
|
|
20
|
+
- Fallback: email **minh2416294@gmail.com**.
|
|
21
|
+
|
|
22
|
+
This is a solo, best-effort project — there is no formal SLA, but I aim to acknowledge a report within
|
|
23
|
+
a few days and will keep you updated on a fix. Please give me a reasonable window to address the issue
|
|
24
|
+
before any public disclosure.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
# Keep the GitHub Actions in .github/workflows/ up to date. clinescope has no runtime
|
|
4
|
+
# dependencies (dependencies = []), so there is no pip ecosystem to watch — Actions is
|
|
5
|
+
# the only surface that drifts.
|
|
6
|
+
- package-ecosystem: "github-actions"
|
|
7
|
+
directory: "/"
|
|
8
|
+
schedule:
|
|
9
|
+
interval: "weekly"
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
concurrency:
|
|
13
|
+
group: ci-${{ github.workflow }}-${{ github.ref }}
|
|
14
|
+
cancel-in-progress: true
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
test:
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
strategy:
|
|
20
|
+
fail-fast: false
|
|
21
|
+
matrix:
|
|
22
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v7
|
|
25
|
+
- uses: actions/setup-python@v6
|
|
26
|
+
with:
|
|
27
|
+
python-version: ${{ matrix.python-version }}
|
|
28
|
+
- name: Install package and dev deps
|
|
29
|
+
run: pip install -e ".[dev]"
|
|
30
|
+
- name: Lint
|
|
31
|
+
run: ruff check .
|
|
32
|
+
- name: Format check
|
|
33
|
+
run: ruff format --check .
|
|
34
|
+
- name: Type-check
|
|
35
|
+
run: mypy src
|
|
36
|
+
- name: Test (with coverage gate)
|
|
37
|
+
run: pytest -q --cov=clinescope --cov-report=term-missing --cov-fail-under=90
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
|
|
3
|
+
# Fires only when a GitHub Release is published. It is inert until then — no PR,
|
|
4
|
+
# push, or tag alone triggers it — so it never collides with the main-guard ruleset
|
|
5
|
+
# (which gates pull_request -> main). Publishing to PyPI uses Trusted Publishing
|
|
6
|
+
# (OIDC): no API token is stored in the repo; the `pypi` environment + a PyPI
|
|
7
|
+
# pending-publisher authorize the upload. See CONTRIBUTING.md "Releasing".
|
|
8
|
+
on:
|
|
9
|
+
release:
|
|
10
|
+
types: [published]
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
build:
|
|
17
|
+
name: Build distribution
|
|
18
|
+
runs-on: ubuntu-latest
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v7
|
|
21
|
+
- uses: actions/setup-python@v6
|
|
22
|
+
with:
|
|
23
|
+
python-version: "3.12"
|
|
24
|
+
- name: Install build backend
|
|
25
|
+
run: python -m pip install --upgrade build
|
|
26
|
+
- name: Build sdist and wheel
|
|
27
|
+
run: python -m build
|
|
28
|
+
- name: Upload dist artifacts
|
|
29
|
+
uses: actions/upload-artifact@v4
|
|
30
|
+
with:
|
|
31
|
+
name: dist
|
|
32
|
+
path: dist/
|
|
33
|
+
|
|
34
|
+
publish:
|
|
35
|
+
name: Publish to PyPI
|
|
36
|
+
needs: build
|
|
37
|
+
runs-on: ubuntu-latest
|
|
38
|
+
# The environment gates the release: PyPI's pending-publisher is scoped to it,
|
|
39
|
+
# and it is where an optional required-reviewer approval would apply.
|
|
40
|
+
environment:
|
|
41
|
+
name: pypi
|
|
42
|
+
url: https://pypi.org/p/clinescope
|
|
43
|
+
permissions:
|
|
44
|
+
id-token: write # OIDC token for Trusted Publishing; no stored PyPI secret.
|
|
45
|
+
steps:
|
|
46
|
+
- name: Download dist artifacts
|
|
47
|
+
uses: actions/download-artifact@v4
|
|
48
|
+
with:
|
|
49
|
+
name: dist
|
|
50
|
+
path: dist/
|
|
51
|
+
- name: Publish to PyPI
|
|
52
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# --- Python ---
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.egg-info/
|
|
6
|
+
.eggs/
|
|
7
|
+
build/
|
|
8
|
+
dist/
|
|
9
|
+
*.egg
|
|
10
|
+
.pytest_cache/
|
|
11
|
+
.ruff_cache/
|
|
12
|
+
.mypy_cache/
|
|
13
|
+
|
|
14
|
+
# --- Virtual environments ---
|
|
15
|
+
.venv/
|
|
16
|
+
venv/
|
|
17
|
+
env/
|
|
18
|
+
|
|
19
|
+
# --- IDE / editor ---
|
|
20
|
+
.idea/
|
|
21
|
+
.vscode/
|
|
22
|
+
*.swp
|
|
23
|
+
|
|
24
|
+
# --- OS ---
|
|
25
|
+
.DS_Store
|
|
26
|
+
Thumbs.db
|
|
27
|
+
|
|
28
|
+
# --- Build paper trail (git-excluded by design; feeds /public-writing) ---
|
|
29
|
+
writing-content/
|
|
30
|
+
artifacts/
|
|
31
|
+
|
|
32
|
+
# --- Machine/workflow state (skills read this back) ---
|
|
33
|
+
.planning/
|
|
34
|
+
|
|
35
|
+
# Windows folder settings
|
|
36
|
+
desktop.ini
|
|
37
|
+
|
|
38
|
+
# Coverage data file (pytest-cov / coverage.py)
|
|
39
|
+
.coverage
|
|
40
|
+
htmlcov/
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# CLAUDE.md — agent-eval-harness
|
|
2
|
+
|
|
3
|
+
Project-local instructions for any Claude Code session opened in this repo.
|
|
4
|
+
|
|
5
|
+
> **This file is a local pointer + copy of the operating protocol.** The single source of truth is
|
|
6
|
+
> in the user's memory files — read them FIRST every session:
|
|
7
|
+
> - **Charter (WHAT):** `~/.claude/memory/project_agent_eval_harness.md`
|
|
8
|
+
> - **Operating protocol (HOW — canonical):** `~/.claude/memory/project_agent_eval_harness_protocol.md`
|
|
9
|
+
>
|
|
10
|
+
> The Charter's Living Log (bottom of that file) is the append-only progress record. Read the last
|
|
11
|
+
> entry's EVIDENCE + NEXT ACTION before doing any work, so sessions never conflict.
|
|
12
|
+
|
|
13
|
+
## What this project is (one line)
|
|
14
|
+
|
|
15
|
+
A **Cline eval harness**: scores diff quality + tool-trajectory from a real Cline `messages.json` v1
|
|
16
|
+
trace. Framework-agnostic core; Cline World-A adapter is the flagship + first adapter. Purpose =
|
|
17
|
+
hireability + reputation, NOT paid users.
|
|
18
|
+
|
|
19
|
+
**Hard floor (v1 is "done" only when BOTH are true):**
|
|
20
|
+
1. Runs against Cline's golden fixture — ingests `sdk/packages/core/fixtures/messages/success.messages.json`,
|
|
21
|
+
emits a scored report (tool-selection + diff-quality + completion).
|
|
22
|
+
2. Ships the diff-coherence / minimal-diff / apply-recovery scorer the incumbents don't, on ≥1 real trace.
|
|
23
|
+
|
|
24
|
+
## Standing rules (check every session — from the protocol)
|
|
25
|
+
|
|
26
|
+
1. **WIP = 1.** One task in flight. One task per Claude Code session.
|
|
27
|
+
2. **No task without a CHECK.** The verifying command/test is written BEFORE any code. No check =
|
|
28
|
+
task doesn't enter the log.
|
|
29
|
+
3. **Every task serves hard-floor criterion 1 or 2**, or it's tagged `~` (roadmap, dropped by default).
|
|
30
|
+
4. **Never modify the golden fixture** at `**/fixtures/messages/success.messages.json`. The harness
|
|
31
|
+
INGESTS it from the Cline checkout; it is never copied or edited. (Hook-enforced.)
|
|
32
|
+
5. **No demos disconnected from Cline's real trace.**
|
|
33
|
+
6. **Max 2 weeks without a public artifact.** Silence is the #1 OSS death signal.
|
|
34
|
+
7. **Tooling-config urges = procrastination.** Log the urge, return to the CHECK.
|
|
35
|
+
8. **Log is append-only.** Decisions are immutable; to change one, write a NEW entry that supersedes
|
|
36
|
+
and links the old (ADR discipline). Never edit past Living-Log entries.
|
|
37
|
+
|
|
38
|
+
## Sequencing law — walking skeleton
|
|
39
|
+
|
|
40
|
+
Until the thin path **load World-A trace → score → emit report** runs against the golden fixture,
|
|
41
|
+
EVERY build task is a skeleton segment. Keep it ugly and runnable. After the skeleton runs, every
|
|
42
|
+
task FILLS it (a new scorer, a new metric — deterministic zero-LLM gates first). Never a disconnected
|
|
43
|
+
module. No second adapter before a real one exists (two-adapter rule).
|
|
44
|
+
|
|
45
|
+
## Task types (only three exist)
|
|
46
|
+
|
|
47
|
+
| Type | Rule |
|
|
48
|
+
|---|---|
|
|
49
|
+
| **BUILD** | Fills the skeleton. Verification-first, sized to one session, machine-checkable. |
|
|
50
|
+
| **SPIKE** | One question, hard timebox (2–3h), throwaway code, MUST end with a written decision. Timebox expiry IS the answer. Only for genuine unknowns. |
|
|
51
|
+
| **PUBLISH** | Triggered by artifact milestones, never by calendar. Raw material mined from the Living Log + commits → `writing-content/`. |
|
|
52
|
+
|
|
53
|
+
## Living-Log entry template (append to the Charter file, append-only)
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
## YYYY-MM-DD — <session goal, one sentence, ends in a verifiable state>
|
|
57
|
+
- TYPE: BUILD | SPIKE (timebox: Xh) | PUBLISH
|
|
58
|
+
- CHECK: <exact command/test + expected output that proves done — written first>
|
|
59
|
+
- APPETITE: ≤ N sessions
|
|
60
|
+
- CONTEXT: <files, fixture paths, relevant log entries>
|
|
61
|
+
- EVIDENCE: <pasted actual output — never an assertion>
|
|
62
|
+
- DECISIONS: <immutable; supersede-don't-edit>
|
|
63
|
+
- OPEN QUESTIONS: <what you now don't know>
|
|
64
|
+
- NEXT ACTION: <the first thing next session does>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Session gates (from the user's global CLAUDE.md)
|
|
68
|
+
|
|
69
|
+
- Set a `/goal` with a measurable success criterion; match `/effort` (feature work = xhigh); Plan Mode
|
|
70
|
+
for anything multi-step.
|
|
71
|
+
- Demand EVIDENCE (pasted output), never assertions of "done".
|
|
72
|
+
- The paper trail (`writing-content/`, `artifacts/`) is git-excluded and feeds `/public-writing`.
|
|
73
|
+
|
|
74
|
+
## Layout
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
src/clinescope/ # the package (import clinescope)
|
|
78
|
+
pyproject.toml # metadata, no deps yet
|
|
79
|
+
.venv/ # local venv (git-ignored)
|
|
80
|
+
writing-content/ # git-excluded build paper trail (created when a build phase runs)
|
|
81
|
+
artifacts/ # git-excluded keeper artifacts
|
|
82
|
+
```
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
|
2
|
+
|
|
3
|
+
## Our Pledge
|
|
4
|
+
|
|
5
|
+
We as members, contributors, and leaders pledge to make participation in our
|
|
6
|
+
community a harassment-free experience for everyone, regardless of age, body
|
|
7
|
+
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
|
8
|
+
identity and expression, level of experience, education, socio-economic status,
|
|
9
|
+
nationality, personal appearance, race, religion, or sexual identity
|
|
10
|
+
and orientation.
|
|
11
|
+
|
|
12
|
+
We pledge to act and interact in ways that contribute to an open, welcoming,
|
|
13
|
+
diverse, inclusive, and healthy community.
|
|
14
|
+
|
|
15
|
+
## Our Standards
|
|
16
|
+
|
|
17
|
+
Examples of behavior that contributes to a positive environment for our
|
|
18
|
+
community include:
|
|
19
|
+
|
|
20
|
+
* Demonstrating empathy and kindness toward other people
|
|
21
|
+
* Being respectful of differing opinions, viewpoints, and experiences
|
|
22
|
+
* Giving and gracefully accepting constructive feedback
|
|
23
|
+
* Accepting responsibility and apologizing to those affected by our mistakes,
|
|
24
|
+
and learning from the experience
|
|
25
|
+
* Focusing on what is best not just for us as individuals, but for the
|
|
26
|
+
overall community
|
|
27
|
+
|
|
28
|
+
Examples of unacceptable behavior include:
|
|
29
|
+
|
|
30
|
+
* The use of sexualized language or imagery, and sexual attention or
|
|
31
|
+
advances of any kind
|
|
32
|
+
* Trolling, insulting or derogatory comments, and personal or political attacks
|
|
33
|
+
* Public or private harassment
|
|
34
|
+
* Publishing others' private information, such as a physical or email
|
|
35
|
+
address, without their explicit permission
|
|
36
|
+
* Other conduct which could reasonably be considered inappropriate in a
|
|
37
|
+
professional setting
|
|
38
|
+
|
|
39
|
+
## Enforcement Responsibilities
|
|
40
|
+
|
|
41
|
+
Community leaders are responsible for clarifying and enforcing our standards of
|
|
42
|
+
acceptable behavior and will take appropriate and fair corrective action in
|
|
43
|
+
response to any behavior that they deem inappropriate, threatening, offensive,
|
|
44
|
+
or harmful.
|
|
45
|
+
|
|
46
|
+
Community leaders have the right and responsibility to remove, edit, or reject
|
|
47
|
+
comments, commits, code, wiki edits, issues, and other contributions that are
|
|
48
|
+
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
|
49
|
+
decisions when appropriate.
|
|
50
|
+
|
|
51
|
+
## Scope
|
|
52
|
+
|
|
53
|
+
This Code of Conduct applies within all community spaces, and also applies when
|
|
54
|
+
an individual is officially representing the community in public spaces.
|
|
55
|
+
Examples of representing our community include using an official e-mail address,
|
|
56
|
+
posting via an official social media account, or acting as an appointed
|
|
57
|
+
representative at an online or offline event.
|
|
58
|
+
|
|
59
|
+
## Enforcement
|
|
60
|
+
|
|
61
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
62
|
+
reported to the community leaders responsible for enforcement at
|
|
63
|
+
minh2416294@gmail.com.
|
|
64
|
+
All complaints will be reviewed and investigated promptly and fairly.
|
|
65
|
+
|
|
66
|
+
All community leaders are obligated to respect the privacy and security of the
|
|
67
|
+
reporter of any incident.
|
|
68
|
+
|
|
69
|
+
## Enforcement Guidelines
|
|
70
|
+
|
|
71
|
+
Community leaders will follow these Community Impact Guidelines in determining
|
|
72
|
+
the consequences for any action they deem in violation of this Code of Conduct:
|
|
73
|
+
|
|
74
|
+
### 1. Correction
|
|
75
|
+
|
|
76
|
+
**Community Impact**: Use of inappropriate language or other behavior deemed
|
|
77
|
+
unprofessional or unwelcome in the community.
|
|
78
|
+
|
|
79
|
+
**Consequence**: A private, written warning from community leaders, providing
|
|
80
|
+
clarity around the nature of the violation and an explanation of why the
|
|
81
|
+
behavior was inappropriate. A public apology may be requested.
|
|
82
|
+
|
|
83
|
+
### 2. Warning
|
|
84
|
+
|
|
85
|
+
**Community Impact**: A violation through a single incident or series
|
|
86
|
+
of actions.
|
|
87
|
+
|
|
88
|
+
**Consequence**: A warning with consequences for continued behavior. No
|
|
89
|
+
interaction with the people involved, including unsolicited interaction with
|
|
90
|
+
those enforcing the Code of Conduct, for a specified period of time. This
|
|
91
|
+
includes avoiding interactions in community spaces as well as external channels
|
|
92
|
+
like social media. Violating these terms may lead to a temporary or
|
|
93
|
+
permanent ban.
|
|
94
|
+
|
|
95
|
+
### 3. Temporary Ban
|
|
96
|
+
|
|
97
|
+
**Community Impact**: A serious violation of community standards, including
|
|
98
|
+
sustained inappropriate behavior.
|
|
99
|
+
|
|
100
|
+
**Consequence**: A temporary ban from any sort of interaction or public
|
|
101
|
+
communication with the community for a specified period of time. No public or
|
|
102
|
+
private interaction with the people involved, including unsolicited interaction
|
|
103
|
+
with those enforcing the Code of Conduct, is allowed during this period.
|
|
104
|
+
Violating these terms may lead to a permanent ban.
|
|
105
|
+
|
|
106
|
+
### 4. Permanent Ban
|
|
107
|
+
|
|
108
|
+
**Community Impact**: Demonstrating a pattern of violation of community
|
|
109
|
+
standards, including sustained inappropriate behavior, harassment of an
|
|
110
|
+
individual, or aggression toward or disparagement of classes of individuals.
|
|
111
|
+
|
|
112
|
+
**Consequence**: A permanent ban from any sort of public interaction within
|
|
113
|
+
the community.
|
|
114
|
+
|
|
115
|
+
## Attribution
|
|
116
|
+
|
|
117
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
|
118
|
+
version 2.0, available at
|
|
119
|
+
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
|
120
|
+
|
|
121
|
+
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
|
122
|
+
enforcement ladder](https://github.com/mozilla/diversity).
|
|
123
|
+
|
|
124
|
+
[homepage]: https://www.contributor-covenant.org
|
|
125
|
+
|
|
126
|
+
For answers to common questions about this code of conduct, see the FAQ at
|
|
127
|
+
https://www.contributor-covenant.org/faq. Translations are available at
|
|
128
|
+
https://www.contributor-covenant.org/translations.
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Contributing to clinescope
|
|
2
|
+
|
|
3
|
+
Thanks for helping build clinescope. Small, discussed-first changes are the norm here — for anything
|
|
4
|
+
larger than a bug fix or a doc tweak, please open an issue first so we can agree on the shape before
|
|
5
|
+
you write code.
|
|
6
|
+
|
|
7
|
+
This is a `src`-layout Python package (`import clinescope`), Python 3.11+.
|
|
8
|
+
|
|
9
|
+
## Dev setup
|
|
10
|
+
|
|
11
|
+
Fork and clone, then install the package **editable, with the dev extras**, from inside your checkout:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
git clone https://github.com/<you>/clinescope
|
|
15
|
+
cd clinescope
|
|
16
|
+
python -m venv .venv && source .venv/Scripts/activate # Windows Git Bash; use bin/activate on macOS/Linux
|
|
17
|
+
pip install -e ".[dev]"
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The `[dev]` extra pulls in `pytest`, `pytest-cov`, `ruff`, and `mypy` — the same tools CI runs.
|
|
21
|
+
|
|
22
|
+
## Running the tests and linters
|
|
23
|
+
|
|
24
|
+
Run these before you push; they are exactly what CI checks:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
pytest -q # tests
|
|
28
|
+
ruff check . # lint
|
|
29
|
+
ruff format --check . # formatting (drop --check to auto-format)
|
|
30
|
+
mypy src # type-check
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`pytest` is install-independent — `pyproject.toml` sets `[tool.pytest.ini_options] pythonpath = ["src"]`,
|
|
34
|
+
so `pytest -q` finds the package whether or not it's installed.
|
|
35
|
+
|
|
36
|
+
CI additionally runs the suite under coverage and **fails if line coverage drops below 90%**
|
|
37
|
+
(measured at 94%). To reproduce that gate locally:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pytest -q --cov=clinescope --cov-report=term-missing --cov-fail-under=90
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
A bare `pytest -q` still works without the coverage plugin — the `--cov` flags live on the CI command
|
|
44
|
+
line, not in `addopts`, so base pytest isn't required to run the tests.
|
|
45
|
+
|
|
46
|
+
## The multi-worktree editable-install gotcha (read this if you use git worktrees)
|
|
47
|
+
|
|
48
|
+
An editable install (`pip install -e .`) writes a `.pth` into the active virtualenv that pins imports to
|
|
49
|
+
**one** checkout's `src/`. If you share a single `.venv` across several git worktrees of this repo,
|
|
50
|
+
whichever worktree ran `pip install -e .` **last** wins — the others import stale code, or fail with
|
|
51
|
+
`No module named clinescope`, even though their own source is correct.
|
|
52
|
+
|
|
53
|
+
Two ways to stay safe:
|
|
54
|
+
|
|
55
|
+
- **Re-run `pip install -e .` inside the worktree you're working in** (repoints the `.pth`), **or**
|
|
56
|
+
- **Use `PYTHONPATH=src`** for a one-off run, which needs no install:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
PYTHONPATH=src python -m clinescope examples/sample-trace.json --expected read_files apply_patch
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The gotcha only bites `python -m clinescope` (and editor type-checkers), which don't read
|
|
63
|
+
`pyproject.toml`; `pytest` is already immune via the setting above.
|
|
64
|
+
|
|
65
|
+
## Fork, branch, PR
|
|
66
|
+
|
|
67
|
+
1. Fork the repo and create a branch off `main` (`fix/…`, `feat/…`, `chore/…`).
|
|
68
|
+
2. Make the change; keep the diff focused on one thing.
|
|
69
|
+
3. Run the tests + linters above until they're all green.
|
|
70
|
+
4. Push to your fork and open a PR against `minh2416294/clinescope:main`. CI runs on the PR.
|
|
71
|
+
|
|
72
|
+
## What a PR should include
|
|
73
|
+
|
|
74
|
+
- **A scorer change needs a trace + its expected score.** Add (or extend) a fixture trace and assert
|
|
75
|
+
the number the scorer should produce on it — a scorer without a test proving its output isn't
|
|
76
|
+
reviewable. Never edit or copy in Cline's own golden fixture; add your own small synthetic trace
|
|
77
|
+
(see `examples/sample-trace.json` for the World-A v1 shape).
|
|
78
|
+
- **Open an issue first for anything large** — a new scorer, a new adapter, a format change. A quick
|
|
79
|
+
agreement on the approach saves a rewrite.
|
|
80
|
+
- Keep behavior changes and refactors in separate commits where you can; explain *why* in the PR body,
|
|
81
|
+
not just *what*.
|
|
82
|
+
|
|
83
|
+
## Releasing (maintainer only)
|
|
84
|
+
|
|
85
|
+
Releases publish to PyPI automatically via **Trusted Publishing** (OIDC) — there is no PyPI API token
|
|
86
|
+
stored in the repo. `.github/workflows/release.yml` builds the sdist + wheel and uploads them when a
|
|
87
|
+
**GitHub Release is published** (not on a tag alone, and never on a PR).
|
|
88
|
+
|
|
89
|
+
To cut a release:
|
|
90
|
+
|
|
91
|
+
1. Bump `version` in `pyproject.toml` (and anywhere else it's mirrored), and land it on `main` via PR.
|
|
92
|
+
2. On GitHub, **Releases → Draft a new release**, create a tag matching the version (e.g. `v1.0.1`), and
|
|
93
|
+
**Publish**. The `Release` workflow runs and uploads to PyPI.
|
|
94
|
+
3. Verify the new version renders at <https://pypi.org/project/clinescope/> and installs cleanly into a
|
|
95
|
+
fresh venv (`pip install clinescope` → `clinescope-corpus` exits 0).
|
|
96
|
+
|
|
97
|
+
One-time setup (already configured; documented here for the record) — on PyPI, **Account → Publishing →
|
|
98
|
+
Add a pending publisher** with: PyPI Project Name `clinescope`, Owner `minh2416294`, Repository name
|
|
99
|
+
`clinescope`, Workflow name `release.yml`, Environment name `pypi`; and a GitHub repo Environment named
|
|
100
|
+
`pypi` (Settings → Environments), where an optional required-reviewer gate can be added.
|