diff --git a/docs/collaboration.md b/docs/collaboration.md index 1ed66d6..cb28c7d 100644 --- a/docs/collaboration.md +++ b/docs/collaboration.md @@ -29,3 +29,7 @@ Next owner/action: ## Review independence The reviewer must inspect the actual diff and tests. Do not provide the implementer's reasoning as a substitute for evidence; it can anchor the reviewer and hide alternative failure modes. + +## Parallel development + +Parallel implementation uses separate worktrees, exclusive writable paths, and cross-review. The current ownership map and delivery waves are recorded in `docs/workstreams.md`. diff --git a/docs/workstreams.md b/docs/workstreams.md new file mode 100644 index 0000000..7665850 --- /dev/null +++ b/docs/workstreams.md @@ -0,0 +1,105 @@ +# Codex and Claude workstreams + +## Operating rule + +Codex and Claude may work concurrently only in separate Git worktrees and branches. A task must name one writer, one reviewer, and exclusive writable paths before implementation starts. Shared build files, navigation, manifests, domain contracts, and integration are Codex-owned unless a later task explicitly transfers them. + +## Branches and worktrees + +- Codex branch prefix: `codex/` +- Claude branch prefix: `claude/` +- Codex working tree: the primary repository worktree +- Claude working tree: a separate worktree created from a reviewed contract commit + +Neither agent may edit files owned by the other active workstream. Generated build output is never handed off or committed. + +Feature resources use mandatory name prefixes even when stored in separate XML files: `repositories_`, `codebrowser_`, `history_`, and `workitems_`. The final integration gate builds merged resources to detect collisions. + +## Codex ownership + +Codex owns security-sensitive foundations and final integration: + +- OAuth, PKCE, App Links, secure token storage, logout, and account state. +- Gitea base configuration, HTTP client, authentication injection, DTO mapping, pagination, and typed failures. +- Shared domain contracts and repository interfaces. +- Repository and branch list feature. +- Application navigation, dependency wiring, manifests, Gradle files, and shared design system. +- Final integration build, secret scan, and release evidence. + +Default writable paths: + +```text +app/build.gradle.kts +app/src/main/AndroidManifest.xml +app/src/main/java/com/ubisam/ubgitea/core/ +app/src/main/java/com/ubisam/ubgitea/data/ +app/src/main/java/com/ubisam/ubgitea/domain/ +app/src/main/java/com/ubisam/ubgitea/feature/auth/ +app/src/main/java/com/ubisam/ubgitea/feature/repositories/ +app/src/main/java/com/ubisam/ubgitea/ui/navigation/ +app/src/main/java/com/ubisam/ubgitea/ui/theme/ +app/src/test/java/com/ubisam/ubgitea/core/ +app/src/test/java/com/ubisam/ubgitea/data/ +app/src/test/java/com/ubisam/ubgitea/domain/ +app/src/test/java/com/ubisam/ubgitea/feature/auth/ +app/src/test/java/com/ubisam/ubgitea/feature/repositories/ +``` + +## Claude ownership + +Claude owns independent read-only feature implementations after Codex freezes the required domain/API contract: + +- Repository tree and source-code viewer UI. +- Content classification for text, binary, Git LFS pointers, symlinks, submodules, unsupported encodings, and oversized files. +- Commit history, changed-file list, bounded diff presentation, and branch comparison UI. +- Pull request and issue read-only UI after their contracts are supplied. +- Feature-specific accessibility and Compose tests. + +Default writable paths: + +```text +app/src/main/java/com/ubisam/ubgitea/feature/codebrowser/ +app/src/main/java/com/ubisam/ubgitea/feature/history/ +app/src/main/java/com/ubisam/ubgitea/feature/workitems/ +app/src/test/java/com/ubisam/ubgitea/feature/codebrowser/ +app/src/test/java/com/ubisam/ubgitea/feature/history/ +app/src/test/java/com/ubisam/ubgitea/feature/workitems/ +app/src/main/res/values/strings_codebrowser.xml +app/src/main/res/values/strings_history.xml +app/src/main/res/values/strings_workitems.xml +``` + +Claude must not modify shared Gradle, manifest, navigation, domain, data, or generic `strings.xml` files. Needed shared changes are reported as a handoff request for Codex. + +## Contract freeze and change requests + +A Claude task starts from an exact reviewed Codex commit recorded in that task's evidence as its contract-freeze commit. A shared-contract request must state: + +```text +Requesting task: +Required domain/API/navigation change: +Acceptance tests: +Requested owner: +Blocking: yes | no +``` + +Codex handles the request only under an existing acceptance-criteria task with matching writable paths or a new task. Breaking shared-contract changes are prohibited during the freeze unless both owners approve them. After an approved change, Codex records the new freeze commit, Claude rebases its worktree, reruns contract and feature tests, and records acceptance before implementation continues. + +## Delivery waves + +1. Codex completes OAuth core, TASK-004 API foundations, and TASK-005 repository/ref selection. +2. After TASK-005's reviewed contract commit, Claude builds TASK-006 in a separate worktree while Codex builds TASK-009 history/diff contracts. +3. After both are reviewed, Claude builds TASK-007 while Codex builds TASK-010 work-item contracts and integrates TASK-006. +4. After TASK-010's reviewed contract commit, Claude builds TASK-008 while Codex verifies merged history/navigation behavior. +5. Codex performs final integration and all repository-wide gates. + +## Cross-review + +- Claude reviews Codex-owned tasks read-only. +- Codex reviews Claude-owned tasks read-only before integration. +- The implementing agent resolves findings in its own branch. +- Codex performs the final merged build, tests, lint, secret scan, and acceptance-criteria review. + +## Integration ownership transfer + +When a Claude task passes its checks and Codex review, its handoff names the exact commit and explicitly transfers the task's feature paths to the Codex integration task. Codex may then wire navigation and dependencies and make only integration-scoped fixes listed in that task. Feature-behavior defects are returned to Claude's branch unless a new integration task explicitly grants Codex the affected feature paths. Merged-only failures must be recorded with reproduction evidence before either owner edits them. diff --git a/tasks/002-oauth-spike.md b/tasks/002-oauth-spike.md index 60d1cee..13384a2 100644 --- a/tasks/002-oauth-spike.md +++ b/tasks/002-oauth-spike.md @@ -1,9 +1,22 @@ # TASK-002: Prove OAuth PKCE and App Link end to end -Status: blocked by TASK-001 and external App Link configuration +Status: core implementation ready; end-to-end verification blocked by external App Link configuration Owner: Codex Reviewer: Claude +## Writable paths + +- `app/src/main/java/com/ubisam/ubgitea/core/auth/` +- `app/src/main/java/com/ubisam/ubgitea/feature/auth/` +- `app/src/test/java/com/ubisam/ubgitea/core/auth/` +- `app/src/test/java/com/ubisam/ubgitea/feature/auth/` +- `app/src/main/AndroidManifest.xml` +- `app/src/main/res/values/strings_auth.xml` +- `app/build.gradle.kts` +- `gradle/libs.versions.toml` +- `docs/decisions/002-oauth-security.md` +- `tasks/002-oauth-spike.md` + ## Outcome A user can authorize UBGitea through the system browser, return through the verified App Link, exchange the code using PKCE, and view their Gitea identity. @@ -22,7 +35,6 @@ A user can authorize UBGitea through the system browser, return through the veri ## External prerequisites -- Final application ID - Debug and release signing certificate fingerprints - Correct `assetlinks.json` hosted on the Gitea domain - OAuth application configured as a public client diff --git a/tasks/004-gitea-api-client.md b/tasks/004-gitea-api-client.md index 3d94198..bc06ab4 100644 --- a/tasks/004-gitea-api-client.md +++ b/tasks/004-gitea-api-client.md @@ -4,6 +4,19 @@ Status: planned — depends on TASK-003 and authentication contract Owner: Codex Reviewer: Claude +## Writable paths + +- `app/src/main/java/com/ubisam/ubgitea/core/network/` +- `app/src/main/java/com/ubisam/ubgitea/data/` +- `app/src/main/java/com/ubisam/ubgitea/domain/` +- `app/src/test/java/com/ubisam/ubgitea/core/network/` +- `app/src/test/java/com/ubisam/ubgitea/data/` +- `app/src/test/java/com/ubisam/ubgitea/domain/` +- `app/build.gradle.kts` +- `gradle/libs.versions.toml` +- `docs/decisions/003-http-client.md` +- `tasks/004-gitea-api-client.md` + ## Outcome Connect the repository browsing domain to authenticated, paginated Gitea API calls while keeping DTOs and tokens out of domain and UI layers. diff --git a/tasks/005-repository-branch-ui.md b/tasks/005-repository-branch-ui.md index 6aa62bf..e58314e 100644 --- a/tasks/005-repository-branch-ui.md +++ b/tasks/005-repository-branch-ui.md @@ -4,6 +4,15 @@ Status: planned — depends on TASK-002 and TASK-004 Owner: Codex Reviewer: Claude +## Writable paths + +- `app/src/main/java/com/ubisam/ubgitea/feature/repositories/` +- `app/src/test/java/com/ubisam/ubgitea/feature/repositories/` +- `app/src/main/res/values/strings_repositories.xml` +- `app/src/main/java/com/ubisam/ubgitea/ui/navigation/` +- `app/src/test/java/com/ubisam/ubgitea/ui/navigation/` +- `tasks/005-repository-branch-ui.md` + ## Outcome A signed-in user can browse every repository and branch visible to their Gitea account with loading, pagination, refresh, empty, offline, expired-authentication, and server-error states. @@ -15,3 +24,5 @@ A signed-in user can browse every repository and branch visible to their Gitea a - [ ] Loading, empty, offline, authentication-expired, and server-error states are accessible and localized. - [ ] Retry and pagination cannot create duplicate items or overlapping requests. - [ ] UI and ViewModel tests cover primary states and selection behavior. +- [ ] Resource names use the `repositories_` prefix. +- [ ] The reviewed completion commit is recorded as TASK-006's contract-freeze base. diff --git a/tasks/006-code-browser.md b/tasks/006-code-browser.md index bfd5fd9..7d71578 100644 --- a/tasks/006-code-browser.md +++ b/tasks/006-code-browser.md @@ -1,13 +1,22 @@ # TASK-006: Browse trees and source code by ref Status: planned — depends on TASK-005 -Owner: Codex -Reviewer: Claude +Owner: Claude +Reviewer: Codex ## Outcome A user can navigate directories and view source files at an explicit branch, tag, or commit without silently changing refs. +## Writable paths + +- `app/src/main/java/com/ubisam/ubgitea/feature/codebrowser/` +- `app/src/test/java/com/ubisam/ubgitea/feature/codebrowser/` +- `app/src/main/res/values/strings_codebrowser.xml` +- TASK-006 evidence only + +Shared domain, data, Gradle, manifest, and navigation changes must be requested from Codex instead of edited by Claude. + ## Acceptance criteria - [ ] Repository, selected ref, and current path remain visible. @@ -16,3 +25,5 @@ A user can navigate directories and view source files at an explicit branch, tag - [ ] Binary, Git LFS, submodule, unsupported encoding, and oversized-file states have explicit fallbacks. - [ ] Loading, empty, offline, authentication-expired, not-found, and server-error states are localized and accessible. - [ ] Tests cover ref preservation, path navigation, content classification, and size limits. +- [ ] Resource names use the `codebrowser_` prefix. +- [ ] Evidence records the exact reviewed TASK-005 contract-freeze commit. diff --git a/tasks/007-history-and-changes.md b/tasks/007-history-and-changes.md index 506bf67..1ca768c 100644 --- a/tasks/007-history-and-changes.md +++ b/tasks/007-history-and-changes.md @@ -1,13 +1,22 @@ # TASK-007: View commit history and changes -Status: planned — depends on TASK-004 and TASK-006 -Owner: Codex -Reviewer: Claude +Status: planned — depends on TASK-006 and Codex TASK-009 +Owner: Claude +Reviewer: Codex ## Outcome A user can inspect commit history, changed files, per-commit patches, and comparisons between refs in a read-only interface. +## Writable paths + +- `app/src/main/java/com/ubisam/ubgitea/feature/history/` +- `app/src/test/java/com/ubisam/ubgitea/feature/history/` +- `app/src/main/res/values/strings_history.xml` +- TASK-007 evidence only + +Shared domain, data, Gradle, manifest, and navigation changes must be requested from Codex instead of edited by Claude. + ## Acceptance criteria - [ ] Commit history supports pagination and clearly identifies the active ref. @@ -16,3 +25,5 @@ A user can inspect commit history, changed files, per-commit patches, and compar - [ ] Large or truncated diffs are explicitly identified and bounded for mobile rendering. - [ ] Ref comparisons validate and encode both refs independently. - [ ] Tests cover change mapping, rename/delete behavior, pagination, truncation, and error states. +- [ ] Resource names use the `history_` prefix. +- [ ] Evidence records the exact reviewed TASK-009 contract-freeze commit. diff --git a/tasks/008-work-items-ui.md b/tasks/008-work-items-ui.md new file mode 100644 index 0000000..df7bb3b --- /dev/null +++ b/tasks/008-work-items-ui.md @@ -0,0 +1,37 @@ +# TASK-008: Browse pull requests and issues + +Status: planned — depends on Codex TASK-010 +Owner: Claude +Reviewer: Codex + +## Outcome + +A signed-in user can browse pull requests, issues, reviews, and comments visible to the account in a localized read-only interface. + +## Writable paths + +- `app/src/main/java/com/ubisam/ubgitea/feature/workitems/` +- `app/src/test/java/com/ubisam/ubgitea/feature/workitems/` +- `app/src/main/res/values/strings_workitems.xml` +- TASK-008 evidence only + +Shared domain, data, Gradle, manifest, and navigation changes must be requested from Codex instead of edited by Claude. + +## Acceptance criteria + +- [ ] Pull requests and issues use distinct immutable UI models. +- [ ] Repository, number, state, author availability, and updated time are unambiguous. +- [ ] Loading, pagination, empty, offline, 401, 403, 404, and server-error states are localized and accessible. +- [ ] Deleted users and unavailable comments do not crash rendering. +- [ ] Diff status and work-item state are never communicated by color alone. +- [ ] Compose and presentation tests cover primary states, pagination dedupe, retry, and accessibility semantics. +- [ ] Resource names use the `workitems_` prefix. +- [ ] Evidence records the exact reviewed TASK-010 contract-freeze commit. + +## Required checks + +```text +./gradlew assembleDebug +./gradlew testDebugUnitTest +./gradlew lintDebug +``` diff --git a/tasks/009-history-diff-api-contract.md b/tasks/009-history-diff-api-contract.md new file mode 100644 index 0000000..9e10ac8 --- /dev/null +++ b/tasks/009-history-diff-api-contract.md @@ -0,0 +1,36 @@ +# TASK-009: Implement history and diff API contracts + +Status: planned — depends on TASK-004 +Owner: Codex +Reviewer: Claude + +## Outcome + +Provide frozen read-only domain and data contracts for commit history, changed files, bounded patches, and ref comparison so Claude can implement TASK-007 without editing shared layers. + +## Writable paths + +- `app/src/main/java/com/ubisam/ubgitea/domain/history/` +- `app/src/main/java/com/ubisam/ubgitea/data/history/` +- `app/src/test/java/com/ubisam/ubgitea/domain/history/` +- `app/src/test/java/com/ubisam/ubgitea/data/history/` +- `tasks/009-history-diff-api-contract.md` + +## Acceptance criteria + +- [ ] Domain contracts distinguish added, modified, renamed, and deleted files. +- [ ] Commit history and comparison pagination is explicit and immutable. +- [ ] Patch size and line limits produce an explicit truncated state. +- [ ] Base and head refs are encoded independently exactly once. +- [ ] Empty repository, missing ref, 401, 403, 404, 409, 422, rate-limit, network, parse, and server failures map to typed results. +- [ ] Representative JSON and fake-server tests cover commit detail, rename/delete, comparison, pagination, and truncation. +- [ ] No write endpoint is exposed. +- [ ] Evidence records the reviewed contract-freeze commit for TASK-007. + +## Required checks + +```text +./gradlew assembleDebug +./gradlew testDebugUnitTest +./gradlew lintDebug +``` diff --git a/tasks/010-work-items-api-contract.md b/tasks/010-work-items-api-contract.md new file mode 100644 index 0000000..7c844bf --- /dev/null +++ b/tasks/010-work-items-api-contract.md @@ -0,0 +1,36 @@ +# TASK-010: Implement pull-request and issue API contracts + +Status: planned — depends on TASK-004 +Owner: Codex +Reviewer: Claude + +## Outcome + +Provide frozen read-only domain and data contracts for pull requests, issues, reviews, and comments so Claude can implement TASK-008 without editing shared layers. + +## Writable paths + +- `app/src/main/java/com/ubisam/ubgitea/domain/workitems/` +- `app/src/main/java/com/ubisam/ubgitea/data/workitems/` +- `app/src/test/java/com/ubisam/ubgitea/domain/workitems/` +- `app/src/test/java/com/ubisam/ubgitea/data/workitems/` +- `tasks/010-work-items-api-contract.md` + +## Acceptance criteria + +- [ ] Pull requests and issues use separate immutable domain models. +- [ ] Lists, reviews, and comments have explicit immutable pagination contracts. +- [ ] Nullable or deleted authors map without crashes or invented identity. +- [ ] 401, 403, 404, 422, rate-limit, network, parse, and server failures map to typed results. +- [ ] Endpoint DTOs remain outside domain and UI packages. +- [ ] Representative JSON and fake-server tests cover lists, reviews, comments, deleted users, pagination, and failures. +- [ ] No create, edit, merge, close, comment, or notification-write endpoint is exposed. +- [ ] Evidence records the reviewed contract-freeze commit for TASK-008. + +## Required checks + +```text +./gradlew assembleDebug +./gradlew testDebugUnitTest +./gradlew lintDebug +```