sovereign-fleet 0.6.0__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.
- sovereign_fleet-0.6.0/.github/FUNDING.yml +2 -0
- sovereign_fleet-0.6.0/.github/ISSUE_TEMPLATE/bug_report.yml +32 -0
- sovereign_fleet-0.6.0/.github/ISSUE_TEMPLATE/feature_request.yml +21 -0
- sovereign_fleet-0.6.0/.github/dependabot.yml +17 -0
- sovereign_fleet-0.6.0/.github/pull_request_template.md +11 -0
- sovereign_fleet-0.6.0/.github/workflows/ci.yml +38 -0
- sovereign_fleet-0.6.0/.github/workflows/contribution-check.yml +111 -0
- sovereign_fleet-0.6.0/.github/workflows/guardrails.yml +27 -0
- sovereign_fleet-0.6.0/.github/workflows/publish-pypi.yml +29 -0
- sovereign_fleet-0.6.0/.github/workflows/release.yml +64 -0
- sovereign_fleet-0.6.0/.gitignore +14 -0
- sovereign_fleet-0.6.0/AGENTS.md +28 -0
- sovereign_fleet-0.6.0/CHANGELOG.md +423 -0
- sovereign_fleet-0.6.0/CODE_OF_CONDUCT.md +43 -0
- sovereign_fleet-0.6.0/CONTRIBUTING.md +83 -0
- sovereign_fleet-0.6.0/LICENSE +21 -0
- sovereign_fleet-0.6.0/PKG-INFO +432 -0
- sovereign_fleet-0.6.0/README.md +379 -0
- sovereign_fleet-0.6.0/SECURITY.md +24 -0
- sovereign_fleet-0.6.0/docs/EVALS_AND_BENCHMARKS.md +94 -0
- sovereign_fleet-0.6.0/docs/HARNESS_PLUGINS.md +284 -0
- sovereign_fleet-0.6.0/docs/INSTALL.md +137 -0
- sovereign_fleet-0.6.0/docs/MIGRATION.md +189 -0
- sovereign_fleet-0.6.0/examples/custom_harness/README.md +41 -0
- sovereign_fleet-0.6.0/examples/custom_harness/echo_agent/__init__.py +5 -0
- sovereign_fleet-0.6.0/examples/custom_harness/echo_agent/cli.py +34 -0
- sovereign_fleet-0.6.0/examples/custom_harness/echo_agent/harness.py +66 -0
- sovereign_fleet-0.6.0/examples/custom_harness/pyproject.toml +23 -0
- sovereign_fleet-0.6.0/llms.txt +31 -0
- sovereign_fleet-0.6.0/pyproject.toml +61 -0
- sovereign_fleet-0.6.0/recipes/fleet-ab-proposal-eval/README.md +36 -0
- sovereign_fleet-0.6.0/recipes/fleet-ab-proposal-eval/recipe.yaml +85 -0
- sovereign_fleet-0.6.0/recipes/fleet-bench-runner/README.md +33 -0
- sovereign_fleet-0.6.0/recipes/fleet-bench-runner/recipe.yaml +85 -0
- sovereign_fleet-0.6.0/recipes/fleet-self-improvement/README.md +38 -0
- sovereign_fleet-0.6.0/recipes/fleet-self-improvement/recipe.yaml +86 -0
- sovereign_fleet-0.6.0/scripts/bump_version.py +353 -0
- sovereign_fleet-0.6.0/scripts/check_pr_guardrails.py +236 -0
- sovereign_fleet-0.6.0/scripts/verify.sh +8 -0
- sovereign_fleet-0.6.0/src/fleet/__init__.py +23 -0
- sovereign_fleet-0.6.0/src/fleet/api/app.py +807 -0
- sovereign_fleet-0.6.0/src/fleet/api/auth.py +83 -0
- sovereign_fleet-0.6.0/src/fleet/api/background.py +148 -0
- sovereign_fleet-0.6.0/src/fleet/api/cli.py +631 -0
- sovereign_fleet-0.6.0/src/fleet/api/dashboard.html +6188 -0
- sovereign_fleet-0.6.0/src/fleet/api/manifest.json +38 -0
- sovereign_fleet-0.6.0/src/fleet/api/mcp_server.py +499 -0
- sovereign_fleet-0.6.0/src/fleet/api/static/icon-192.png +0 -0
- sovereign_fleet-0.6.0/src/fleet/api/static/icon-512.png +0 -0
- sovereign_fleet-0.6.0/src/fleet/api/static/icon.svg +21 -0
- sovereign_fleet-0.6.0/src/fleet/api/static/sw.js +54 -0
- sovereign_fleet-0.6.0/src/fleet/core/backends.py +745 -0
- sovereign_fleet-0.6.0/src/fleet/core/bakeoff_priors.json +22 -0
- sovereign_fleet-0.6.0/src/fleet/core/catalog.py +223 -0
- sovereign_fleet-0.6.0/src/fleet/core/config.py +600 -0
- sovereign_fleet-0.6.0/src/fleet/core/conformance.py +419 -0
- sovereign_fleet-0.6.0/src/fleet/core/engine.py +796 -0
- sovereign_fleet-0.6.0/src/fleet/core/executor.py +239 -0
- sovereign_fleet-0.6.0/src/fleet/core/gateguard.py +77 -0
- sovereign_fleet-0.6.0/src/fleet/core/gates.py +294 -0
- sovereign_fleet-0.6.0/src/fleet/core/landing.py +210 -0
- sovereign_fleet-0.6.0/src/fleet/core/lane_health.py +569 -0
- sovereign_fleet-0.6.0/src/fleet/core/models.py +103 -0
- sovereign_fleet-0.6.0/src/fleet/core/quirks.py +171 -0
- sovereign_fleet-0.6.0/src/fleet/core/quota.py +264 -0
- sovereign_fleet-0.6.0/src/fleet/core/receipts.py +230 -0
- sovereign_fleet-0.6.0/src/fleet/core/review.py +195 -0
- sovereign_fleet-0.6.0/src/fleet/core/roster.py +197 -0
- sovereign_fleet-0.6.0/src/fleet/core/router.py +668 -0
- sovereign_fleet-0.6.0/src/fleet/core/sandbox.py +333 -0
- sovereign_fleet-0.6.0/src/fleet/core/settings.py +72 -0
- sovereign_fleet-0.6.0/src/fleet/core/taskstore.py +352 -0
- sovereign_fleet-0.6.0/src/fleet/core/worktree.py +243 -0
- sovereign_fleet-0.6.0/src/fleet/fleet.example.toml +146 -0
- sovereign_fleet-0.6.0/src/fleet/plugins/base.py +116 -0
- sovereign_fleet-0.6.0/src/fleet/plugins/harness_base.py +430 -0
- sovereign_fleet-0.6.0/src/fleet/plugins/intake.py +661 -0
- sovereign_fleet-0.6.0/src/fleet/plugins/landing.py +113 -0
- sovereign_fleet-0.6.0/src/fleet/plugins/matrix_input.py +39 -0
- sovereign_fleet-0.6.0/src/fleet/plugins/output_matrix.py +303 -0
- sovereign_fleet-0.6.0/src/fleet/plugins/registry.py +168 -0
- sovereign_fleet-0.6.0/tests/conftest.py +74 -0
- sovereign_fleet-0.6.0/tests/test_api.py +446 -0
- sovereign_fleet-0.6.0/tests/test_autopsy.py +197 -0
- sovereign_fleet-0.6.0/tests/test_bump_version.py +510 -0
- sovereign_fleet-0.6.0/tests/test_cancel_local.py +263 -0
- sovereign_fleet-0.6.0/tests/test_catalog.py +52 -0
- sovereign_fleet-0.6.0/tests/test_cli.py +86 -0
- sovereign_fleet-0.6.0/tests/test_composite_backend.py +205 -0
- sovereign_fleet-0.6.0/tests/test_config.py +301 -0
- sovereign_fleet-0.6.0/tests/test_conformance.py +149 -0
- sovereign_fleet-0.6.0/tests/test_dashboard_h4.py +110 -0
- sovereign_fleet-0.6.0/tests/test_dashboard_layout.py +52 -0
- sovereign_fleet-0.6.0/tests/test_dashboard_offline.py +46 -0
- sovereign_fleet-0.6.0/tests/test_engine.py +191 -0
- sovereign_fleet-0.6.0/tests/test_example_harness.py +165 -0
- sovereign_fleet-0.6.0/tests/test_executor.py +637 -0
- sovereign_fleet-0.6.0/tests/test_executor_daemon.py +265 -0
- sovereign_fleet-0.6.0/tests/test_gateguard.py +48 -0
- sovereign_fleet-0.6.0/tests/test_gates.py +276 -0
- sovereign_fleet-0.6.0/tests/test_grid_backend.py +413 -0
- sovereign_fleet-0.6.0/tests/test_guardrails_ci.py +117 -0
- sovereign_fleet-0.6.0/tests/test_harness_select.py +146 -0
- sovereign_fleet-0.6.0/tests/test_harnesses.py +463 -0
- sovereign_fleet-0.6.0/tests/test_intake.py +548 -0
- sovereign_fleet-0.6.0/tests/test_landing.py +276 -0
- sovereign_fleet-0.6.0/tests/test_lane_health.py +516 -0
- sovereign_fleet-0.6.0/tests/test_live_pair.py +78 -0
- sovereign_fleet-0.6.0/tests/test_matrix_plugin.py +216 -0
- sovereign_fleet-0.6.0/tests/test_mcp.py +164 -0
- sovereign_fleet-0.6.0/tests/test_models.py +333 -0
- sovereign_fleet-0.6.0/tests/test_models_from_lanes.py +98 -0
- sovereign_fleet-0.6.0/tests/test_output_plugin.py +17 -0
- sovereign_fleet-0.6.0/tests/test_pair_failover.py +87 -0
- sovereign_fleet-0.6.0/tests/test_plugins_base.py +26 -0
- sovereign_fleet-0.6.0/tests/test_quirks.py +161 -0
- sovereign_fleet-0.6.0/tests/test_quota.py +63 -0
- sovereign_fleet-0.6.0/tests/test_recipes.py +135 -0
- sovereign_fleet-0.6.0/tests/test_registry.py +226 -0
- sovereign_fleet-0.6.0/tests/test_repo_files.py +55 -0
- sovereign_fleet-0.6.0/tests/test_review_loop.py +306 -0
- sovereign_fleet-0.6.0/tests/test_roster.py +110 -0
- sovereign_fleet-0.6.0/tests/test_router.py +500 -0
- sovereign_fleet-0.6.0/tests/test_router_pairs.py +320 -0
- sovereign_fleet-0.6.0/tests/test_sandbox.py +30 -0
- sovereign_fleet-0.6.0/tests/test_security.py +238 -0
- sovereign_fleet-0.6.0/tests/test_shadow_parity.py +29 -0
- sovereign_fleet-0.6.0/tests/test_taskstore.py +159 -0
- sovereign_fleet-0.6.0/tests/test_version.py +11 -0
- sovereign_fleet-0.6.0/tests/test_worktree.py +127 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: Bug Report
|
|
2
|
+
description: Create a report to help us fix a bug in Sovereign Fleet
|
|
3
|
+
labels: ["bug"]
|
|
4
|
+
body:
|
|
5
|
+
- type: markdown
|
|
6
|
+
attributes:
|
|
7
|
+
value: Thanks for reporting an issue! Please verify your environment and include actionable logs.
|
|
8
|
+
- type: textarea
|
|
9
|
+
id: what-happened
|
|
10
|
+
attributes:
|
|
11
|
+
label: What happened?
|
|
12
|
+
description: Describe the problem clearly.
|
|
13
|
+
validations:
|
|
14
|
+
required: true
|
|
15
|
+
- type: textarea
|
|
16
|
+
id: steps-to-reproduce
|
|
17
|
+
attributes:
|
|
18
|
+
label: Steps to reproduce
|
|
19
|
+
description: Exact commands or configuration to reproduce the issue.
|
|
20
|
+
placeholder: |
|
|
21
|
+
1. Run `fleet ...`
|
|
22
|
+
2. Dispatch task ...
|
|
23
|
+
validations:
|
|
24
|
+
required: true
|
|
25
|
+
- type: textarea
|
|
26
|
+
id: environment
|
|
27
|
+
attributes:
|
|
28
|
+
label: Environment
|
|
29
|
+
description: OS version, kernel (`uname -r`), Python version (`python3 --version`), and agent CLI versions.
|
|
30
|
+
render: shell
|
|
31
|
+
validations:
|
|
32
|
+
required: true
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
name: Feature Request
|
|
2
|
+
description: Suggest an idea or enhancement for Sovereign Fleet
|
|
3
|
+
labels: ["enhancement"]
|
|
4
|
+
body:
|
|
5
|
+
- type: markdown
|
|
6
|
+
attributes:
|
|
7
|
+
value: Proposals should align with sovereign local execution, verified gates, or pluggable harnesses.
|
|
8
|
+
- type: textarea
|
|
9
|
+
id: problem
|
|
10
|
+
attributes:
|
|
11
|
+
label: Is your feature request related to a problem?
|
|
12
|
+
description: A clear and concise description of what the problem is.
|
|
13
|
+
validations:
|
|
14
|
+
required: true
|
|
15
|
+
- type: textarea
|
|
16
|
+
id: proposal
|
|
17
|
+
attributes:
|
|
18
|
+
label: Proposed Solution
|
|
19
|
+
description: How should Sovereign Fleet address this?
|
|
20
|
+
validations:
|
|
21
|
+
required: true
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: pip
|
|
4
|
+
directory: /
|
|
5
|
+
schedule:
|
|
6
|
+
interval: weekly
|
|
7
|
+
groups:
|
|
8
|
+
dependencies:
|
|
9
|
+
patterns: ["*"]
|
|
10
|
+
|
|
11
|
+
- package-ecosystem: github-actions
|
|
12
|
+
directory: /
|
|
13
|
+
schedule:
|
|
14
|
+
interval: weekly
|
|
15
|
+
groups:
|
|
16
|
+
actions:
|
|
17
|
+
patterns: ["*"]
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
## Summary
|
|
2
|
+
<!-- Describe what this change accomplishes, why it is needed, and link any related issues. -->
|
|
3
|
+
|
|
4
|
+
## Changes Made
|
|
5
|
+
-
|
|
6
|
+
|
|
7
|
+
## Verification & Quality Checklist
|
|
8
|
+
- [ ] `./scripts/verify.sh` passes locally (all tests and lint checks green).
|
|
9
|
+
- [ ] No secrets, tokens, or private hostnames committed.
|
|
10
|
+
- [ ] Tests added or updated for new functionality or bug fixes.
|
|
11
|
+
- [ ] Documentation updated if CLI options, endpoints, or configuration changed.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ main ]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [ main ]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
fail-fast: false
|
|
14
|
+
matrix:
|
|
15
|
+
python-version: ["3.11", "3.12"]
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- name: Check out repository
|
|
19
|
+
uses: actions/checkout@v7
|
|
20
|
+
|
|
21
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
22
|
+
uses: actions/setup-python@v7
|
|
23
|
+
with:
|
|
24
|
+
python-version: ${{ matrix.python-version }}
|
|
25
|
+
cache: "pip"
|
|
26
|
+
|
|
27
|
+
- name: Install dependencies
|
|
28
|
+
run: |
|
|
29
|
+
python -m pip install --upgrade pip
|
|
30
|
+
pip install -e ".[dev]"
|
|
31
|
+
|
|
32
|
+
- name: Check syntax and lint (Ruff)
|
|
33
|
+
run: |
|
|
34
|
+
python -m ruff check --select F,E9,B src tests
|
|
35
|
+
|
|
36
|
+
- name: Run test suite (pytest)
|
|
37
|
+
run: |
|
|
38
|
+
python -m pytest -q
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# Checks that issues and pull requests from outside the project are complete, and says what is missing.
|
|
2
|
+
#
|
|
3
|
+
# No LLM and no checkout: a small script reads the issue or PR through the GitHub API, compares it with
|
|
4
|
+
# the templates (.github/ISSUE_TEMPLATE/*.yml, .github/pull_request_template.md), and keeps one comment
|
|
5
|
+
# up to date plus the label "needs info". It runs again when the author edits the text or pushes, so the
|
|
6
|
+
# comment and the label follow. Maintainers, collaborators and bots are skipped.
|
|
7
|
+
#
|
|
8
|
+
# Maintainers are listed by login below on purpose: author_association is not enough, because an org
|
|
9
|
+
# member with private membership shows up as CONTRIBUTOR to the workflow token.
|
|
10
|
+
name: contribution-check
|
|
11
|
+
|
|
12
|
+
on:
|
|
13
|
+
issues:
|
|
14
|
+
types: [opened, edited, reopened]
|
|
15
|
+
pull_request_target: # base-branch code only; the contributed code is never checked out or run
|
|
16
|
+
types: [opened, edited, reopened, synchronize]
|
|
17
|
+
|
|
18
|
+
permissions:
|
|
19
|
+
contents: read
|
|
20
|
+
issues: write
|
|
21
|
+
pull-requests: write
|
|
22
|
+
|
|
23
|
+
concurrency:
|
|
24
|
+
group: contribution-check-${{ github.event.issue.number || github.event.pull_request.number }}
|
|
25
|
+
cancel-in-progress: true
|
|
26
|
+
|
|
27
|
+
jobs:
|
|
28
|
+
check:
|
|
29
|
+
if: >-
|
|
30
|
+
(github.event.issue.user.type || github.event.pull_request.user.type) != 'Bot' &&
|
|
31
|
+
!contains(fromJSON('["cipherfoxie"]'),
|
|
32
|
+
github.event.issue.user.login || github.event.pull_request.user.login) &&
|
|
33
|
+
!contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'),
|
|
34
|
+
github.event.issue.author_association || github.event.pull_request.author_association)
|
|
35
|
+
runs-on: ubuntu-latest
|
|
36
|
+
timeout-minutes: 5
|
|
37
|
+
steps:
|
|
38
|
+
- uses: actions/github-script@v9
|
|
39
|
+
with:
|
|
40
|
+
script: |
|
|
41
|
+
const MARK = '<!-- contribution-check -->';
|
|
42
|
+
const LABEL = 'needs info';
|
|
43
|
+
const isPR = !!context.payload.pull_request;
|
|
44
|
+
const item = isPR ? context.payload.pull_request : context.payload.issue;
|
|
45
|
+
const number = item.number;
|
|
46
|
+
const body = item.body || '';
|
|
47
|
+
const labels = (item.labels || []).map((l) => l.name);
|
|
48
|
+
const missing = [];
|
|
49
|
+
|
|
50
|
+
// text under a "### Heading" (issue forms) or "## Heading" (PR template), without HTML
|
|
51
|
+
// comments, the forms' "_No response_" and empty list bullets
|
|
52
|
+
const esc = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
53
|
+
const section = (title) => {
|
|
54
|
+
const re = new RegExp(`^#{2,3}\\s*${esc(title)}\\s*$([\\s\\S]*?)(?=^#{2,3}\\s|$(?![\\s\\S]))`, 'mi');
|
|
55
|
+
const m = body.match(re);
|
|
56
|
+
if (!m) return null;
|
|
57
|
+
return m[1].replace(/<!--[\s\S]*?-->/g, '').replace(/_No response_/g, '')
|
|
58
|
+
.replace(/^\s*[-*]\s*$/gm, '').trim();
|
|
59
|
+
};
|
|
60
|
+
const need = (title, hint) => { if (!section(title)) missing.push(hint || `"${title}"`); };
|
|
61
|
+
|
|
62
|
+
if (isPR) {
|
|
63
|
+
need('Summary', 'what the change does and why ("Summary")');
|
|
64
|
+
need('Changes Made', 'the list of changes ("Changes Made")');
|
|
65
|
+
const checklist = section('Verification & Quality Checklist') || '';
|
|
66
|
+
if (!/^\s*-\s*\[[xX]\]\s*`?\.\/scripts\/verify\.sh`?/m.test(checklist)) {
|
|
67
|
+
missing.push('`./scripts/verify.sh` run locally and ticked in the checklist');
|
|
68
|
+
}
|
|
69
|
+
const files = await github.paginate(github.rest.pulls.listFiles,
|
|
70
|
+
{ owner: context.repo.owner, repo: context.repo.repo, pull_number: number, per_page: 100 });
|
|
71
|
+
const names = files.map((f) => f.filename);
|
|
72
|
+
const docsOnly = names.length > 0 && names.every((n) => n.startsWith('docs/') || n.endsWith('.md'));
|
|
73
|
+
if (!docsOnly && !names.includes('CHANGELOG.md')) missing.push('a line in `CHANGELOG.md` under `[Unreleased]`');
|
|
74
|
+
const code = names.filter((n) => n.startsWith('src/'));
|
|
75
|
+
if (code.length && !names.some((n) => n.startsWith('tests/'))) missing.push('a test for the change under `tests/`');
|
|
76
|
+
} else if (labels.includes('bug')) {
|
|
77
|
+
need('What happened?');
|
|
78
|
+
need('Steps to reproduce');
|
|
79
|
+
need('Environment');
|
|
80
|
+
} else if (labels.includes('enhancement')) {
|
|
81
|
+
need('Is your feature request related to a problem?');
|
|
82
|
+
need('Proposed Solution');
|
|
83
|
+
} else if (!labels.some((l) => l.startsWith('roadmap') || l === 'idea' || l === 'question')) {
|
|
84
|
+
missing.push('the bug report or feature request template (New issue, then pick one)');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const who = `@${item.user.login}`;
|
|
88
|
+
const first = ['FIRST_TIME_CONTRIBUTOR', 'FIRST_TIMER'].includes(item.author_association);
|
|
89
|
+
const thanks = first ? `Thanks for your first ${isPR ? 'pull request' : 'issue'}, ${who}!` : `Thanks, ${who}!`;
|
|
90
|
+
const text = missing.length
|
|
91
|
+
? `${MARK}\n${thanks} To look at this, the maintainer needs:\n\n${missing.map((m) => `- ${m}`).join('\n')}\n\n` +
|
|
92
|
+
`Edit the ${isPR ? 'description or push a commit' : 'issue'} and this note updates by itself.`
|
|
93
|
+
: `${MARK}\n${thanks} Everything the template asks for is here; the maintainer will follow up.`;
|
|
94
|
+
|
|
95
|
+
const { owner, repo } = context.repo;
|
|
96
|
+
const comments = await github.paginate(github.rest.issues.listComments, { owner, repo, issue_number: number, per_page: 100 });
|
|
97
|
+
const mine = comments.find((c) => c.user.type === 'Bot' && c.body.startsWith(MARK));
|
|
98
|
+
if (mine) {
|
|
99
|
+
if (mine.body !== text) await github.rest.issues.updateComment({ owner, repo, comment_id: mine.id, body: text });
|
|
100
|
+
} else {
|
|
101
|
+
await github.rest.issues.createComment({ owner, repo, issue_number: number, body: text });
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (missing.length && !labels.includes(LABEL)) {
|
|
105
|
+
try { await github.rest.issues.getLabel({ owner, repo, name: LABEL }); }
|
|
106
|
+
catch { await github.rest.issues.createLabel({ owner, repo, name: LABEL, color: 'fbca04', description: 'Waiting for details from the author' }); }
|
|
107
|
+
await github.rest.issues.addLabels({ owner, repo, issue_number: number, labels: [LABEL] });
|
|
108
|
+
} else if (!missing.length && labels.includes(LABEL)) {
|
|
109
|
+
await github.rest.issues.removeLabel({ owner, repo, issue_number: number, name: LABEL });
|
|
110
|
+
}
|
|
111
|
+
core.info(missing.length ? `missing: ${missing.join('; ')}` : 'complete');
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
name: PR Guardrails
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
types: [opened, synchronize, reopened, edited]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
guardrails:
|
|
9
|
+
name: Scope & Gate Guardrails
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- name: Check out repository
|
|
13
|
+
uses: actions/checkout@v7
|
|
14
|
+
with:
|
|
15
|
+
fetch-depth: 0
|
|
16
|
+
|
|
17
|
+
- name: Set up Python
|
|
18
|
+
uses: actions/setup-python@v7
|
|
19
|
+
with:
|
|
20
|
+
python-version: "3.12"
|
|
21
|
+
|
|
22
|
+
- name: Run Guardrail Checks
|
|
23
|
+
env:
|
|
24
|
+
PR_BODY: ${{ github.event.pull_request.body }}
|
|
25
|
+
BASE_REF: origin/${{ github.base_ref }}
|
|
26
|
+
run: |
|
|
27
|
+
python3 scripts/check_pr_guardrails.py --pr-body "$PR_BODY" --base-ref "$BASE_REF"
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
name: publish-pypi
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
push:
|
|
6
|
+
tags: ["v*.*.*"]
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
pypi-publish:
|
|
10
|
+
name: Build and publish to PyPI
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
environment:
|
|
13
|
+
name: pypi
|
|
14
|
+
url: https://pypi.org/project/sovereign-fleet/
|
|
15
|
+
permissions:
|
|
16
|
+
id-token: write # Mandatory for PyPI trusted publishing (OIDC)
|
|
17
|
+
contents: read
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v7
|
|
20
|
+
- name: Install uv
|
|
21
|
+
uses: astral-sh/setup-uv@v7
|
|
22
|
+
- name: Build package
|
|
23
|
+
run: uv build
|
|
24
|
+
- name: Publish package distributions to PyPI
|
|
25
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
26
|
+
with:
|
|
27
|
+
packages-dir: dist/
|
|
28
|
+
# skip-existing: true ensures idempotent publishes
|
|
29
|
+
skip-existing: true
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
name: release
|
|
2
|
+
|
|
3
|
+
# A tag v*.*.* builds the package and creates a GitHub release whose notes are
|
|
4
|
+
# that version's CHANGELOG.md section. No PyPI publish yet.
|
|
5
|
+
on:
|
|
6
|
+
push:
|
|
7
|
+
tags: ["v*.*.*"]
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: write
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
build:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v7
|
|
17
|
+
- uses: actions/setup-python@v7
|
|
18
|
+
with:
|
|
19
|
+
python-version: "3.12"
|
|
20
|
+
cache: "pip"
|
|
21
|
+
- name: install build deps
|
|
22
|
+
run: |
|
|
23
|
+
python -m pip install --upgrade pip
|
|
24
|
+
pip install build pytest ruff
|
|
25
|
+
pip install -e ".[dev]"
|
|
26
|
+
- name: run tests
|
|
27
|
+
run: python -m pytest -q tests/test_bump_version.py
|
|
28
|
+
- name: build sdist and wheel
|
|
29
|
+
run: python -m build
|
|
30
|
+
- name: upload artifacts
|
|
31
|
+
uses: actions/upload-artifact@v7
|
|
32
|
+
with:
|
|
33
|
+
name: dist
|
|
34
|
+
path: dist/
|
|
35
|
+
|
|
36
|
+
release:
|
|
37
|
+
needs: build
|
|
38
|
+
runs-on: ubuntu-latest
|
|
39
|
+
steps:
|
|
40
|
+
- uses: actions/checkout@v7
|
|
41
|
+
- name: notes from CHANGELOG.md
|
|
42
|
+
run: |
|
|
43
|
+
v="${GITHUB_REF_NAME#v}"
|
|
44
|
+
awk -v v="$v" '$0 ~ "^## \\[" v "\\]" {on=1; next} /^## \[/ {if (on) exit} on' CHANGELOG.md > notes.md
|
|
45
|
+
test -s notes.md || echo "See CHANGELOG.md" > notes.md
|
|
46
|
+
- name: download artifacts
|
|
47
|
+
uses: actions/download-artifact@v8
|
|
48
|
+
with:
|
|
49
|
+
name: dist
|
|
50
|
+
path: dist/
|
|
51
|
+
- name: create or update the release
|
|
52
|
+
env:
|
|
53
|
+
GH_TOKEN: ${{ github.token }}
|
|
54
|
+
run: |
|
|
55
|
+
if gh release view "$GITHUB_REF_NAME" >/dev/null 2>&1; then
|
|
56
|
+
gh release upload "$GITHUB_REF_NAME" dist/* --clobber
|
|
57
|
+
else
|
|
58
|
+
gh release create "$GITHUB_REF_NAME" --title "Sovereign Fleet $GITHUB_REF_NAME" --notes-file notes.md --verify-tag dist/*
|
|
59
|
+
fi
|
|
60
|
+
# TODO: publish to PyPI when ready
|
|
61
|
+
# - name: publish to PyPI
|
|
62
|
+
# uses: pypa/gh-action-pypi-publish@release/v1
|
|
63
|
+
# with:
|
|
64
|
+
# password: ${{ secrets.PYPI_API_TOKEN }}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# AGENTS.md - Agent Fleet Repository Contract
|
|
2
|
+
|
|
3
|
+
> Canonical rules for all autonomous agents operating on this repository.
|
|
4
|
+
|
|
5
|
+
## 1. Principles
|
|
6
|
+
- **Modularity:** Core engine has zero dependencies on specific chat or UI frameworks.
|
|
7
|
+
- **Plugin Architecture:** Ingestion (Input), Remotes (Control), Harnesses, and Notifications (Output) are isolated plugins.
|
|
8
|
+
- **Fail-Safe Sandboxing:** Never execute untrusted agent commands outside landlock-isolated worktrees.
|
|
9
|
+
- **Deterministic Gates:** Verify before claim. A task is only complete when verified by automated tests.
|
|
10
|
+
|
|
11
|
+
## 2. Directory Layout
|
|
12
|
+
- `src/fleet/core/`: TaskStore, Landlock sandbox, worktrees, engine, settings, roster, quota, GateGuard.
|
|
13
|
+
- `src/fleet/plugins/`: Plugin interfaces and builtin implementations (Matrix, HTTP, Harnesses).
|
|
14
|
+
- `src/fleet/api/`: Standalone FastAPI control plane and CLI entrypoint.
|
|
15
|
+
- `tests/`: Automated unit and integration test suite.
|
|
16
|
+
|
|
17
|
+
## 3. Test Standards
|
|
18
|
+
- Run tests via `pytest`.
|
|
19
|
+
- 100% passing tests required before committing changes.
|
|
20
|
+
- Security properties have tests that exercise the real thing (`tests/test_security.py`: sandbox, token, path traversal; `tests/test_worktree.py`: git config injection). Never weaken or skip them to make a change pass.
|
|
21
|
+
|
|
22
|
+
## 4. Honesty
|
|
23
|
+
- README, llms.txt, dashboard texts and the health endpoint describe what the code does today. No status value is hardcoded; anything not implemented is labelled as such.
|
|
24
|
+
|
|
25
|
+
## 5. Current work
|
|
26
|
+
- Migration from the grid runner: `docs/MIGRATION.md`. Phases 0 to 6 (6a to 6g: local daemon executor loop, crash recovery and worktree pruning, process-group cancellation, failure autopsies and atomic receipts, cross-lane review loop, Matrix output notifications and approvals-by-reply, and per-project `backend = "local"` strangler migration via `CompositeBackend`) are complete and verified in `docs/MIGRATION.md`.
|
|
27
|
+
- Review history: the maintainer's handover notes (outside this repository) and CHANGELOG.md, section "Corrected".
|
|
28
|
+
- A claim is not done until a test that fails without the change passes with it.
|