New projects from conversation (M2.5, PR B)
- propose_project(name, purpose, decisions) in a conversation goes up for a go-ahead (checked: a slug, not an existing project, no trailing question). - On go, the provisioning checklist (D1): a repository with a README, protection on its default branch, the agent as a collaborator, a build VM, a deploy key, and the project entry as YAML with <...> to fill in. - On "done", the agent reads its configuration again and adds the new project live (build_loop_agent(load=...); only additions), then checks what was provided (D4, verified, not assumed): permissions and protection as it sees them, then on a throwaway branch with an empty commit, a branch push must succeed and a push to the default branch and merging its own PR must be refused. The check's PR is closed and its branch deleted. Failures are said per item; nothing starts. - Checked: the tracking issue (the distilled decisions, carrying the new item's ID), and the project's item, agreed and labelled `design`, whose first milestone is ARCHITECTURE.md and the build plan. A conversation waiting on provisioning doesn't close as idle. - The walk replays exactly from its seed (item IDs too), and event IDs stay unique across simulated restarts, as a server's are. - The test config holds output to 8192 tokens, under the test key's per-request cost cap. Tests: new-project unit tests (checklist and its YAML parse as config, done before the entry, what isn't set up, a checked project's record and first PR, an existing name), protection enforced by a hook on the fake forge, the walk proposing projects and saying done, and an e2e new project in a repository the test operator provisions from the agent's checklist. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PPQ14L3LikyefCMFBqEbKE
This commit is contained in:
1 parent
9a86ccb2a4
commit
ad2d090143
13 files changed
+723
-54
No files matched your search
@@ -61,7 +61,7 @@ class FreshRepo:
|
||||
|
||||
@contextlib.contextmanager
|
||||
def fresh_repo(
|
||||
operator: GiteaClient, run: str, keys: Path, *, agent: str
|
||||
operator: GiteaClient, run: str, keys: Path, *, agent: str, seed: bool = True
|
||||
) -> Iterator[FreshRepo]:
|
||||
"""A repository of its own for one test run, as the operator would make a
|
||||
project's (D4, D8): seeded with a small Python package, the ``agent``
|
||||
@@ -88,14 +88,21 @@ def fresh_repo(
|
||||
"content": base64.b64encode(path.read_bytes()).decode(),
|
||||
}
|
||||
for path in sorted(SEED.rglob("*"))
|
||||
if path.is_file() and path.name != "README.md"
|
||||
if seed and path.is_file() and path.name != "README.md"
|
||||
]
|
||||
operator._request(
|
||||
"POST",
|
||||
f"/repos/{full}/contents",
|
||||
json={"branch": "main", "message": "Seed the test project", "files": files},
|
||||
)
|
||||
if files:
|
||||
operator._request(
|
||||
"POST",
|
||||
f"/repos/{full}/contents",
|
||||
json={
|
||||
"branch": "main",
|
||||
"message": "Seed the test project",
|
||||
"files": files,
|
||||
},
|
||||
)
|
||||
readme = operator._request("GET", f"/repos/{full}/contents/README.md")
|
||||
# A new project's README says only what it is; a seeded one, the seed's.
|
||||
text = (SEED / "README.md").read_bytes() if seed else f"# {name}\n".encode()
|
||||
operator._request(
|
||||
"PUT",
|
||||
f"/repos/{full}/contents/README.md",
|
||||
@@ -103,7 +110,7 @@ def fresh_repo(
|
||||
"branch": "main",
|
||||
"message": "README",
|
||||
"sha": readme["sha"],
|
||||
"content": base64.b64encode((SEED / "README.md").read_bytes()).decode(),
|
||||
"content": base64.b64encode(text).decode(),
|
||||
},
|
||||
)
|
||||
operator._request(
|
||||
|
||||
Reference in new issue
Block a user