diff --git a/project/TICKETS.md b/project/TICKETS.md index 1f138af..393eeb9 100644 --- a/project/TICKETS.md +++ b/project/TICKETS.md @@ -1,3 +1,8 @@ -# Ticket Index +# Ticket index (`project/`) -- [ticket-001](project/ticket-001/README.md): Adopt wellmanifest/new-project 0.20.35 + +| Ticket ID | Spec | Preprompt | Human input | Agent plans | Agent logs | Changelog | +| :--- | :--- | :--- | :--- | :--- | :--- | :--- | +| **ticket-001** | [`README.md`](./ticket-001/README.md) | - | - | - | - | - | +| **ticket-002** | [`README.md`](./ticket-002/README.md) | - | - | - | - | - | + diff --git a/project/ticket-002/README.md b/project/ticket-002/README.md new file mode 100644 index 0000000..cc7ea99 --- /dev/null +++ b/project/ticket-002/README.md @@ -0,0 +1,21 @@ +# Ticket 002: fix password store test isolation with dotenv + +- **ID**: ticket-002 +- **Owner**: agent:gemini +- **Status**: IN_PROGRESS +- **Workflow state**: EDIT +- **Created**: 2026-10-04 + +## Goal and scope + +Ensure `test_password_store.py` scenarios with cleared environment are properly +isolated from host `.env` files via `patch("dotenv.load_dotenv")`. + +## Acceptance criteria + +- [x] AC-01: `pytest -q tests/unit/test_password_store.py` passes cleanly. +- [x] AC-02: `project/governance-check.sh` passes cleanly. + +## Tracking boundary + +This directory contains the minimal reviewed intent. diff --git a/project/ticket-002/intent.json b/project/ticket-002/intent.json new file mode 100644 index 0000000..421f533 --- /dev/null +++ b/project/ticket-002/intent.json @@ -0,0 +1,78 @@ +{ + "schema": "new-project.intent/v3", + "ticket": "ticket-002", + "summary": "fix password store test isolation with dotenv", + "workstream": "application", + "classification": { + "kind": "BUG", + "priority": "P2", + "origin": "health" + }, + "allowedPaths": [ + "project/ticket-002/**", + "TODO.md", + "project/TICKETS.md", + "tests/unit/test_password_store.py" + ], + "forbiddenPaths": [ + "project/ticket-*/user-*.md" + ], + "stacks": [], + "dependsOn": [], + "conflictsWith": [], + "integrationTicket": null, + "delivery": { + "acceptedBaseSha": "3f41b339c2b7dc82f196cb5da9c9990ad81a7ee8", + "targetBranch": "main", + "outcome": "Ensure test_password_store unit tests are isolated from host dotenv environment.", + "nonGoals": [ + "No production credential store changes." + ], + "complexity": "XS", + "estimatedMinutes": 10, + "budgets": { + "maxImplementationFiles": 2, + "maxAffectedComponents": 1, + "maxPublicInterfaceChanges": 0, + "maxRuntimeDependencies": 0 + }, + "architecture": { + "status": "accepted", + "decision": "Patch dotenv.load_dotenv in test_scenario_github_login_only to isolate cleared environment", + "components": [ + { + "name": "tests", + "paths": [ + "tests/unit/test_password_store.py" + ] + } + ], + "responsibilityChanges": false, + "interfaceChanges": [], + "dataChanges": [], + "ui": { + "impact": "none", + "states": [], + "evidence": [] + }, + "rollback": "git revert" + }, + "runtimeDependencies": [], + "validation": [ + { + "criterion": "AC-01", + "commands": [ + "pytest -q tests/unit/test_password_store.py" + ], + "evidence": "All 31 password store tests pass." + }, + { + "criterion": "AC-02", + "commands": [ + "bash project/governance-check.sh --base origin/main --head HEAD" + ], + "evidence": "governance gate reports GOV-PASS." + } + ] + } +} diff --git a/tests/unit/test_password_store.py b/tests/unit/test_password_store.py index a8025db..bc1a962 100644 --- a/tests/unit/test_password_store.py +++ b/tests/unit/test_password_store.py @@ -226,7 +226,7 @@ def test_scenario_github_login_only(self): creds = [Credential("https://github.com", "github.com", "myuser", "mypass", "firefox")] store = self._make_store_with_firefox_creds(creds) - with patch.dict(os.environ, {}, clear=True): + with patch.dict(os.environ, {}, clear=True), patch("dotenv.load_dotenv"): cred = store.get_credentials("github.com") assert cred is not None assert cred.username == "myuser" @@ -242,7 +242,7 @@ def test_scenario_anthropic_no_creds(self): """Anthropic: no credentials anywhere → manual login required.""" store = self._make_store_with_firefox_creds([]) - with patch.dict(os.environ, {}, clear=True): + with patch.dict(os.environ, {}, clear=True), patch("dotenv.load_dotenv"): cred = store.get_credentials("anthropic.com") assert cred is None