microcosm-emitter 0.2.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.
- microcosm_emitter-0.2.0/.github/workflows/ci.yml +99 -0
- microcosm_emitter-0.2.0/.github/workflows/pr.yaml +52 -0
- microcosm_emitter-0.2.0/.github/workflows/push.yaml +97 -0
- microcosm_emitter-0.2.0/.gitignore +12 -0
- microcosm_emitter-0.2.0/AGENTS.md +10 -0
- microcosm_emitter-0.2.0/CHANGELOG.md +28 -0
- microcosm_emitter-0.2.0/LICENSE +21 -0
- microcosm_emitter-0.2.0/PKG-INFO +83 -0
- microcosm_emitter-0.2.0/README.md +68 -0
- microcosm_emitter-0.2.0/changelog.d/.gitkeep +0 -0
- microcosm_emitter-0.2.0/conftest.py +29 -0
- microcosm_emitter-0.2.0/package.json +15 -0
- microcosm_emitter-0.2.0/pyproject.toml +79 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/__init__.py +1 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/core/__init__.py +1 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/core/alembic/env.py +28 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/core/alembic/script.py.mako +31 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/core/alembic/versions/v20261007_01_initial_spool.py +85 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/core/alembic/versions/v20261008_02_graph_publication.py +27 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/core/auth.py +169 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/core/constants.py +69 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/core/database.py +34 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/core/migrations.py +78 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/core/models.py +145 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/host/__init__.py +1 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/host/__main__.py +50 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/host/client.py +132 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/host/constants.py +21 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/host/contracts.py +35 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/host/errors.py +52 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/host/launcher.py +184 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/host/loading.py +22 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/host/process.py +20 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/host/request_dispatch.py +96 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/host/runtime.py +227 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/orrery/__init__.py +1 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/orrery/cli.py +39 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/orrery/client.py +229 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/orrery/constants.py +5 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/orrery/contracts.py +57 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/orrery/py.typed +1 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/orrery/service/__init__.py +8 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/orrery/service/module.py +98 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/orrery/service/queue.py +447 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/py.typed +1 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/telemetry/__init__.py +1 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/telemetry/client.py +295 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/telemetry/constants.py +16 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/telemetry/protocol.py +57 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/telemetry/requests.py +14 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/telemetry/serialization.py +24 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/telemetry/service/__init__.py +14 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/telemetry/service/collector.py +186 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/telemetry/service/lifecycle.py +346 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/telemetry/service/module.py +128 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/telemetry/service/resources.py +45 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/telemetry/service/sanitization.py +94 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/telemetry/service/spool.py +286 -0
- microcosm_emitter-0.2.0/src/microcosm_emitter/telemetry/service/timestamps.py +11 -0
- microcosm_emitter-0.2.0/tests/fixtures/microcosm-1099.json +7 -0
- microcosm_emitter-0.2.0/tests/fixtures/microcosm-1099.sqlite3 +0 -0
- microcosm_emitter-0.2.0/tests/host/test_failures.py +111 -0
- microcosm_emitter-0.2.0/tests/host/test_multiple_modules.py +346 -0
- microcosm_emitter-0.2.0/tests/host/test_runtime.py +278 -0
- microcosm_emitter-0.2.0/tests/host/test_startup.py +296 -0
- microcosm_emitter-0.2.0/tests/orrery/test_client.py +352 -0
- microcosm_emitter-0.2.0/tests/orrery/test_publication.py +632 -0
- microcosm_emitter-0.2.0/tests/telemetry/test_client.py +319 -0
- microcosm_emitter-0.2.0/tests/telemetry/test_delivery.py +483 -0
- microcosm_emitter-0.2.0/tests/telemetry/test_module.py +477 -0
- microcosm_emitter-0.2.0/tests/telemetry/test_persistence.py +87 -0
- microcosm_emitter-0.2.0/tests/test_boundaries.py +123 -0
- microcosm_emitter-0.2.0/tests/test_collector_contract.py +317 -0
- microcosm_emitter-0.2.0/tests/test_package_names.py +53 -0
- microcosm_emitter-0.2.0/tests/test_queue_compatibility.py +53 -0
- microcosm_emitter-0.2.0/tests/test_subprocess.py +207 -0
- microcosm_emitter-0.2.0/tests/test_workflows.py +178 -0
- microcosm_emitter-0.2.0/tools/bump-version.py +101 -0
- microcosm_emitter-0.2.0/tools/check-artifacts.sh +10 -0
- microcosm_emitter-0.2.0/tools/check-changelog.sh +6 -0
- microcosm_emitter-0.2.0/tools/check-collector.sh +11 -0
- microcosm_emitter-0.2.0/tools/check-installed.py +53 -0
- microcosm_emitter-0.2.0/tools/check-quality.sh +8 -0
- microcosm_emitter-0.2.0/tools/check-reader-installed.ts +65 -0
- microcosm_emitter-0.2.0/tools/check-reader.sh +11 -0
- microcosm_emitter-0.2.0/tools/installed-smoke.py +201 -0
- microcosm_emitter-0.2.0/tools/publish-git-tag.sh +18 -0
- microcosm_emitter-0.2.0/tools/publish-reader.sh +10 -0
- microcosm_emitter-0.2.0/tools/update-version.sh +9 -0
- microcosm_emitter-0.2.0/typescript/orrery/README.md +13 -0
- microcosm_emitter-0.2.0/typescript/orrery/bun.lock +88 -0
- microcosm_emitter-0.2.0/typescript/orrery/package.json +46 -0
- microcosm_emitter-0.2.0/typescript/orrery/src/browser.ts +98 -0
- microcosm_emitter-0.2.0/typescript/orrery/src/contract.ts +130 -0
- microcosm_emitter-0.2.0/typescript/orrery/src/server.ts +52 -0
- microcosm_emitter-0.2.0/typescript/orrery/tests/contract.test.ts +43 -0
- microcosm_emitter-0.2.0/typescript/orrery/tests/reader.test.ts +160 -0
- microcosm_emitter-0.2.0/typescript/orrery/tsconfig.build.json +11 -0
- microcosm_emitter-0.2.0/typescript/orrery/tsconfig.json +13 -0
- microcosm_emitter-0.2.0/uv.lock +1028 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
name: Verify emitter
|
|
2
|
+
|
|
3
|
+
# Called by pr.yaml for every pull request and by push.yaml before tagging and
|
|
4
|
+
# publishing a release commit.
|
|
5
|
+
on:
|
|
6
|
+
workflow_call:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
quality:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
|
|
16
|
+
- uses: astral-sh/setup-uv@d0d8abe699bfb85fec6de9f7adb5ae17292296ff # v6
|
|
17
|
+
with:
|
|
18
|
+
python-version: "3.13"
|
|
19
|
+
- run: uv sync --locked
|
|
20
|
+
- run: bash tools/check-quality.sh
|
|
21
|
+
|
|
22
|
+
tests:
|
|
23
|
+
name: Tests (${{ matrix.os }}, Python ${{ matrix.python }})
|
|
24
|
+
runs-on: ${{ matrix.os }}
|
|
25
|
+
strategy:
|
|
26
|
+
fail-fast: false
|
|
27
|
+
matrix:
|
|
28
|
+
os: [ubuntu-latest, macos-latest]
|
|
29
|
+
python: ["3.13", "3.14"]
|
|
30
|
+
steps:
|
|
31
|
+
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
|
|
32
|
+
- uses: astral-sh/setup-uv@d0d8abe699bfb85fec6de9f7adb5ae17292296ff # v6
|
|
33
|
+
with:
|
|
34
|
+
python-version: ${{ matrix.python }}
|
|
35
|
+
- run: uv sync --locked
|
|
36
|
+
- run: uv run --no-sync pytest -m "not collector"
|
|
37
|
+
- run: bash tools/check-artifacts.sh
|
|
38
|
+
|
|
39
|
+
build-packages:
|
|
40
|
+
runs-on: ubuntu-latest
|
|
41
|
+
steps:
|
|
42
|
+
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
|
|
43
|
+
- uses: astral-sh/setup-uv@d0d8abe699bfb85fec6de9f7adb5ae17292296ff # v6
|
|
44
|
+
with:
|
|
45
|
+
python-version: "3.13"
|
|
46
|
+
- run: uv sync --locked
|
|
47
|
+
- run: bash tools/check-artifacts.sh
|
|
48
|
+
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
|
49
|
+
with:
|
|
50
|
+
name: distributions
|
|
51
|
+
path: dist/*
|
|
52
|
+
if-no-files-found: error
|
|
53
|
+
|
|
54
|
+
collector:
|
|
55
|
+
needs: build-packages
|
|
56
|
+
runs-on: ubuntu-latest
|
|
57
|
+
services:
|
|
58
|
+
postgres:
|
|
59
|
+
image: postgres:16-alpine
|
|
60
|
+
env:
|
|
61
|
+
POSTGRES_PASSWORD: postgres
|
|
62
|
+
POSTGRES_DB: telemetry_test
|
|
63
|
+
ports:
|
|
64
|
+
- 5432:5432
|
|
65
|
+
options: >-
|
|
66
|
+
--health-cmd "pg_isready -U postgres -d telemetry_test"
|
|
67
|
+
--health-interval 5s --health-timeout 5s --health-retries 10
|
|
68
|
+
env:
|
|
69
|
+
TEST_DATABASE_URL: postgresql+psycopg://postgres:postgres@127.0.0.1:5432/telemetry_test
|
|
70
|
+
steps:
|
|
71
|
+
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
|
|
72
|
+
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
|
|
73
|
+
with:
|
|
74
|
+
repository: PolicyEngine/calibration-diagnostics
|
|
75
|
+
ref: 280459c8d782658b3fb6098b27e9acba11af29d8
|
|
76
|
+
path: .collector
|
|
77
|
+
persist-credentials: false
|
|
78
|
+
- uses: astral-sh/setup-uv@d0d8abe699bfb85fec6de9f7adb5ae17292296ff # v6
|
|
79
|
+
with:
|
|
80
|
+
python-version: "3.13"
|
|
81
|
+
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
|
82
|
+
with:
|
|
83
|
+
name: distributions
|
|
84
|
+
path: dist
|
|
85
|
+
- run: bash tools/check-collector.sh
|
|
86
|
+
|
|
87
|
+
reader:
|
|
88
|
+
runs-on: ubuntu-latest
|
|
89
|
+
steps:
|
|
90
|
+
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
|
|
91
|
+
- uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
|
|
92
|
+
with:
|
|
93
|
+
bun-version: "1.4.2"
|
|
94
|
+
- run: bash tools/check-reader.sh
|
|
95
|
+
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
|
96
|
+
with:
|
|
97
|
+
name: orrery-reader
|
|
98
|
+
path: reader-dist/*.tgz
|
|
99
|
+
if-no-files-found: error
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
name: Pull request
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
|
|
6
|
+
# A new push to a pull request supersedes the run on its previous head.
|
|
7
|
+
concurrency:
|
|
8
|
+
group: ${{ github.workflow }}-${{ github.event.pull_request.number }}
|
|
9
|
+
cancel-in-progress: true
|
|
10
|
+
|
|
11
|
+
permissions:
|
|
12
|
+
contents: read
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
lint-workflows:
|
|
16
|
+
name: Lint workflows
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
|
|
20
|
+
with:
|
|
21
|
+
persist-credentials: false
|
|
22
|
+
# rhysd/actionlint 1.7.12, which also runs shellcheck on `run:` steps.
|
|
23
|
+
- uses: docker://rhysd/actionlint@sha256:b1934ee5f1c509618f2508e6eb47ee0d3520686341fec936f3b79331f9315667
|
|
24
|
+
with:
|
|
25
|
+
args: -color
|
|
26
|
+
|
|
27
|
+
changelog:
|
|
28
|
+
name: Check changelog fragment
|
|
29
|
+
runs-on: ubuntu-latest
|
|
30
|
+
steps:
|
|
31
|
+
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
|
|
32
|
+
with:
|
|
33
|
+
persist-credentials: false
|
|
34
|
+
- uses: astral-sh/setup-uv@d0d8abe699bfb85fec6de9f7adb5ae17292296ff # v6
|
|
35
|
+
with:
|
|
36
|
+
python-version: "3.13"
|
|
37
|
+
- run: bash tools/check-changelog.sh
|
|
38
|
+
|
|
39
|
+
verify:
|
|
40
|
+
uses: ./.github/workflows/ci.yml
|
|
41
|
+
|
|
42
|
+
# The main ruleset requires this check by name.
|
|
43
|
+
required:
|
|
44
|
+
name: Required checks
|
|
45
|
+
if: always()
|
|
46
|
+
needs: [lint-workflows, changelog, verify]
|
|
47
|
+
runs-on: ubuntu-latest
|
|
48
|
+
steps:
|
|
49
|
+
- name: Require all validation jobs to succeed
|
|
50
|
+
env:
|
|
51
|
+
RESULTS: ${{ join(needs.*.result, ' ') }}
|
|
52
|
+
run: test "$RESULTS" = "success success success"
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
name: Push
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
# Every merge runs this workflow twice. On the merge commit, versioning commits
|
|
11
|
+
# the new version and changelog as "Update microcosm-emitter" with the
|
|
12
|
+
# PolicyEngine GitHub App token: unlike GITHUB_TOKEN, its push starts another
|
|
13
|
+
# run, and the app may bypass the main ruleset. On that release commit, the
|
|
14
|
+
# remaining jobs verify, tag, then publish, each only after the one before.
|
|
15
|
+
#
|
|
16
|
+
# PyPI and npm trust this file by name, in the pypi environment, which only
|
|
17
|
+
# main can use. Renaming it stops publication.
|
|
18
|
+
jobs:
|
|
19
|
+
versioning:
|
|
20
|
+
name: Update versioning
|
|
21
|
+
if: |
|
|
22
|
+
github.repository == 'PolicyEngine/microcosm-emitter'
|
|
23
|
+
&& github.event.head_commit.message != 'Update microcosm-emitter'
|
|
24
|
+
runs-on: ubuntu-latest
|
|
25
|
+
steps:
|
|
26
|
+
- id: app-token
|
|
27
|
+
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
|
|
28
|
+
with:
|
|
29
|
+
app-id: ${{ secrets.APP_ID }}
|
|
30
|
+
private-key: ${{ secrets.APP_PRIVATE_KEY }}
|
|
31
|
+
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
|
|
32
|
+
with:
|
|
33
|
+
token: ${{ steps.app-token.outputs.token }}
|
|
34
|
+
- uses: astral-sh/setup-uv@d0d8abe699bfb85fec6de9f7adb5ae17292296ff # v6
|
|
35
|
+
with:
|
|
36
|
+
python-version: "3.13"
|
|
37
|
+
- run: bash tools/update-version.sh
|
|
38
|
+
- uses: EndBug/add-and-commit@290ea2c423ad77ca9c62ae0f5b224379612c0321 # v10
|
|
39
|
+
with:
|
|
40
|
+
add: "."
|
|
41
|
+
author_name: Github Actions[bot]
|
|
42
|
+
committer_name: Github Actions[bot]
|
|
43
|
+
message: Update microcosm-emitter
|
|
44
|
+
github_token: ${{ steps.app-token.outputs.token }}
|
|
45
|
+
fetch: false
|
|
46
|
+
|
|
47
|
+
verify:
|
|
48
|
+
if: |
|
|
49
|
+
github.repository == 'PolicyEngine/microcosm-emitter'
|
|
50
|
+
&& github.event.head_commit.message == 'Update microcosm-emitter'
|
|
51
|
+
uses: ./.github/workflows/ci.yml
|
|
52
|
+
|
|
53
|
+
tag:
|
|
54
|
+
name: Publish git tag
|
|
55
|
+
needs: verify
|
|
56
|
+
runs-on: ubuntu-latest
|
|
57
|
+
permissions:
|
|
58
|
+
contents: write
|
|
59
|
+
steps:
|
|
60
|
+
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
|
|
61
|
+
with:
|
|
62
|
+
fetch-depth: 0
|
|
63
|
+
- run: bash tools/publish-git-tag.sh
|
|
64
|
+
|
|
65
|
+
publish:
|
|
66
|
+
needs: tag
|
|
67
|
+
runs-on: ubuntu-latest
|
|
68
|
+
environment: pypi
|
|
69
|
+
permissions:
|
|
70
|
+
id-token: write
|
|
71
|
+
steps:
|
|
72
|
+
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
|
73
|
+
with:
|
|
74
|
+
name: distributions
|
|
75
|
+
path: dist
|
|
76
|
+
- uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # release/v1
|
|
77
|
+
with:
|
|
78
|
+
packages-dir: dist/
|
|
79
|
+
|
|
80
|
+
publish-reader:
|
|
81
|
+
needs: [verify, publish]
|
|
82
|
+
runs-on: ubuntu-latest
|
|
83
|
+
environment: pypi
|
|
84
|
+
permissions:
|
|
85
|
+
contents: read
|
|
86
|
+
id-token: write
|
|
87
|
+
steps:
|
|
88
|
+
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
|
|
89
|
+
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
|
|
90
|
+
with:
|
|
91
|
+
node-version: "24"
|
|
92
|
+
registry-url: "https://registry.npmjs.org"
|
|
93
|
+
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
|
94
|
+
with:
|
|
95
|
+
name: orrery-reader
|
|
96
|
+
path: reader-dist
|
|
97
|
+
- run: bash tools/publish-reader.sh
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Development instructions
|
|
2
|
+
|
|
3
|
+
- Use uv, Python 3.13+, pytest, and Ruff. Keep workflows as single-command calls to Bash scripts when shell logic has multiple lines.
|
|
4
|
+
- The generic runtime must not import telemetry or Microcosm. The telemetry client must not import service implementation, database, or authentication modules.
|
|
5
|
+
- Graph adapters must not import service, database, authentication or HTTP code. Inventory hashing, durable enqueue, receipt lookup and retries run in the separate local emitter service; no direct-database fallback.
|
|
6
|
+
- Publish only the `microcosm-emitter` distribution. Keep the generic host and required telemetry library internally separate under `microcosm_emitter`; do not introduce standalone telemetry packages or optional telemetry installation.
|
|
7
|
+
- Python databases use SQLAlchemy declarative ORM and Alembic exclusively. No handwritten SQL, direct-driver persistence, create_all(), schema repair, or pre-Alembic adoption. TypeScript database work, if introduced, must use Drizzle ORM and Drizzle Kit migrations.
|
|
8
|
+
- Tests use temporary databases created through real migrations, synthetic credentials, and loopback network services. Never use ambient credentials or contact the production collector in tests.
|
|
9
|
+
- Preserve the existing collector protocol; do not add a general hosted events API.
|
|
10
|
+
- Push feature branches and open PRs; do not push directly to main. Do not automatically merge or monitor queued checks.
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
## [0.2.0] - 2026-10-14
|
|
2
|
+
|
|
3
|
+
### Added
|
|
4
|
+
|
|
5
|
+
- Extract the local-service host, thin build adapter, and required telemetry library into the `microcosm-emitter` distribution.
|
|
6
|
+
- Add independent completed-graph publication and verified Orrery document readers alongside telemetry in the local provider.
|
|
7
|
+
|
|
8
|
+
### Changed
|
|
9
|
+
|
|
10
|
+
- Release automatically on every merge to main: bump one shared version from the changelog fragment types, commit the changelog, run all checks, tag the commit with the bare version, then publish to PyPI and npm through trusted publishing. Pull requests now require a typed changelog fragment, and GitHub releases no longer trigger publication.
|
|
11
|
+
- Define explicit types for publication inventories and results, and return a frozen record when reserving a graph upload.
|
|
12
|
+
- Integrate completed-graph publication into the single microcosm-emitter package. Keep graph adapters limited to socket requests and preserve shared SQLAlchemy/Alembic persistence, telemetry lifecycle behavior and separate TypeScript readers.
|
|
13
|
+
- Consolidate the process host and required telemetry library into one `microcosm-emitter` distribution, including Python imports, installed-module registration, CI, artifact verification, and publication.
|
|
14
|
+
|
|
15
|
+
Rename the GitHub project to `PolicyEngine/microcosm-emitter` and update source metadata, installation checks, and publishing documentation.
|
|
16
|
+
|
|
17
|
+
Rename the CI package-build job to `build-packages` and update its dependent jobs.
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- Use a shared 15-second startup default, enforce configuration and readiness deadlines, and report safe startup failure reasons without retaining private exception details.
|
|
22
|
+
- Keep graph file requests independent of telemetry acknowledgements, drain accepted requests before closing modules, and prevent older attempts from replacing newer graph publication status documents.
|
|
23
|
+
- Preserve valid stage identifiers unchanged in telemetry events and heartbeats. Reject malformed stage identifiers before persistence while continuing to redact credentials from messages and details.
|
|
24
|
+
- Preserve validation-refused build outcomes and caller-supplied failure codes in the telemetry service. Allow shared-host cleanup to wait until graph publication finishes. Retain only rejected producers' records locally after permanent collector HTTP client errors, and test these behaviors against the installed package and collector.
|
|
25
|
+
- Keep graph publication running when a preserved directory is removed or the local queue reports an error, and record the latest status only after the queue commit.
|
|
26
|
+
- Move stage tracking, event construction, and credential redaction into the separate local telemetry emitter service. Keep the build adapter limited to process startup, request serialization, socket transport, and shutdown. Commit all events from each request atomically before acknowledging it.
|
|
27
|
+
|
|
28
|
+
Wait for a successful socket ping before runtime tests send requests, and clean up the service when test setup fails. Cover delayed listening and failed initialization with regression tests.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 PolicyEngine
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: microcosm-emitter
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Local emitter process host with required build telemetry support
|
|
5
|
+
Project-URL: Source, https://github.com/PolicyEngine/microcosm-emitter
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Python: >=3.13
|
|
9
|
+
Requires-Dist: alembic<2,>=1.13.3
|
|
10
|
+
Requires-Dist: httpx<1,>=0.27
|
|
11
|
+
Requires-Dist: huggingface-hub<2,>=0.20
|
|
12
|
+
Requires-Dist: psutil<8,>=6
|
|
13
|
+
Requires-Dist: sqlalchemy<3,>=2
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
|
|
16
|
+
# Microcosm emitter
|
|
17
|
+
|
|
18
|
+
`microcosm-emitter` is one Python distribution containing the process host, required telemetry library and completed-graph publication library:
|
|
19
|
+
|
|
20
|
+
- `microcosm_emitter.host` owns subprocess startup, a private Unix socket, explicit module loading, parent-process monitoring, and shutdown. Its code does not import telemetry, database, authentication, or Microcosm modules.
|
|
21
|
+
- `microcosm_emitter.telemetry.client` is the thin build adapter. It starts the local telemetry emitter service and sends build requests, without importing the service implementation, database, or authentication libraries.
|
|
22
|
+
- `microcosm_emitter.telemetry.service` interprets those requests in the separate process. It owns stage tracking, event construction, credential redaction, resource sampling, SQLAlchemy ORM persistence, Alembic migrations, authentication, and collector delivery.
|
|
23
|
+
- `microcosm_emitter.orrery.client` sends graph inventory, enqueue, receipt and retry requests over the same private socket. It does not hash files, open a database, authenticate or upload.
|
|
24
|
+
- `microcosm_emitter.orrery.service` validates and hashes the selected graph files, commits publication jobs, and uploads exact bytes with retry and expiring worker reservations. A graph publication requires no telemetry run registration.
|
|
25
|
+
- `microcosm_emitter.core` provides service-side authentication and SQLAlchemy/Alembic persistence shared by the telemetry and graph libraries. The generic host does not import it.
|
|
26
|
+
|
|
27
|
+
Installing `microcosm-emitter` always installs the telemetry library and all its dependencies. Telemetry is not a standalone distribution or an optional extra. The package keeps import boundaries between the host, adapter, and service implementation; they do not need separate installation or publication.
|
|
28
|
+
|
|
29
|
+
The build process imports only the adapter, not the service implementation. It supplies run metadata, its existing queue path, and build identity. The adapter starts a separate local telemetry emitter service process automatically and sends requests over a private Unix socket. The adapter does not track stages, construct events, or redact telemetry. Imports alone create no processes, sockets, files, or network requests.
|
|
30
|
+
|
|
31
|
+
## Delivery and persistence
|
|
32
|
+
|
|
33
|
+
The service interprets requests such as a stage change or build failure, timestamps and redacts the resulting events, and saves them before acknowledging the socket request. A stage change can complete one stage and start another; both events commit in one SQLAlchemy ORM transaction, and the service changes its stage state only after that transaction succeeds. Periodic retention maintenance runs outside this acknowledgement path.
|
|
34
|
+
|
|
35
|
+
The adapter bounds socket calls and reports telemetry failures without failing the build. It converts Python arguments into JSON but does not process their telemetry meaning. Network requests run on the service worker, outside the message-handling lock.
|
|
36
|
+
|
|
37
|
+
`block()` finishes the current stage and records that validation checks refused the build, including the phase, check identifiers, failure count and optional check statuses. `fail(error_code=...)` preserves the caller's failure code alongside the exception type and failure class. Microcosm classifies interruptions, process termination and memory failures; this package forwards those classifications rather than duplicating them. Both outcomes finish telemetry, so later heartbeat or parent-exit handling cannot replace them.
|
|
38
|
+
|
|
39
|
+
The service uses the existing Hugging Face credential from the environment or local login cache. The collector validates PolicyEngine membership before issuing a short-lived write credential. Missing or rejected credentials permanently mark that producer's events as local-only. Permanent HTTP client errors when registering a run or uploading events also keep only the affected producer's records local; HTTP 408, 429, server errors and network failures remain retryable. HTTP 401 invalidates the short-lived credential for renewal. The production destination belongs to the package; development overrides accept loopback addresses only.
|
|
40
|
+
|
|
41
|
+
The queue upgrades the existing `20261007_01` Alembic revision to `20261008_02`, adding graph-job records without changing producer sequences, event IDs or upload eligibility. Unversioned databases are rejected without schema modification. There is no raw SQL, automatic schema adoption, or parallel legacy implementation. The hosted telemetry collector and calibration dashboard do not change.
|
|
42
|
+
|
|
43
|
+
## Graph publication
|
|
44
|
+
|
|
45
|
+
`GraphPublicationClient.start()` starts the graph module in a separate local emitter service process. `inventory()` asks that process to hash an explicit set of allowed graph files; `enqueue()` returns a pending receipt only after the job commits. `receipt()` reads its result and `retry()` makes a pending job eligible again. Startup or socket failures return an unavailable result, not a claim that a job was saved; the build adapter never writes a fallback database.
|
|
46
|
+
|
|
47
|
+
Graph requests allow up to 30 seconds for bounded file validation and hashing; telemetry acknowledgements, readiness probes and close requests keep their existing short timeout. Very slow storage can still exceed the graph request limit, so a timeout is not proof that a late service-side commit did or did not occur. Repeating an enqueue with the same publication ID and inventory is idempotent.
|
|
48
|
+
|
|
49
|
+
The host can also start telemetry and graph modules together with `start_services()`. Each module has an independent worker, so a slow graph upload does not block telemetry requests. Construct the telemetry adapter with `close_service_on_finish=False` when a build must publish graphs after recording completion, failure or refusal. Telemetry still finishes, but explicit outer cleanup closes the shared host after graph requests; standalone adapters close automatically by default. A module-specific graph client does not own shared-host shutdown. Both libraries share an existing HF credential and short-lived collector session, but graph jobs remain pending independently of telemetry event retention or local-only upload eligibility.
|
|
50
|
+
|
|
51
|
+
Preserve the selected source files until publication succeeds. `microcosm-emitter-publish-graph` asks the service to retry a publication by ID and can re-enqueue a preserved directory on another machine. It never rewrites the original build receipt; the queue and separate latest-status file record retries.
|
|
52
|
+
|
|
53
|
+
The existing TypeScript package `@policyengine/microcosm-provider-orrery` reads immutable published graph files on a server or in a browser. It remains separate from the Python distribution and does not change the hosted telemetry API.
|
|
54
|
+
|
|
55
|
+
## Development
|
|
56
|
+
|
|
57
|
+
Use Python 3.13 or 3.14 on Linux or macOS.
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
uv sync --locked
|
|
61
|
+
bash tools/check-quality.sh
|
|
62
|
+
uv run --no-sync pytest -m 'not collector'
|
|
63
|
+
bash tools/check-artifacts.sh
|
|
64
|
+
bash tools/check-reader.sh
|
|
65
|
+
bash tools/check-changelog.sh
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Tests isolate ambient credentials and use synthetic identities. The artifact check builds one source archive and wheel, installs that wheel into a clean environment away from the source checkout, verifies import boundaries, and exercises telemetry-only, graph-only and combined service startup with packaged migrations. Reader checks cover tests, formatting, types, build and an isolated tarball installation; they do not inspect visual styling.
|
|
69
|
+
|
|
70
|
+
The collector compatibility job tests the installed wheel against a pinned dashboard collector and disposable PostgreSQL. It covers the HTTP exchange, event ingestion, blocked outcomes and supplied failure codes in dashboard run documents, rejected identities, and duplicate delivery after a lost acknowledgement. Local execution requires that pinned collector checkout and a loopback test database; `tools/check-collector.sh` verifies these inputs. Never point this test at a deployed database. The pin verifies source compatibility, not which revision the hosted collector currently runs.
|
|
71
|
+
|
|
72
|
+
## Publication
|
|
73
|
+
|
|
74
|
+
Every merge to `main` releases the Python distribution `microcosm-emitter` to PyPI and the TypeScript reader `@policyengine/microcosm-provider-orrery` to npm at one shared version. Each pull request adds a changelog fragment named `changelog.d/<name>.<type>.md`, where the type is `breaking`, `added`, `changed`, `fixed` or `removed`; `tools/check-changelog.sh` refuses a pull request without one.
|
|
75
|
+
|
|
76
|
+
`push.yaml` runs twice for each merge:
|
|
77
|
+
|
|
78
|
+
1. On the merge commit, it bumps the version in `pyproject.toml`, both `package.json` files and `uv.lock`: a major bump for a breaking fragment, a minor bump for an added or removed fragment, and a patch bump otherwise. It collects the fragments into `CHANGELOG.md` and commits the result as "Update microcosm-emitter" using the PolicyEngine GitHub App, which may bypass the `main` ruleset.
|
|
79
|
+
2. On that commit, it runs every CI check, tags the commit with the bare version (for example `0.2.0`), publishes the tested wheel and source archive to PyPI, and then publishes the tested reader tarball to npm. Each step starts only after the one before succeeds.
|
|
80
|
+
|
|
81
|
+
Both registries accept uploads only through trusted publishing from `push.yaml` in the `pypi` environment, which only `main` can use. CI holds no long-lived registry token. Renaming the workflow or the environment stops publication until both registries' trusted-publisher settings change to match.
|
|
82
|
+
|
|
83
|
+
No hosted-service deployment or consumer activation follows from publishing this package.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Microcosm emitter
|
|
2
|
+
|
|
3
|
+
`microcosm-emitter` is one Python distribution containing the process host, required telemetry library and completed-graph publication library:
|
|
4
|
+
|
|
5
|
+
- `microcosm_emitter.host` owns subprocess startup, a private Unix socket, explicit module loading, parent-process monitoring, and shutdown. Its code does not import telemetry, database, authentication, or Microcosm modules.
|
|
6
|
+
- `microcosm_emitter.telemetry.client` is the thin build adapter. It starts the local telemetry emitter service and sends build requests, without importing the service implementation, database, or authentication libraries.
|
|
7
|
+
- `microcosm_emitter.telemetry.service` interprets those requests in the separate process. It owns stage tracking, event construction, credential redaction, resource sampling, SQLAlchemy ORM persistence, Alembic migrations, authentication, and collector delivery.
|
|
8
|
+
- `microcosm_emitter.orrery.client` sends graph inventory, enqueue, receipt and retry requests over the same private socket. It does not hash files, open a database, authenticate or upload.
|
|
9
|
+
- `microcosm_emitter.orrery.service` validates and hashes the selected graph files, commits publication jobs, and uploads exact bytes with retry and expiring worker reservations. A graph publication requires no telemetry run registration.
|
|
10
|
+
- `microcosm_emitter.core` provides service-side authentication and SQLAlchemy/Alembic persistence shared by the telemetry and graph libraries. The generic host does not import it.
|
|
11
|
+
|
|
12
|
+
Installing `microcosm-emitter` always installs the telemetry library and all its dependencies. Telemetry is not a standalone distribution or an optional extra. The package keeps import boundaries between the host, adapter, and service implementation; they do not need separate installation or publication.
|
|
13
|
+
|
|
14
|
+
The build process imports only the adapter, not the service implementation. It supplies run metadata, its existing queue path, and build identity. The adapter starts a separate local telemetry emitter service process automatically and sends requests over a private Unix socket. The adapter does not track stages, construct events, or redact telemetry. Imports alone create no processes, sockets, files, or network requests.
|
|
15
|
+
|
|
16
|
+
## Delivery and persistence
|
|
17
|
+
|
|
18
|
+
The service interprets requests such as a stage change or build failure, timestamps and redacts the resulting events, and saves them before acknowledging the socket request. A stage change can complete one stage and start another; both events commit in one SQLAlchemy ORM transaction, and the service changes its stage state only after that transaction succeeds. Periodic retention maintenance runs outside this acknowledgement path.
|
|
19
|
+
|
|
20
|
+
The adapter bounds socket calls and reports telemetry failures without failing the build. It converts Python arguments into JSON but does not process their telemetry meaning. Network requests run on the service worker, outside the message-handling lock.
|
|
21
|
+
|
|
22
|
+
`block()` finishes the current stage and records that validation checks refused the build, including the phase, check identifiers, failure count and optional check statuses. `fail(error_code=...)` preserves the caller's failure code alongside the exception type and failure class. Microcosm classifies interruptions, process termination and memory failures; this package forwards those classifications rather than duplicating them. Both outcomes finish telemetry, so later heartbeat or parent-exit handling cannot replace them.
|
|
23
|
+
|
|
24
|
+
The service uses the existing Hugging Face credential from the environment or local login cache. The collector validates PolicyEngine membership before issuing a short-lived write credential. Missing or rejected credentials permanently mark that producer's events as local-only. Permanent HTTP client errors when registering a run or uploading events also keep only the affected producer's records local; HTTP 408, 429, server errors and network failures remain retryable. HTTP 401 invalidates the short-lived credential for renewal. The production destination belongs to the package; development overrides accept loopback addresses only.
|
|
25
|
+
|
|
26
|
+
The queue upgrades the existing `20261007_01` Alembic revision to `20261008_02`, adding graph-job records without changing producer sequences, event IDs or upload eligibility. Unversioned databases are rejected without schema modification. There is no raw SQL, automatic schema adoption, or parallel legacy implementation. The hosted telemetry collector and calibration dashboard do not change.
|
|
27
|
+
|
|
28
|
+
## Graph publication
|
|
29
|
+
|
|
30
|
+
`GraphPublicationClient.start()` starts the graph module in a separate local emitter service process. `inventory()` asks that process to hash an explicit set of allowed graph files; `enqueue()` returns a pending receipt only after the job commits. `receipt()` reads its result and `retry()` makes a pending job eligible again. Startup or socket failures return an unavailable result, not a claim that a job was saved; the build adapter never writes a fallback database.
|
|
31
|
+
|
|
32
|
+
Graph requests allow up to 30 seconds for bounded file validation and hashing; telemetry acknowledgements, readiness probes and close requests keep their existing short timeout. Very slow storage can still exceed the graph request limit, so a timeout is not proof that a late service-side commit did or did not occur. Repeating an enqueue with the same publication ID and inventory is idempotent.
|
|
33
|
+
|
|
34
|
+
The host can also start telemetry and graph modules together with `start_services()`. Each module has an independent worker, so a slow graph upload does not block telemetry requests. Construct the telemetry adapter with `close_service_on_finish=False` when a build must publish graphs after recording completion, failure or refusal. Telemetry still finishes, but explicit outer cleanup closes the shared host after graph requests; standalone adapters close automatically by default. A module-specific graph client does not own shared-host shutdown. Both libraries share an existing HF credential and short-lived collector session, but graph jobs remain pending independently of telemetry event retention or local-only upload eligibility.
|
|
35
|
+
|
|
36
|
+
Preserve the selected source files until publication succeeds. `microcosm-emitter-publish-graph` asks the service to retry a publication by ID and can re-enqueue a preserved directory on another machine. It never rewrites the original build receipt; the queue and separate latest-status file record retries.
|
|
37
|
+
|
|
38
|
+
The existing TypeScript package `@policyengine/microcosm-provider-orrery` reads immutable published graph files on a server or in a browser. It remains separate from the Python distribution and does not change the hosted telemetry API.
|
|
39
|
+
|
|
40
|
+
## Development
|
|
41
|
+
|
|
42
|
+
Use Python 3.13 or 3.14 on Linux or macOS.
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
uv sync --locked
|
|
46
|
+
bash tools/check-quality.sh
|
|
47
|
+
uv run --no-sync pytest -m 'not collector'
|
|
48
|
+
bash tools/check-artifacts.sh
|
|
49
|
+
bash tools/check-reader.sh
|
|
50
|
+
bash tools/check-changelog.sh
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Tests isolate ambient credentials and use synthetic identities. The artifact check builds one source archive and wheel, installs that wheel into a clean environment away from the source checkout, verifies import boundaries, and exercises telemetry-only, graph-only and combined service startup with packaged migrations. Reader checks cover tests, formatting, types, build and an isolated tarball installation; they do not inspect visual styling.
|
|
54
|
+
|
|
55
|
+
The collector compatibility job tests the installed wheel against a pinned dashboard collector and disposable PostgreSQL. It covers the HTTP exchange, event ingestion, blocked outcomes and supplied failure codes in dashboard run documents, rejected identities, and duplicate delivery after a lost acknowledgement. Local execution requires that pinned collector checkout and a loopback test database; `tools/check-collector.sh` verifies these inputs. Never point this test at a deployed database. The pin verifies source compatibility, not which revision the hosted collector currently runs.
|
|
56
|
+
|
|
57
|
+
## Publication
|
|
58
|
+
|
|
59
|
+
Every merge to `main` releases the Python distribution `microcosm-emitter` to PyPI and the TypeScript reader `@policyengine/microcosm-provider-orrery` to npm at one shared version. Each pull request adds a changelog fragment named `changelog.d/<name>.<type>.md`, where the type is `breaking`, `added`, `changed`, `fixed` or `removed`; `tools/check-changelog.sh` refuses a pull request without one.
|
|
60
|
+
|
|
61
|
+
`push.yaml` runs twice for each merge:
|
|
62
|
+
|
|
63
|
+
1. On the merge commit, it bumps the version in `pyproject.toml`, both `package.json` files and `uv.lock`: a major bump for a breaking fragment, a minor bump for an added or removed fragment, and a patch bump otherwise. It collects the fragments into `CHANGELOG.md` and commits the result as "Update microcosm-emitter" using the PolicyEngine GitHub App, which may bypass the `main` ruleset.
|
|
64
|
+
2. On that commit, it runs every CI check, tags the commit with the bare version (for example `0.2.0`), publishes the tested wheel and source archive to PyPI, and then publishes the tested reader tarball to npm. Each step starts only after the one before succeeds.
|
|
65
|
+
|
|
66
|
+
Both registries accept uploads only through trusted publishing from `push.yaml` in the `pypi` environment, which only `main` can use. CI holds no long-lived registry token. Renaming the workflow or the environment stops publication until both registries' trusted-publisher settings change to match.
|
|
67
|
+
|
|
68
|
+
No hosted-service deployment or consumer activation follows from publishing this package.
|
|
File without changes
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""Tests cannot consume ambient credentials or send traffic to the collector."""
|
|
2
|
+
|
|
3
|
+
from urllib.parse import urlsplit
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@pytest.fixture(autouse=True)
|
|
9
|
+
def isolate_credentials_and_network(tmp_path, monkeypatch):
|
|
10
|
+
for name in ("HF_TOKEN", "HUGGINGFACE_TOKEN", "HUGGING_FACE_HUB_TOKEN"):
|
|
11
|
+
monkeypatch.delenv(name, raising=False)
|
|
12
|
+
hf_home = tmp_path / "hf"
|
|
13
|
+
monkeypatch.setenv("HF_HOME", str(hf_home))
|
|
14
|
+
monkeypatch.setenv("HF_TOKEN_PATH", str(hf_home / "token"))
|
|
15
|
+
from huggingface_hub import constants
|
|
16
|
+
|
|
17
|
+
monkeypatch.setattr(constants, "HF_TOKEN_PATH", str(hf_home / "token"))
|
|
18
|
+
from microcosm_emitter.core import auth
|
|
19
|
+
from microcosm_emitter.telemetry.service import collector
|
|
20
|
+
|
|
21
|
+
real_post = collector._http_post
|
|
22
|
+
|
|
23
|
+
def loopback_post(url, *args, **kwargs):
|
|
24
|
+
if urlsplit(url).hostname not in {"localhost", "127.0.0.1", "::1"}:
|
|
25
|
+
raise AssertionError("Tests must not contact a hosted collector")
|
|
26
|
+
return real_post(url, *args, **kwargs)
|
|
27
|
+
|
|
28
|
+
monkeypatch.setattr(collector, "_http_post", loopback_post)
|
|
29
|
+
monkeypatch.setattr(auth, "_http_post", loopback_post)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@policyengine/microcosm-provider-orrery",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"description": "Pinned-source development entry points; publish the built package from typescript/orrery",
|
|
7
|
+
"exports": {
|
|
8
|
+
"./contract": "./typescript/orrery/src/contract.ts",
|
|
9
|
+
"./browser": "./typescript/orrery/src/browser.ts",
|
|
10
|
+
"./server": "./typescript/orrery/src/server.ts"
|
|
11
|
+
},
|
|
12
|
+
"peerDependencies": {
|
|
13
|
+
"@axiom-foundation/orrery": "0.6.1"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "microcosm-emitter"
|
|
3
|
+
version = "0.2.0"
|
|
4
|
+
description = "Local emitter process host with required build telemetry support"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.13"
|
|
7
|
+
license = "MIT"
|
|
8
|
+
dependencies = [
|
|
9
|
+
"alembic>=1.13.3,<2",
|
|
10
|
+
"sqlalchemy>=2,<3",
|
|
11
|
+
"huggingface-hub>=0.20,<2",
|
|
12
|
+
"psutil>=6,<8",
|
|
13
|
+
"httpx>=0.27,<1",
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
[project.urls]
|
|
17
|
+
Source = "https://github.com/PolicyEngine/microcosm-emitter"
|
|
18
|
+
|
|
19
|
+
[project.entry-points."microcosm.emitter.modules"]
|
|
20
|
+
telemetry = "microcosm_emitter.telemetry.service:create_module"
|
|
21
|
+
orrery = "microcosm_emitter.orrery.service:create_module"
|
|
22
|
+
|
|
23
|
+
[project.scripts]
|
|
24
|
+
microcosm-emitter-publish-graph = "microcosm_emitter.orrery.cli:main"
|
|
25
|
+
|
|
26
|
+
[build-system]
|
|
27
|
+
requires = ["hatchling"]
|
|
28
|
+
build-backend = "hatchling.build"
|
|
29
|
+
|
|
30
|
+
[tool.hatch.build.targets.wheel]
|
|
31
|
+
packages = ["src/microcosm_emitter"]
|
|
32
|
+
|
|
33
|
+
[dependency-groups]
|
|
34
|
+
dev = ["pytest>=8,<9", "ruff>=0.11,<1", "build>=1,<2", "twine>=7,<8", "pyyaml>=6,<7"]
|
|
35
|
+
|
|
36
|
+
[tool.pytest.ini_options]
|
|
37
|
+
testpaths = ["tests"]
|
|
38
|
+
addopts = "-q --import-mode=importlib"
|
|
39
|
+
markers = ["collector: requires the pinned collector and disposable PostgreSQL"]
|
|
40
|
+
|
|
41
|
+
[tool.ruff]
|
|
42
|
+
line-length = 88
|
|
43
|
+
target-version = "py313"
|
|
44
|
+
|
|
45
|
+
[tool.ruff.lint]
|
|
46
|
+
select = ["E", "F", "I", "N", "W", "UP", "B"]
|
|
47
|
+
ignore = ["E501"]
|
|
48
|
+
|
|
49
|
+
[tool.towncrier]
|
|
50
|
+
directory = "changelog.d"
|
|
51
|
+
filename = "CHANGELOG.md"
|
|
52
|
+
title_format = "## [{version}] - {project_date}"
|
|
53
|
+
issue_format = ""
|
|
54
|
+
underlines = ["", "", ""]
|
|
55
|
+
|
|
56
|
+
[[tool.towncrier.type]]
|
|
57
|
+
directory = "breaking"
|
|
58
|
+
name = "Breaking changes"
|
|
59
|
+
showcontent = true
|
|
60
|
+
|
|
61
|
+
[[tool.towncrier.type]]
|
|
62
|
+
directory = "added"
|
|
63
|
+
name = "Added"
|
|
64
|
+
showcontent = true
|
|
65
|
+
|
|
66
|
+
[[tool.towncrier.type]]
|
|
67
|
+
directory = "changed"
|
|
68
|
+
name = "Changed"
|
|
69
|
+
showcontent = true
|
|
70
|
+
|
|
71
|
+
[[tool.towncrier.type]]
|
|
72
|
+
directory = "fixed"
|
|
73
|
+
name = "Fixed"
|
|
74
|
+
showcontent = true
|
|
75
|
+
|
|
76
|
+
[[tool.towncrier.type]]
|
|
77
|
+
directory = "removed"
|
|
78
|
+
name = "Removed"
|
|
79
|
+
showcontent = true
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Local emitter host and required telemetry library, without import side effects."""
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Shared provider services; importing this package has no runtime side effects."""
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""Alembic environment for the local telemetry spool."""
|
|
2
|
+
|
|
3
|
+
from alembic import context
|
|
4
|
+
from sqlalchemy.engine import Connection
|
|
5
|
+
|
|
6
|
+
from microcosm_emitter.core.models import SpoolModel
|
|
7
|
+
|
|
8
|
+
_MISSING_CONNECTION_ERROR = (
|
|
9
|
+
"telemetry spool migrations require a programmatically supplied connection"
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def run_migrations() -> None:
|
|
14
|
+
"""Run migrations on the connection supplied by the emitter service."""
|
|
15
|
+
|
|
16
|
+
connection = context.config.attributes.get("connection")
|
|
17
|
+
if not isinstance(connection, Connection):
|
|
18
|
+
raise RuntimeError(_MISSING_CONNECTION_ERROR)
|
|
19
|
+
context.configure(
|
|
20
|
+
connection=connection,
|
|
21
|
+
target_metadata=SpoolModel.metadata,
|
|
22
|
+
render_as_batch=True,
|
|
23
|
+
)
|
|
24
|
+
with context.begin_transaction():
|
|
25
|
+
context.run_migrations()
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
run_migrations()
|