Factory experiment #54. Hypothesis: Add --issue flag to factory ceo and factory run for GitHub/GitLab issue targeting (issue #202).
What to Build
-
New module factory/issue.py with:
IssueSpec dataclass: number, title, body, labels, url, forge
parse_issue_ref(ref: str, project_path: Path) → (forge, owner_repo, number) — handles bare numbers, GitHub URLs, GitLab URLs, owner/repo#N shorthand
infer_remote(project_path: Path) → (forge, owner_repo) — parses git remote get-url origin for HTTPS and SSH remotes
fetch_issue(issue_ref: str, project_path: Path) → IssueSpec — fetches via gh issue view (GitHub) or glab issue view (GitLab)
format_issue_as_spec(spec: IssueSpec) → markdown string
-
CLI modifications in factory/cli.py:
- Add
--issue argparse arg to both ceo and run subparsers
- Add mutual-exclusion validation (vs
--prompt, --focus, --no-github, --mode interactive)
- Wire into
cmd_ceo and cmd_run: fetch → format → persist to .factory/strategy/current.md → pass as context
- Update
_build_ceo_task with issue_number/issue_url params for Directive + finalize tracking
-
Tests in tests/test_issue.py:
- URL parsing (GitHub, GitLab, bare number, shorthand)
- Remote inference (HTTPS, SSH)
- Spec formatting
- Subprocess mocking for fetch
- CLI mutual-exclusion errors
Acceptance Criteria
Constraints
- Read CLAUDE.md before starting
- Do NOT modify eval/score.py or .factory/
- Follow the --prompt pattern exactly
- Use subprocess for gh/glab CLI calls
Factory experiment #54. Hypothesis: Add --issue flag to factory ceo and factory run for GitHub/GitLab issue targeting (issue #202).
What to Build
New module
factory/issue.pywith:IssueSpecdataclass:number,title,body,labels,url,forgeparse_issue_ref(ref: str, project_path: Path)→(forge, owner_repo, number)— handles bare numbers, GitHub URLs, GitLab URLs,owner/repo#Nshorthandinfer_remote(project_path: Path)→(forge, owner_repo)— parsesgit remote get-url originfor HTTPS and SSH remotesfetch_issue(issue_ref: str, project_path: Path)→IssueSpec— fetches viagh issue view(GitHub) orglab issue view(GitLab)format_issue_as_spec(spec: IssueSpec)→ markdown stringCLI modifications in
factory/cli.py:--issueargparse arg to bothceoandrunsubparsers--prompt,--focus,--no-github,--mode interactive)cmd_ceoandcmd_run: fetch → format → persist to.factory/strategy/current.md→ pass as context_build_ceo_taskwithissue_number/issue_urlparams for Directive + finalize trackingTests in
tests/test_issue.py:Acceptance Criteria
factory ceo /path --issue 42fetches issue ACE self-improvement: evolve agent playbooks from experiment data #42 and runs as specfactory ceo /path --issue https://github.com/owner/repo/issues/42works with full URLfactory ceo /path --issue 42 --prompt foo.mderrors (mutual exclusion)factory ceo /path --issue 42 --no-githuberrorsConstraints