Feature: Project CLI command functions coverage As a developer I want the project CLI command functions exercised directly So that cli/commands/project.py achieves high coverage Background: Given a project CLI commands test database is initialized # ── helpers that are never reached from the repository-only tests ── Scenario: _get_namespaced_project_repo returns a repository When I call _get_namespaced_project_repo via the patched container Then the helper should return a NamespacedProjectRepository Scenario: _get_resource_link_repo returns a repository When I call _get_resource_link_repo via the patched container Then the helper should return a ProjectResourceLinkRepository Scenario: _get_resource_registry_service returns a service When I call _get_resource_registry_service via the patched container Then the helper should return a ResourceRegistryService Scenario: _store_project_extras stores invariants via file DB When I call _store_project_extras with invariants "no-delete" and actor "guard" Then the extras call should complete without error # ── create command ──────────────────────────────────────────── Scenario: create command with bare name uses rich output When I invoke project-create with bare name "my-app" Then the project cmd output should contain "created" And the project cmd should succeed Scenario: create command with explicit namespace When I invoke project-create with bare name "team/my-svc" Then the project cmd output should contain "created" And the project cmd should succeed Scenario: create command with description When I invoke project-create with name "desc-proj" description "A nice project" Then the project cmd output should contain "created" And the project cmd should succeed Scenario: create command with json format When I invoke project-create with name "json-proj" format "json" Then the project cmd output should contain "namespaced_name" And the project cmd should succeed Scenario: create command with invariants When I invoke project-create with name "inv-proj" invariant "do not delete files" Then the project cmd output should contain "created" And the project cmd should succeed Scenario: create command with linked resource Given a resource "my-git-res" is registered in the commands DB When I invoke project-create with name "res-proj" linking resource "my-git-res" Then the project cmd output should contain "created" And the project cmd should succeed Scenario: create command with invalid name fails When I invoke project-create with bare name "123bad" Then the project cmd should fail Scenario: create command with DatabaseError from repo When I invoke project-create triggering a database error Then the project cmd should fail # ── list command ───────────────────────────────────────────── Scenario: list command shows projects in rich format Given a project "local/list-a" is created in the commands DB And a project "local/list-b" is created in the commands DB When I invoke project-list with default options Then the project cmd output should contain "list-a" And the project cmd output should contain "list-b" Scenario: list command with namespace filter Given a project "local/ns-x" is created in the commands DB And a project "team/ns-y" is created in the commands DB When I invoke project-list with namespace "team" Then the project cmd output should contain "ns-y" Scenario: list command with regex filter Given a project "local/api-svc" is created in the commands DB And a project "local/web-ui" is created in the commands DB When I invoke project-list with regex "api" Then the project cmd output should contain "api-svc" Scenario: list command with invalid regex fails When I invoke project-list with invalid regex "[bad" Then the project cmd should fail Scenario: list command when empty When I invoke project-list with default options Then the project cmd output should contain "No projects found" Scenario: list command with json format Given a project "local/fmt-list" is created in the commands DB When I invoke project-list with format "json" Then the project cmd output should contain "namespaced_name" # ── show command ───────────────────────────────────────────── Scenario: show command displays project in rich format Given a project "local/show-cmd" is created in the commands DB When I invoke project-show for "local/show-cmd" default format Then the project cmd output should contain "show-cmd" And the project cmd should succeed Scenario: show command with linked resources Given a project "local/show-linked" is created in the commands DB And a resource is linked to project "local/show-linked" in the commands DB When I invoke project-show for "local/show-linked" default format Then the project cmd output should contain "show-linked" Scenario: show command with json format Given a project "local/show-json" is created in the commands DB When I invoke project-show for "local/show-json" format "json" Then the project cmd output should contain "namespaced_name" Scenario: show nonexistent project fails When I invoke project-show for "local/ghost" default format Then the project cmd should fail # ── link-resource command ──────────────────────────────────── Scenario: link-resource command in rich format Given a project "local/link-cmd" is created in the commands DB And a resource "link-res" is registered in the commands DB When I invoke project-link for "local/link-cmd" resource "link-res" default format Then the project cmd output should contain "Linked" And the project cmd should succeed Scenario: link-resource command with read-only Given a project "local/ro-cmd" is created in the commands DB And a resource "ro-res" is registered in the commands DB When I invoke project-link for "local/ro-cmd" resource "ro-res" read-only Then the project cmd output should contain "read-only" And the project cmd should succeed Scenario: link-resource command with json format Given a project "local/link-json" is created in the commands DB And a resource "json-res" is registered in the commands DB When I invoke project-link for "local/link-json" resource "json-res" format "json" Then the project cmd output should contain "resource_id" Scenario: link-resource to nonexistent project fails When I invoke project-link for "local/nope" resource "anything" default format Then the project cmd should fail Scenario: link-resource with nonexistent resource fails Given a project "local/link-fail" is created in the commands DB When I invoke project-link for "local/link-fail" resource "no-such-res" default format Then the project cmd should fail # ── unlink-resource command ────────────────────────────────── Scenario: unlink-resource command in rich format Given a project "local/unlink-cmd" is created in the commands DB And a resource is linked to project "local/unlink-cmd" in the commands DB When I invoke project-unlink for "local/unlink-cmd" with yes default format Then the project cmd output should contain "Unlinked" And the project cmd should succeed Scenario: unlink-resource command with json format Given a project "local/unlink-json" is created in the commands DB And a resource is linked to project "local/unlink-json" in the commands DB When I invoke project-unlink for "local/unlink-json" with yes format "json" Then the project cmd output should contain "unlinked" Scenario: unlink-resource for nonexistent project fails When I invoke project-unlink for "local/ghost-proj" resource "any" with yes Then the project cmd should fail Scenario: unlink-resource for nonexistent resource fails Given a project "local/unlink-fail" is created in the commands DB When I invoke project-unlink for "local/unlink-fail" resource "no-such" with yes Then the project cmd should fail Scenario: unlink-resource when resource not linked fails Given a project "local/unlink-none" is created in the commands DB And a resource "orphan-res" is registered in the commands DB When I invoke project-unlink for "local/unlink-none" resource "orphan-res" with yes Then the project cmd should fail # ── delete command ─────────────────────────────────────────── Scenario: delete command removes project Given a project "local/del-cmd" is created in the commands DB When I invoke project-delete for "local/del-cmd" with yes Then the project cmd output should contain "deleted" And the project cmd should succeed Scenario: delete command with json format Given a project "local/del-json" is created in the commands DB When I invoke project-delete for "local/del-json" with yes format "json" Then the project cmd output should contain "deleted" Scenario: delete command JSON includes deletion timestamp Given a project "local/del-json-ts" is created in the commands DB When I invoke project-delete for "local/del-json-ts" with yes format "json" Then the project cmd JSON data should include deleted_at Scenario: delete nonexistent project fails When I invoke project-delete for "local/nope" with yes Then the project cmd should fail Scenario: delete project with linked resources without force fails Given a project "local/del-linked" is created in the commands DB And a resource is linked to project "local/del-linked" in the commands DB When I invoke project-delete for "local/del-linked" with yes no force Then the project cmd should fail Scenario: delete project with linked resources with force succeeds Given a project "local/del-force" is created in the commands DB And a resource is linked to project "local/del-force" in the commands DB When I invoke project-delete for "local/del-force" with yes and force Then the project cmd output should contain "deleted" And the project cmd should succeed Scenario: delete command accepts -f short form for --force Given a project "local/del-sf" is created in the commands DB And a resource is linked to project "local/del-sf" in the commands DB When I invoke project-delete for "local/del-sf" with yes and short force flag Then the project cmd output should contain "deleted" And the project cmd should succeed