refactor(#5080): remove DirConfig, unexport raw config structs - #5428
Conversation
Completes the config encapsulation refactor (3/3). Now that all consumers use opaque interfaces, this removes the old surface: - Delete DirConfig struct and helpers (dirConfigFromOrg, dirConfigFromPerRepo, emptyDirConfig) - Delete OrgConfigFromPerRepo adapter - Remove LoadFromDir / LoadFromFile (replaced by LoadConfig / LoadConfigWriter) - Rename OrgConfig -> orgConfig (unexported) - Rename PerRepoConfig -> perRepoConfig (unexported) - Update ParseOrgConfig / ParsePerRepoConfig to return interface types (OrgConfigReader / PerRepoConfigReader) - Add ParseOrgConfigWriter / ParsePerRepoConfigWriter for callers needing write access - Add PerRepoConfigWriter interface with SetRoles / SetRuntime - Add DisabledRepos() to OrgConfigReader interface - Update all consumer packages to use interface types - Migrate all external tests to use constructors and setters Closes #5080
|
🤖 Finished Review · ✅ Success · Started 11:29 PM UTC · Completed 11:45 PM UTC |
Site previewPreview: https://de85ff3c-site.fullsend-ai.workers.dev Commit: |
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
ReviewFindingsLow
Previous runReviewFindingsHigh
Medium
Low
Labels: Go refactoring that improves internal config architecture across harness components |
|
/fs-fix fix the review agent's concerns |
|
🤖 Finished Fix · ✅ Success · Started 6:18 AM UTC · Completed 6:28 AM UTC |
- Restore runtimeName passthrough: add SetDefaultRuntime to OrgConfigWriter and call it in runDryRun/runInstall so --runtime flag is honoured - Add SetRepo to OrgConfigWriter so callers mutate config through the writer interface instead of the map returned by the reader's RepoMap() - Restore specific error assertion in TestLoadConfig_InvalidOrgConfig - Add clarifying comment on StatusNotifications type assertion in run.go Addresses review feedback on #5428
🔧 Fix agent — iteration 1 (human-triggered)Addressed all 4 review findings: restored dropped runtimeName passthrough via new SetDefaultRuntime method, added SetRepo writer method to fix mutation-through-reader concern, restored specific test assertion, and documented the StatusNotifications type assertion intent. Fixed (4):
Tests: passed Updated by fullsend fix agent |
E2E tests are runningAuthorization passed for this commit. See the E2E Tests workflow for results. |
|
/fs-review |
|
🤖 Finished Review · ✅ Success · Started 10:06 AM UTC · Completed 10:20 AM UTC |
Superseded by updated review
There was a problem hiding this comment.
Note: The following inline comments could not be posted on the diff (GitHub returned 422) and are included here instead:
internal/config/interfaces.go:148: [low] api-contract
RepoMap() returns the internal map by reference (return c.Repos). Callers holding an OrgConfigReader can read and mutate the returned map, bypassing SetRepo(). The PR has migrated all write-path callers to use SetRepo(), and remaining callers only perform reads. Consider returning a shallow copy if this interface is ever consumed externally.
internal/config/interfaces.go:274: [low] pattern-violation
parseConfigReader and parseConfigWriter each perform a preliminary yaml.Unmarshal into an interface{} probe variable that is never inspected beyond the error check. IsPerRepoYAML performs its own yaml.Unmarshal, and the final Parse*Config function does a third unmarshal. The probe unmarshal is redundant.
internal/cli/run.go:2668: [low] fail-open
StatusNotifications path uses a type assertion to OrgConfigReader to extract notification config. When the loaded config is per-repo, the assertion falls through silently, leaving notifyCfg at its zero value. This is correct behavior (per-repo configs don't support status notifications) and is now well-documented.
internal/config/interfaces.go(file-level): Line 68 · [low] pattern-inconsistency
Per-repo interface getter methods use Config prefix (ConfigRoles, ConfigRuntime) while org interface getters use descriptive nouns (DispatchSettings, InferenceSettings, OrgRepoDefaults). This is intentional to avoid field name conflicts in perRepoConfig.
|
/fs-fix the review agent comments |
|
🤖 Finished Fix · ✅ Success · Started 1:39 PM UTC · Completed 1:48 PM UTC |
Remove the preliminary yaml.Unmarshal probe from parseConfigReader and parseConfigWriter. IsPerRepoYAML already performs its own unmarshal for config-type detection, and the final Parse*Config function performs the actual parse — making the probe a redundant third unmarshal per config load. Update TestLoadConfig_MalformedYAML to expect the more specific "parsing org config" error that now surfaces when malformed YAML falls through IsPerRepoYAML. Addresses review feedback on #5428
🔧 Fix agent — iteration 2 (human-triggered)Addressed 1 of 5 review findings (removed redundant probe unmarshal). Disagreed with 4 findings: all are LOW severity and acknowledged by the reviewer as correct behavior, intentional design, standard practice, or out of scope. Fixed (1):
Disagreed (4):
Tests: passed Updated by fullsend fix agent |
The behaviour test suite completes in ~29m on a good day, leaving only ~1m margin against the 30m job timeout. GitHub API latency variance and non-fast-forward commit retries in pool-repo setup can push runs past 30m without any assertion failures. Raise both the GHA job timeout-minutes and the Makefile go test -timeout from 30m to 45m to provide adequate headroom. Addresses review feedback on #5428
🔧 Fix agent — iteration 4 (human-triggered)No code regression found in config encapsulation changes. Raised behaviour test timeout from 30m to 45m in both the GHA workflow and Makefile. Note: the e2e.yml change won't take effect on this PR's current CI run because pull_request_target reads the workflow from main. A re-run will be needed after this change reaches main. Fixed (1):
Disagreed (1):
Tests: passed
Decision points
Updated by fullsend fix agent |
Behaviour timeout follow-upThe fix agent raised timeouts on this branch in Opened a minimal unblock PR against main: #5483 ( Once #5483 merges, I'll re-run the behaviour job here. Unit/ |
|
/fs-fix Sync from
|
| Merged PR | What it does for BT wall-clock |
|---|---|
| #5444 | Per-scenario World + in-process repo lease pool |
| #5499 / #5491 | Merge triage sufficient + sandbox URL-block scenarios |
| #5497 / #5492 | Skip negative harness settle when positive wait already elapsed |
| #5500 / #5495 | Fold wrong-label negative into issue-label positive |
| #5501 / #5494 | Fold fork-PR issue-harness negative into fork-label positive |
Resolve any merge conflicts from the config encapsulation work (OrgConfigReader / unexported structs / interface accessors). Prefer interface accessors (OrgRepoDefaults(), DisabledRepos(), etc.) — do not reintroduce concrete field access on unexported types.
After the sync push
- Let CI re-run (or ensure it is triggered).
- If unit / e2e / behaviour fail with real assertion or compile errors, fix them in follow-up commits on this branch.
- Do not rely on raising
timeout-minutesagain — that path is blocked until a separate main change; rely on the shorter suite frommain. - Keep the earlier fixes:
"parsing org config"assertions andparsedCfg.OrgRepoDefaults().Rolesine2e/admin.
Verify
go test ./internal/cli/ ./internal/harnessdispatch/ ./internal/config/go test -c -tags e2e ./e2e/admin/- Full CI green on the PR, especially
behaviourfinishing under the existing 30m job limit
Goal: PR #5428 green after syncing BT speedups from main.
|
🤖 Finished Fix · ✅ Success · Started 8:16 AM UTC · Completed 8:27 AM UTC |
Merge origin/main to pick up BT runtime-shortening changes (#5444, #5491, #5492, #5494, #5495). The merge completed without conflicts. Fix TestMintAgentToken_RepoResolutionError and TestResolveMintRepos_NeitherSet to explicitly clear REPO_FULL_NAME and MINT_REPOS via t.Setenv — these tests assumed the env vars were unset but failed when REPO_FULL_NAME was set in the test environment. Addresses review feedback on #5428
🔧 Fix agent — iteration 5 (human-triggered)Merged origin/main (59 commits, no conflicts) to pick up BT runtime-shortening changes. Fixed 2 env-dependent test failures in internal/cli/run_test.go. All tests pass (excluding pre-existing TestStartFetchService failures unrelated to this PR). go build, go vet pass cleanly. e2e/admin compiles successfully. Fixed (2):
Tests: passed
Decision points
Updated by fullsend fix agent |
|
/fs-fix Force PR synchronize — merge already on the branch tipIteration 5 correctly merged But GitHub still reports this PR's head as Do this now
Verify after push
|
|
🤖 Finished Fix · ✅ Success · Started 8:41 AM UTC · Completed 8:48 AM UTC |
🔧 Fix agent — iteration 5 (human-triggered)Created empty commit to force PR synchronize event. The previous push (c138cba) reached the remote but GitHub's PR head tracking remained stale. This new commit will trigger a synchronize webhook when pushed by the post-script, causing CI to run on the merged tree. All PR-related tests verified passing locally. Fixed (1):
Tests: passed Updated by fullsend fix agent |
|
/fs-fix Behaviour failure after main sync (suite finished under 30m — good)Sync + CI on FailureTest: All other scenarios PASS (including the merged triage+sandbox scenario and folded fork/wrong-label paths elsewhere). This is the scenario that now includes the folded wrong-label negative (from #5495 on What to do
Do not
|
|
🤖 Finished Fix · ✅ Success · Started 9:19 AM UTC · Completed 9:36 AM UTC |
The behaviour test scenario "Issue label dispatches issue-only harness" fails intermittently because WaitForWorkflow's 2-minute polling window misses the fullsend.yaml (issues) workflow run. This happens when GitHub Actions webhook delivery lags or when clock drift between the CI runner and GitHub causes the run's CreatedAt to fall before the trigger timestamp. Extract the drain into drainIssueOpenWorkflow which retries once with a 30-second clock-skew buffer on the trigger time. This doubles the effective wait window and handles NTP drift without bumping the global test timeout. Addresses review feedback on #5428
🔧 Fix agent — iteration 7 (human-triggered)Hardened the issue-open drain in createIssue with a retry mechanism and 30-second clock-skew buffer. The behaviour test failure is a flake caused by GitHub Actions webhook delivery lag or clock drift, not a regression from the config encapsulation refactor. Fixed (1):
Tests: passed
Decision points
Updated by fullsend fix agent |
|
🤖 Finished Retro · ✅ Success · Started 11:04 AM UTC · Completed 11:30 AM UTC |
Retro: PR #5428 — Config encapsulation refactor (part 3/3)Workflow: Issue #5080 → triage → code → PR #5428 → review → 7 fix iterations → merged. Timeline: 36 hours from PR open to merge. 39 files changed (+837/−859). The code agent produced a solid large-scale refactoring. The review agent caught a genuine high-severity bug (dropped What went well
What went wrong
Autonomy assessmentThe review agent's performance matched the two human reviewers — both humans approved after the same fixes the review agent requested. On internal refactoring PRs with net-negative LOC and no public API changes, the review agent could potentially operate with higher autonomy. Agents repoAgents resolved from Proposals filed
|
Summary
Completes the config encapsulation refactor (part 3 of 3, per #5014). Removes
DirConfig, unexports raw config structs (OrgConfig→orgConfig,PerRepoConfig→perRepoConfig), and updates all consumers to use opaque interfaces.Changes
DirConfigstruct and helpers,OrgConfigFromPerRepoadapter,LoadFromDir/LoadFromFilefunctionsOrgConfig→orgConfig,PerRepoConfig→perRepoConfigParseOrgConfig/ParsePerRepoConfignow return interface types (OrgConfigReader/PerRepoConfigReader); addedParseOrgConfigWriter/ParsePerRepoConfigWriterfor callers needing write accessPerRepoConfigWriterwithSetRoles/SetRuntime; addedDisabledRepos()toOrgConfigReaderinternal/cli,internal/harnessdispatch,internal/layers,internal/repos,internal/runtime, andpkg/behaviourtestto use interface types instead of concrete struct referencesNewOrgConfig,NewPerRepoConfig) and setters instead of struct literalsTesting
go build ./...passes — all non-test code compiles cleanlygo vet ./...passes — no vet errorsgo test ./internal/config/...passesgo test ./internal/harnessdispatch/...passesgo test ./internal/harness/...passesgo test ./internal/layers/...passesgo test ./internal/runtime/...passesgo test ./internal/repos/...passesgo test ./internal/cli/...passes (excluding pre-existing TestStartFetchService failures unrelated to this change)Checklist
!for breaking changes)Closes #5080
Post-script verification
agent/5080-config-encapsulation)6ef9152c619fe81daeb47b3df138b2f72626d456..HEAD)