aetherius 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.
Files changed (168) hide show
  1. aetherius-0.2.0/.env.example +20 -0
  2. aetherius-0.2.0/.github/workflows/ci.yml +69 -0
  3. aetherius-0.2.0/.gitignore +43 -0
  4. aetherius-0.2.0/CHANGELOG.md +39 -0
  5. aetherius-0.2.0/CONTRIBUTING.md +125 -0
  6. aetherius-0.2.0/LICENSE +11 -0
  7. aetherius-0.2.0/Makefile +68 -0
  8. aetherius-0.2.0/PKG-INFO +606 -0
  9. aetherius-0.2.0/README.md +541 -0
  10. aetherius-0.2.0/RELEASING.md +49 -0
  11. aetherius-0.2.0/blueprints/UKIT.king.blueprint.json +51 -0
  12. aetherius-0.2.0/blueprints/direct.linkaetherius.blueprint.json +25 -0
  13. aetherius-0.2.0/blueprints/github.aetherius.blueprint.json +34 -0
  14. aetherius-0.2.0/blueprints/github.github.blueprint.json +33 -0
  15. aetherius-0.2.0/blueprints/github.zeb.blueprint.json +56 -0
  16. aetherius-0.2.0/blueprints/licence.aetherius.blueprint.json +25 -0
  17. aetherius-0.2.0/blueprints/record.aetherius.blueprint.json +17 -0
  18. aetherius-0.2.0/contracts/blueprint.schema.json +144 -0
  19. aetherius-0.2.0/contracts/events.schema.json +29 -0
  20. aetherius-0.2.0/contracts/openapi.yaml +152 -0
  21. aetherius-0.2.0/pyproject.toml +114 -0
  22. aetherius-0.2.0/src/aetherius/__init__.py +42 -0
  23. aetherius-0.2.0/src/aetherius/__main__.py +12 -0
  24. aetherius-0.2.0/src/aetherius/_contracts/__init__.py +0 -0
  25. aetherius-0.2.0/src/aetherius/_contracts/blueprint.schema.json +144 -0
  26. aetherius-0.2.0/src/aetherius/acts/__init__.py +1 -0
  27. aetherius-0.2.0/src/aetherius/acts/_shared.py +61 -0
  28. aetherius-0.2.0/src/aetherius/acts/continuum/__init__.py +7 -0
  29. aetherius-0.2.0/src/aetherius/acts/continuum/actions.py +149 -0
  30. aetherius-0.2.0/src/aetherius/acts/continuum/bridge.py +159 -0
  31. aetherius-0.2.0/src/aetherius/acts/continuum/browser.py +164 -0
  32. aetherius-0.2.0/src/aetherius/acts/continuum/debug_overlay.py +65 -0
  33. aetherius-0.2.0/src/aetherius/acts/continuum/driver.py +127 -0
  34. aetherius-0.2.0/src/aetherius/acts/continuum/human_actions.py +74 -0
  35. aetherius-0.2.0/src/aetherius/acts/oracle/__init__.py +1 -0
  36. aetherius-0.2.0/src/aetherius/acts/oracle/driver.py +1 -0
  37. aetherius-0.2.0/src/aetherius/acts/oracle/locator.py +1 -0
  38. aetherius-0.2.0/src/aetherius/acts/oracle/model.py +1 -0
  39. aetherius-0.2.0/src/aetherius/acts/oracle/perception.py +1 -0
  40. aetherius-0.2.0/src/aetherius/acts/phantom/__init__.py +1 -0
  41. aetherius-0.2.0/src/aetherius/acts/phantom/driver.py +1 -0
  42. aetherius-0.2.0/src/aetherius/acts/phantom/loop.py +1 -0
  43. aetherius-0.2.0/src/aetherius/acts/phantom/memory.py +1 -0
  44. aetherius-0.2.0/src/aetherius/acts/phantom/perception.py +1 -0
  45. aetherius-0.2.0/src/aetherius/acts/phantom/planner.py +1 -0
  46. aetherius-0.2.0/src/aetherius/acts/vector/__init__.py +1 -0
  47. aetherius-0.2.0/src/aetherius/acts/vector/auth.py +108 -0
  48. aetherius-0.2.0/src/aetherius/acts/vector/client.py +129 -0
  49. aetherius-0.2.0/src/aetherius/acts/vector/driver.py +128 -0
  50. aetherius-0.2.0/src/aetherius/builder/__init__.py +40 -0
  51. aetherius-0.2.0/src/aetherius/builder/catalog.py +93 -0
  52. aetherius-0.2.0/src/aetherius/builder/factory.py +243 -0
  53. aetherius-0.2.0/src/aetherius/builder/templates.py +150 -0
  54. aetherius-0.2.0/src/aetherius/builder/validation.py +120 -0
  55. aetherius-0.2.0/src/aetherius/cli.py +236 -0
  56. aetherius-0.2.0/src/aetherius/config/__init__.py +1 -0
  57. aetherius-0.2.0/src/aetherius/config/secrets.py +71 -0
  58. aetherius-0.2.0/src/aetherius/config/settings.py +44 -0
  59. aetherius-0.2.0/src/aetherius/console/__init__.py +1 -0
  60. aetherius-0.2.0/src/aetherius/console/app.py +66 -0
  61. aetherius-0.2.0/src/aetherius/console/console.tcss +97 -0
  62. aetherius-0.2.0/src/aetherius/console/daemon_control.py +83 -0
  63. aetherius-0.2.0/src/aetherius/console/run_bridge.py +43 -0
  64. aetherius-0.2.0/src/aetherius/console/screens/__init__.py +1 -0
  65. aetherius-0.2.0/src/aetherius/console/screens/_pending.py +38 -0
  66. aetherius-0.2.0/src/aetherius/console/screens/builder/__init__.py +1 -0
  67. aetherius-0.2.0/src/aetherius/console/screens/builder/act_picker.py +75 -0
  68. aetherius-0.2.0/src/aetherius/console/screens/builder/io_editor.py +167 -0
  69. aetherius-0.2.0/src/aetherius/console/screens/builder/options_editor.py +132 -0
  70. aetherius-0.2.0/src/aetherius/console/screens/builder/preview.py +57 -0
  71. aetherius-0.2.0/src/aetherius/console/screens/builder/screen.py +235 -0
  72. aetherius-0.2.0/src/aetherius/console/screens/builder/step_editor.py +249 -0
  73. aetherius-0.2.0/src/aetherius/console/screens/catalog.py +52 -0
  74. aetherius-0.2.0/src/aetherius/console/screens/home.py +90 -0
  75. aetherius-0.2.0/src/aetherius/console/screens/library.py +124 -0
  76. aetherius-0.2.0/src/aetherius/console/screens/library_scan.py +99 -0
  77. aetherius-0.2.0/src/aetherius/console/screens/recorder.py +193 -0
  78. aetherius-0.2.0/src/aetherius/console/screens/runs.py +138 -0
  79. aetherius-0.2.0/src/aetherius/console/screens/sessions.py +14 -0
  80. aetherius-0.2.0/src/aetherius/console/screens/settings.py +132 -0
  81. aetherius-0.2.0/src/aetherius/console/screenshots.py +173 -0
  82. aetherius-0.2.0/src/aetherius/console/theme.py +114 -0
  83. aetherius-0.2.0/src/aetherius/console/widgets/__init__.py +1 -0
  84. aetherius-0.2.0/src/aetherius/console/widgets/event_log.py +44 -0
  85. aetherius-0.2.0/src/aetherius/console/widgets/form.py +101 -0
  86. aetherius-0.2.0/src/aetherius/console/widgets/json_preview.py +18 -0
  87. aetherius-0.2.0/src/aetherius/console/widgets/run_summary.py +82 -0
  88. aetherius-0.2.0/src/aetherius/core/__init__.py +1 -0
  89. aetherius-0.2.0/src/aetherius/core/actions/__init__.py +1 -0
  90. aetherius-0.2.0/src/aetherius/core/actions/base.py +99 -0
  91. aetherius-0.2.0/src/aetherius/core/actions/data.py +126 -0
  92. aetherius-0.2.0/src/aetherius/core/actions/flow.py +76 -0
  93. aetherius-0.2.0/src/aetherius/core/actions/interaction.py +109 -0
  94. aetherius-0.2.0/src/aetherius/core/actions/navigation.py +32 -0
  95. aetherius-0.2.0/src/aetherius/core/actions/registry.py +70 -0
  96. aetherius-0.2.0/src/aetherius/core/actions/spec.py +42 -0
  97. aetherius-0.2.0/src/aetherius/core/blueprint/__init__.py +1 -0
  98. aetherius-0.2.0/src/aetherius/core/blueprint/loader.py +82 -0
  99. aetherius-0.2.0/src/aetherius/core/blueprint/models.py +81 -0
  100. aetherius-0.2.0/src/aetherius/core/blueprint/template.py +101 -0
  101. aetherius-0.2.0/src/aetherius/core/blueprint/validator.py +45 -0
  102. aetherius-0.2.0/src/aetherius/core/driver.py +36 -0
  103. aetherius-0.2.0/src/aetherius/core/errors.py +134 -0
  104. aetherius-0.2.0/src/aetherius/core/events/__init__.py +1 -0
  105. aetherius-0.2.0/src/aetherius/core/events/bus.py +28 -0
  106. aetherius-0.2.0/src/aetherius/core/events/models.py +29 -0
  107. aetherius-0.2.0/src/aetherius/core/events/sinks.py +55 -0
  108. aetherius-0.2.0/src/aetherius/core/extraction/__init__.py +1 -0
  109. aetherius-0.2.0/src/aetherius/core/extraction/html_extractor.py +52 -0
  110. aetherius-0.2.0/src/aetherius/core/extraction/json_extractor.py +125 -0
  111. aetherius-0.2.0/src/aetherius/core/runtime/__init__.py +1 -0
  112. aetherius-0.2.0/src/aetherius/core/runtime/context.py +61 -0
  113. aetherius-0.2.0/src/aetherius/core/runtime/engine.py +188 -0
  114. aetherius-0.2.0/src/aetherius/core/runtime/result.py +39 -0
  115. aetherius-0.2.0/src/aetherius/core/runtime/selector.py +1 -0
  116. aetherius-0.2.0/src/aetherius/models/__init__.py +1 -0
  117. aetherius-0.2.0/src/aetherius/models/registry.py +1 -0
  118. aetherius-0.2.0/src/aetherius/models/store/.gitkeep +0 -0
  119. aetherius-0.2.0/src/aetherius/recorder/__init__.py +12 -0
  120. aetherius-0.2.0/src/aetherius/recorder/_capture_js.py +80 -0
  121. aetherius-0.2.0/src/aetherius/recorder/_gesture_js.py +40 -0
  122. aetherius-0.2.0/src/aetherius/recorder/_names.py +20 -0
  123. aetherius-0.2.0/src/aetherius/recorder/_overlay_js.py +262 -0
  124. aetherius-0.2.0/src/aetherius/recorder/_playwright.py +49 -0
  125. aetherius-0.2.0/src/aetherius/recorder/_selector_js.py +148 -0
  126. aetherius-0.2.0/src/aetherius/recorder/_transform.py +214 -0
  127. aetherius-0.2.0/src/aetherius/recorder/_vector_js.py +174 -0
  128. aetherius-0.2.0/src/aetherius/recorder/base.py +92 -0
  129. aetherius-0.2.0/src/aetherius/recorder/blueprint_recorder.py +72 -0
  130. aetherius-0.2.0/src/aetherius/recorder/capture.py +59 -0
  131. aetherius-0.2.0/src/aetherius/recorder/continuum_backend.py +119 -0
  132. aetherius-0.2.0/src/aetherius/recorder/gesture_recorder.py +193 -0
  133. aetherius-0.2.0/src/aetherius/recorder/selector_synth.py +83 -0
  134. aetherius-0.2.0/src/aetherius/recorder/session.py +101 -0
  135. aetherius-0.2.0/src/aetherius/recorder/vector_backend.py +158 -0
  136. aetherius-0.2.0/src/aetherius/server/__init__.py +12 -0
  137. aetherius-0.2.0/src/aetherius/server/app.py +37 -0
  138. aetherius-0.2.0/src/aetherius/server/config.py +25 -0
  139. aetherius-0.2.0/src/aetherius/server/deps.py +50 -0
  140. aetherius-0.2.0/src/aetherius/server/jobs.py +155 -0
  141. aetherius-0.2.0/src/aetherius/server/routes/__init__.py +1 -0
  142. aetherius-0.2.0/src/aetherius/server/routes/blueprints.py +45 -0
  143. aetherius-0.2.0/src/aetherius/server/routes/recorder.py +25 -0
  144. aetherius-0.2.0/src/aetherius/server/routes/runs.py +49 -0
  145. aetherius-0.2.0/src/aetherius/server/routes/stream.py +53 -0
  146. aetherius-0.2.0/src/aetherius/server/schemas.py +78 -0
  147. aetherius-0.2.0/src/aetherius/stealth/__init__.py +1 -0
  148. aetherius-0.2.0/src/aetherius/stealth/fingerprint/__init__.py +1 -0
  149. aetherius-0.2.0/src/aetherius/stealth/fingerprint/patch.py +38 -0
  150. aetherius-0.2.0/src/aetherius/stealth/fingerprint/profile.py +95 -0
  151. aetherius-0.2.0/src/aetherius/stealth/gestures/__init__.py +1 -0
  152. aetherius-0.2.0/src/aetherius/stealth/gestures/data/human_library.json +7107 -0
  153. aetherius-0.2.0/src/aetherius/stealth/gestures/library.py +126 -0
  154. aetherius-0.2.0/src/aetherius/stealth/gestures/seed.py +97 -0
  155. aetherius-0.2.0/src/aetherius/stealth/humanizer/__init__.py +1 -0
  156. aetherius-0.2.0/src/aetherius/stealth/humanizer/input.py +89 -0
  157. aetherius-0.2.0/src/aetherius/stealth/humanizer/keyboard.py +75 -0
  158. aetherius-0.2.0/src/aetherius/stealth/humanizer/mouse.py +153 -0
  159. aetherius-0.2.0/src/aetherius/stealth/humanizer/scroll.py +55 -0
  160. aetherius-0.2.0/src/aetherius/stealth/humanizer/timing.py +54 -0
  161. aetherius-0.2.0/src/aetherius/stealth/ml/__init__.py +1 -0
  162. aetherius-0.2.0/src/aetherius/stealth/ml/fingerprint_model.py +1 -0
  163. aetherius-0.2.0/src/aetherius/stealth/ml/motion_model.py +1 -0
  164. aetherius-0.2.0/src/aetherius/stealth/policy.py +133 -0
  165. aetherius-0.2.0/src/aetherius/stealth/session/__init__.py +1 -0
  166. aetherius-0.2.0/src/aetherius/stealth/session/store.py +35 -0
  167. aetherius-0.2.0/src/aetherius/stealth/session/warmup.py +52 -0
  168. aetherius-0.2.0/src/aetherius/version.py +3 -0
@@ -0,0 +1,20 @@
1
+ # Aetherius local secrets — TEMPLATE.
2
+ #
3
+ # Copy this file to `.env` (which is git-ignored and never committed) and fill in real values:
4
+ # cp .env.example .env
5
+ #
6
+ # Each Blueprint declares secrets by name only; the value is read at run time from the environment
7
+ # variable AETHERIUS_SECRET_<NAME> (the secret name, upper-cased). Example: a Blueprint secret
8
+ # `cas_pass` is read from AETHERIUS_SECRET_CAS_PASS. Existing environment variables win over `.env`,
9
+ # so CI and production stay in control. Single-quote values that contain # ! $ or spaces.
10
+ #
11
+ # In the Console (Runs screen), a secret found here is shown "loaded from .env" and can be left
12
+ # blank. On the CLI, `.env` is loaded automatically when running from the repo, or pass --secret.
13
+
14
+ # Demo login — quotes.toscrape.com accepts any username/password.
15
+ AETHERIUS_SECRET_QUOTES_USER=demo
16
+ AETHERIUS_SECRET_QUOTES_PASS=demo
17
+
18
+ # Universite de Bordeaux ENT/CAS.
19
+ AETHERIUS_SECRET_BORDEAUX_USER=your-username
20
+ AETHERIUS_SECRET_BORDEAUX_PASS='your-password'
@@ -0,0 +1,69 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ # Least privilege: the workflow only needs to read the repository.
9
+ permissions:
10
+ contents: read
11
+
12
+ # Cancel superseded runs on the same ref to save minutes.
13
+ concurrency:
14
+ group: ci-${{ github.ref }}
15
+ cancel-in-progress: true
16
+
17
+ jobs:
18
+ python:
19
+ name: Python (${{ matrix.python-version }})
20
+ runs-on: ubuntu-latest
21
+ strategy:
22
+ fail-fast: false
23
+ matrix:
24
+ python-version: ["3.11", "3.12"]
25
+ steps:
26
+ - uses: actions/checkout@v4
27
+ - uses: actions/setup-python@v5
28
+ with:
29
+ python-version: ${{ matrix.python-version }}
30
+ cache: pip
31
+ cache-dependency-path: pyproject.toml
32
+ # Base install stays light; heavy Act extras are not needed, tests marked
33
+ # browser/vision/agent skip themselves when their dependency is absent.
34
+ - run: python -m pip install -e ".[dev]"
35
+ - run: make lint
36
+ - run: make typecheck
37
+ - run: make test
38
+
39
+ browser:
40
+ name: Browser (Act II)
41
+ runs-on: ubuntu-latest
42
+ steps:
43
+ - uses: actions/checkout@v4
44
+ - uses: actions/setup-python@v5
45
+ with:
46
+ python-version: "3.12"
47
+ cache: pip
48
+ cache-dependency-path: pyproject.toml
49
+ # Act II needs the [browser] extra and a real Chromium; --with-deps pulls the OS libraries.
50
+ - run: python -m pip install -e ".[browser,dev]"
51
+ - run: python -m playwright install --with-deps chromium
52
+ - run: make test-browser
53
+
54
+ typescript:
55
+ name: TypeScript SDK
56
+ runs-on: ubuntu-latest
57
+ steps:
58
+ - uses: actions/checkout@v4
59
+ - uses: actions/setup-node@v4
60
+ with:
61
+ node-version: "20"
62
+ - uses: actions/setup-python@v5
63
+ with:
64
+ python-version: "3.12"
65
+ cache: pip
66
+ cache-dependency-path: pyproject.toml
67
+ # The SDK end-to-end test spawns the real daemon, so the package must be importable.
68
+ - run: python -m pip install -e .
69
+ - run: make test-ts
@@ -0,0 +1,43 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *.egg-info/
5
+ .eggs/
6
+ build/
7
+ dist/
8
+ .venv/
9
+ venv/
10
+ .mypy_cache/
11
+ .ruff_cache/
12
+ .pytest_cache/
13
+ .coverage
14
+ coverage.xml
15
+ htmlcov/
16
+
17
+ # Node / TypeScript SDK
18
+ node_modules/
19
+ sdks/typescript/dist/
20
+ *.tsbuildinfo
21
+
22
+ # Aetherius runtime artifacts
23
+ src/aetherius/models/store/*
24
+ !src/aetherius/models/store/.gitkeep
25
+ runs/
26
+ profiles/
27
+ *.har
28
+
29
+ # Training assets (kept out of git; heavy)
30
+ training/datasets/
31
+ training/checkpoints/
32
+ training/runs/
33
+
34
+ # Secrets and local config
35
+ .env
36
+ .env.*
37
+ !.env.example
38
+
39
+ # OS / editor / tooling
40
+ .DS_Store
41
+ .idea/
42
+ .vscode/
43
+ .claude/
@@ -0,0 +1,39 @@
1
+ # Changelog
2
+
3
+ Toutes les évolutions notables du projet sont consignées ici. Le format s'inspire de
4
+ [Keep a Changelog](https://keepachangelog.com/fr/1.1.0/) et le versionnage suit
5
+ [SemVer](https://semver.org/lang/fr/). Tant que la version reste en `0.x`, l'API publique peut encore
6
+ évoluer entre deux versions mineures (durcissement de la Phase 1 en conditions réelles).
7
+
8
+ ## [0.2.0] - 2026-07-10
9
+
10
+ Première release publique. Elle clôt la **Phase 1** : le socle d'Aetherius, utilisable comme
11
+ **bibliothèque** (in-process Python) et comme **service** (daemon local + SDK), avec sa Console.
12
+
13
+ ### Ajouté
14
+ - **Daemon local (FastAPI)** — passerelle HTTP + WebSocket exposant le moteur à tout langage
15
+ (`aetherius serve`, bind loopback, token bearer optionnel) : `POST /v1/runs`, `GET /v1/runs/{id}`,
16
+ `WS /v1/runs/{id}/events` (rejeu bufferisé + flux live jusqu'à `done`), `POST /v1/blueprints/validate`,
17
+ `GET /v1/schema`, `GET /health`. L'enregistrement reste host-local (`POST /v1/recorder/sessions` → 501).
18
+ Voir [docs/daemon.md](docs/daemon.md).
19
+ - **SDK TypeScript** `@aetherius/client` (Node 20+) — spawn du daemon (ou `baseUrl`),
20
+ `client.run(blueprint, { inputs, secrets, onEvent })`, streaming d'événements typé.
21
+ - **Console : écran Settings** — démarrer/arrêter le daemon et voir son statut, sans quitter le terminal.
22
+ - **Act I — Vector** : client HTTP/API (requêtes, retries/backoff, 5 stratégies d'auth, extraction
23
+ JSONPath et CSS/XPath, moteur de templates Jinja2).
24
+ - **Act II — Continuum** : automatisation d'un vrai navigateur (Playwright, extra `[browser]`) —
25
+ navigation, interactions, extraction DOM, `wait_for` avec échec nommé, sessions persistantes, debug.
26
+ - **Système de discrétion (stealth)** : couche transverse (`options.stealth`) — souris humaine par
27
+ rejeu géométrique de gestes, clavier/scroll/timing humains, fingerprint, warmup de profil.
28
+ - **Recorder** : création de Blueprint par démonstration (Continuum et Vector) + gesture recorder.
29
+ - **Builder headless + Blueprint Studio** : construction guidée de Blueprints sans JSON, avec aperçu
30
+ validé en direct, réutilisable par la Console, le daemon et les SDKs.
31
+ - **Console (Textual)** : Library, Runs, Catalog, Recorder, Blueprint Studio, Settings.
32
+ - **Contrats** langage-agnostiques (`contracts/`) : schéma Blueprint, OpenAPI du daemon, schéma
33
+ d'événements — source de vérité, gardés par des tests.
34
+
35
+ ### Notes
36
+ - SemVer `0.x` : l'API peut évoluer pendant le durcissement de la Phase 1.
37
+ - La **Phase 2** ajoutera Act III (Oracle, vision) et Act IV (Phantom, agent autonome).
38
+
39
+ [0.2.0]: https://github.com/kln-mltre/Aetherius/releases/tag/v0.2.0
@@ -0,0 +1,125 @@
1
+ # Contribuer à Aetherius
2
+
3
+ Merci de contribuer. Ce document résume le workflow de développement et les conventions à suivre.
4
+ Le cadrage produit est dans le [README](README.md), l'architecture dans
5
+ [docs/architecture.md](docs/architecture.md).
6
+
7
+ ## Mise en place
8
+
9
+ Prérequis : Python 3.11+ et, pour le SDK TypeScript, Node 20+.
10
+
11
+ ```bash
12
+ make install-dev # installe le paquet en editable + les outils de dev
13
+ ```
14
+
15
+ ## Workflow
16
+
17
+ Une seule commande fait foi, en local comme en CI :
18
+
19
+ ```bash
20
+ make check # format + lint (ruff) + types (mypy) + tests (pytest)
21
+ ```
22
+
23
+ Cibles utiles :
24
+
25
+ ```bash
26
+ make test # tests seuls, avec couverture
27
+ make lint # ruff
28
+ make typecheck # mypy (strict)
29
+ make check-all # tout le dépôt : Python + SDK TypeScript
30
+ make help # liste des cibles
31
+ ```
32
+
33
+ Ouvre une branche par changement, garde `make check` vert, et découpe en commits lisibles.
34
+
35
+ ## Définition de « terminé »
36
+
37
+ Une capacité utilisateur (un Act, une action, une option) n'est terminée que lorsque **tout** ceci
38
+ est vrai. On ne saute pas une étape en attendant qu'on la réclame :
39
+
40
+ 1. **Tests miroir** écrits avec le code — voir [Tests](#tests).
41
+ 2. **Exemple exécutable** ajouté dans `examples/<act>/`, lançable depuis `aetherius run` et la
42
+ Console — voir [Exemples exécutables](#exemples-exécutables).
43
+ 3. **Doc à jour** dans le même changement — voir [Documentation](#documentation).
44
+ 4. **`make check` vert.**
45
+ 5. **Flux vérifié à la main** au moins une fois : le vrai `run`, pas seulement les tests (chaque
46
+ doc d'Act a une section « Tester … » pour ça).
47
+ 6. **Prise en main UI** pour une capacité **liée à l'UI et non triviale** (nouvel écran ou
48
+ interaction non évidente de la Console) : un walkthrough orienté UI dans la doc **et** des captures
49
+ SVG générées (`make screenshots`) — voir [Documentation](#documentation). Exception : une
50
+ interaction rudimentaire (ex. sélectionner une ligne pour lancer un run) n'en a pas besoin.
51
+
52
+ ## Principes de code
53
+
54
+ - Un fichier de logique reste sous ~300 lignes ; au-delà, on découpe en sous-modules.
55
+ - Typage strict (pydantic v2) ; les erreurs sont typées et jamais avalées.
56
+ - `import aetherius` reste léger : aucune dépendance lourde (Playwright, ONNX, OpenCV, Anthropic)
57
+ importée au niveau module — elles sont chargées à la demande dans les Acts.
58
+ - Les contrats (`contracts/`) sont la source de vérité ; le code et les SDK s'y conforment.
59
+ - Le dictionnaire d'actions (`core/actions/registry.py`) est l'unique source ; le catalogue du
60
+ builder en est une projection (pas de duplication).
61
+ - Commentaires sobres, orientés « pourquoi » ; pas d'emoji dans le code ni les logs. Le formatage et
62
+ le lint sont gérés par ruff (`make format`).
63
+
64
+ ## Tests
65
+
66
+ - Toute nouvelle logique arrive **avec son test miroir** dans `tests/`. Une contribution n'est prête
67
+ que si `make check` est vert.
68
+ - La suite doit passer **sans les extras lourds** : un test qui exige `[browser]`, `[vision]` ou
69
+ `[agent]` se skippe proprement via `pytest.importorskip(...)` et porte le marker correspondant.
70
+ - Les contrats sont gardés par `tests/contracts/` : les garder verts quand un contrat évolue.
71
+ - Structure, markers, fixtures et couverture sont détaillés dans [docs/testing.md](docs/testing.md).
72
+
73
+ ## Exemples exécutables
74
+
75
+ Une capacité utilisateur arrive avec **au moins un Blueprint d'exemple réellement exécutable**,
76
+ rangé dans `examples/<act>/` et lançable tel quel depuis `aetherius run` comme depuis la Console. Un
77
+ exemple n'est pas un extrait décoratif : il doit tourner.
78
+
79
+ - Privilégier un endpoint **public et autorisé** pour un exemple **zéro configuration** (ex.
80
+ `quotes.toscrape.com`, `books.toscrape.com`) : l'utilisateur ouvre la Console, clique Run, ça
81
+ marche.
82
+ - Si des identifiants sont nécessaires, les passer par `.env` (`AETHERIUS_SECRET_*`, voir
83
+ [docs/secrets.md](docs/secrets.md)) et le signaler ; ne jamais coder un secret en dur, ni dans un
84
+ exemple, un test ou une fixture.
85
+ - Un gabarit non exécutable (URLs placeholder, service privé) est marqué comme tel dans sa
86
+ `description` et ne compte pas comme l'exemple exécutable requis.
87
+ - Les exemples sont validés contre le schéma par la CI (`tests/contracts/`), à n'importe quelle
88
+ profondeur sous `examples/`.
89
+
90
+ ## Documentation
91
+
92
+ La doc évolue **avec** le code, dans le même changement — jamais « plus tard ». Un autre
93
+ contributeur doit pouvoir reprendre à partir de la seule doc, sans contexte oral. À chaque
94
+ contribution, mettre à jour :
95
+
96
+ - la **doc de la partie concernée** (ex. [`docs/acts/<act>.md`](docs/acts/)) : décrire le *comment*
97
+ et les **limites connues**, pas seulement le *quoi* ; noter les décisions de conception
98
+ non-évidentes, pour qu'on ne les « corrige » pas par erreur plus tard ;
99
+ - le **statut** dans le [README](README.md), section « État d'avancement » : la source de vérité du
100
+ jalon atteint et du prochain ;
101
+ - tout **doc transverse** réellement touché (par ex. [docs/console.md](docs/console.md),
102
+ [docs/secrets.md](docs/secrets.md), [docs/testing.md](docs/testing.md)) ; ne pas dupliquer, mais
103
+ laisser un pointeur là où c'est utile.
104
+
105
+ Style : sobre, orienté « pourquoi », sans emoji — comme le code.
106
+
107
+ ### Captures d'écran de la Console
108
+
109
+ Les images de la doc (`docs/screenshots/*.svg`) sont **générées**, jamais prises à la main. La source
110
+ unique est [`console/screenshots.py`](src/aetherius/console/screenshots.py), qui pilote l'app en
111
+ headless et exporte chaque écran en SVG déterministe (identifiant normalisé, chemin local neutralisé).
112
+ Règles :
113
+
114
+ - après **toute** évolution d'un écran ou d'un layout Console, exécuter `make screenshots` et commiter
115
+ le résultat ;
116
+ - pour un **nouvel** écran/interaction, ajouter un scénario dans `screenshots.py` (une fonction de
117
+ pilotage + une entrée dans `_SHOTS`), régénérer, puis l'intégrer dans la doc concernée ;
118
+ - `make screenshots-check` (garde-fou, rejouable en CI) échoue si les captures committées sont
119
+ périmées, grâce au déterminisme.
120
+
121
+ ## Intégration continue
122
+
123
+ La CI (`.github/workflows/ci.yml`) rejoue exactement les cibles `make` sur Python 3.11 et 3.12 et
124
+ compile le SDK TypeScript. Il n'y a pas de logique de test hors du `Makefile` : ce qui passe en local
125
+ passe en CI, et inversement.
@@ -0,0 +1,11 @@
1
+ Aetherius
2
+ Copyright (c) 2026 Kylian MALARTRE (kln-mltre)
3
+
4
+ This work is licensed under the Creative Commons Attribution-NonCommercial 4.0 International License.
5
+
6
+ To view a copy of this license, visit http://creativecommons.org/licenses/by-nc/4.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
7
+
8
+ COMMERCIAL USE RESTRICTION
9
+ Any commercial use, including but not limited to selling the software, offering it as a paid service (SaaS), or using it to generate revenue directly or indirectly, is strictly prohibited without prior written consent from the author.
10
+
11
+ For commercial licensing inquiries or dual-licensing options, please contact the author directly.
@@ -0,0 +1,68 @@
1
+ # Aetherius developer tasks.
2
+ # Single source of truth for "how we check the project": the CI (.github/workflows/ci.yml) calls
3
+ # these same targets, so local and CI runs never drift.
4
+
5
+ .DEFAULT_GOAL := help
6
+ PY := python3
7
+ TS_DIR := sdks/typescript
8
+
9
+ .PHONY: help install-dev lint format format-check typecheck test test-fast test-browser test-ts check check-all screenshots screenshots-check dist release-check
10
+
11
+ help: ## List available targets
12
+ @grep -E '^[a-zA-Z_-]+:.*?## ' $(MAKEFILE_LIST) \
13
+ | awk 'BEGIN{FS=":.*?## "}{printf " \033[36m%-14s\033[0m %s\n", $$1, $$2}'
14
+
15
+ install-dev: ## Install the package with dev tooling (editable)
16
+ $(PY) -m pip install -e ".[dev]"
17
+
18
+ lint: ## Lint with Ruff
19
+ ruff check .
20
+
21
+ format: ## Format the code with Ruff
22
+ ruff format .
23
+
24
+ format-check: ## Check formatting without writing (CI)
25
+ ruff format --check .
26
+
27
+ typecheck: ## Strict static typing with mypy
28
+ mypy
29
+
30
+ test: ## Run the full Python test suite with coverage
31
+ pytest --cov=aetherius --cov-report=term-missing
32
+
33
+ test-fast: ## Run only the fast tests (skip heavy extras and slow tests)
34
+ pytest -m "not browser and not vision and not agent and not slow"
35
+
36
+ test-browser: ## Run the browser tests (Act II) against a real Chromium; needs the [browser] extra
37
+ pytest -m browser
38
+
39
+ test-ts: ## Typecheck, build and test the TypeScript SDK (unit + a real spawn E2E)
40
+ npm --prefix $(TS_DIR) install
41
+ npm --prefix $(TS_DIR) test
42
+
43
+ screenshots: ## Regenerate the Console SVG screenshots under docs/screenshots/
44
+ $(PY) -m aetherius.console.screenshots
45
+
46
+ screenshots-check: ## Fail if the committed screenshots are stale (deterministic; CI guard)
47
+ @tmp=$$(mktemp -d); \
48
+ $(PY) -c "import asyncio; from pathlib import Path; from aetherius.console.screenshots import capture_all; asyncio.run(capture_all(Path('$$tmp')))" >/dev/null; \
49
+ if diff -rq docs/screenshots "$$tmp" >/dev/null; then \
50
+ echo "screenshots up to date"; rm -rf "$$tmp"; \
51
+ else \
52
+ echo "Screenshots are stale — run 'make screenshots' and commit the result."; \
53
+ diff -rq docs/screenshots "$$tmp" || true; rm -rf "$$tmp"; exit 1; \
54
+ fi
55
+
56
+ check: ## Full Python gate: format check, lint, types, tests
57
+ @$(MAKE) format-check lint typecheck test
58
+
59
+ check-all: ## Full repository gate: Python + TypeScript SDK
60
+ @$(MAKE) check test-ts
61
+
62
+ dist: ## Build the Python distribution (wheel + sdist) into dist/
63
+ rm -rf dist
64
+ $(PY) -m build
65
+
66
+ release-check: ## Build and validate the distribution metadata before uploading (see RELEASING.md)
67
+ @$(MAKE) dist
68
+ $(PY) -m twine check dist/*