Imported from chrystiamjr/git-forge-release-migrator (
AGENTS.md). Install upstream withnpx skills add chrystiamjr/git-forge-release-migrator. Copyright stays with the author.
AGENTS.md
High-signal context for coding agents working in this repository.
Global context: See .github/instructions/caveman.instructions.md for caveman ultra patterns.
Quick Start
- Read this file and
dart_cli/README.mdbefore touching code. - Run
yarn lint:dart && yarn test:dart && yarn coverage:dartfrom the repo root before finalizing changes. - All production Dart code lives in
dart_cli/lib/src/. - If behavior visible to users changes, update docs under
website/docs/**andwebsite/i18n/pt-BR/**. - Check
Critical Invariants,Architecture Map, andChange Rulesbefore making structural decisions.
Decision Index
- Changing CLI behavior or outputs: read
Product ContractandCritical Invariants. - Changing runtime orchestration or validation: read
Architecture MapandChange Rules. - Changing docs or website code: read
Documentation Sync. - Handling PR review comments: follow
docs/engineering/pr-review-playbook.md. - Creating commits or PR text: follow
docs/engineering/commit-conventions.mdanddocs/engineering/pr-template.md.
Product Contract
Project baseline:
- Name:
git-forge-release-migrator - Public CLI command:
gfrm - Runtime: Dart-only
- Domain: migrate tags, releases, and assets across Git forges with idempotent retry behavior
Supported provider pairs:
gitlab -> githubgithub -> gitlabgithub -> bitbucketbitbucket -> githubgitlab -> bitbucketbitbucket -> gitlab
Out of scope:
- same-provider migrations
- Bitbucket Data Center / Server
Public CLI commands:
gfrm migrategfrm resumegfrm demogfrm smokegfrm setupgfrm settings
gfrm settings actions:
initset-token-envset-token-plainunset-tokenshow
Behavior that must stay stable:
--settings-profileworks formigrateandresume- exit code is
0on success and non-zero on validation or operational failure - retry command in
summary.jsonmust usegfrm resume - token precedence is deterministic:
migrate: settings (token_env, thentoken_plain) -> env aliasesresume: session token context -> settings (token_env, thentoken_plain) -> env aliases
- hidden legacy overrides still work when explicitly provided:
--source-token--target-token
Artifact contract:
- every run writes under
migration-results/<timestamp>/ - required artifacts:
migration-log.jsonlsummary.jsonfailed-tags.txt
summary.jsonmust keepschema_version: 2
Critical Invariants
- Tags-first order:
- tags migrate before releases
--skip-tagsis only safe when destination tags already exist
- Release selection:
- release migration targets semver tags only (
vX.Y.Z)
- Idempotency and resume:
- terminal checkpoint states prevent repeated work
- completed items are skipped
- incomplete items are retried
- Bitbucket release model:
- Bitbucket synthetic releases are represented by tag + notes + downloads +
.gfrm-release-<tag>.json - missing source Bitbucket manifest must not hard-fail by itself
- Security:
- never log raw tokens
- preserve provider auth models and current token precedence
Architecture Map
Main code lives in dart_cli/lib/src/.
Core layers:
cli.dart: terminal-facing adapterconfig.dartandconfig/*: CLI parsing, settings resolution, and validationapplication/*: typed run orchestration and structured preflightmigrations/*: execution core for selection, tag phase, release phase, and summary generationproviders/*: forge adapters and registrycore/*: shared infrastructure, files, settings, HTTP, session store, logging, and types
Boundary rules:
cli.dartshould delegatemigrateandresumeorchestration to the application layerapplication/run_service.dartowns typed orchestration, session persistence, summary finalization, and result mappingapplication/preflight_service.dartowns reusable startup readiness checks via typedPreflightCheckdatamigrations/engine.dartstays execution-only; do not move CLI parsing or provider-specific behavior into it- provider adapters must produce canonical release data consumed by the engine
Change Rules
Safe defaults:
- read the impacted flow first before changing a signature or behavior
- preserve unaffected provider pairs
- prefer additive or refactor-safe changes over broad rewrites
- keep docs and tests aligned with implementation
- update this file only when contract, invariants, or architecture actually change
Token Budget
Default agent behavior for this repository:
- Default to one thread per PR/ticket. When a PR/ticket closes, start a fresh thread with a handoff of 20 lines or fewer.
- Do not repeat large plans, diffs, logs, JSON payloads, or previously established context. Summarize only the current decision, blocker, or result.
- For long commands, write output to
/tmp/<task>.logand report only exit code plus the relevant failing lines or final summary. - Use focused validation during development. Run full suites only before commit/push or when the risk justifies it.
- For PR review work, inspect unresolved inline threads first. Do not load resolved review history unless investigating stale/duplicate review behavior.
$self-reviewdefaults to active diff plus directly related files, withmax_relevant_files=8unless explicitly expanded.- Review/fix loops default to
max_review_cycles=2unless a user explicitly asks for deeper passes. - Prefer concise final handoffs: changed behavior, validation, commit/push/PR state, and remaining blockers only.
Engineering rules:
- avoid
var; prefer explicit typing andfinal - Dart/Flutter production code must use one class/type/enum per file, including private widgets, models, controllers, DTOs, and view models.
- Flutter components must follow the established atomic design layers: atoms, molecules, organisms, and templates. Do not create feature-local design primitives that bypass those layers.
- Test files may group small local fakes or test-only helpers when readability improves and production architecture is unaffected.
- keep helpers small and single-purpose
- keep methods under 120 lines
- keep orchestration-heavy files under 500 lines
- no runtime type dispatch in engine flow (
if (source is ...)) - no magic strings or numbers when a named constant is appropriate
- extract shared logic only after 2+ real callsites
Known pitfalls:
- do not call provider APIs directly from
engine.dart - do not weaken the
--skip-tagssafety check - do not change
summary.jsonschema version unless explicitly versioning the contract - do not treat Bitbucket downloads and
.gfrm-release-<tag>.jsonas separate units
Agent constraints:
- do not introduce new top-level CLI commands without updating
Product Contract - do not change token precedence without updating code and docs together
- do not expand release selection beyond semver-only behavior
- do not add Bitbucket Data Center / Server support
roadmap/is local planning space only; shipped behavior and public docs still live elsewhere
File Size Exceptions (Architectural Necessity)
The codebase has 7 files exceeding the recommended 500-line limit. These are intentional exceptions justified by their single-responsibility focus and high test coverage. Future refactoring should follow the decomposition strategies outlined below:
Provider Adapters
bitbucket.dart (782 lines, 1 class, ~42 methods)
- Responsibility: Complete Bitbucket Cloud API adapter
- Justification: Bitbucket's synthetic release model requires tag + downloads + manifest handling in one orchestration point
- Future decomposition: Consider extracting into:
bitbucket_api.dart— core tag/commit operationsbitbucket_downloads.dart— asset upload/download/pagination logicbitbucket_manifest.dart—.gfrm-release-<tag>.jsonmanifest handling
- Blocking: Keep as-is unless Bitbucket API changes significantly
gitlab.dart (610 lines, 1 class, ~31 methods)
- Responsibility: Complete GitLab API adapter
- Justification: Mirrors GitHub/Bitbucket pattern for consistency; single provider adapter per file
- Future decomposition: Consider extracting release asset operations into helper once 2+ adapters share logic
- Blocking: Keep as-is unless new provider pair requires shared abstraction
github.dart (558 lines, 1 class, ~36 methods)
- Responsibility: Complete GitHub API adapter
- Justification: Single provider adapter pattern; mirrors GitLab/Bitbucket
- Future decomposition: Low priority; functions are already well-scoped
- Blocking: Keep as-is
Configuration & Settings
config.dart (622 lines, 0 classes, ~102 functions)
- Responsibility: CLI argument parsing, token resolution, runtime options building
- Justification: All code is private functions (
_*) serving the publicCliRequestParserclass. Logical separation by stage:- Provider normalization (
_normalizeProvider) - Argument extraction helpers (
_requiredString,_optionalBool, etc.) - Runtime option building (
_buildRuntimeOptions,_buildDemoRuntime) - Token resolution flow (
_resolveTokenFromSession,_resolveTokenWithFallback) - Command parsing (
_parseSettingsCommand,_parseSetupRequest,_parseMigrateRequest)
- Provider normalization (
- Future decomposition: Consider extracting into:
config/token_resolver.dart— token precedence logicconfig/request_builders.dart— CliRequest constructionconfig/extraction_helpers.dart—_requiredString,_optionalBool, etc.
- Blocking: Keep monolithic until refactoring clearly improves testability
settings.dart (583 lines, 0 classes, ~95 functions)
- Responsibility: Settings file I/O, masking, environment variable integration
- Justification: Private function utilities (
_*) supporting publicSettingsManagerAPI. Stages:- File operations (
_readSettingsFile,_writeSettingsFile,_settingsPath) - Env var mapping (
_envVariableForKey,_expandEnvVars) - Masking logic (
_maskValue,_isSensitiveKey) - Merging strategies (
_mergeSettings,_effectiveValue)
- File operations (
- Future decomposition: Consider extracting into:
core/settings_file.dart— file I/O onlycore/settings_masking.dart— secret masking utilitiescore/settings_env_mapper.dart— environment variable integration
- Blocking: Keep monolithic for now; logic is cohesive around settings lifecycle
Application Orchestration
run_service.dart (651 lines, 1 class, ~18 methods)
- Responsibility: Run lifecycle orchestration (preflight → execution → summary → session persistence)
- Justification: Owns multiple stages but each is essential to transactional correctness:
- Preflight validation flow
- Checkpoint-aware engine execution
- Summary generation & artifact writing
- Session context finalization
- Future decomposition: Consider extracting into:
application/run_engine_wrapper.dart— engine execution + checkpointsapplication/run_summary_service.dart— summary generation + artifacts- Keep
run_service.dartfor high-level orchestration
- Blocking: Keep as-is; decomposition requires careful handling of transactional state
Migration Phases
release_phase.dart (523 lines, 1 class, ~13 methods)
- Responsibility: Release migration execution (semver selection, asset handling, idempotency)
- Justification: All methods support a single execution flow; fairly cohesive
- Future decomposition: Could extract asset handling into helper once shared by >1 caller
- Blocking: Low priority; current structure is clean
Refactoring Priority
- High value, low risk:
config.darttoken resolver logic → separate file - Medium value, medium risk:
run_service.dartengine wrapper → separate file - Low value: Other files are either ~500L or serve essential single flows
Rule: Do not refactor unless:
- Tests demonstrate the decomposition improves them (not cosmetic)
- A new feature cannot otherwise be implemented cleanly
- Decomposition is explicitly requested in a design document or RFC
Validation Commands
Run from repo root unless debugging inside dart_cli/:
yarn lint:dart
yarn test:dart
yarn coverage:dart
When website/ changes, also run:
yarn docs:build
Helpful direct Dart fallback inside dart_cli/:
fvm dart format -l 120 --set-exit-if-changed bin lib test
fvm dart analyze --fatal-infos
fvm dart test
Documentation Sync
website/ is the source of truth for public docs.
If command contract, auth model, support matrix, output artifacts, or user-visible behavior changes, update:
website/docs/**(EN)website/i18n/pt-BR/docusaurus-plugin-content-docs/current/**(PT-BR)README.mddart_cli/README.mdwhen development or runtime behavior changes
Rules:
- keep EN and PT-BR aligned for public docs changes
README.mdanddart_cli/README.mdoutsidewebsite/should stay short and point back to the docs site- run
yarn docs:buildbefore merging website changes
Short Links to Deeper Docs
- commit conventions:
docs/engineering/commit-conventions.md - PR review handling:
docs/engineering/pr-review-playbook.md - PR template:
docs/engineering/pr-template.md - website and i18n conventions:
docs/engineering/website-conventions.md - CI and release details:
website/docs/project/ci-and-release.md - macOS release and signing notes:
docs/engineering/release-macos-notes.md