eb770643c2
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 16s
CI / build (pull_request) Successful in 17s
CI / quality (pull_request) Successful in 19s
CI / e2e_tests (pull_request) Successful in 32s
CI / security (pull_request) Successful in 37s
CI / typecheck (pull_request) Successful in 39s
CI / unit_tests (pull_request) Successful in 3m1s
CI / integration_tests (pull_request) Successful in 3m39s
CI / docker (pull_request) Successful in 40s
CI / coverage (pull_request) Successful in 6m49s
CI / lint (push) Successful in 12s
CI / build (push) Successful in 15s
CI / quality (push) Successful in 17s
CI / e2e_tests (push) Successful in 30s
CI / typecheck (push) Successful in 36s
CI / benchmark-regression (push) Has been skipped
CI / security (push) Successful in 49s
CI / unit_tests (push) Successful in 3m16s
CI / integration_tests (push) Successful in 3m37s
CI / docker (push) Successful in 51s
CI / coverage (push) Successful in 6m40s
CI / benchmark-publish (push) Successful in 20m12s
CI / benchmark-regression (pull_request) Successful in 37m11s
Add four CLI-based integration test cases to the M5 E2E verification suite that exercise the exact commands from the v3.4.0 milestone description via real subprocess calls to `python -m cleveragents`. CLI test cases: - CLI Project Create Large Project: `agents project create local/large-project` - CLI Resource Add Git Checkout: `agents resource add git-checkout ...` - CLI Project Link Resource: `agents project link-resource ...` - CLI Project Show Displays Linked Resource: `agents project show ...` Each test creates an isolated temp directory with its own CLEVERAGENTS_HOME, initialises a workspace via `agents init`, runs the target CLI command as a subprocess with `on_timeout=kill`, asserts zero exit code and verifies expected output, then tears down the temp directory. Bug fix: ProjectResourceLinkRepository.create_link() and remove_link() only called session.flush() without session.commit(), causing linked resource data to be silently lost between sessions. Added session.commit() to both methods, plus finally: session.close() to match the session-factory lifecycle pattern used by all other mutating repository methods. Added session.refresh() and session.expunge() before return in create_link() so the returned ORM instance is fully loaded and usable in detached state after session close. Regression guard: Added two cross-session persistence Behave scenarios (project_repository.feature) that open a new session from the same engine after create_link/remove_link and verify the operation was durably committed. Test improvements from review feedback (rounds 1 and 2): - Per-test CLEVERAGENTS_HOME isolation via env: override on all Run Process calls to prevent shared state between tests. - Stronger ULID-based assertions: CLI tests capture the resource_id ULID from resource show output and verify the exact ID in project show output. - Regex-based branch assertion (branch.*main) instead of generic string match. - Test 4 differentiated from Test 3 by verifying resource show independently after linking and asserting the specific resource ULID. - Documentation noting context tier and ACMS criteria are validated at the Python API level via helper_m5_e2e_verification.py. - Updated ProjectResourceLinkRepository class docstring documenting commit and close behaviour of mutating methods. - CHANGELOG entry for both test additions and production bug fix. - Redundant Library imports removed, --format plain on project list, comments explaining fake repo directories, standardised Run Process line style. Context/ACMS CLI coverage is intentionally not added because the CLI does not yet expose dedicated context/ACMS inspection commands. These criteria are validated at the Python API level via helper_m5_e2e_verification.py. ISSUES CLOSED: #496
149 lines
7.7 KiB
Gherkin
149 lines
7.7 KiB
Gherkin
Feature: Namespaced project repository operations
|
|
As a developer
|
|
I want project and resource-link repositories
|
|
So that namespaced projects and their resource links are persisted correctly
|
|
|
|
Background:
|
|
Given a project repository in-memory database is initialized
|
|
|
|
# ---------- NamespacedProjectRepository ----------
|
|
|
|
Scenario: Create a namespaced project
|
|
When I create a namespaced project "local/test-project" via the repository
|
|
Then the project "local/test-project" should exist in the repository
|
|
|
|
Scenario: Get a namespaced project by primary key
|
|
Given a namespaced project "local/get-project" exists in the repository
|
|
When I get the project "local/get-project" from the repository
|
|
Then the returned project name should be "get-project"
|
|
And the returned project namespace should be "local"
|
|
|
|
Scenario: Get a non-existent project raises ProjectNotFoundError
|
|
When I get the project "local/no-such-project" from the repository expecting an error
|
|
Then the repository error should be "ProjectNotFoundError"
|
|
|
|
Scenario: List projects returns all projects
|
|
Given a namespaced project "local/alpha" exists in the repository
|
|
And a namespaced project "local/beta" exists in the repository
|
|
When I list all projects from the repository
|
|
Then the project list should contain 2 projects
|
|
|
|
Scenario: List projects filtered by namespace
|
|
Given a namespaced project "local/ns-a" exists in the repository
|
|
And a namespaced project "team/ns-b" exists in the repository
|
|
When I list projects with namespace "local" from the repository
|
|
Then the project list should contain 1 projects
|
|
And the first project in the list should be "local/ns-a"
|
|
|
|
Scenario: List projects respects limit
|
|
Given a namespaced project "local/lim-a" exists in the repository
|
|
And a namespaced project "local/lim-b" exists in the repository
|
|
And a namespaced project "local/lim-c" exists in the repository
|
|
When I list projects with limit 2 from the repository
|
|
Then the project list should contain 2 projects
|
|
|
|
Scenario: Update a namespaced project description
|
|
Given a namespaced project "local/update-me" exists in the repository
|
|
When I update the project "local/update-me" description to "Updated desc"
|
|
Then the project "local/update-me" description should be "Updated desc"
|
|
|
|
Scenario: Update a non-existent project raises ProjectNotFoundError
|
|
When I update a non-existent project "local/ghost" expecting an error
|
|
Then the repository error should be "ProjectNotFoundError"
|
|
|
|
Scenario: Delete a namespaced project
|
|
Given a namespaced project "local/delete-me" exists in the repository
|
|
When I delete the project "local/delete-me" from the repository
|
|
Then the delete result should be True
|
|
And getting "local/delete-me" should raise ProjectNotFoundError
|
|
|
|
Scenario: Delete a non-existent project returns False
|
|
When I delete the project "local/not-here" from the repository
|
|
Then the delete result should be False
|
|
|
|
Scenario: Delete cascades to resource links
|
|
Given a namespaced project "local/cascade-proj" exists in the repository
|
|
And a resource link exists for project "local/cascade-proj"
|
|
When I delete the project "local/cascade-proj" from the repository
|
|
Then the links for project "local/cascade-proj" should be empty
|
|
|
|
Scenario: Create duplicate project raises error
|
|
Given a namespaced project "local/dup-proj" exists in the repository
|
|
When I create a duplicate project "local/dup-proj" expecting an error
|
|
Then the repository error message should contain "already exists"
|
|
|
|
# ---------- ProjectResourceLinkRepository ----------
|
|
|
|
Scenario: Create a resource link
|
|
Given a namespaced project "local/link-proj" exists in the repository
|
|
And a resource exists with id "00000000000000000000000001"
|
|
When I create a link for project "local/link-proj" to resource "00000000000000000000000001" without alias
|
|
Then the link should have a valid link_id
|
|
And the link project_name should be "local/link-proj"
|
|
|
|
Scenario: Create a resource link with alias
|
|
Given a namespaced project "local/alias-proj" exists in the repository
|
|
And a resource exists with id "00000000000000000000000002"
|
|
When I create an aliased link for project "local/alias-proj" resource "00000000000000000000000002" alias "my-repo"
|
|
Then the link alias should be "my-repo"
|
|
|
|
Scenario: Duplicate alias within same project raises DuplicateLinkError
|
|
Given a namespaced project "local/dup-alias" exists in the repository
|
|
And a resource exists with id "00000000000000000000000003"
|
|
And a resource exists with id "00000000000000000000000004"
|
|
And an aliased link exists for project "local/dup-alias" resource "00000000000000000000000003" alias "dupe"
|
|
When I create a duplicate alias link for project "local/dup-alias" resource "00000000000000000000000004" alias "dupe"
|
|
Then the repository error should be "DuplicateLinkError"
|
|
|
|
Scenario: List links for a project
|
|
Given a namespaced project "local/list-links" exists in the repository
|
|
And a resource exists with id "00000000000000000000000005"
|
|
And a resource exists with id "00000000000000000000000006"
|
|
And a link exists for project "local/list-links" to resource "00000000000000000000000005" without alias
|
|
And a link exists for project "local/list-links" to resource "00000000000000000000000006" without alias
|
|
When I list links for project "local/list-links"
|
|
Then the link list should contain 2 links
|
|
|
|
Scenario: Get a specific link by id
|
|
Given a namespaced project "local/get-link" exists in the repository
|
|
And a resource exists with id "00000000000000000000000007"
|
|
And a link exists for project "local/get-link" to resource "00000000000000000000000007" without alias
|
|
When I get the link by its stored id
|
|
Then the returned link should not be None
|
|
|
|
Scenario: Get a non-existent link returns None
|
|
When I get a link with id "00000000000000000000000099"
|
|
Then the returned link should be None
|
|
|
|
Scenario: Remove a link
|
|
Given a namespaced project "local/rm-link" exists in the repository
|
|
And a resource exists with id "00000000000000000000000008"
|
|
And a link exists for project "local/rm-link" to resource "00000000000000000000000008" without alias
|
|
When I remove the link by its stored id
|
|
Then the remove result should be True
|
|
And the link list for project "local/rm-link" should be empty
|
|
|
|
Scenario: Remove a non-existent link returns False
|
|
When I remove a link with id "00000000000000000000000099"
|
|
Then the remove result should be False
|
|
|
|
Scenario: Create link with read_only flag
|
|
Given a namespaced project "local/ro-proj" exists in the repository
|
|
And a resource exists with id "00000000000000000000000009"
|
|
When I create a read-only link for project "local/ro-proj" to resource "00000000000000000000000009"
|
|
Then the link read_only flag should be True
|
|
|
|
Scenario: Created link is visible in a new session (cross-session persistence)
|
|
Given a namespaced project "local/xsess-proj" exists in the repository
|
|
And a resource exists with id "00000000000000000000000010"
|
|
When I create a link for project "local/xsess-proj" to resource "00000000000000000000000010" without alias
|
|
Then the link should be visible in a new session from the same engine
|
|
|
|
Scenario: Removed link is absent in a new session (cross-session persistence)
|
|
Given a namespaced project "local/xsess-rm" exists in the repository
|
|
And a resource exists with id "00000000000000000000000011"
|
|
And a link exists for project "local/xsess-rm" to resource "00000000000000000000000011" without alias
|
|
When I remove the link by its stored id
|
|
Then the remove result should be True
|
|
And the removed link should be absent in a new session from the same engine
|