feat(settings): unify workflow settings behind one resolver + migrate config-root legacy - #3893
feat(settings): unify workflow settings behind one resolver + migrate config-root legacy#3893snowykr wants to merge 7 commits into
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ce6611c3c8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
… move fallback Addresses upstream PR Yeachan-Heo#3893 review P2 (chatgpt-codex-connector): 1. The generated config.schema.json allowed any JSON number for gjc.ultragoal.nudgeBudget, while the runtime enforces a non-negative integer; an editor validating against the published schema accepted -1 or 1.5, which the runtime then rejects. The schema generator now emits type: integer, minimum: 0 for the key (same pattern as sdk.promptDeadlineMs) and the artifact is regenerated. 2. #moveLegacySourceNoReplace's fallback for filesystems without hard links used a raw POSIX rename after an lstat check; a destination created in the race could be overwritten (settings.json.bak or marker quarantine). The fallback is now a COPYFILE_EXCL copy, which fails with EEXIST and can never replace an existing destination. Lore-id: settings-unify-20260805 Tested: 292 focused tests 0 fail; check:schemas clean (regenerated); check:types clean; biome clean
3c292ec to
522ab32
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 522ab32fb5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
522ab32 to
352f3ab
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 352f3abc4e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
352f3ab to
2e9d49e
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2e9d49ee7a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
44a4bca to
2f16ff6
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2f16ff6d9c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
0a055fd to
d0a62bd
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d0a62bd0d6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
d0a62bd to
17b1565
Compare
|
@codex review |
17b1565 to
0b2cdfb
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0b2cdfb4e9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
0b2cdfb to
19fa5f8
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 19fa5f8600
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
19fa5f8 to
1408842
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 14088421bb
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
f589c3a to
8e79772
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8e79772c9b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
99999c2 to
a641218
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a641218126
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
a641218 to
d530a6d
Compare
11c528f to
708ea14
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 11c528f5f2
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 708ea14c9a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
708ea14 to
338a786
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 338a7866f0
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
15ac207 to
7f3be62
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7f3be62a50
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9070431356
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 966230084d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 435defcc00
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f61a58a5d2
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 016691bb0c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: aae955b3f8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 84d3e91102
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
Author hold recorded from snowy_kr in #playground-ko.
— |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 65d2934c79
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 19b6ec56e7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 30e8952646
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f50c6d672c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| await Bun.write(tempPath, serialized); | ||
| await fs.promises.rename(tempPath, markerPath); |
There was a problem hiding this comment.
Durably sync the migration marker before publication
If the machine loses power after this rename, neither the temporary marker nor its parent directory has been synced, even though the target config write uses both barriers. The target patch and .bak can therefore survive while the marker disappears; the next load sees source plus backup without a valid marker and deliberately refuses recovery, so the copied agent value can permanently shadow later legacy-source edits. Sync the marker file before renaming and sync the parent directory afterward.
Useful? React with 👍 / 👎.
The config-root workflow-settings migration must read the target config.yml, decide absent-only patches, apply them, and finalize a marker/source transition inside one critical section. withAtomicYamlConfigTransaction re-exposes the existing per-file queue + cross-process lock so a caller can inspect root/current and applyPatches without re-acquiring the lock; parse failures surface before the callback so no migration action can run against a malformed target. Lore-id: settings-unify-20260805 Constraint: preserve validateRoot/onRestored CAS-restore semantics for existing callers Tested: atomic-yaml-patch suite (12 pass incl. root/current exposure, parse-before-callback, scalar-root no-write)
The ultragoal nudge budget is a workflow setting read by the runtime but was missing from SETTINGS_SCHEMA, so gjc config set rejected it as an unknown path and the generated config.schema.json did not document it. Registered with the existing default (10) and integer >= 0 validation, schema regenerated. Lore-id: settings-unify-20260805 Tested: check:schemas clean; generated config.schema.json contains ultragoal.nudgeBudget default 10
Introduce workflow-settings.ts as the single source of precedence for the four workflow setting surfaces (project config.yml > project settings.json > agent config.yml > legacy config-root settings.json > default). No workflow runtime hand-rolls file discovery, YAML/JSON parsing, or key extraction anymore; the resolver exposes typed diagnostics, an explicit invalid policy (continue by default, throw for ralplan), flat/nested extraction (flat wins), and canonical realpath sources using the exported standardizeMacOSPath precedent. Lore-id: settings-unify-20260805 Constraint: pure module - no Settings/discovery imports, no module-scope path hoisting Tested: workflow-settings suite (11 pass) + atomic-yaml suite (12 pass); package + utils check:types clean
…g.yml One-time migration of the orphan config-root settings.json workflow keys into the default global agent config.yml, hardened by codex review: malformed config.yml never aborts settings load (pre-transaction short-circuit + resilience catch); only valid target values block the patch; invalid flat keys are removed verbatim (removeTopLevelKeys, non-restorable receipt); legacy values are validated before migrating; invalid strict ralplan values keep the source active so gjc ralplan still fails loudly; flat keys are honored only in legacy JSON; future-schema config.yml targets are skipped; quoted numeric values are coerced like the Settings schema; the no-clobber move fallback uses COPYFILE_EXCL. Lore-id: settings-unify-20260805 Constraint: custom/temporary agentDir (SDK loadForScope, tests) must never consume the global source Constraint: future-schema config.yml stays read-only across all Settings paths Tested: 291 focused tests 0 fail; check:types clean; biome clean
ralplan, ultragoal, and deep-interview no longer hand-roll settings.json reads. All five workflow keys resolve through workflow-settings.ts with the fixed five-layer precedence; project configuration now beats user configuration (deep-interview's former user-YAML-first inversion is corrected), and ralplan is strict for all three keys (malformed/invalid explicit sources exit 2; the former silent maxIterations fallback is removed, user-confirmed option B). ultragoal/deep-interview stay tolerant (invalid optional files continue). Lore-id: settings-unify-20260805 Constraint: keep resolve* signatures, JSON source fields, and ralplan exit-2 error contract (malformed JSON/YAML reasons stable) Tested: 188 focused tests (ralplan 110, deep-interview 25, ultragoal-nudge 17, config-root 3, resolver 11, migration 10, atomic-yaml 12) + settings-manager/state-runtime/ultragoal-runtime 258 pass; check:types clean
All three workflow SKILL files now describe the identical precedence (project .gjc/config.yml > project .gjc/settings.json > user agentDir/config.yml > legacy config-root settings.json > default), flat/nested key shapes (flat wins), project-beats-user, canonical source, and the one-time paired root migration. ralplan states the strict exit-2 contract including the removed maxIterations silent fallback; ultragoal/deep-interview state the tolerant continue-to-default behavior. Stale deep-interview user-YAML-first and ralplan project-only paragraphs removed. Lore-id: settings-unify-20260805 Tested: default-gjc-definitions (28 pass), check-visible-definitions OK, verify-g002-gates pass, verify-gjc-skill-docs --fail 0 drift, rebrand-inventory --strict clean
User-facing changes per CONTRIBUTING.md: five-layer settings precedence, nudgeBudget schema registration, config-root one-time migration, strict ralplan exit-2, and nested-only config.yml key form. Lore-id: settings-unify-20260805
|
Closing during the emergency maintenance freeze. This PR is not in the retained critical or maintainer-owned set. Do not open a replacement PR unless a maintainer explicitly directs it. — |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e16bfa408e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| ## [Unreleased] | ||
|
|
||
| ## [0.12.15] - 2026-08-06 | ||
| ### Added |
There was a problem hiding this comment.
Restore the released changelog boundaries
Adding this section removes the existing 0.12.15, 0.12.14, and 0.12.13 headings, so all previously released 0.12.13 entries are now incorrectly presented as Unreleased and the release history is corrupted. Keep the new entries under Unreleased while restoring every released version heading exactly where it was.
AGENTS.md reference: AGENTS.md:L178-L178
Useful? React with 👍 / 👎.
| // Only clear patches when a backup verifies they are still the | ||
| // migration write; without one the target values may be newer | ||
| // overrides and must be preserved. | ||
| if (marker?.status === "pending" && backupExists) { |
There was a problem hiding this comment.
Expose malformed roots during no-backup recovery
When a fresh migration crashes after applying its target patch but before creating .bak, and the legacy source is then replaced by null, a scalar, or an array, backupExists is false, so this branch preserves the stale marker-owned target and returns. Direct strict ralplan resolution cannot verify stale ownership without the backup, accepts the higher-precedence valid agent value, and never reaches the malformed legacy source to exit 2; handle this pending/no-backup state as fail-closed rather than leaving the stale patch effective.
Useful? React with 👍 / 👎.
What
Unify the three workflow runtimes' (ralplan / ultragoal / deep-interview) settings reads behind one shared resolver with a fixed five-layer precedence, and migrate the orphan legacy config-root
settings.jsoninto the modernconfig.ymlexactly once.src/gjc-runtime/workflow-settings.ts— one resolver, five layers: project.gjc/config.yml→ project.gjc/settings.json→ user<agentDir>/config.yml(trustedGJC_CODING_AGENT_DIR/GJC_CONFIG_DIR+ XDG) → legacy<configRoot>/settings.json→ built-in default.config.ymluses the nested schema form (flat dotted keys honored only in legacysettings.json), so every effective override stays manageable viaSettings/gjc config. Canonical realpathsource, typed diagnostics, explicit invalid policy (continue by default, throw for ralplan).src/config/atomic-yaml-patch.ts—withAtomicYamlConfigTransaction(under-lock transaction seam withremoveTopLevelKeysfor dotted top-level keys).src/config/settings.ts— one-time config-root migration into the default global agentconfig.yml(absent-only, durable pending/complete marker, no-clobber.bak, crash-recovery state machine, strengthened default-global pairing gate; invalid strict ralplan legacy values keep the source active; future-schema targets never touched).src/config/settings-schema.ts— registergjc.ultragoal.nudgeBudget(default 10, integer ≥ 0);schemas/config.schema.jsonregenerated.maxIterationsfallback removed — user-confirmed); ultragoal/deep-interview tolerant; deep-interview's inverted precedence corrected to project-beats-user.Why
The workflow runtimes hand-rolled
settings.json-only reads and never consulted the modernconfig.yml, sogjc config set gjc.ralplan.maxIterations 7(config.yml) was silently ignored by ralplan. The legacy config-root~/.gjc/settings.jsonwas an orphan path no migration covered, thegjc.ultragoal.nudgeBudgetkey was missing from the public schema, and deep-interview read user YAML before project JSON (inverted precedence). This PR makes the settings surface single-source: whatgjc configwrites is what the runtimes read, with one documented precedence.Testing
check:types,generate-schemas/check:schemasclean; biome clean on the change set.check-visible-definitionsOK,verify-g002-gatespass,verify-gjc-skill-docs --fail0 drift,rebrand-inventory --strictclean,default-gjc-definitions28 pass.gjc ralplan --writewith project.gjc/config.ymlmaxIterations: 2): 3rd revision opener exits 3 withPLANNING-STUCK,max_iterations: 2,max_iterations_source: <project>/.gjc/config.yml— config.yml honored end-to-end.bun checkis run by CI on this head (not completed locally — 15-min timeout); the TS/schema/gate subset passed locally.GJC verdict
devbun checkpasses (full run in CI on this head; focused TS/schema/gate subset passed locally)