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.
Files changed (130) hide show
  1. sovereign_fleet-0.6.0/.github/FUNDING.yml +2 -0
  2. sovereign_fleet-0.6.0/.github/ISSUE_TEMPLATE/bug_report.yml +32 -0
  3. sovereign_fleet-0.6.0/.github/ISSUE_TEMPLATE/feature_request.yml +21 -0
  4. sovereign_fleet-0.6.0/.github/dependabot.yml +17 -0
  5. sovereign_fleet-0.6.0/.github/pull_request_template.md +11 -0
  6. sovereign_fleet-0.6.0/.github/workflows/ci.yml +38 -0
  7. sovereign_fleet-0.6.0/.github/workflows/contribution-check.yml +111 -0
  8. sovereign_fleet-0.6.0/.github/workflows/guardrails.yml +27 -0
  9. sovereign_fleet-0.6.0/.github/workflows/publish-pypi.yml +29 -0
  10. sovereign_fleet-0.6.0/.github/workflows/release.yml +64 -0
  11. sovereign_fleet-0.6.0/.gitignore +14 -0
  12. sovereign_fleet-0.6.0/AGENTS.md +28 -0
  13. sovereign_fleet-0.6.0/CHANGELOG.md +423 -0
  14. sovereign_fleet-0.6.0/CODE_OF_CONDUCT.md +43 -0
  15. sovereign_fleet-0.6.0/CONTRIBUTING.md +83 -0
  16. sovereign_fleet-0.6.0/LICENSE +21 -0
  17. sovereign_fleet-0.6.0/PKG-INFO +432 -0
  18. sovereign_fleet-0.6.0/README.md +379 -0
  19. sovereign_fleet-0.6.0/SECURITY.md +24 -0
  20. sovereign_fleet-0.6.0/docs/EVALS_AND_BENCHMARKS.md +94 -0
  21. sovereign_fleet-0.6.0/docs/HARNESS_PLUGINS.md +284 -0
  22. sovereign_fleet-0.6.0/docs/INSTALL.md +137 -0
  23. sovereign_fleet-0.6.0/docs/MIGRATION.md +189 -0
  24. sovereign_fleet-0.6.0/examples/custom_harness/README.md +41 -0
  25. sovereign_fleet-0.6.0/examples/custom_harness/echo_agent/__init__.py +5 -0
  26. sovereign_fleet-0.6.0/examples/custom_harness/echo_agent/cli.py +34 -0
  27. sovereign_fleet-0.6.0/examples/custom_harness/echo_agent/harness.py +66 -0
  28. sovereign_fleet-0.6.0/examples/custom_harness/pyproject.toml +23 -0
  29. sovereign_fleet-0.6.0/llms.txt +31 -0
  30. sovereign_fleet-0.6.0/pyproject.toml +61 -0
  31. sovereign_fleet-0.6.0/recipes/fleet-ab-proposal-eval/README.md +36 -0
  32. sovereign_fleet-0.6.0/recipes/fleet-ab-proposal-eval/recipe.yaml +85 -0
  33. sovereign_fleet-0.6.0/recipes/fleet-bench-runner/README.md +33 -0
  34. sovereign_fleet-0.6.0/recipes/fleet-bench-runner/recipe.yaml +85 -0
  35. sovereign_fleet-0.6.0/recipes/fleet-self-improvement/README.md +38 -0
  36. sovereign_fleet-0.6.0/recipes/fleet-self-improvement/recipe.yaml +86 -0
  37. sovereign_fleet-0.6.0/scripts/bump_version.py +353 -0
  38. sovereign_fleet-0.6.0/scripts/check_pr_guardrails.py +236 -0
  39. sovereign_fleet-0.6.0/scripts/verify.sh +8 -0
  40. sovereign_fleet-0.6.0/src/fleet/__init__.py +23 -0
  41. sovereign_fleet-0.6.0/src/fleet/api/app.py +807 -0
  42. sovereign_fleet-0.6.0/src/fleet/api/auth.py +83 -0
  43. sovereign_fleet-0.6.0/src/fleet/api/background.py +148 -0
  44. sovereign_fleet-0.6.0/src/fleet/api/cli.py +631 -0
  45. sovereign_fleet-0.6.0/src/fleet/api/dashboard.html +6188 -0
  46. sovereign_fleet-0.6.0/src/fleet/api/manifest.json +38 -0
  47. sovereign_fleet-0.6.0/src/fleet/api/mcp_server.py +499 -0
  48. sovereign_fleet-0.6.0/src/fleet/api/static/icon-192.png +0 -0
  49. sovereign_fleet-0.6.0/src/fleet/api/static/icon-512.png +0 -0
  50. sovereign_fleet-0.6.0/src/fleet/api/static/icon.svg +21 -0
  51. sovereign_fleet-0.6.0/src/fleet/api/static/sw.js +54 -0
  52. sovereign_fleet-0.6.0/src/fleet/core/backends.py +745 -0
  53. sovereign_fleet-0.6.0/src/fleet/core/bakeoff_priors.json +22 -0
  54. sovereign_fleet-0.6.0/src/fleet/core/catalog.py +223 -0
  55. sovereign_fleet-0.6.0/src/fleet/core/config.py +600 -0
  56. sovereign_fleet-0.6.0/src/fleet/core/conformance.py +419 -0
  57. sovereign_fleet-0.6.0/src/fleet/core/engine.py +796 -0
  58. sovereign_fleet-0.6.0/src/fleet/core/executor.py +239 -0
  59. sovereign_fleet-0.6.0/src/fleet/core/gateguard.py +77 -0
  60. sovereign_fleet-0.6.0/src/fleet/core/gates.py +294 -0
  61. sovereign_fleet-0.6.0/src/fleet/core/landing.py +210 -0
  62. sovereign_fleet-0.6.0/src/fleet/core/lane_health.py +569 -0
  63. sovereign_fleet-0.6.0/src/fleet/core/models.py +103 -0
  64. sovereign_fleet-0.6.0/src/fleet/core/quirks.py +171 -0
  65. sovereign_fleet-0.6.0/src/fleet/core/quota.py +264 -0
  66. sovereign_fleet-0.6.0/src/fleet/core/receipts.py +230 -0
  67. sovereign_fleet-0.6.0/src/fleet/core/review.py +195 -0
  68. sovereign_fleet-0.6.0/src/fleet/core/roster.py +197 -0
  69. sovereign_fleet-0.6.0/src/fleet/core/router.py +668 -0
  70. sovereign_fleet-0.6.0/src/fleet/core/sandbox.py +333 -0
  71. sovereign_fleet-0.6.0/src/fleet/core/settings.py +72 -0
  72. sovereign_fleet-0.6.0/src/fleet/core/taskstore.py +352 -0
  73. sovereign_fleet-0.6.0/src/fleet/core/worktree.py +243 -0
  74. sovereign_fleet-0.6.0/src/fleet/fleet.example.toml +146 -0
  75. sovereign_fleet-0.6.0/src/fleet/plugins/base.py +116 -0
  76. sovereign_fleet-0.6.0/src/fleet/plugins/harness_base.py +430 -0
  77. sovereign_fleet-0.6.0/src/fleet/plugins/intake.py +661 -0
  78. sovereign_fleet-0.6.0/src/fleet/plugins/landing.py +113 -0
  79. sovereign_fleet-0.6.0/src/fleet/plugins/matrix_input.py +39 -0
  80. sovereign_fleet-0.6.0/src/fleet/plugins/output_matrix.py +303 -0
  81. sovereign_fleet-0.6.0/src/fleet/plugins/registry.py +168 -0
  82. sovereign_fleet-0.6.0/tests/conftest.py +74 -0
  83. sovereign_fleet-0.6.0/tests/test_api.py +446 -0
  84. sovereign_fleet-0.6.0/tests/test_autopsy.py +197 -0
  85. sovereign_fleet-0.6.0/tests/test_bump_version.py +510 -0
  86. sovereign_fleet-0.6.0/tests/test_cancel_local.py +263 -0
  87. sovereign_fleet-0.6.0/tests/test_catalog.py +52 -0
  88. sovereign_fleet-0.6.0/tests/test_cli.py +86 -0
  89. sovereign_fleet-0.6.0/tests/test_composite_backend.py +205 -0
  90. sovereign_fleet-0.6.0/tests/test_config.py +301 -0
  91. sovereign_fleet-0.6.0/tests/test_conformance.py +149 -0
  92. sovereign_fleet-0.6.0/tests/test_dashboard_h4.py +110 -0
  93. sovereign_fleet-0.6.0/tests/test_dashboard_layout.py +52 -0
  94. sovereign_fleet-0.6.0/tests/test_dashboard_offline.py +46 -0
  95. sovereign_fleet-0.6.0/tests/test_engine.py +191 -0
  96. sovereign_fleet-0.6.0/tests/test_example_harness.py +165 -0
  97. sovereign_fleet-0.6.0/tests/test_executor.py +637 -0
  98. sovereign_fleet-0.6.0/tests/test_executor_daemon.py +265 -0
  99. sovereign_fleet-0.6.0/tests/test_gateguard.py +48 -0
  100. sovereign_fleet-0.6.0/tests/test_gates.py +276 -0
  101. sovereign_fleet-0.6.0/tests/test_grid_backend.py +413 -0
  102. sovereign_fleet-0.6.0/tests/test_guardrails_ci.py +117 -0
  103. sovereign_fleet-0.6.0/tests/test_harness_select.py +146 -0
  104. sovereign_fleet-0.6.0/tests/test_harnesses.py +463 -0
  105. sovereign_fleet-0.6.0/tests/test_intake.py +548 -0
  106. sovereign_fleet-0.6.0/tests/test_landing.py +276 -0
  107. sovereign_fleet-0.6.0/tests/test_lane_health.py +516 -0
  108. sovereign_fleet-0.6.0/tests/test_live_pair.py +78 -0
  109. sovereign_fleet-0.6.0/tests/test_matrix_plugin.py +216 -0
  110. sovereign_fleet-0.6.0/tests/test_mcp.py +164 -0
  111. sovereign_fleet-0.6.0/tests/test_models.py +333 -0
  112. sovereign_fleet-0.6.0/tests/test_models_from_lanes.py +98 -0
  113. sovereign_fleet-0.6.0/tests/test_output_plugin.py +17 -0
  114. sovereign_fleet-0.6.0/tests/test_pair_failover.py +87 -0
  115. sovereign_fleet-0.6.0/tests/test_plugins_base.py +26 -0
  116. sovereign_fleet-0.6.0/tests/test_quirks.py +161 -0
  117. sovereign_fleet-0.6.0/tests/test_quota.py +63 -0
  118. sovereign_fleet-0.6.0/tests/test_recipes.py +135 -0
  119. sovereign_fleet-0.6.0/tests/test_registry.py +226 -0
  120. sovereign_fleet-0.6.0/tests/test_repo_files.py +55 -0
  121. sovereign_fleet-0.6.0/tests/test_review_loop.py +306 -0
  122. sovereign_fleet-0.6.0/tests/test_roster.py +110 -0
  123. sovereign_fleet-0.6.0/tests/test_router.py +500 -0
  124. sovereign_fleet-0.6.0/tests/test_router_pairs.py +320 -0
  125. sovereign_fleet-0.6.0/tests/test_sandbox.py +30 -0
  126. sovereign_fleet-0.6.0/tests/test_security.py +238 -0
  127. sovereign_fleet-0.6.0/tests/test_shadow_parity.py +29 -0
  128. sovereign_fleet-0.6.0/tests/test_taskstore.py +159 -0
  129. sovereign_fleet-0.6.0/tests/test_version.py +11 -0
  130. sovereign_fleet-0.6.0/tests/test_worktree.py +127 -0
@@ -0,0 +1,2 @@
1
+ # Sponsor button: value-for-value support on sovgrid.org
2
+ custom: ["https://sovgrid.org/support/"]
@@ -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,14 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *$py.class
4
+ *.so
5
+ .pytest_cache/
6
+ .ruff_cache/
7
+ build/
8
+ dist/
9
+ *.egg-info/
10
+ .venv/
11
+ certs/
12
+ *.crt
13
+ *.key
14
+ .fleet_test_spool/
@@ -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.