foundry-testing-actor 0.2.0__tar.gz → 0.3.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.
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/PKG-INFO +2 -2
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/README.md +1 -1
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/pyproject.toml +1 -1
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/src/foundry_testing_actor/config.py +22 -3
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/src/foundry_testing_actor/schemas/agentic-context.schema.yaml +3 -2
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/tests/test_config.py +45 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/uv.lock +1 -1
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/.github/workflows/ci.yml +0 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/.github/workflows/release.yml +0 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/.gitignore +0 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/CLAUDE.md +0 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/adr/ADR-FTA-0001-the-machinery-leaves-the-capability.md +0 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/adr/ADR-FTA-0002-this-actors-half-of-the-three-amigos-round.md +0 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/adr/ADR-FTA-0003-every-expectation-says-how-its-data-comes-to-exist.md +0 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/adr/README.md +0 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/adr/template.md +0 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/docker/Dockerfile +0 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/examples/ACME.PARTS.CAP.SUP.007.WID-testing/Dockerfile +0 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/examples/ACME.PARTS.CAP.SUP.007.WID-testing/actor-agentic-context.yaml +0 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/examples/README.md +0 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/scripts/probe_grounding.py +0 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/src/foundry_testing_actor/__init__.py +0 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/src/foundry_testing_actor/cards/actor-data.yaml +0 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/src/foundry_testing_actor/cards/actor-message.yaml +0 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/src/foundry_testing_actor/cards/actor-synchronous-messaging.yaml +0 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/src/foundry_testing_actor/cards/actor.yaml +0 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/src/foundry_testing_actor/cli.py +0 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/src/foundry_testing_actor/conformance.py +0 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/src/foundry_testing_actor/correlation.py +0 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/src/foundry_testing_actor/engine.py +0 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/src/foundry_testing_actor/grounding.py +0 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/src/foundry_testing_actor/handler.py +0 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/src/foundry_testing_actor/instance.py +0 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/src/foundry_testing_actor/runner/Dockerfile +0 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/src/foundry_testing_actor/serve.py +0 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/tests/conftest.py +0 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/tests/fixtures/broken/actor-agentic-context.yaml +0 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/tests/test_cards.py +0 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/tests/test_cli.py +0 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/tests/test_conformance.py +0 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/tests/test_engine.py +0 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/tests/test_grounding.py +0 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/tests/test_handler.py +0 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/tests/test_instance.py +0 -0
- {foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/tests/test_portability.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: foundry-testing-actor
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Runs a headless Claude Code black-box test-authoring session against one capability's own testing repo — a papeete-actor for one use, with the capability supplied by a sidecar.
|
|
5
5
|
Project-URL: Homepage, https://github.com/papeete-hub/foundry-testing-actor
|
|
6
6
|
Author-email: Papeete Consulting <yoann.remy@outlook.com>
|
|
@@ -202,7 +202,7 @@ It never opens a pull request, and never runs what it wrote beyond `pytest --col
|
|
|
202
202
|
|
|
203
203
|
| rendering | from |
|
|
204
204
|
|---|---|
|
|
205
|
-
| `ACME.PARTS.CAP.SUP.007.WID-testing` | actor name, git `user.name` (
|
|
205
|
+
| `ACME.PARTS.CAP.SUP.007.WID-testing` | actor name, git `user.name` (`{capability}-testing`) |
|
|
206
206
|
| `acme-lab/ACME.PARTS.CAP.SUP.007.WID-implementation` | `implementation_repo`, when not declared |
|
|
207
207
|
| `acme.parts/sup.007.wid` | the id, split at its `CAP` segment |
|
|
208
208
|
| `acme.parts.cap.sup.007.wid-backend-tests` | the name `papeete-version` versions the test image under |
|
|
@@ -179,7 +179,7 @@ It never opens a pull request, and never runs what it wrote beyond `pytest --col
|
|
|
179
179
|
|
|
180
180
|
| rendering | from |
|
|
181
181
|
|---|---|
|
|
182
|
-
| `ACME.PARTS.CAP.SUP.007.WID-testing` | actor name, git `user.name` (
|
|
182
|
+
| `ACME.PARTS.CAP.SUP.007.WID-testing` | actor name, git `user.name` (`{capability}-testing`) |
|
|
183
183
|
| `acme-lab/ACME.PARTS.CAP.SUP.007.WID-implementation` | `implementation_repo`, when not declared |
|
|
184
184
|
| `acme.parts/sup.007.wid` | the id, split at its `CAP` segment |
|
|
185
185
|
| `acme.parts.cap.sup.007.wid-backend-tests` | the name `papeete-version` versions the test image under |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "foundry-testing-actor"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.3.0"
|
|
4
4
|
description = "Runs a headless Claude Code black-box test-authoring session against one capability's own testing repo — a papeete-actor for one use, with the capability supplied by a sidecar."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.11"
|
{foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/src/foundry_testing_actor/config.py
RENAMED
|
@@ -14,7 +14,7 @@ They are now derivations of two fields. Nothing in this package spells a capabil
|
|
|
14
14
|
source_repo <owner>/ACME.PARTS.CAP.SUP.007.WID-testing ← and the only repo
|
|
15
15
|
|
|
16
16
|
implementation_repo <owner>/<capability>-implementation (declared only when it differs)
|
|
17
|
-
actor_name
|
|
17
|
+
actor_name {capability}-testing
|
|
18
18
|
actor_slug same, lowercased, dots to hyphens
|
|
19
19
|
git_author_name actor_name
|
|
20
20
|
git_author_email {actor_slug}@users.noreply.github.com
|
|
@@ -26,6 +26,15 @@ They are now derivations of two fields. Nothing in this package spells a capabil
|
|
|
26
26
|
image_name(c) {capability lowercased}-{c} ← what implementation versions
|
|
27
27
|
image_ref(r,c,v) {r}/{capability_path}/{c}:{v} ← what implementation published
|
|
28
28
|
|
|
29
|
+
IDENTITY IS `capability` + ROLE, NOT THE REPO HALF. `actor_name` used to be whatever came after
|
|
30
|
+
the `/` in `source_repo`, which reads as a derivation but is really an assumption: that one
|
|
31
|
+
repository holds exactly one actor. Every sidecar in existence satisfies
|
|
32
|
+
`source_repo == "<owner>/" + capability + "-" + ROLE`, so deriving the name from the two facts it
|
|
33
|
+
was always shorthand for produces the identical string — and it keeps producing the right one when
|
|
34
|
+
a capability's three actors come to share a repository, where the repo half would name all three
|
|
35
|
+
the same thing. `source_repo` is unchanged and still required: it is where this actor clones from
|
|
36
|
+
and pushes to, which is a different question from who it is.
|
|
37
|
+
|
|
29
38
|
THE IMAGE REFS ARE A THREE-WAY CONTRACT. `image_ref` must stay byte-identical to what the
|
|
30
39
|
implementation actor publishes, because this actor recomputes it rather than being told it — and
|
|
31
40
|
`test_image_ref` is what the orchestrating actor parses back apart to run. A component's tests are
|
|
@@ -66,6 +75,10 @@ _CAPABILITY_SEGMENT = "cap"
|
|
|
66
75
|
# convention never writes the field at all, and one that does not says so in one line.
|
|
67
76
|
_IMPLEMENTATION_SUFFIX = "-implementation"
|
|
68
77
|
|
|
78
|
+
# The role this package plays for the capability it serves. Half of this actor's identity — see
|
|
79
|
+
# `CapabilityConfig.actor_name` — and the half that is a property of the package, not of the use.
|
|
80
|
+
ROLE = "testing"
|
|
81
|
+
|
|
69
82
|
# What an unsubstituted placeholder looks like: a bare lowercase word in braces, and nothing else.
|
|
70
83
|
# Narrow on purpose — see `CapabilityConfig.expand`.
|
|
71
84
|
_PLACEHOLDER = re.compile(r"\{([a-z_]+)\}")
|
|
@@ -233,6 +246,7 @@ class CapabilityConfig:
|
|
|
233
246
|
)
|
|
234
247
|
# Force the derivations that can fail, here rather than at the first request that needs
|
|
235
248
|
# one. A capability id with no `cap` segment is a typo, and it should not survive startup.
|
|
249
|
+
_split_repo(config.source_repo, "source_repo")
|
|
236
250
|
_ = config.capability_path, config.actor_name, config.implementation_repo
|
|
237
251
|
return config
|
|
238
252
|
|
|
@@ -240,8 +254,13 @@ class CapabilityConfig:
|
|
|
240
254
|
|
|
241
255
|
@property
|
|
242
256
|
def actor_name(self) -> str:
|
|
243
|
-
"""
|
|
244
|
-
|
|
257
|
+
"""`{capability}-{ROLE}` — this actor's own name, and its git author name.
|
|
258
|
+
|
|
259
|
+
Not the repo half of `source_repo`, which is the same string for every sidecar that
|
|
260
|
+
exists but stops being this actor's name alone the moment a capability's actors share a
|
|
261
|
+
repository. See this module's own docstring.
|
|
262
|
+
"""
|
|
263
|
+
return f"{self.capability}-{ROLE}"
|
|
245
264
|
|
|
246
265
|
@property
|
|
247
266
|
def actor_slug(self) -> str:
|
|
@@ -71,8 +71,9 @@ fields:
|
|
|
71
71
|
type: string
|
|
72
72
|
doc: >-
|
|
73
73
|
`<owner>/<repo>` of the TESTING repository this actor clones, writes black-box tests into,
|
|
74
|
-
and pushes a `test/<task_id>` branch to.
|
|
75
|
-
are derived from
|
|
74
|
+
and pushes a `test/<task_id>` branch to. Where it works, not who it is: the actor's own
|
|
75
|
+
name and its git commit identity are `<capability>-testing`, derived from `capability`
|
|
76
|
+
and this package's own role.
|
|
76
77
|
|
|
77
78
|
implementation_repo:
|
|
78
79
|
type: string
|
|
@@ -258,3 +258,48 @@ def test_components_may_not_be_empty(sidecar_dict, write_sidecar):
|
|
|
258
258
|
sidecar_dict["components"] = []
|
|
259
259
|
with pytest.raises(ConfigError, match="empty"):
|
|
260
260
|
CapabilityConfig.load(write_sidecar(sidecar_dict))
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
# ── identity: capability + role, not the repo half ──────────────────────────────────────────
|
|
264
|
+
|
|
265
|
+
def test_the_actor_name_is_exactly_what_the_repo_half_used_to_be(config):
|
|
266
|
+
"""The no-op half of the change, pinned.
|
|
267
|
+
|
|
268
|
+
`actor_name` was `_split_repo(source_repo)[1]`. It is `{capability}-{ROLE}` now. Every
|
|
269
|
+
sidecar that exists satisfies `source_repo == "<owner>/" + capability + "-" + ROLE`, so the
|
|
270
|
+
two derivations agree on all of them — which is what makes this releasable on its own, ahead
|
|
271
|
+
of any repository moving.
|
|
272
|
+
"""
|
|
273
|
+
assert config.source_repo == f"acme-lab/{config.capability}-testing"
|
|
274
|
+
assert config.actor_name == config.source_repo.partition("/")[2]
|
|
275
|
+
assert config.actor_name == "ACME.PARTS.CAP.SUP.007.WID-testing"
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
def test_the_actor_name_no_longer_follows_the_repository(sidecar_dict, write_sidecar):
|
|
279
|
+
"""The point of the change: three actors in one repository still have three names.
|
|
280
|
+
|
|
281
|
+
A consolidated capability repository is named for the capability alone, with no role suffix,
|
|
282
|
+
because all three of its actors live in it. Under the old derivation this actor would have
|
|
283
|
+
been called `ACME.PARTS.CAP.SUP.007.WID` — and so would both of its siblings.
|
|
284
|
+
"""
|
|
285
|
+
sidecar_dict["source_repo"] = "acme-lab/ACME.PARTS.CAP.SUP.007.WID"
|
|
286
|
+
sidecar_dict["implementation_repo"] = "acme-lab/ACME.PARTS.CAP.SUP.007.WID"
|
|
287
|
+
config = CapabilityConfig.load(write_sidecar(sidecar_dict))
|
|
288
|
+
assert config.actor_name == "ACME.PARTS.CAP.SUP.007.WID-testing"
|
|
289
|
+
assert config.git_author_name == config.actor_name
|
|
290
|
+
assert config.actor_slug == "acme-parts-cap-sup-007-wid-testing"
|
|
291
|
+
assert config.clone_prefix("TASK-042") == "acme-parts-cap-sup-007-wid-testing-TASK-042-"
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
def test_a_malformed_source_repo_is_refused_even_when_the_implementation_repo_is_declared(
|
|
295
|
+
sidecar_dict, write_sidecar):
|
|
296
|
+
"""`actor_name` used to validate this shape on its way past.
|
|
297
|
+
|
|
298
|
+
The only other reader of `source_repo` at load time is `implementation_repo`, and it reaches
|
|
299
|
+
the field ONLY when it is not declared — so a sidecar that declares one would have carried a
|
|
300
|
+
malformed `source_repo` all the way to its first clone.
|
|
301
|
+
"""
|
|
302
|
+
sidecar_dict["source_repo"] = "just-a-name"
|
|
303
|
+
sidecar_dict["implementation_repo"] = "acme-lab/ACME.PARTS.CAP.SUP.007.WID-implementation"
|
|
304
|
+
with pytest.raises(ConfigError, match="source_repo"):
|
|
305
|
+
CapabilityConfig.load(write_sidecar(sidecar_dict))
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/src/foundry_testing_actor/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/src/foundry_testing_actor/cli.py
RENAMED
|
File without changes
|
{foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/src/foundry_testing_actor/conformance.py
RENAMED
|
File without changes
|
{foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/src/foundry_testing_actor/correlation.py
RENAMED
|
File without changes
|
{foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/src/foundry_testing_actor/engine.py
RENAMED
|
File without changes
|
{foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/src/foundry_testing_actor/grounding.py
RENAMED
|
File without changes
|
{foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/src/foundry_testing_actor/handler.py
RENAMED
|
File without changes
|
{foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/src/foundry_testing_actor/instance.py
RENAMED
|
File without changes
|
|
File without changes
|
{foundry_testing_actor-0.2.0 → foundry_testing_actor-0.3.0}/src/foundry_testing_actor/serve.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|