PaperFarm 0.2.0b1__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.
- paperfarm-0.2.0b1/.github/ISSUE_TEMPLATE/bug_report.yml +66 -0
- paperfarm-0.2.0b1/.github/ISSUE_TEMPLATE/feature_request.yml +40 -0
- paperfarm-0.2.0b1/.github/dependabot.yml +26 -0
- paperfarm-0.2.0b1/.github/pull_request_template.md +21 -0
- paperfarm-0.2.0b1/.github/workflows/cancel-on-merge.yml +45 -0
- paperfarm-0.2.0b1/.github/workflows/ci.yml +221 -0
- paperfarm-0.2.0b1/.github/workflows/codeql.yml +36 -0
- paperfarm-0.2.0b1/.github/workflows/publish.yml +49 -0
- paperfarm-0.2.0b1/.gitignore +41 -0
- paperfarm-0.2.0b1/AUTO_REVIEW.md +1140 -0
- paperfarm-0.2.0b1/CHANGELOG.md +43 -0
- paperfarm-0.2.0b1/CODE_OF_CONDUCT.md +38 -0
- paperfarm-0.2.0b1/CONTRIBUTING.md +44 -0
- paperfarm-0.2.0b1/LICENSE +21 -0
- paperfarm-0.2.0b1/Makefile +36 -0
- paperfarm-0.2.0b1/PKG-INFO +385 -0
- paperfarm-0.2.0b1/README.md +345 -0
- paperfarm-0.2.0b1/REVIEW_STATE.json +16 -0
- paperfarm-0.2.0b1/demo.py +278 -0
- paperfarm-0.2.0b1/docs/architecture-review.md +334 -0
- paperfarm-0.2.0b1/docs/assets/demo-start.tape +41 -0
- paperfarm-0.2.0b1/docs/assets/demo-tabs.tape +47 -0
- paperfarm-0.2.0b1/docs/assets/dual-agent.mmd +45 -0
- paperfarm-0.2.0b1/docs/assets/dual-agent.svg +1 -0
- paperfarm-0.2.0b1/docs/assets/screenshot-charts.svg +218 -0
- paperfarm-0.2.0b1/docs/assets/screenshot-docs.svg +221 -0
- paperfarm-0.2.0b1/docs/assets/screenshot-ideas.svg +216 -0
- paperfarm-0.2.0b1/docs/assets/screenshot-logs.svg +215 -0
- paperfarm-0.2.0b1/docs/assets/screenshot-overview.svg +218 -0
- paperfarm-0.2.0b1/docs/assets/tui-layout.mmd +43 -0
- paperfarm-0.2.0b1/docs/assets/tui-layout.svg +1 -0
- paperfarm-0.2.0b1/docs/assets/workflow.mmd +43 -0
- paperfarm-0.2.0b1/docs/assets/workflow.svg +1 -0
- paperfarm-0.2.0b1/docs/plans/2026-03-08-open-researcher-design.md +147 -0
- paperfarm-0.2.0b1/docs/plans/2026-03-08-open-researcher-implementation.md +1854 -0
- paperfarm-0.2.0b1/docs/plans/2026-03-09-beta-release-design.md +291 -0
- paperfarm-0.2.0b1/docs/plans/2026-03-09-beta-release-plan.md +1760 -0
- paperfarm-0.2.0b1/docs/plans/2026-03-09-dual-agent-tui-design.md +222 -0
- paperfarm-0.2.0b1/docs/plans/2026-03-09-multiagent-tui-implementation.md +2076 -0
- paperfarm-0.2.0b1/docs/plans/2026-03-09-multiagent-tui-redesign.md +223 -0
- paperfarm-0.2.0b1/docs/plans/2026-03-09-parallel-experiments-design.md +139 -0
- paperfarm-0.2.0b1/docs/plans/2026-03-09-parallel-experiments-plan.md +1008 -0
- paperfarm-0.2.0b1/docs/plans/2026-03-09-prompt-enhancement-design.md +57 -0
- paperfarm-0.2.0b1/docs/plans/2026-03-09-tui-simplification-design.md +78 -0
- paperfarm-0.2.0b1/docs/plans/2026-03-09-tui-simplification-plan.md +416 -0
- paperfarm-0.2.0b1/docs/plans/2026-03-09-tui-visual-overhaul-design.md +95 -0
- paperfarm-0.2.0b1/docs/plans/2026-03-09-tui-visual-overhaul-plan.md +719 -0
- paperfarm-0.2.0b1/docs/plans/2026-03-09-v1-implementation.md +1947 -0
- paperfarm-0.2.0b1/docs/plans/2026-03-09-v1-release-design.md +188 -0
- paperfarm-0.2.0b1/docs/plans/2026-03-10-headless-mode-design.md +58 -0
- paperfarm-0.2.0b1/docs/plans/2026-03-10-headless-mode-plan.md +852 -0
- paperfarm-0.2.0b1/docs/plans/2026-03-10-start-command-design.md +201 -0
- paperfarm-0.2.0b1/docs/plans/2026-03-10-start-command-plan.md +1377 -0
- paperfarm-0.2.0b1/docs/plans/2026-03-13-microkernel-architecture-design.md +452 -0
- paperfarm-0.2.0b1/docs/plans/2026-03-13-microkernel-implementation-plan.md +2204 -0
- paperfarm-0.2.0b1/docs/plans/2026-03-13-module-migration-design.md +95 -0
- paperfarm-0.2.0b1/docs/plans/2026-03-14-round6-deep-audit-design.md +59 -0
- paperfarm-0.2.0b1/docs/plans/2026-03-14-system-audit-tech-debt.md +359 -0
- paperfarm-0.2.0b1/docs/plans/2026-03-14-system-fix-design.md +402 -0
- paperfarm-0.2.0b1/docs/plans/2026-03-14-system-fix-implementation.md +779 -0
- paperfarm-0.2.0b1/docs/plans/2026-03-14-tui-pipeline-phase-design.md +148 -0
- paperfarm-0.2.0b1/docs/plans/2026-03-14-tui-status-at-a-glance-design.md +159 -0
- paperfarm-0.2.0b1/docs/plans/2026-03-14-tui-status-at-a-glance-plan.md +482 -0
- paperfarm-0.2.0b1/docs/plans/2026-03-15-crash-retry-design.md +196 -0
- paperfarm-0.2.0b1/docs/plans/2026-03-15-crash-retry-implementation.md +339 -0
- paperfarm-0.2.0b1/docs/repo_inventory.md +98 -0
- paperfarm-0.2.0b1/docs/tui-design-comparison.md +106 -0
- paperfarm-0.2.0b1/examples/cartpole/README.md +53 -0
- paperfarm-0.2.0b1/examples/cartpole/requirements.txt +2 -0
- paperfarm-0.2.0b1/examples/cartpole/train.py +171 -0
- paperfarm-0.2.0b1/examples/cifar10-speedrun/README.md +50 -0
- paperfarm-0.2.0b1/examples/code-perf/README.md +53 -0
- paperfarm-0.2.0b1/examples/code-perf/bench.py +67 -0
- paperfarm-0.2.0b1/examples/code-perf/parser.py +12 -0
- paperfarm-0.2.0b1/examples/code-perf/requirements.txt +2 -0
- paperfarm-0.2.0b1/examples/hf-glue/README.md +31 -0
- paperfarm-0.2.0b1/examples/liger-kernel/README.md +30 -0
- paperfarm-0.2.0b1/examples/nanogpt/README.md +101 -0
- paperfarm-0.2.0b1/examples/whisper-finetune/README.md +52 -0
- paperfarm-0.2.0b1/examples/yolo-tiny/README.md +51 -0
- paperfarm-0.2.0b1/examples/yolo-tiny/train.py +51 -0
- paperfarm-0.2.0b1/imgs/docs.png +0 -0
- paperfarm-0.2.0b1/imgs/execution.png +0 -0
- paperfarm-0.2.0b1/imgs/overview.png +0 -0
- paperfarm-0.2.0b1/pyproject.toml +68 -0
- paperfarm-0.2.0b1/run_demo.sh +204 -0
- paperfarm-0.2.0b1/src/paperfarm/__init__.py +0 -0
- paperfarm-0.2.0b1/src/paperfarm/agent.py +255 -0
- paperfarm-0.2.0b1/src/paperfarm/cli.py +215 -0
- paperfarm-0.2.0b1/src/paperfarm/parallel.py +458 -0
- paperfarm-0.2.0b1/src/paperfarm/skill_runner.py +278 -0
- paperfarm-0.2.0b1/src/paperfarm/skills/critic.md +206 -0
- paperfarm-0.2.0b1/src/paperfarm/skills/experiment.md +126 -0
- paperfarm-0.2.0b1/src/paperfarm/skills/manager.md +239 -0
- paperfarm-0.2.0b1/src/paperfarm/skills/protocol.yaml +17 -0
- paperfarm-0.2.0b1/src/paperfarm/skills/scout.md +101 -0
- paperfarm-0.2.0b1/src/paperfarm/skills/scripts/record.py +81 -0
- paperfarm-0.2.0b1/src/paperfarm/skills/scripts/rollback.sh +6 -0
- paperfarm-0.2.0b1/src/paperfarm/state.py +393 -0
- paperfarm-0.2.0b1/src/paperfarm/tui/__init__.py +0 -0
- paperfarm-0.2.0b1/src/paperfarm/tui/app.py +166 -0
- paperfarm-0.2.0b1/src/paperfarm/tui/styles.css +51 -0
- paperfarm-0.2.0b1/src/paperfarm/tui/widgets.py +188 -0
- paperfarm-0.2.0b1/tests/__init__.py +0 -0
- paperfarm-0.2.0b1/tests/test_agent.py +240 -0
- paperfarm-0.2.0b1/tests/test_cli.py +182 -0
- paperfarm-0.2.0b1/tests/test_integration.py +400 -0
- paperfarm-0.2.0b1/tests/test_parallel.py +614 -0
- paperfarm-0.2.0b1/tests/test_record_script.py +189 -0
- paperfarm-0.2.0b1/tests/test_rollback_script.py +42 -0
- paperfarm-0.2.0b1/tests/test_skill_runner.py +358 -0
- paperfarm-0.2.0b1/tests/test_state.py +342 -0
- paperfarm-0.2.0b1/tests/test_tui_app.py +266 -0
- paperfarm-0.2.0b1/tests/test_tui_widgets.py +172 -0
- paperfarm-0.2.0b1/uv.lock +1735 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
name: Bug Report
|
|
2
|
+
description: Report a bug or unexpected behavior
|
|
3
|
+
labels: ["bug"]
|
|
4
|
+
body:
|
|
5
|
+
- type: markdown
|
|
6
|
+
attributes:
|
|
7
|
+
value: |
|
|
8
|
+
Thanks for reporting! Please run `open-researcher doctor` and paste the output below.
|
|
9
|
+
|
|
10
|
+
- type: textarea
|
|
11
|
+
id: description
|
|
12
|
+
attributes:
|
|
13
|
+
label: Bug description
|
|
14
|
+
description: What happened? What did you expect to happen?
|
|
15
|
+
validations:
|
|
16
|
+
required: true
|
|
17
|
+
|
|
18
|
+
- type: textarea
|
|
19
|
+
id: reproduce
|
|
20
|
+
attributes:
|
|
21
|
+
label: Steps to reproduce
|
|
22
|
+
description: Minimal steps to trigger the bug.
|
|
23
|
+
placeholder: |
|
|
24
|
+
1. `open-researcher init`
|
|
25
|
+
2. `open-researcher run --agent claude-code`
|
|
26
|
+
3. See error...
|
|
27
|
+
validations:
|
|
28
|
+
required: true
|
|
29
|
+
|
|
30
|
+
- type: textarea
|
|
31
|
+
id: doctor
|
|
32
|
+
attributes:
|
|
33
|
+
label: Doctor output
|
|
34
|
+
description: Paste the output of `open-researcher doctor`
|
|
35
|
+
render: text
|
|
36
|
+
validations:
|
|
37
|
+
required: true
|
|
38
|
+
|
|
39
|
+
- type: input
|
|
40
|
+
id: os
|
|
41
|
+
attributes:
|
|
42
|
+
label: OS
|
|
43
|
+
placeholder: "macOS 15.2 / Ubuntu 24.04 / Windows 11"
|
|
44
|
+
validations:
|
|
45
|
+
required: true
|
|
46
|
+
|
|
47
|
+
- type: input
|
|
48
|
+
id: python
|
|
49
|
+
attributes:
|
|
50
|
+
label: Python version
|
|
51
|
+
placeholder: "3.12.1"
|
|
52
|
+
validations:
|
|
53
|
+
required: true
|
|
54
|
+
|
|
55
|
+
- type: input
|
|
56
|
+
id: agent
|
|
57
|
+
attributes:
|
|
58
|
+
label: Agent used
|
|
59
|
+
placeholder: "claude-code / codex / aider / opencode"
|
|
60
|
+
|
|
61
|
+
- type: textarea
|
|
62
|
+
id: logs
|
|
63
|
+
attributes:
|
|
64
|
+
label: Relevant logs
|
|
65
|
+
description: Paste from `.research/run.log` or terminal output.
|
|
66
|
+
render: text
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
name: Feature Request
|
|
2
|
+
description: Suggest a new feature or improvement
|
|
3
|
+
labels: ["enhancement"]
|
|
4
|
+
body:
|
|
5
|
+
- type: textarea
|
|
6
|
+
id: problem
|
|
7
|
+
attributes:
|
|
8
|
+
label: Problem or use case
|
|
9
|
+
description: What are you trying to do that isn't possible or convenient today?
|
|
10
|
+
validations:
|
|
11
|
+
required: true
|
|
12
|
+
|
|
13
|
+
- type: textarea
|
|
14
|
+
id: solution
|
|
15
|
+
attributes:
|
|
16
|
+
label: Proposed solution
|
|
17
|
+
description: How would you like this to work?
|
|
18
|
+
validations:
|
|
19
|
+
required: true
|
|
20
|
+
|
|
21
|
+
- type: dropdown
|
|
22
|
+
id: area
|
|
23
|
+
attributes:
|
|
24
|
+
label: Area
|
|
25
|
+
options:
|
|
26
|
+
- CLI commands
|
|
27
|
+
- TUI dashboard
|
|
28
|
+
- Agent adapters
|
|
29
|
+
- Parallel workers / GPU
|
|
30
|
+
- Config / templates
|
|
31
|
+
- Documentation
|
|
32
|
+
- Other
|
|
33
|
+
validations:
|
|
34
|
+
required: true
|
|
35
|
+
|
|
36
|
+
- type: textarea
|
|
37
|
+
id: alternatives
|
|
38
|
+
attributes:
|
|
39
|
+
label: Alternatives considered
|
|
40
|
+
description: Any workarounds or alternative approaches you've tried?
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
# Python dependencies
|
|
4
|
+
- package-ecosystem: "pip"
|
|
5
|
+
directory: "/"
|
|
6
|
+
schedule:
|
|
7
|
+
interval: "weekly"
|
|
8
|
+
day: "monday"
|
|
9
|
+
open-pull-requests-limit: 5
|
|
10
|
+
labels:
|
|
11
|
+
- "dependencies"
|
|
12
|
+
commit-message:
|
|
13
|
+
prefix: "deps"
|
|
14
|
+
|
|
15
|
+
# GitHub Actions
|
|
16
|
+
- package-ecosystem: "github-actions"
|
|
17
|
+
directory: "/"
|
|
18
|
+
schedule:
|
|
19
|
+
interval: "weekly"
|
|
20
|
+
day: "monday"
|
|
21
|
+
open-pull-requests-limit: 5
|
|
22
|
+
labels:
|
|
23
|
+
- "dependencies"
|
|
24
|
+
- "ci"
|
|
25
|
+
commit-message:
|
|
26
|
+
prefix: "ci"
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
## Summary
|
|
2
|
+
|
|
3
|
+
<!-- What does this PR do? 1-2 sentences. -->
|
|
4
|
+
|
|
5
|
+
## Changes
|
|
6
|
+
|
|
7
|
+
<!-- Bulleted list of key changes. -->
|
|
8
|
+
|
|
9
|
+
-
|
|
10
|
+
|
|
11
|
+
## Test plan
|
|
12
|
+
|
|
13
|
+
<!-- How was this tested? -->
|
|
14
|
+
|
|
15
|
+
- [ ] `make test` passes
|
|
16
|
+
- [ ] `make lint` passes
|
|
17
|
+
- [ ] New tests added for new functionality
|
|
18
|
+
|
|
19
|
+
## Related issues
|
|
20
|
+
|
|
21
|
+
<!-- Link any related issues: Fixes #123, Closes #456 -->
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
name: Cancel PR workflows on merge
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request_target:
|
|
5
|
+
types: [closed]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
actions: write
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
cancel:
|
|
12
|
+
if: github.event.pull_request.merged == true
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
timeout-minutes: 5
|
|
15
|
+
steps:
|
|
16
|
+
- name: Cancel in-progress and queued CI runs for merged PR
|
|
17
|
+
uses: actions/github-script@v7
|
|
18
|
+
with:
|
|
19
|
+
script: |
|
|
20
|
+
const branch = context.payload.pull_request.head.ref;
|
|
21
|
+
const headRepo = context.payload.pull_request.head.repo.full_name;
|
|
22
|
+
|
|
23
|
+
for (const status of ['in_progress', 'queued']) {
|
|
24
|
+
const { data: runs } = await github.rest.actions.listWorkflowRunsForRepo({
|
|
25
|
+
owner: context.repo.owner,
|
|
26
|
+
repo: context.repo.repo,
|
|
27
|
+
branch,
|
|
28
|
+
status,
|
|
29
|
+
});
|
|
30
|
+
for (const run of runs.workflow_runs) {
|
|
31
|
+
// Skip our own run
|
|
32
|
+
if (run.id === context.runId) continue;
|
|
33
|
+
// Only cancel runs from the same head repo (avoid fork name collisions)
|
|
34
|
+
if (run.head_repository?.full_name !== headRepo) continue;
|
|
35
|
+
// Only cancel PR-triggered runs
|
|
36
|
+
if (run.event !== 'pull_request') continue;
|
|
37
|
+
|
|
38
|
+
console.log(`Cancelling ${status} run ${run.id} (${run.name})`);
|
|
39
|
+
await github.rest.actions.cancelWorkflowRun({
|
|
40
|
+
owner: context.repo.owner,
|
|
41
|
+
repo: context.repo.repo,
|
|
42
|
+
run_id: run.id,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: read
|
|
12
|
+
pull-requests: read
|
|
13
|
+
|
|
14
|
+
concurrency:
|
|
15
|
+
group: ci-${{ github.workflow }}-${{ github.ref }}
|
|
16
|
+
cancel-in-progress: true
|
|
17
|
+
|
|
18
|
+
env:
|
|
19
|
+
COVERAGE_MIN: "75"
|
|
20
|
+
UV_CACHE_DIR: /tmp/.uv-cache
|
|
21
|
+
|
|
22
|
+
jobs:
|
|
23
|
+
# ── Path-based change detection ───────────────────────────────────
|
|
24
|
+
# Inverted logic: '**' matches every file, then '!' excludes docs/images.
|
|
25
|
+
# If ANY changed file is NOT a doc, 'code' is true → run CI.
|
|
26
|
+
# If ALL changed files are docs/images, 'code' is false → skip CI.
|
|
27
|
+
# On push/workflow_dispatch the filter always evaluates to true.
|
|
28
|
+
changes:
|
|
29
|
+
runs-on: ubuntu-latest
|
|
30
|
+
outputs:
|
|
31
|
+
should_run: ${{ steps.decide.outputs.should_run }}
|
|
32
|
+
steps:
|
|
33
|
+
- uses: actions/checkout@v6
|
|
34
|
+
- uses: dorny/paths-filter@v3
|
|
35
|
+
id: filter
|
|
36
|
+
with:
|
|
37
|
+
filters: |
|
|
38
|
+
code:
|
|
39
|
+
- '**'
|
|
40
|
+
- '!docs/**'
|
|
41
|
+
- '!plans/**'
|
|
42
|
+
- '!docs/**/*.md'
|
|
43
|
+
- '!CHANGELOG.md'
|
|
44
|
+
- '!CONTRIBUTING.md'
|
|
45
|
+
- '!**/*.png'
|
|
46
|
+
- '!**/*.jpg'
|
|
47
|
+
- '!**/*.svg'
|
|
48
|
+
- '!LICENSE'
|
|
49
|
+
- '!.gitignore'
|
|
50
|
+
- id: decide
|
|
51
|
+
run: |
|
|
52
|
+
# On push/workflow_dispatch always run; on PR skip if only docs changed
|
|
53
|
+
if [[ "${{ github.event_name }}" != "pull_request" ]]; then
|
|
54
|
+
echo "should_run=true" >> "$GITHUB_OUTPUT"
|
|
55
|
+
elif [[ "${{ steps.filter.outputs.code }}" == "true" ]]; then
|
|
56
|
+
echo "should_run=true" >> "$GITHUB_OUTPUT"
|
|
57
|
+
else
|
|
58
|
+
echo "should_run=false" >> "$GITHUB_OUTPUT"
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
# ── Lint ──────────────────────────────────────────────────────────
|
|
62
|
+
lint:
|
|
63
|
+
needs: changes
|
|
64
|
+
if: needs.changes.outputs.should_run == 'true'
|
|
65
|
+
runs-on: ubuntu-latest
|
|
66
|
+
timeout-minutes: 10
|
|
67
|
+
|
|
68
|
+
steps:
|
|
69
|
+
- uses: actions/checkout@v6
|
|
70
|
+
|
|
71
|
+
- uses: astral-sh/setup-uv@v7
|
|
72
|
+
with:
|
|
73
|
+
enable-cache: true
|
|
74
|
+
cache-dependency-glob: "pyproject.toml"
|
|
75
|
+
|
|
76
|
+
- name: Set up Python 3.11
|
|
77
|
+
uses: actions/setup-python@v6
|
|
78
|
+
with:
|
|
79
|
+
python-version: "3.11"
|
|
80
|
+
|
|
81
|
+
- name: Install dependencies
|
|
82
|
+
run: uv pip install --system -e ".[dev]"
|
|
83
|
+
|
|
84
|
+
- name: Lint
|
|
85
|
+
run: make lint
|
|
86
|
+
|
|
87
|
+
# ── Test matrix ───────────────────────────────────────────────────
|
|
88
|
+
test:
|
|
89
|
+
needs: [lint, changes]
|
|
90
|
+
if: needs.changes.outputs.should_run == 'true'
|
|
91
|
+
runs-on: ubuntu-latest
|
|
92
|
+
timeout-minutes: 20
|
|
93
|
+
strategy:
|
|
94
|
+
fail-fast: false
|
|
95
|
+
matrix:
|
|
96
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
97
|
+
|
|
98
|
+
steps:
|
|
99
|
+
- uses: actions/checkout@v6
|
|
100
|
+
|
|
101
|
+
- uses: astral-sh/setup-uv@v7
|
|
102
|
+
with:
|
|
103
|
+
enable-cache: true
|
|
104
|
+
cache-dependency-glob: "pyproject.toml"
|
|
105
|
+
|
|
106
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
107
|
+
uses: actions/setup-python@v6
|
|
108
|
+
with:
|
|
109
|
+
python-version: ${{ matrix.python-version }}
|
|
110
|
+
|
|
111
|
+
- name: Install dependencies
|
|
112
|
+
run: uv pip install --system -e ".[dev]"
|
|
113
|
+
|
|
114
|
+
- name: Test
|
|
115
|
+
run: pytest tests/ -q
|
|
116
|
+
|
|
117
|
+
# ── Coverage ──────────────────────────────────────────────────────
|
|
118
|
+
coverage:
|
|
119
|
+
needs: [lint, changes]
|
|
120
|
+
if: needs.changes.outputs.should_run == 'true'
|
|
121
|
+
runs-on: ubuntu-latest
|
|
122
|
+
timeout-minutes: 20
|
|
123
|
+
|
|
124
|
+
steps:
|
|
125
|
+
- uses: actions/checkout@v6
|
|
126
|
+
|
|
127
|
+
- uses: astral-sh/setup-uv@v7
|
|
128
|
+
with:
|
|
129
|
+
enable-cache: true
|
|
130
|
+
cache-dependency-glob: "pyproject.toml"
|
|
131
|
+
|
|
132
|
+
- name: Set up Python 3.11
|
|
133
|
+
uses: actions/setup-python@v6
|
|
134
|
+
with:
|
|
135
|
+
python-version: "3.11"
|
|
136
|
+
|
|
137
|
+
- name: Install dependencies
|
|
138
|
+
run: uv pip install --system -e ".[dev]"
|
|
139
|
+
|
|
140
|
+
- name: Coverage
|
|
141
|
+
run: |
|
|
142
|
+
pytest tests/ \
|
|
143
|
+
--cov=paperfarm \
|
|
144
|
+
--cov-report=term-missing \
|
|
145
|
+
--cov-report=xml \
|
|
146
|
+
--cov-fail-under=${COVERAGE_MIN}
|
|
147
|
+
|
|
148
|
+
- name: Upload coverage artifact
|
|
149
|
+
uses: actions/upload-artifact@v4
|
|
150
|
+
with:
|
|
151
|
+
name: coverage-xml
|
|
152
|
+
path: coverage.xml
|
|
153
|
+
|
|
154
|
+
- name: Upload to Codecov
|
|
155
|
+
if: always()
|
|
156
|
+
uses: codecov/codecov-action@v5
|
|
157
|
+
with:
|
|
158
|
+
files: coverage.xml
|
|
159
|
+
fail_ci_if_error: false
|
|
160
|
+
env:
|
|
161
|
+
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
162
|
+
|
|
163
|
+
# ── Security: pip-audit ───────────────────────────────────────────
|
|
164
|
+
security-audit:
|
|
165
|
+
needs: changes
|
|
166
|
+
if: needs.changes.outputs.should_run == 'true'
|
|
167
|
+
runs-on: ubuntu-latest
|
|
168
|
+
timeout-minutes: 10
|
|
169
|
+
|
|
170
|
+
steps:
|
|
171
|
+
- uses: actions/checkout@v6
|
|
172
|
+
|
|
173
|
+
- uses: astral-sh/setup-uv@v7
|
|
174
|
+
with:
|
|
175
|
+
enable-cache: true
|
|
176
|
+
cache-dependency-glob: "pyproject.toml"
|
|
177
|
+
|
|
178
|
+
- name: Set up Python 3.11
|
|
179
|
+
uses: actions/setup-python@v6
|
|
180
|
+
with:
|
|
181
|
+
python-version: "3.11"
|
|
182
|
+
|
|
183
|
+
- name: Install dependencies from frozen lockfile
|
|
184
|
+
run: |
|
|
185
|
+
uv sync --frozen
|
|
186
|
+
uv pip install --system pip-audit
|
|
187
|
+
|
|
188
|
+
- name: Audit dependencies for known vulnerabilities
|
|
189
|
+
run: |
|
|
190
|
+
uv export --frozen --no-hashes -o /tmp/requirements-audit.txt
|
|
191
|
+
pip-audit -r /tmp/requirements-audit.txt
|
|
192
|
+
|
|
193
|
+
# ── Package smoke test ────────────────────────────────────────────
|
|
194
|
+
package-smoke:
|
|
195
|
+
needs: [lint, changes]
|
|
196
|
+
if: needs.changes.outputs.should_run == 'true'
|
|
197
|
+
runs-on: ubuntu-latest
|
|
198
|
+
timeout-minutes: 10
|
|
199
|
+
|
|
200
|
+
steps:
|
|
201
|
+
- uses: actions/checkout@v6
|
|
202
|
+
|
|
203
|
+
- uses: astral-sh/setup-uv@v7
|
|
204
|
+
with:
|
|
205
|
+
enable-cache: true
|
|
206
|
+
cache-dependency-glob: "pyproject.toml"
|
|
207
|
+
|
|
208
|
+
- name: Set up Python 3.11
|
|
209
|
+
uses: actions/setup-python@v6
|
|
210
|
+
with:
|
|
211
|
+
python-version: "3.11"
|
|
212
|
+
|
|
213
|
+
- name: Build and install wheel
|
|
214
|
+
run: |
|
|
215
|
+
uv pip install --system build
|
|
216
|
+
python -m build
|
|
217
|
+
uv pip install --system dist/*.whl
|
|
218
|
+
|
|
219
|
+
- name: Smoke CLI entrypoint
|
|
220
|
+
run: paperfarm --help > /dev/null
|
|
221
|
+
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
name: CodeQL
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
schedule:
|
|
9
|
+
- cron: "0 6 * * 1" # Every Monday at 06:00 UTC
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
security-events: write
|
|
14
|
+
|
|
15
|
+
concurrency:
|
|
16
|
+
group: codeql-${{ github.ref }}
|
|
17
|
+
cancel-in-progress: true
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
analyze:
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
timeout-minutes: 15
|
|
23
|
+
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@v6
|
|
26
|
+
|
|
27
|
+
- name: Initialize CodeQL
|
|
28
|
+
uses: github/codeql-action/init@v4
|
|
29
|
+
with:
|
|
30
|
+
languages: python
|
|
31
|
+
queries: +security-extended
|
|
32
|
+
|
|
33
|
+
- name: Perform CodeQL analysis
|
|
34
|
+
uses: github/codeql-action/analyze@v4
|
|
35
|
+
with:
|
|
36
|
+
category: "/language:python"
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags: ["v*"]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
build:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
timeout-minutes: 10
|
|
14
|
+
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v6
|
|
17
|
+
|
|
18
|
+
- uses: actions/setup-python@v6
|
|
19
|
+
with:
|
|
20
|
+
python-version: "3.11"
|
|
21
|
+
|
|
22
|
+
- name: Install build tools
|
|
23
|
+
run: pip install build
|
|
24
|
+
|
|
25
|
+
- name: Build sdist and wheel
|
|
26
|
+
run: python -m build
|
|
27
|
+
|
|
28
|
+
- name: Upload dist artifacts
|
|
29
|
+
uses: actions/upload-artifact@v4
|
|
30
|
+
with:
|
|
31
|
+
name: dist
|
|
32
|
+
path: dist/
|
|
33
|
+
|
|
34
|
+
publish-pypi:
|
|
35
|
+
needs: build
|
|
36
|
+
runs-on: ubuntu-latest
|
|
37
|
+
timeout-minutes: 10
|
|
38
|
+
environment: pypi
|
|
39
|
+
permissions:
|
|
40
|
+
id-token: write
|
|
41
|
+
|
|
42
|
+
steps:
|
|
43
|
+
- uses: actions/download-artifact@v4
|
|
44
|
+
with:
|
|
45
|
+
name: dist
|
|
46
|
+
path: dist/
|
|
47
|
+
|
|
48
|
+
- name: Publish to PyPI
|
|
49
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
*$py.class
|
|
4
|
+
*.egg-info/
|
|
5
|
+
dist/
|
|
6
|
+
build/
|
|
7
|
+
.eggs/
|
|
8
|
+
*.egg
|
|
9
|
+
.venv/
|
|
10
|
+
.venv-pf/
|
|
11
|
+
venv/
|
|
12
|
+
env/
|
|
13
|
+
.pytest_cache/
|
|
14
|
+
.ruff_cache/
|
|
15
|
+
.mypy_cache/
|
|
16
|
+
htmlcov/
|
|
17
|
+
.coverage
|
|
18
|
+
coverage.xml
|
|
19
|
+
*.log
|
|
20
|
+
.DS_Store
|
|
21
|
+
|
|
22
|
+
# Research runtime data (created by `open-researcher init`)
|
|
23
|
+
.research/
|
|
24
|
+
/events.jsonl
|
|
25
|
+
|
|
26
|
+
# Demo workspace
|
|
27
|
+
_demo_workspace/
|
|
28
|
+
|
|
29
|
+
# Editor/IDE
|
|
30
|
+
.idea/
|
|
31
|
+
.vscode/
|
|
32
|
+
*.swp
|
|
33
|
+
*.swo
|
|
34
|
+
*~
|
|
35
|
+
|
|
36
|
+
# OS
|
|
37
|
+
Thumbs.db
|
|
38
|
+
|
|
39
|
+
# Analysis reports (generated, not source)
|
|
40
|
+
analysis/
|
|
41
|
+
.worktrees/
|