foundry-implementation-actor 0.6.0__tar.gz → 0.7.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_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/PKG-INFO +1 -1
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/pyproject.toml +1 -1
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/src/foundry_implementation_actor/config.py +30 -9
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/src/foundry_implementation_actor/schemas/agentic-context.schema.yaml +2 -1
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/tests/test_config.py +42 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/uv.lock +1 -1
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/.github/workflows/ci.yml +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/.github/workflows/release.yml +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/.gitignore +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/CLAUDE.md +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/README.md +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/adr/ADR-FIA-0001-the-machinery-leaves-the-capability.md +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/adr/ADR-FIA-0002-testing-leaves-this-actors-contract.md +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/adr/ADR-FIA-0003-the-dev-test-agreement-has-no-home-yet.md +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/adr/ADR-FIA-0004-the-three-amigos-round.md +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/adr/ADR-FIA-0005-the-actor-ships-an-image.md +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/adr/ADR-FIA-0006-the-image-is-published-to-two-registries.md +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/adr/ADR-FIA-0007-a-sessions-budget-is-an-environment-setting.md +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/adr/README.md +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/adr/template.md +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/docker/Dockerfile +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/examples/ACME.PARTS.CAP.SUP.007.WID-implementation/Dockerfile +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/examples/ACME.PARTS.CAP.SUP.007.WID-implementation/actor-agentic-context.yaml +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/examples/README.md +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/scripts/probe_grounding.py +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/src/foundry_implementation_actor/__init__.py +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/src/foundry_implementation_actor/cards/actor-data.yaml +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/src/foundry_implementation_actor/cards/actor-message.yaml +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/src/foundry_implementation_actor/cards/actor-synchronous-messaging.yaml +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/src/foundry_implementation_actor/cards/actor.yaml +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/src/foundry_implementation_actor/cli.py +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/src/foundry_implementation_actor/conformance.py +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/src/foundry_implementation_actor/correlation.py +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/src/foundry_implementation_actor/engine.py +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/src/foundry_implementation_actor/grounding.py +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/src/foundry_implementation_actor/handler.py +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/src/foundry_implementation_actor/instance.py +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/src/foundry_implementation_actor/serve.py +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/src/foundry_implementation_actor/settings.py +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/tests/conftest.py +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/tests/fixtures/broken/actor-agentic-context.yaml +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/tests/test_cards.py +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/tests/test_cli.py +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/tests/test_conformance.py +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/tests/test_engine.py +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/tests/test_grounding.py +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/tests/test_handler.py +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/tests/test_instance.py +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/tests/test_portability.py +0 -0
- {foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/tests/test_settings.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: foundry-implementation-actor
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: Runs a headless Claude Code implementation session against one capability's own 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-implementation-actor
|
|
6
6
|
Author-email: Papeete Consulting <yoann.remy@outlook.com>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "foundry-implementation-actor"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.7.0"
|
|
4
4
|
description = "Runs a headless Claude Code implementation session against one capability's own 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"
|
|
@@ -12,7 +12,7 @@ They are now derivations of two fields. Nothing in this package spells a capabil
|
|
|
12
12
|
capability ACME.PARTS.CAP.SUP.007.WID ← the only id anyone writes
|
|
13
13
|
source_repo <owner>/ACME.PARTS.CAP.SUP.007.WID-impl ← and the only repo
|
|
14
14
|
|
|
15
|
-
actor_name
|
|
15
|
+
actor_name {capability}-implementation
|
|
16
16
|
actor_slug same, lowercased, dots to hyphens
|
|
17
17
|
git_author_name actor_name
|
|
18
18
|
git_author_email {actor_slug}@users.noreply.github.com
|
|
@@ -21,6 +21,15 @@ They are now derivations of two fields. Nothing in this package spells a capabil
|
|
|
21
21
|
image_name(c) {capability lowercased}-{c}
|
|
22
22
|
image_ref(r, c, v) {r}/{capability_path}/{c}:{v}
|
|
23
23
|
|
|
24
|
+
IDENTITY IS `capability` + ROLE, NOT THE REPO HALF. `actor_name` used to be whatever came after
|
|
25
|
+
the `/` in `source_repo`, which reads as a derivation but is really an assumption: that one
|
|
26
|
+
repository holds exactly one actor. Every sidecar in existence satisfies
|
|
27
|
+
`source_repo == "<owner>/" + capability + "-" + ROLE`, so deriving the name from the two facts it
|
|
28
|
+
was always shorthand for produces the identical string — and it keeps producing the right one when
|
|
29
|
+
a capability's three actors come to share a repository, where the repo half would name all three
|
|
30
|
+
the same thing. `source_repo` is unchanged and still required: it is where this actor clones from
|
|
31
|
+
and pushes to, which is a different question from who it is.
|
|
32
|
+
|
|
24
33
|
THE IMAGE REF IS A THREE-WAY CONTRACT. The testing actor recomputes the identical string and the
|
|
25
34
|
orchestration actor parses it back apart. `image_ref` must therefore stay byte-identical to what
|
|
26
35
|
those two agree on; it is derivation output or nothing, and no tag scheme is invented here.
|
|
@@ -53,6 +62,10 @@ _CARDS_PATH = Path(__file__).resolve().parent / "cards"
|
|
|
53
62
|
# segments rather than concatenated.
|
|
54
63
|
_CAPABILITY_SEGMENT = "cap"
|
|
55
64
|
|
|
65
|
+
# The role this package plays for the capability it serves. Half of this actor's identity — see
|
|
66
|
+
# `CapabilityConfig.actor_name` — and the half that is a property of the package, not of the use.
|
|
67
|
+
ROLE = "implementation"
|
|
68
|
+
|
|
56
69
|
# What an unsubstituted placeholder looks like: a bare lowercase word in braces, and nothing else.
|
|
57
70
|
# Narrow on purpose — see `CapabilityConfig.expand`.
|
|
58
71
|
_PLACEHOLDER = re.compile(r"\{([a-z_]+)\}")
|
|
@@ -187,9 +200,17 @@ class CapabilityConfig:
|
|
|
187
200
|
ground_in = tuple(_grounding(entry, source, i)
|
|
188
201
|
for i, entry in enumerate(raw["ground_in"] or ()))
|
|
189
202
|
|
|
203
|
+
source_repo = str(raw["source_repo"])
|
|
204
|
+
owner, _, repo = source_repo.partition("/")
|
|
205
|
+
if not owner or not repo:
|
|
206
|
+
# `actor_name` used to be the repo half and validated this shape on the way past. It
|
|
207
|
+
# is derived from `capability` now, so the field every clone and push URL is built
|
|
208
|
+
# from needs checking in its own right rather than by a side effect.
|
|
209
|
+
raise ConfigError(f"{source}: source_repo '{source_repo}' is not '<owner>/<repo>'")
|
|
210
|
+
|
|
190
211
|
config = cls(
|
|
191
212
|
capability=str(raw["capability"]),
|
|
192
|
-
source_repo=
|
|
213
|
+
source_repo=source_repo,
|
|
193
214
|
registry_repo=str(raw["registry_repo"]),
|
|
194
215
|
engine=str(raw["engine"]),
|
|
195
216
|
components=components,
|
|
@@ -204,13 +225,13 @@ class CapabilityConfig:
|
|
|
204
225
|
|
|
205
226
|
@property
|
|
206
227
|
def actor_name(self) -> str:
|
|
207
|
-
"""
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
return
|
|
228
|
+
"""`{capability}-{ROLE}` — this actor's own name, and its git author name.
|
|
229
|
+
|
|
230
|
+
Not the repo half of `source_repo`, which is the same string for every sidecar that
|
|
231
|
+
exists but stops being this actor's name alone the moment a capability's actors share a
|
|
232
|
+
repository. See this module's own docstring.
|
|
233
|
+
"""
|
|
234
|
+
return f"{self.capability}-{ROLE}"
|
|
214
235
|
|
|
215
236
|
@property
|
|
216
237
|
def actor_slug(self) -> str:
|
|
@@ -76,7 +76,8 @@ fields:
|
|
|
76
76
|
type: string
|
|
77
77
|
doc: >-
|
|
78
78
|
`<owner>/<repo>` of the repository this actor clones, writes to, and pushes a branch to.
|
|
79
|
-
|
|
79
|
+
Where it works, not who it is: the actor's own name and its git commit identity are
|
|
80
|
+
`<capability>-implementation`, derived from `capability` and this package's own role.
|
|
80
81
|
|
|
81
82
|
registry_repo:
|
|
82
83
|
type: string
|
{foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/tests/test_config.py
RENAMED
|
@@ -205,3 +205,45 @@ def test_components_may_not_be_empty(sidecar_dict, write_sidecar):
|
|
|
205
205
|
sidecar_dict["components"] = []
|
|
206
206
|
with pytest.raises(ConfigError, match="empty"):
|
|
207
207
|
CapabilityConfig.load(write_sidecar(sidecar_dict))
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
# ── identity: capability + role, not the repo half ──────────────────────────────────────────
|
|
211
|
+
|
|
212
|
+
def test_the_actor_name_is_exactly_what_the_repo_half_used_to_be(config):
|
|
213
|
+
"""The no-op half of the change, pinned.
|
|
214
|
+
|
|
215
|
+
`actor_name` was `source_repo.partition("/")[2]`. It is `{capability}-{ROLE}` now. Every
|
|
216
|
+
sidecar that exists satisfies `source_repo == "<owner>/" + capability + "-" + ROLE`, so the
|
|
217
|
+
two derivations agree on all of them — which is what makes this releasable on its own, ahead
|
|
218
|
+
of any repository moving.
|
|
219
|
+
"""
|
|
220
|
+
assert config.source_repo == f"acme-lab/{config.capability}-implementation"
|
|
221
|
+
assert config.actor_name == config.source_repo.partition("/")[2]
|
|
222
|
+
assert config.actor_name == "ACME.PARTS.CAP.SUP.007.WID-implementation"
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def test_the_actor_name_no_longer_follows_the_repository(sidecar_dict, write_sidecar):
|
|
226
|
+
"""The point of the change: three actors in one repository still have three names.
|
|
227
|
+
|
|
228
|
+
A consolidated capability repository is named for the capability alone, with no role suffix,
|
|
229
|
+
because all three of its actors live in it. Under the old derivation this actor would have
|
|
230
|
+
been called `ACME.PARTS.CAP.SUP.007.WID` — and so would both of its siblings.
|
|
231
|
+
"""
|
|
232
|
+
sidecar_dict["source_repo"] = "acme-lab/ACME.PARTS.CAP.SUP.007.WID"
|
|
233
|
+
config = CapabilityConfig.load(write_sidecar(sidecar_dict))
|
|
234
|
+
assert config.actor_name == "ACME.PARTS.CAP.SUP.007.WID-implementation"
|
|
235
|
+
assert config.git_author_name == config.actor_name
|
|
236
|
+
assert config.actor_slug == "acme-parts-cap-sup-007-wid-implementation"
|
|
237
|
+
assert config.clone_prefix("TASK-042") == \
|
|
238
|
+
"acme-parts-cap-sup-007-wid-implementation-TASK-042-"
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def test_a_malformed_source_repo_is_still_refused(sidecar_dict, write_sidecar):
|
|
242
|
+
"""`actor_name` used to validate this shape on its way past, and nothing else did.
|
|
243
|
+
|
|
244
|
+
`source_repo` is still what every clone and push URL is built from, so a `source_repo` that
|
|
245
|
+
is not `<owner>/<repo>` has to keep failing at load rather than at the first push.
|
|
246
|
+
"""
|
|
247
|
+
sidecar_dict["source_repo"] = "just-a-name"
|
|
248
|
+
with pytest.raises(ConfigError, match="<owner>/<repo>"):
|
|
249
|
+
CapabilityConfig.load(write_sidecar(sidecar_dict))
|
{foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/.github/workflows/ci.yml
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/examples/README.md
RENAMED
|
File without changes
|
{foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/scripts/probe_grounding.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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/tests/test_cards.py
RENAMED
|
File without changes
|
|
File without changes
|
{foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/tests/test_conformance.py
RENAMED
|
File without changes
|
{foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/tests/test_engine.py
RENAMED
|
File without changes
|
{foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/tests/test_grounding.py
RENAMED
|
File without changes
|
{foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/tests/test_handler.py
RENAMED
|
File without changes
|
{foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/tests/test_instance.py
RENAMED
|
File without changes
|
{foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/tests/test_portability.py
RENAMED
|
File without changes
|
{foundry_implementation_actor-0.6.0 → foundry_implementation_actor-0.7.0}/tests/test_settings.py
RENAMED
|
File without changes
|