codee-agent 0.5.0__tar.gz → 0.5.2__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.
Files changed (83) hide show
  1. {codee_agent-0.5.0 → codee_agent-0.5.2}/PKG-INFO +4 -7
  2. {codee_agent-0.5.0 → codee_agent-0.5.2}/README.md +3 -6
  3. {codee_agent-0.5.0 → codee_agent-0.5.2}/pyproject.toml +1 -1
  4. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/admin.py +3 -1
  5. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/admin_service.py +9 -0
  6. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/templates/skills/story-code-reviewer/SKILL.md +9 -2
  7. codee_agent-0.5.2/src/codee/templates/skills/story-developer/SKILL.md +34 -0
  8. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/templates/skills/story-planner/SKILL.md +9 -2
  9. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/templates/skills/story-qa/SKILL.md +8 -1
  10. codee_agent-0.5.2/src/codee/templates/skills/story-security-reviewer/SKILL.md +38 -0
  11. codee_agent-0.5.2/src/codee/templates/skills/task-code-reviewer/SKILL.md +33 -0
  12. codee_agent-0.5.2/src/codee/templates/skills/task-developer/SKILL.md +33 -0
  13. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/templates/skills/task-qa/SKILL.md +7 -1
  14. codee_agent-0.5.2/src/codee/templates/skills/task-security-reviewer/SKILL.md +35 -0
  15. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/test_admin_service.py +67 -2
  16. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee_tasks_abstract/provider.py +1 -1
  17. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee_tasks_azure_devops/provider.py +42 -28
  18. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee_tasks_azure_devops/test.py +11 -3
  19. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee_tasks_jira/provider.py +1 -1
  20. codee_agent-0.5.0/src/codee/templates/skills/story-developer/SKILL.md +0 -26
  21. codee_agent-0.5.0/src/codee/templates/skills/task-developer/SKILL.md +0 -25
  22. {codee_agent-0.5.0 → codee_agent-0.5.2}/LICENSE +0 -0
  23. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/.gitignore +0 -0
  24. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/__init__.py +0 -0
  25. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/admin_api.py +0 -0
  26. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/admin_cli.py +0 -0
  27. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/agent_cli.py +0 -0
  28. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/coding_agents.py +0 -0
  29. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/executor.py +0 -0
  30. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/init_cli.py +0 -0
  31. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/lib/__init__.py +0 -0
  32. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/lib/cron_describe.py +0 -0
  33. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/lib/mcp_config.py +0 -0
  34. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/lib/runs_db.py +0 -0
  35. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/lib/test_mcp_config.py +0 -0
  36. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/lib/test_runs_db.py +0 -0
  37. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/lib/test_trigger_cron_skills.py +0 -0
  38. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/lib/test_trigger_issue_skills.py +0 -0
  39. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/lib/trigger_aws_sqs_skills.py +0 -0
  40. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/lib/trigger_cron_skills.py +0 -0
  41. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/lib/trigger_email_skills.py +0 -0
  42. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/lib/trigger_issue_skills.py +0 -0
  43. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/mail_server.py +0 -0
  44. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/setup_wizard.py +0 -0
  45. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/start_cli.py +0 -0
  46. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/tasks_providers.py +0 -0
  47. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/templates/AGENTS.md +0 -0
  48. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/templates/CLAUDE.md +0 -0
  49. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/templates/skills/aws-sqs-alarm-response/SKILL.md +0 -0
  50. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/templates/skills/cron-research-5xx-errors/SKILL.md +0 -0
  51. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/templates/skills/story-planner/assets/readme-template.md +0 -0
  52. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/test_admin_api.py +0 -0
  53. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/test_admin_cli.py +0 -0
  54. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/test_agent_cli.py +0 -0
  55. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/test_executor.py +0 -0
  56. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/test_init_cli.py +0 -0
  57. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/test_memory_index.py +0 -0
  58. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/test_setup_wizard.py +0 -0
  59. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/test_start_cli.py +0 -0
  60. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee/workflow_graph.py +0 -0
  61. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee_admin/__init__.py +0 -0
  62. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee_admin/codee_admin.py +0 -0
  63. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee_agent_abstract/__init__.py +0 -0
  64. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee_agent_abstract/provider.py +0 -0
  65. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee_agent_claude_code/__init__.py +0 -0
  66. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee_agent_claude_code/provider.py +0 -0
  67. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee_agent_claude_code/test.py +0 -0
  68. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee_agent_github_copilot/__init__.py +0 -0
  69. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee_agent_github_copilot/provider.py +0 -0
  70. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee_agent_github_copilot/test.py +0 -0
  71. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee_database/__init__.py +0 -0
  72. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee_database/database.py +0 -0
  73. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee_database/oauth_tokens.py +0 -0
  74. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee_main_context/__init__.py +0 -0
  75. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee_main_context/context.py +0 -0
  76. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee_main_context/logging.py +0 -0
  77. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee_main_context/test_context.py +0 -0
  78. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee_main_context/test_logging.py +0 -0
  79. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee_tasks_abstract/__init__.py +0 -0
  80. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee_tasks_azure_devops/__init__.py +0 -0
  81. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee_tasks_azure_devops/oauth.py +0 -0
  82. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee_tasks_jira/__init__.py +0 -0
  83. {codee_agent-0.5.0 → codee_agent-0.5.2}/src/codee_tasks_jira/test.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codee-agent
3
- Version: 0.5.0
3
+ Version: 0.5.2
4
4
  Summary: A virtual co-worker that picks up Jira and Azure DevOps tasks and solves them with coding agents.
5
5
  Keywords: ai,agent,jira,azure-devops,claude-code,github-copilot,automation
6
6
  Author: Denis Kibalko
@@ -35,11 +35,11 @@ Description-Content-Type: text/markdown
35
35
 
36
36
  # Codee - a virtual co-worker
37
37
 
38
- The goal of this project is to provide an assistant that will integrate into your existing environment in order to help you to solve tasks.
38
+ The goal of this project is to provide an assistant that will integrate into your existing environment in order to help you to work on tasks (development, code review, testing).
39
39
 
40
- Codee works with Jira and Azure DevOps as tasks provider, new providers are quite easy to create, PRs are welcome.
40
+ Codee works with Jira and Azure DevOps as tasks providers, new providers are quite easy to create, PRs are welcome.
41
41
 
42
- As agents it current works with Claude Code and Github Copilot.
42
+ As agents it currently works with Claude Code and Github Copilot.
43
43
 
44
44
  ## Run Codee
45
45
 
@@ -71,6 +71,3 @@ uv run codee-start --debug-all # ...plus reflex, boto3, urllib3 and friends
71
71
  ### Skills
72
72
 
73
73
  Codee uses skills to perform tasks. It is the same skills which are used in Claude Code, Codex and other agents.
74
-
75
-
76
- TODO: add skill types, x-codee skills extension
@@ -1,10 +1,10 @@
1
1
  # Codee - a virtual co-worker
2
2
 
3
- The goal of this project is to provide an assistant that will integrate into your existing environment in order to help you to solve tasks.
3
+ The goal of this project is to provide an assistant that will integrate into your existing environment in order to help you to work on tasks (development, code review, testing).
4
4
 
5
- Codee works with Jira and Azure DevOps as tasks provider, new providers are quite easy to create, PRs are welcome.
5
+ Codee works with Jira and Azure DevOps as tasks providers, new providers are quite easy to create, PRs are welcome.
6
6
 
7
- As agents it current works with Claude Code and Github Copilot.
7
+ As agents it currently works with Claude Code and Github Copilot.
8
8
 
9
9
  ## Run Codee
10
10
 
@@ -36,6 +36,3 @@ uv run codee-start --debug-all # ...plus reflex, boto3, urllib3 and friends
36
36
  ### Skills
37
37
 
38
38
  Codee uses skills to perform tasks. It is the same skills which are used in Claude Code, Codex and other agents.
39
-
40
-
41
- TODO: add skill types, x-codee skills extension
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "codee-agent"
3
- version = "0.5.0"
3
+ version = "0.5.2"
4
4
  description = "A virtual co-worker that picks up Jira and Azure DevOps tasks and solves them with coding agents."
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -2215,7 +2215,9 @@ def task_filter_setting() -> rx.Component:
2215
2215
  rows="2", width="100%")),
2216
2216
  hint=rx.text("Optional. Added to every task query as one more AND "
2217
2217
  "condition, on top of the work items above. Leave it "
2218
- "empty to pick up everything they match.",
2218
+ "empty to pick up everything they match. The poll does "
2219
+ "not filter on an assignee — put one here if you want "
2220
+ "one.",
2219
2221
  color=MUTED, font_size="0.8rem"))
2220
2222
 
2221
2223
 
@@ -380,6 +380,15 @@ def _remove_redundant_skill_transitions(
380
380
  for transition in transitions:
381
381
  if transition is candidate or transition["label"].casefold() != label:
382
382
  continue
383
+ # Another entry for the same pair is a duplicate, not a detour.
384
+ # Counting it would make each copy the "longer path" that deletes
385
+ # the other, and the edge would vanish entirely. A skill that
386
+ # states one transition in several places (story-planner names
387
+ # `AI Decomposition review` for both a finished plan and an open
388
+ # question) is exactly what makes the agent emit those copies.
389
+ if (transition["source"].casefold() == source
390
+ and transition["target"].casefold() == target):
391
+ continue
383
392
  adjacency.setdefault(transition["source"].casefold(), set()).add(
384
393
  transition["target"].casefold()
385
394
  )
@@ -3,7 +3,7 @@ name: story-code-reviewer
3
3
  description: Review a pull request for one subtask in an Issue Tracker story.
4
4
  disable-model-invocation: true
5
5
  x-codee-trigger: issue
6
- x-codee-issue-status: ['AI CR Needed']
6
+ x-codee-issue-status: ['AI Ready for CR']
7
7
  x-codee-issue-type: story
8
8
  argument-hint: <STORY_ID>
9
9
  ---
@@ -19,6 +19,13 @@ argument-hint: <STORY_ID>
19
19
  5. Review security, correctness, requirement coverage, performance, tests, error handling, and maintainability.
20
20
  6. Post line comments for specific defects and a findings-first pull request review.
21
21
  7. Add a concise Issue Tracker comment with the verdict, blocking findings, and verification performed.
22
+ 8. Move the story to `AI Ready for security review` when the review passes, or back to `AI Ready for development` when it does not.
23
+
24
+ ## Status Transitions
25
+
26
+ - Review passed with no blocking findings: move the story to `AI Ready for security review`.
27
+ - Blocking findings, or a relevant failing pipeline: move the story to `AI Ready for development` so the developer skill addresses them.
28
+ - Subtasks still awaiting review: leave the story in `AI Ready for CR` so the next run reviews the next one.
22
29
 
23
30
  ## Guidelines
24
31
 
@@ -26,4 +33,4 @@ argument-hint: <STORY_ID>
26
33
  - Distinguish blocking defects from optional suggestions.
27
34
  - Do not approve changes with unresolved blocking findings.
28
35
  - Do not approve a failing pipeline unless the failure is clearly unrelated.
29
- - Make feedback actionable by naming the observed behavior, expected behavior, and affected location.
36
+ - Make feedback actionable by naming the observed behavior, expected behavior, and affected location.
@@ -0,0 +1,34 @@
1
+ ---
2
+ name: story-developer
3
+ description: Implement one subtask from an Issue Tracker story and submit a pull request.
4
+ disable-model-invocation: true
5
+ x-codee-trigger: issue
6
+ x-codee-issue-status: ['AI Ready for development', 'AI In Progress']
7
+ x-codee-issue-type: story
8
+ argument-hint: <STORY_ID>
9
+ ---
10
+
11
+ # Story Developer
12
+
13
+ ## Workflow
14
+
15
+ 1. Read the story, acceptance criteria, attachments, comments, and subtasks in the Issue Tracker.
16
+ 2. Read `story-spec/{STORY_ID}/README.md` and the affected projects' `CLAUDE.md`, `AGENTS.md`, and relevant local skills.
17
+ 3. Move the story to `AI In Progress` before doing any work, so a story already being worked on is not picked up as new.
18
+ 4. Select one open subtask and inspect any related branches, pull requests, and review comments.
19
+ 5. For bugs and regressions, reproduce the problem and identify the root cause before editing code.
20
+ 6. Create or reuse a dedicated worktree and branch according to repository conventions.
21
+ 7. Install dependencies, implement the smallest complete change, and update the story specification when useful.
22
+ 8. Run focused tests, the project build, and any required browser checks.
23
+ 9. Review the complete diff for correctness, security, regressions, and missing tests.
24
+ 10. Commit, push, and create or update the pull request. Do not merge it unless explicitly requested.
25
+ 11. Add a concise Issue Tracker comment describing the change, validation, pull request, and any remaining risk.
26
+ 12. Move the story to `AI Ready for CR` once every open subtask is implemented and its pull request is open.
27
+
28
+ ## Status Transitions
29
+
30
+ - Work started: move the story to `AI In Progress`.
31
+ - All subtasks implemented and pushed: move the story to `AI Ready for CR`.
32
+ - Open subtasks remain: leave the story in `AI In Progress` so the next run continues the work.
33
+
34
+ For UI work, include screenshots or video evidence when appropriate.
@@ -3,7 +3,7 @@ name: story-planner
3
3
  description: Decompose an Issue Tracker story into actionable subtasks and supporting documentation.
4
4
  disable-model-invocation: true
5
5
  x-codee-trigger: issue
6
- x-codee-issue-status: ['AI Decomposition Needed']
6
+ x-codee-issue-status: ['AI Decomposition needed']
7
7
  x-codee-issue-type: story
8
8
  argument-hint: <STORY_ID>
9
9
  ---
@@ -29,8 +29,15 @@ Decompose an Issue Tracker story into actionable subtasks with supporting docume
29
29
 
30
30
  When a plan already exists, re-read new comments and edit the existing subtasks and specification. Create new subtasks only for newly identified work, and avoid duplicates. Move the story back to `AI Decomposition review` when the round is done.
31
31
 
32
+ ## Status Transitions
33
+
34
+ - Plan posted: move the story to `AI Decomposition review`.
35
+ - Waiting on answers to clarifying questions: move the story to `AI Decomposition review` and stop.
36
+
37
+ Never move the story to `AI Ready for development` yourself. Approving the plan is a human decision.
38
+
32
39
  ## Guidelines
33
40
 
34
41
  - Prefer subtasks that can be implemented and reviewed independently.
35
42
  - Order subtasks by dependency.
36
- - Keep technical details concrete and acceptance criteria verifiable.
43
+ - Keep technical details concrete and acceptance criteria verifiable.
@@ -24,5 +24,12 @@ Validate one subtask per invocation. QA is read-only: do not modify the implemen
24
24
  8. Mark each criterion pass or fail and separate blocking defects from non-blocking observations.
25
25
  9. Post a concise Issue Tracker report with the results, evidence, environment, and actionable reproduction steps for failures.
26
26
  10. Update the story specification with a short QA summary when useful.
27
+ 11. Move the story to `AI Ready for Human review` when every criterion passes, or back to `AI Ready for development` when any blocking defect was found.
27
28
 
28
- Create a separate Issue Tracker item for unrelated defects instead of expanding the subtask.
29
+ ## Status Transitions
30
+
31
+ - Every applicable acceptance criterion passed: move the story to `AI Ready for Human review`.
32
+ - Any blocking defect: move the story to `AI Ready for development` with the reproduction steps.
33
+ - Subtasks still awaiting verification: leave the story in `AI Ready for QA` so the next run validates the next one.
34
+
35
+ Create a separate Issue Tracker item for unrelated defects instead of expanding the subtask.
@@ -0,0 +1,38 @@
1
+ ---
2
+ name: story-security-reviewer
3
+ description: Run a security review of the pull request for one subtask in an Issue Tracker story.
4
+ disable-model-invocation: true
5
+ x-codee-trigger: issue
6
+ x-codee-issue-status: ['AI Ready for security review']
7
+ x-codee-issue-type: story
8
+ argument-hint: <STORY_ID>
9
+ ---
10
+
11
+ # Story Security Reviewer
12
+
13
+ A security-only pass over work that already passed code review. In a general review, security findings compete with naming, tests, and performance and usually lose. This run looks at nothing else.
14
+
15
+ ## Workflow
16
+
17
+ 1. Read the story, acceptance criteria, attachments, comments, and linked subtasks in the Issue Tracker.
18
+ 2. Read `story-spec/{STORY_ID}/README.md` when it exists.
19
+ 3. Select one subtask whose pull request has passed code review.
20
+ 4. Read the project instructions, complete diff, affected files, and the trust boundaries the change touches.
21
+ 5. Review authentication, authorization, input validation, injection, secrets and credential handling, sensitive data exposure, unsafe deserialization, path and command handling, dependency risk, and access to third-party services.
22
+ 6. For each finding, record the vulnerable location, the attack it enables, and the concrete fix.
23
+ 7. Post line comments for specific vulnerabilities and a findings-first pull request review.
24
+ 8. Add a concise Issue Tracker comment with the verdict, blocking findings, and what was inspected.
25
+ 9. Move the story to `AI Ready for QA` when the review passes, or back to `AI Ready for development` when it does not.
26
+
27
+ ## Status Transitions
28
+
29
+ - No exploitable findings: move the story to `AI Ready for QA`.
30
+ - Any exploitable finding: move the story to `AI Ready for development` with the location and the fix.
31
+ - Subtasks still awaiting a security pass: leave the story in `AI Ready for security review` so the next run reviews the next one.
32
+
33
+ ## Guidelines
34
+
35
+ - Review one subtask per invocation.
36
+ - Report only findings reachable in this codebase, and name the path that reaches them.
37
+ - Separate exploitable vulnerabilities from hardening suggestions.
38
+ - Do not modify the implementation or merge the pull request.
@@ -0,0 +1,33 @@
1
+ ---
2
+ name: task-code-reviewer
3
+ description: Review the pull request for a standalone Issue Tracker task.
4
+ disable-model-invocation: true
5
+ x-codee-trigger: issue
6
+ x-codee-issue-status: ['AI Ready for CR']
7
+ x-codee-issue-type: task
8
+ argument-hint: <TASK_ID>
9
+ ---
10
+
11
+ # Task Code Reviewer
12
+
13
+ ## Workflow
14
+
15
+ 1. Read the task, acceptance criteria, attachments, and comments in the Issue Tracker.
16
+ 2. Locate the pull request awaiting review.
17
+ 3. Read the project instructions, complete diff, affected files, relevant callers, tests, pipeline results, and unresolved review comments.
18
+ 4. Review security, correctness, requirement coverage, performance, tests, error handling, and maintainability.
19
+ 5. Post line comments for specific defects and a findings-first pull request review.
20
+ 6. Add a concise Issue Tracker comment with the verdict, blocking findings, and verification performed.
21
+ 7. Move the task to `AI Ready for security review` when the review passes, or back to `AI Ready for development` when it does not.
22
+
23
+ ## Status Transitions
24
+
25
+ - Review passed with no blocking findings: move the task to `AI Ready for security review`.
26
+ - Blocking findings, or a relevant failing pipeline: move the task to `AI Ready for development` so the developer skill addresses them.
27
+
28
+ ## Guidelines
29
+
30
+ - Distinguish blocking defects from optional suggestions.
31
+ - Do not approve changes with unresolved blocking findings.
32
+ - Do not approve a failing pipeline unless the failure is clearly unrelated.
33
+ - Make feedback actionable by naming the observed behavior, expected behavior, and affected location.
@@ -0,0 +1,33 @@
1
+ ---
2
+ name: task-developer
3
+ description: Implement a standalone Issue Tracker task and submit a pull request.
4
+ disable-model-invocation: true
5
+ x-codee-trigger: issue
6
+ x-codee-issue-status: ['AI Ready for development', 'AI In Progress']
7
+ x-codee-issue-type: task
8
+ argument-hint: <TASK_ID> [continue]
9
+ ---
10
+
11
+ # Task Developer
12
+
13
+ ## Workflow
14
+
15
+ 1. Read the task, acceptance criteria, attachments, and comments in the Issue Tracker. With `continue`, also read new pull request feedback.
16
+ 2. Read the affected projects' `CLAUDE.md`, `AGENTS.md`, and relevant local skills.
17
+ 3. Move the task to `AI In Progress` before doing any work, so a task already being worked on is not picked up as new.
18
+ 4. For bugs and regressions, reproduce the problem and identify the root cause before editing code. Report evidence when the issue cannot be reproduced or the root cause remains unclear.
19
+ 5. Create or reuse a dedicated worktree and branch according to repository conventions.
20
+ 6. Install dependencies and implement the smallest complete change that satisfies the acceptance criteria.
21
+ 7. Run focused tests, the project build, and browser validation for UI work.
22
+ 8. Review the complete diff for correctness, security, regressions, and missing tests.
23
+ 9. Commit, push, and create or update the pull request. Do not merge it unless explicitly requested.
24
+ 10. Add a concise Issue Tracker comment describing the change, validation, pull request, and any remaining risk.
25
+ 11. Move the task to `AI Ready for CR` once the change is complete and its pull request is open.
26
+
27
+ ## Status Transitions
28
+
29
+ - Work started: move the task to `AI In Progress`.
30
+ - Change complete and pushed: move the task to `AI Ready for CR`.
31
+ - Work unfinished, or the problem could not be reproduced: leave the task in `AI In Progress` and comment with what is missing.
32
+
33
+ For UI work, include screenshots or video evidence when appropriate. On continued work, always refresh the Issue Tracker item and pull request before acting.
@@ -22,5 +22,11 @@ QA is read-only: do not modify the implementation or merge its pull request.
22
22
  6. For service work, test success, validation, authorization, and edge cases. Record requests, responses, HTTP codes, and relevant side effects.
23
23
  7. Mark each criterion pass or fail and separate blocking defects from non-blocking observations.
24
24
  8. Post a concise Issue Tracker report with the results, evidence, environment, and actionable reproduction steps for failures.
25
+ 9. Move the task to `AI Ready for Human review` when every criterion passes, or back to `AI Ready for development` when any blocking defect was found.
25
26
 
26
- Create a separate Issue Tracker item for unrelated defects instead of expanding the task.
27
+ ## Status Transitions
28
+
29
+ - Every acceptance criterion passed: move the task to `AI Ready for Human review`.
30
+ - Any blocking defect: move the task to `AI Ready for development` with the reproduction steps.
31
+
32
+ Create a separate Issue Tracker item for unrelated defects instead of expanding the task.
@@ -0,0 +1,35 @@
1
+ ---
2
+ name: task-security-reviewer
3
+ description: Run a security review of the pull request for a standalone Issue Tracker task.
4
+ disable-model-invocation: true
5
+ x-codee-trigger: issue
6
+ x-codee-issue-status: ['AI Ready for security review']
7
+ x-codee-issue-type: task
8
+ argument-hint: <TASK_ID>
9
+ ---
10
+
11
+ # Task Security Reviewer
12
+
13
+ A security-only pass over work that already passed code review. In a general review, security findings compete with naming, tests, and performance and usually lose. This run looks at nothing else.
14
+
15
+ ## Workflow
16
+
17
+ 1. Read the task, acceptance criteria, attachments, and comments in the Issue Tracker.
18
+ 2. Locate the pull request that has passed code review.
19
+ 3. Read the project instructions, complete diff, affected files, and the trust boundaries the change touches.
20
+ 4. Review authentication, authorization, input validation, injection, secrets and credential handling, sensitive data exposure, unsafe deserialization, path and command handling, dependency risk, and access to third-party services.
21
+ 5. For each finding, record the vulnerable location, the attack it enables, and the concrete fix.
22
+ 6. Post line comments for specific vulnerabilities and a findings-first pull request review.
23
+ 7. Add a concise Issue Tracker comment with the verdict, blocking findings, and what was inspected.
24
+ 8. Move the task to `AI Ready for QA` when the review passes, or back to `AI Ready for development` when it does not.
25
+
26
+ ## Status Transitions
27
+
28
+ - No exploitable findings: move the task to `AI Ready for QA`.
29
+ - Any exploitable finding: move the task to `AI Ready for development` with the location and the fix.
30
+
31
+ ## Guidelines
32
+
33
+ - Report only findings reachable in this codebase, and name the path that reaches them.
34
+ - Separate exploitable vulnerabilities from hardening suggestions.
35
+ - Do not modify the implementation or merge the pull request.
@@ -13,8 +13,8 @@ from codee_agent_claude_code.provider import ClaudeCodeAgent
13
13
  from codee_agent_github_copilot.provider import GitHubCopilotAgent
14
14
 
15
15
  from codee.admin_service import (
16
- MCP_CHECK, TASKS_CHECK, AdminService, azure_oauth, normalize_work_items,
17
- parse_skill, repository_name)
16
+ MCP_CHECK, TASKS_CHECK, AdminService, _remove_redundant_skill_transitions,
17
+ azure_oauth, normalize_work_items, parse_skill, repository_name)
18
18
  from codee_main_context.context import (
19
19
  CodeeMainContext, CodingAgent, Settings, TasksProvider, load_settings,
20
20
  save_settings)
@@ -1676,5 +1676,70 @@ class SetupTasksMcpTest(unittest.TestCase):
1676
1676
  self.assertIn("not valid JSON", message)
1677
1677
 
1678
1678
 
1679
+ class RemoveRedundantSkillTransitionsTest(unittest.TestCase):
1680
+ """Only a genuine detour removes an edge, never a repeated statement."""
1681
+
1682
+ def _transition(self, source: str, target: str, label: str,
1683
+ evidence: str) -> dict[str, str]:
1684
+ return {"source": source, "target": target,
1685
+ "label": label, "evidence": evidence}
1686
+
1687
+ def test_a_bypass_of_a_two_step_path_is_removed(self) -> None:
1688
+ transitions = [
1689
+ self._transition("Ready", "In progress", "dev", "first"),
1690
+ self._transition("In progress", "Review", "dev", "second"),
1691
+ self._transition("Ready", "Review", "dev", "third"),
1692
+ ]
1693
+
1694
+ retained = _remove_redundant_skill_transitions(transitions)
1695
+
1696
+ self.assertEqual([(row["source"], row["target"]) for row in retained],
1697
+ [("Ready", "In progress"), ("In progress", "Review")])
1698
+
1699
+ def test_repeating_one_transition_keeps_it(self) -> None:
1700
+ """A skill that names the same target twice still gets its edge.
1701
+
1702
+ story-planner moves the story to `AI Decomposition review` both when
1703
+ the plan is ready and when it stops to ask a question, so the agent
1704
+ reports the pair twice. Reading the second copy as a longer path made
1705
+ each delete the other and the transition disappeared from the graph.
1706
+ """
1707
+ transitions = [
1708
+ self._transition("AI Decomposition needed", "AI Decomposition review",
1709
+ "story-planner", "plan posted"),
1710
+ self._transition("AI Decomposition needed", "AI Decomposition review",
1711
+ "story-planner", "questions asked"),
1712
+ ]
1713
+
1714
+ retained = _remove_redundant_skill_transitions(transitions)
1715
+
1716
+ self.assertEqual(retained, transitions)
1717
+
1718
+ def test_a_duplicated_bypass_is_still_removed(self) -> None:
1719
+ transitions = [
1720
+ self._transition("Ready", "In progress", "dev", "first"),
1721
+ self._transition("In progress", "Review", "dev", "second"),
1722
+ self._transition("Ready", "Review", "dev", "third"),
1723
+ self._transition("Ready", "Review", "dev", "fourth"),
1724
+ ]
1725
+
1726
+ retained = _remove_redundant_skill_transitions(transitions)
1727
+
1728
+ self.assertEqual([(row["source"], row["target"]) for row in retained],
1729
+ [("Ready", "In progress"), ("In progress", "Review")])
1730
+
1731
+ def test_another_skill_bypass_is_left_alone(self) -> None:
1732
+ """The detour has to belong to the same skill to count as one."""
1733
+ transitions = [
1734
+ self._transition("Ready", "In progress", "dev", "first"),
1735
+ self._transition("In progress", "Review", "dev", "second"),
1736
+ self._transition("Ready", "Review", "qa", "third"),
1737
+ ]
1738
+
1739
+ retained = _remove_redundant_skill_transitions(transitions)
1740
+
1741
+ self.assertEqual(len(retained), 3)
1742
+
1743
+
1679
1744
  if __name__ == "__main__":
1680
1745
  unittest.main()
@@ -146,7 +146,7 @@ class AbstractTasksProvider(ABC):
146
146
  """
147
147
  if not tasks:
148
148
  return (f"Connected to {self.describe()}. "
149
- "No tasks are assigned to it right now.")
149
+ "No tasks are waiting for it right now.")
150
150
  preview = ", ".join(f"{task.key} {task.summary}" for task in tasks[:3])
151
151
  more = f", +{len(tasks) - 3} more" if len(tasks) > 3 else ""
152
152
  return (f"Connected to {self.describe()}. "
@@ -1,7 +1,7 @@
1
1
  """Read-only Azure DevOps tasks provider, authenticated through Entra ID.
2
2
 
3
- Every call here is a read: a WIQL query for the ids assigned to the connected
4
- account, then a batch fetch of those work items. The WIQL endpoint is a POST,
3
+ Every call here is a read: a WIQL query for the ids of the Codee work items in
4
+ the states the skills trigger on, then a batch fetch of those work items. The WIQL endpoint is a POST,
5
5
  but it is a query — nothing in this module creates or modifies a work item.
6
6
  """
7
7
  from urllib.parse import quote
@@ -36,8 +36,8 @@ _FIELDS = [
36
36
  # Which Azure DevOps work item types Codee picks up, and what each stands for,
37
37
  # is configured per installation in Settings — organizations disagree on the
38
38
  # names ("User Story" in Agile, "Product Backlog Item" in Scrum, anything at
39
- # all in a custom process). Anything else assigned to the connected account
40
- # belongs to a human and is left alone.
39
+ # all in a custom process). A work item of any other type belongs to a human
40
+ # and is left alone, whatever state it reaches.
41
41
 
42
42
  # Azure DevOps priority is 1-4 with 1 highest; the executor logs this next to
43
43
  # JIRA-style names, so translate rather than print a bare digit.
@@ -122,7 +122,7 @@ class AzureDevOpsWorkItem(Task):
122
122
 
123
123
 
124
124
  class AzureDevOpsTasksProvider(AbstractTasksProvider):
125
- """Fetches work items assigned to the connected account as provider-agnostic Tasks."""
125
+ """Fetches the organization's Codee work items as provider-agnostic Tasks."""
126
126
 
127
127
  DISPLAY_NAME = "Azure DevOps"
128
128
  MCP_SERVER_NAME = "ado"
@@ -157,11 +157,14 @@ class AzureDevOpsTasksProvider(AbstractTasksProvider):
157
157
  connection = self._auth.connection() or {}
158
158
  account = connection.get("account") or "connected account"
159
159
  types = ", ".join(self._work_item_types.values()) or "no work item types"
160
+ # The account is named as the identity the query runs as, not as a
161
+ # filter — the poll matches on type and state, whoever a work item is
162
+ # assigned to.
160
163
  # The filter only gets a mention when there is one: it is off for most
161
164
  # installations, and "filter none" reads like a setting gone wrong.
162
165
  extra = f", filter {self._task_filter}" if self._task_filter else ""
163
166
  return (f"Azure DevOps {self._config.organization_url} "
164
- f"(all projects, assignee {account}, types {types}{extra})")
167
+ f"(all projects, connected as {account}, types {types}{extra})")
165
168
 
166
169
  def mcp_server(self) -> McpServer | None:
167
170
  """Microsoft's Azure DevOps MCP server, addressed at this organization.
@@ -204,7 +207,7 @@ class AzureDevOpsTasksProvider(AbstractTasksProvider):
204
207
  return [
205
208
  f'Create a new "{item_type}" work item in the {organization} '
206
209
  "organization, in any project you can create work items in, with "
207
- f'the title "{summary}", assigned to {account}.',
210
+ f'the title "{summary}".',
208
211
  "Move that work item to a Done, Closed or Removed state — "
209
212
  "whichever its board offers — so it does not stay open.",
210
213
  ]
@@ -280,7 +283,7 @@ class AzureDevOpsTasksProvider(AbstractTasksProvider):
280
283
 
281
284
  def get_tasks(self, statuses: list[str],
282
285
  raise_errors: bool = False) -> list[Task]:
283
- """Fetch work items assigned to the connected account in the given states."""
286
+ """Fetch the Codee work items sitting in the given states."""
284
287
  # Nothing is waiting on a work item, so there is no request worth
285
288
  # making. The settings check passes no statuses too, but there the whole
286
289
  # point is to reach Azure DevOps, so it queries without a state filter.
@@ -342,29 +345,39 @@ class AzureDevOpsTasksProvider(AbstractTasksProvider):
342
345
  """The state filter, dropped entirely when nothing was requested.
343
346
 
344
347
  ``IN ()`` is not valid WIQL, and the only caller that passes no statuses
345
- is the connection check — it wants every Codee work item assigned to the
346
- account, whatever state it sits in.
348
+ is the connection check — it wants every Codee work item it can see,
349
+ whatever state it sits in.
347
350
  """
348
351
  if not statuses:
349
352
  return ""
350
353
  quoted = ", ".join(_quote_wiql(status) for status in statuses)
351
- return f"AND [System.State] IN ({quoted}) "
354
+ return f"[System.State] IN ({quoted})"
352
355
 
353
356
  def _build_wiql(self, statuses: list[str]) -> str:
354
- """WIQL for Codee work items owned by the connected account, highest priority first.
355
-
356
- Nothing here names a project, and no ``@project`` macro is used — that
357
- is what keeps the query valid with no project in the route, so it spans
358
- the organization. What comes back is still narrow: only the Codee work
359
- item types, only the states asked for, and only what is assigned to the
360
- connected account.
357
+ """WIQL for Codee work items, highest priority first, then oldest.
358
+
359
+ There is no assignee clause: what hands a work item to Codee is its
360
+ type and its state, not who it is assigned to. So a work item a human
361
+ still owns is picked up the moment it reaches a state one of the skills
362
+ triggers on, which is what makes those states the handover — they have
363
+ to be ones only Codee's workflow uses. An installation that does want
364
+ an owner filter writes one as the custom WIQL in Settings, e.g.
365
+ ``[System.AssignedTo] = @Me``.
366
+
367
+ Nothing here names a project either, and no ``@project`` macro is used
368
+ — that is what keeps the query valid with no project in the route, so
369
+ it spans the organization. What comes back is still narrow: only the
370
+ Codee work item types, and only the states asked for.
361
371
  """
372
+ clauses = [clause for clause in (
373
+ self._build_wiql_type_clause(),
374
+ self._build_wiql_status_clause(statuses),
375
+ self._build_wiql_filter_clause(),
376
+ ) if clause]
377
+ where = f"WHERE {' AND '.join(clauses)} " if clauses else ""
362
378
  return (
363
379
  "SELECT [System.Id] FROM WorkItems "
364
- "WHERE [System.AssignedTo] = @Me "
365
- f"{self._build_wiql_type_clause()}"
366
- f"{self._build_wiql_status_clause(statuses)}"
367
- f"{self._build_wiql_filter_clause()}"
380
+ f"{where}"
368
381
  "ORDER BY [Microsoft.VSTS.Common.Priority] ASC, [System.CreatedDate] ASC"
369
382
  )
370
383
 
@@ -373,25 +386,26 @@ class AzureDevOpsTasksProvider(AbstractTasksProvider):
373
386
 
374
387
  Bracketed, because a filter is a whole condition rather than a single
375
388
  term: an unparenthesized ``... OR ...`` would bind its OR across the
376
- assignee and type clauses and hand back items Codee does not own.
389
+ type and state clauses and hand back items Codee does not own.
377
390
  """
378
391
  if not self._task_filter:
379
392
  return ""
380
- return f"AND ({self._task_filter}) "
393
+ return f"({self._task_filter})"
381
394
 
382
395
  def _build_wiql_type_clause(self) -> str:
383
396
  """The work item type filter, from the work items configured in Settings.
384
397
 
385
398
  Dropped when nothing is mapped, like the state clause above and for the
386
- same reason — but this one dropping is worse than a wide query: it would
387
- hand the executor every item assigned to the account. Settings keeps the
388
- mandatory work items filled in so it cannot happen in practice.
399
+ same reason — but this one dropping is worse than a wide query: with no
400
+ assignee clause to fall back on it would hand the executor every item in
401
+ the organization. Settings keeps the mandatory work items filled in so
402
+ it cannot happen in practice.
389
403
  """
390
404
  item_types = list(self._work_item_types.values())
391
405
  if not item_types:
392
406
  return ""
393
407
  quoted = ", ".join(_quote_wiql(item_type) for item_type in item_types)
394
- return f"AND [System.WorkItemType] IN ({quoted}) "
408
+ return f"[System.WorkItemType] IN ({quoted})"
395
409
 
396
410
  def _fetch_work_items(self, token: str, ids: list[int]) -> list[dict]:
397
411
  """Batch-fetch the requested work items. Organization-scoped, as the API requires."""
@@ -339,9 +339,16 @@ class TasksProviderTest(unittest.TestCase):
339
339
  wiql = self.provider._build_wiql(["Ready", "Bob's queue"])
340
340
 
341
341
  self.assertIn("[System.State] IN ('Ready', 'Bob''s queue')", wiql)
342
- self.assertIn("[System.AssignedTo] = @Me", wiql)
343
342
  self.assertIn("ORDER BY [Microsoft.VSTS.Common.Priority] ASC", wiql)
344
343
 
344
+ def test_the_query_does_not_filter_on_an_assignee(self) -> None:
345
+ # Type and state are the handover; who the work item is assigned
346
+ # to is nobody's business but the humans working alongside it.
347
+ wiql = self.provider._build_wiql(["Ready"])
348
+
349
+ self.assertNotIn("System.AssignedTo", wiql)
350
+ self.assertNotIn("@Me", wiql)
351
+
345
352
  def test_wiql_only_asks_for_the_mapped_work_item_types(self) -> None:
346
353
  wiql = self.provider._build_wiql(["Ready"])
347
354
 
@@ -534,7 +541,7 @@ class TasksProviderTest(unittest.TestCase):
534
541
  wiql = self.provider._build_wiql([])
535
542
 
536
543
  self.assertNotIn("[System.State] IN", wiql)
537
- self.assertIn("[System.AssignedTo] = @Me", wiql)
544
+ self.assertIn("[System.WorkItemType] IN", wiql)
538
545
 
539
546
  def test_a_successful_pull_names_the_work_items_it_found(self) -> None:
540
547
  self._connect()
@@ -614,7 +621,8 @@ class AzureDevOpsMcpTest(unittest.TestCase):
614
621
  self.assertIn('"Task" work item', steps[0])
615
622
  self.assertIn("acme organization", steps[0])
616
623
  self.assertIn('title "Codee check 1234"', steps[0])
617
- self.assertIn("assigned to dev@acme.com", steps[0])
624
+ # Nothing is said about the assignee: the poll does not filter on one.
625
+ self.assertNotIn("assigned to", steps[0])
618
626
  self.assertIn("Done, Closed or Removed", steps[1])
619
627
 
620
628
  def test_no_check_steps_before_the_account_is_known(self) -> None:
@@ -174,7 +174,7 @@ class JiraTasksProvider(AbstractTasksProvider):
174
174
 
175
175
  def get_tasks(self, statuses: list[str],
176
176
  raise_errors: bool = False) -> list[Task]:
177
- """Fetch tasks assigned to the target user in the configured states."""
177
+ """Fetch the Codee issues sitting in the configured statuses."""
178
178
  # Nothing is waiting on an issue, so there is no request worth making.
179
179
  # The settings check passes no statuses too, but there the whole point
180
180
  # is to reach JIRA, so it queries without a status filter.
@@ -1,26 +0,0 @@
1
- ---
2
- name: story-developer
3
- description: Implement one subtask from an Issue Tracker story and submit a pull request.
4
- disable-model-invocation: true
5
- x-codee-trigger: issue
6
- x-codee-issue-status: ['AI Ready for development', 'AI In Progress']
7
- x-codee-issue-type: story
8
- argument-hint: <STORY_ID>
9
- ---
10
-
11
- # Story Developer
12
-
13
- ## Workflow
14
-
15
- 1. Read the story, acceptance criteria, attachments, comments, and subtasks in the Issue Tracker.
16
- 2. Read `story-spec/{STORY_ID}/README.md` and the affected projects' `CLAUDE.md`, `AGENTS.md`, and relevant local skills.
17
- 3. Select one open subtask and inspect any related branches, pull requests, and review comments.
18
- 4. For bugs and regressions, reproduce the problem and identify the root cause before editing code.
19
- 5. Create or reuse a dedicated worktree and branch according to repository conventions.
20
- 6. Install dependencies, implement the smallest complete change, and update the story specification when useful.
21
- 7. Run focused tests, the project build, and any required browser checks.
22
- 8. Review the complete diff for correctness, security, regressions, and missing tests.
23
- 9. Commit, push, and create or update the pull request. Do not merge it unless explicitly requested.
24
- 10. Add a concise Issue Tracker comment describing the change, validation, pull request, and any remaining risk.
25
-
26
- For UI work, include screenshots or video evidence when appropriate.
@@ -1,25 +0,0 @@
1
- ---
2
- name: task-developer
3
- description: Implement a standalone Issue Tracker task and submit a pull request.
4
- disable-model-invocation: true
5
- x-codee-trigger: issue
6
- x-codee-issue-status: ['AI Ready for development', 'AI In Progress', Reopened]
7
- x-codee-issue-type: task
8
- argument-hint: <TASK_ID> [continue]
9
- ---
10
-
11
- # Task Developer
12
-
13
- ## Workflow
14
-
15
- 1. Read the task, acceptance criteria, attachments, and comments in the Issue Tracker. With `continue`, also read new pull request feedback.
16
- 2. Read the affected projects' `CLAUDE.md`, `AGENTS.md`, and relevant local skills.
17
- 3. For bugs and regressions, reproduce the problem and identify the root cause before editing code. Report evidence when the issue cannot be reproduced or the root cause remains unclear.
18
- 4. Create or reuse a dedicated worktree and branch according to repository conventions.
19
- 5. Install dependencies and implement the smallest complete change that satisfies the acceptance criteria.
20
- 6. Run focused tests, the project build, and browser validation for UI work.
21
- 7. Review the complete diff for correctness, security, regressions, and missing tests.
22
- 8. Commit, push, and create or update the pull request. Do not merge it unless explicitly requested.
23
- 9. Add a concise Issue Tracker comment describing the change, validation, pull request, and any remaining risk.
24
-
25
- For UI work, include screenshots or video evidence when appropriate. On continued work, always refresh the Issue Tracker item and pull request before acting.
File without changes