feat(#6684): add --gitlab-url flag to repos install - #7087
Conversation
Add a --gitlab-url flag to `fullsend repos install` that sets gitlab.url in the manifest when bootstrapping GitLab repos. This enables first-time GitLab onboarding in a single command without a prior set-default step. Previously, users had to run `fullsend repos set-default gitlab.url <url>` or manually edit repos.yaml before installing GitLab repos, because Validate() rejects manifests where gitlab.url is empty but GitLab repos are present. Changes: - Add gitlabURL field to reposInstallConfig struct - Register --gitlab-url flag in newReposInstallCmd() - Validate the URL early (HTTPS scheme, no path/query/fragment) reusing the existing RejectExtraneousURLParts helper - Set manifest.GitLab.URL and persist via SetDefault after AddToManifest but before Converge validation - Export RejectExtraneousURLParts for use outside the repos package (was unexported rejectExtraneousURLParts) - Add tests for flag registration, bootstrap flow, URL override, and URL validation (non-HTTPS, invalid, extraneous path) - Update docs/cli/repos.md flags table and GitLab example Closes #6684
|
🤖 Finished Review · ✅ Success · Started 1:09 AM UTC · Completed 1:28 AM UTC Commit: Runtime: claude · Model: opus → claude-opus-4-6 · Effort: high · Cost: $5.33 |
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
|
Risk Assessment: moderate (2/5) DetailsTier 1 signals are identical to the prior assessment (9 files, medium blast radius, bot author, 0.22 test ratio, no protected or security-sensitive paths); Tier 2 shows the same elevated churn and fix-commit counts concentrated in high-traffic docs and CLI files as the prior run (sub-score 2.86); Tier 3 confirms tight scope alignment with a strictly additive new flag; composite 0.50x1.50+0.30x2.86+0.20x1.50=1.91 rounds to 2 (moderate), matching the prior score with no change in signal characteristics. Previous runRisk Assessment: moderate (2/5) DetailsTier 1 signals are identical to the prior assessment (9 files, medium blast radius, bot author, 0.22 test ratio, no protected or security-sensitive paths); Tier 2 shows elevated churn and fix-commit counts concentrated in high-traffic docs and CLI files consistent with the prior run; Tier 3 confirms tight scope alignment with a strictly additive change; composite 0.50x1.50+0.30x2.86+0.20x1.50=1.91 rounds to 2 (moderate), matching the prior score with no change in signal characteristics. Previous run (2)Risk Assessment: moderate (2/5) DetailsTier 1 signals are identical to the prior assessment (9 files, medium blast radius, bot author, no protected or security-sensitive paths); Tier 2 confirms active CLI-area churn with zero reverts; Tier 3 confirms tight issue-to-PR scope alignment; composite 1.79 rounds to 2 (moderate), matching the prior score with no change in signal characteristics. Previous run (3)Risk Assessment: moderate (2/5) DetailsTier 1 signals essentially unchanged from prior (9 files, medium blast radius, bot author, no protected or security-sensitive paths); Tier 2 confirms active CLI area churn with zero actual reverts; Tier 3 confirms tight issue-to-PR scope alignment; composite 1.78 rounds to moderate (2). Previous run (4)Risk Assessment: moderate (2/5) DetailsTier 1 signals unchanged from prior (8 files, medium blast, bot author, no protected paths); Tier 2 confirms moderate churn on active CLI area with zero reverts; Tier 3 confirms tight issue-to-PR scope alignment; composite 1.74 rounds to moderate (2). Previous run (5)Risk Assessment: moderate (2/5) DetailsTier 1 signals are unchanged from the prior assessment (7 files, medium blast radius, bot author, no protected paths or security-sensitive files, 0.14 test ratio); Tier 2 confirms known-characteristic high churn on active CLI and docs files but finds no actual revert commits and low change coupling; composite lands at 1.79, rounding to moderate (2) — the PR is a narrow, well-tested single-flag addition that squarely matches the issue scope. Previous run (6)Risk Assessment: moderate (2/5) DetailsTier 1 signals are unchanged from the prior assessment (same file count, no protected paths, no dependency changes, bot author); composite lands at 2.16 (0.50×1.5 + 0.30×3.7 + 0.20×1.5), rounding to moderate (2) — the high Tier 2 churn on these CLI/manifest files is a known characteristic rather than a PR-specific risk, and the change itself remains a narrow, well-tested single-flag addition. Previous run (7)Risk Assessment: moderate (2/5) DetailsWell-scoped single-flag CLI addition with tests and docs, authored by a bot on frequently churned but low-security files; git history churn inflates Tier 2 but the PR itself is narrow and low-risk, landing at moderate (2). |
ReviewFindingsLow
Previous runReviewFindingsMedium
Low
Next steps:
Previous run (2)ReviewFindingsLow
Next steps:
Previous run (3)ReviewFindingsLow
Next steps:
Previous run (4)ReviewFindingsMedium
Low
Next steps:
Previous run (5)ReviewFindingsLow
Next steps:
Previous run (6)ReviewFindingsMedium
Low
Next steps:
Previous run (7)ReviewFindingsMedium
Low
Next steps:
|
|
🤖 Finished Fix · ✅ Success · Started 1:30 AM UTC · Completed 1:42 AM UTC Commit: Runtime: claude · Model: opus → claude-opus-4-6 · Effort: high · Cost: $1.84 |
- Guard --gitlab-url SetDefault with dryRun check to prevent writing to the manifest during dry-run mode - Warn when --gitlab-url is provided but no GitLab repos are in the manifest (silent-no-op) - Add TestRunReposInstall_GitLabURLDryRun to cover the dry-run + --gitlab-url path - Document --gitlab-url in the GitLab URL section of docs/guides/getting-started/repo-management.md Addresses #7087
🔧 Fix agent — iteration 1 (bot-triggered)Addressed all four review findings: guarded --gitlab-url manifest write with dry-run check, added warning for silent no-op when no GitLab repos exist, added dry-run test coverage, and documented the flag in the getting-started guide Fixed (4):
Tests: passedNext steps:
|
|
🤖 Finished Review · ✅ Success · Started 1:43 AM UTC · Completed 1:58 AM UTC Commit: Runtime: claude · Model: opus → claude-opus-4-6 · Effort: high · Cost: $3.81 |
|
🤖 Finished Fix · ✅ Success · Started 2:00 AM UTC · Completed 2:10 AM UTC Commit: Runtime: claude · Model: opus → claude-opus-4-6 · Effort: high · Cost: $1.72 |
The dry-run bootstrap path (new manifest + --forge gitlab + --gitlab-url) returned early before the --gitlab-url block, so users saw no preview of the URL being set. Emit the preview message inside the early-return block. Also restructure the --gitlab-url conditional to use a single outer guard instead of repeating the check, add a bootstrap dry-run test, and document --gitlab-url and --gitlab-bot-token in the cli-internals flag tree. Addresses #7087
🔧 Fix agent — iteration 2 (bot-triggered)Addressed all four review findings: added dry-run preview for --gitlab-url in the bootstrap early-return path, added a bootstrap dry-run test, documented --gitlab-url and --gitlab-bot-token in cli-internals.md flag tree, and restructured the duplicated guard into idiomatic nested conditionals Fixed (4):
Tests: passed Decision points
Next steps:
|
|
🤖 Finished Review · ✅ Success · Started 2:12 AM UTC · Completed 2:27 AM UTC Commit: Runtime: claude · Model: opus → claude-opus-4-6 · Effort: high · Cost: $4.38 |
|
🤖 Finished Fix · ✅ Success · Started 2:29 AM UTC · Completed 2:38 AM UTC Commit: Runtime: claude · Model: opus → claude-opus-4-6 · Effort: high · Cost: $1.51 |
…rence Extract the --gitlab-url dry-run announcement into a shared announceGitlabURLDryRun helper so the message text and guard are defined exactly once, eliminating divergent duplication between the early-return path and the main --gitlab-url handler. Mark the --gitlab-url action item in gitlab-implementation.md as implemented now that this PR delivers the feature. Note: pre-commit hooks were not run. pre-commit could not complete (infrastructure failure — sandbox cannot fetch remote hook repos), and the hooks were run directly instead (gofmt, go vet, go build). Addresses #7087
🔧 Fix agent — iteration 3 (bot-triggered)Addressed both review findings: (1) deduplicated the dry-run message by extracting announceGitlabURLDryRun helper, (2) marked the --gitlab-url action item as implemented in gitlab-implementation.md Fixed (2):
Tests: passed
Decision points
Next steps:
|
|
🤖 Finished Review · ✅ Success · Started 2:40 AM UTC · Completed 3:01 AM UTC Commit: Runtime: claude · Model: opus → claude-opus-4-6 · Effort: high · Cost: $5.16 |
When --gitlab-url was provided without --forge on a manifest that already contained GitHub repos, the forge-inference logic picked ForgeGitHub (because ghHasRepos was true and glHasRepos was false), causing the new repo to land in the wrong platform section. Add an explicit guard before the general inference block so that --gitlab-url always implies ForgeGitLab. Update the test to cover the mixed-manifest case with existing GitHub repos. Note: pre-commit hooks were not run. pre-commit could not complete (infrastructure failure), and the hooks were run directly (gofmt, go vet) instead. Addresses #7087
🔧 Fix agent — iteration 7 (human-triggered)Fixed the remaining logic bug where --gitlab-url with a mixed GitHub/GitLab manifest would incorrectly infer ForgeGitHub. Added explicit forge inference guard and test coverage for the mixed-manifest case. Four previously-addressed findings confirmed as already fixed. Fixed (3):
Disagreed (6):
Tests: passed
Decision points
Next steps:
|
|
🤖 Finished Review · ✅ Success · Started 1:33 AM UTC · Completed 1:49 AM UTC Commit: Runtime: claude · Model: opus → claude-opus-4-6 · Effort: high · Cost: $4.49 |
Superseded by updated review
|
🤖 Finished Retro · ✅ Success · Started 1:38 PM UTC · Completed 1:53 PM UTC Commit: Runtime: claude · Model: opus → claude-opus-4-6 · Effort: high · Cost: $3.28 |
Retro: PR #7087 —
|
| Stage | Time (UTC) | Cost | Outcome |
|---|---|---|---|
| Triage | Sep 7 21:09–21:14 | $1.14 | Good summary, missed dry-run/forge-interaction contracts |
| Code | Sep 8 00:50–01:07 | $5.46 | PR created, 7 files, 4 tests |
| Review×8 + Fix×7 | Sep 8 01:09 – Sep 9 01:49 | $52.63 | 5 bot iterations hit cap; 2 human /fs-fix interventions |
| Human approval + merge | Sep 9 11:58–13:37 | — | Merged with 8 commits |
| Total | ~37 hours wall clock | $59.23 |
This was a well-scoped single-flag CLI addition (314 lines added) that required 8 review/fix iterations before approval — hitting the bot iteration cap twice and requiring human intervention. The review agent found genuine bugs (dry-run contract violation, stale URL ordering, forge inference logic error) but also surfaced new low-severity findings each iteration (naming conventions, code organization, British English spelling), preventing convergence.
Key observations
-
Review-fix loop did not converge within the bot cap. Each of the first 5 bot-triggered reviews surfaced new low-severity findings. Reviews 1–2 found medium bugs (dry-run handling); Reviews 3–5 found only low issues (code organization, doc staleness, spelling). The review agent never approved despite all medium findings being fixed — new low-severity findings kept triggering CHANGES_REQUESTED.
-
The most impactful bug was caught late. The forge-inference logic error (--gitlab-url with a mixed GitHub/GitLab manifest incorrectly infers ForgeGitHub) was present in the initial code but wasn't flagged until Review 6. By then, 5 iterations had been spent on lower-impact issues.
-
Fix agent falsely claimed a finding was "already fixed." In Fix 6, the fix agent marked 7 of 10 findings as "already fixed in prior iterations" — but the forge inference bug was not actually fixed, as Review 7 re-raised the identical finding. Fix 7 finally addressed it correctly.
-
Code agent didn't account for existing CLI contracts. The initial implementation didn't handle
--dry-runfor the new mutation path, didn't validate--forge/--gitlab-urlcross-flag consistency, and had a factory-ordering issue wherenewForgeClientFactorycaptured a stale URL. These accounted for 4+ review findings and at least 2 fix iterations.
Evidence for existing open issues
- Review agent should raise severity threshold for new findings on re-review iterations agents#1208 (review severity threshold on re-review): This PR is strong evidence — 8 iterations with new low findings each time; if re-reviews had been severity-gated to medium+, iterations 3 and 5 (which found only low findings) would have approved, saving ~$15 in review/fix costs.
- Fix agent should constrain scope expansion during review-fix iterations agents#1205 (fix agent scope expansion): Fix iterations introduced helpers, doc updates, and refactored guards that triggered cascading new findings.
- Fix agent should generalize review findings to all instances of the same pattern agents#1220 (fix agent generalize findings): The forge inference fix wasn't applied correctly despite being raised multiple times — the fix agent addressed the specific test but didn't handle the mixed-manifest case.
Proposals filed
- Code agent should verify new CLI code paths respect existing behavioral contracts
- Fix agent should verify "already fixed" claims against current code state
Proposals filed
- Code agent should verify new CLI mutation paths respect existing behavioral contracts (in
fullsend-ai/agents) - Fix agent should verify 'already fixed' claims against current code state (in
fullsend-ai/agents)
Summary
Add a
--gitlab-urlflag tofullsend repos installthat setsgitlab.urlin the manifest when bootstrapping GitLab repos. This enables first-time GitLab onboarding in a single command without needing a priorset-defaultstep.Previously, bootstrapping a new manifest with GitLab repos required running
fullsend repos set-default gitlab.url <url>first, becauseValidate()rejects manifests wheregitlab.urlis empty but GitLab repos are present. With this change, the URL can be provided inline via the new--gitlab-urlflag.Changes
gitlabURLfield toreposInstallConfigand register--gitlab-urlflagRejectExtraneousURLPartshelpermanifest.GitLab.URLand persist it afterAddToManifestbut beforeConvergevalidationRejectExtraneousURLPartsfrom therepospackage (was unexportedrejectExtraneousURLParts)docs/cli/repos.mdflags table and GitLab install exampleTesting
TestReposInstallCmd_GitLabURLFlag)TestRunReposInstall_GitLabURLBootstrap)TestRunReposInstall_GitLabURLOverridesExisting)TestRunReposInstall_GitLabURLValidation)internal/repostests passCloses #6684
Post-script verification
agent/6684-gitlab-url-flag)bccd9e815a09ae063447740473df37908efe17ac..HEAD)