Skip to content

[#541] fix-config-dir-collision#549

Open
nrslib wants to merge 3 commits intomainfrom
takt/541/fix-config-dir-collision
Open

[#541] fix-config-dir-collision#549
nrslib wants to merge 3 commits intomainfrom
takt/541/fix-config-dir-collision

Conversation

@nrslib
Copy link
Copy Markdown
Owner

@nrslib nrslib commented Mar 26, 2026

Summary

背景

cd ~ && takt のように HOME 直下で起動したとき、初回セットアップ後に ~/.takt/config.yaml を global config として作成した直後、それを project config としても読んで strict validation に失敗するケースがある。

典型的には次のようなエラーになる。

[ERROR] Configuration error: invalid (root) in /Users/<user>/.takt/config.yaml: Unrecognized key: "language"

原因

現状の設定パス解決では、

  • global config: ~/.takt/config.yaml
  • project config: <cwd>/.takt/config.yaml

となっている。

このため cwd === ~ のとき、global config dir と project config dir がどちらも ~/.takt を指し、同じ config.yaml を両用途で扱ってしまう。

その結果、global-only key を含む global config を project config schema が弾いて失敗する。

仕様提案

project config dirglobal config dir が同一になる場合は、project config を無効化する。

具体的には:

  • getProjectConfigDir(cwd) === getGlobalConfigDir() の場合
    • project config の初期化をしない
    • project config の読み込みをしない
    • ~/.takt/config.yaml は global config としてのみ扱う

この方針にしたい理由

  • HOME を特別扱いするのではなく、原因そのものである「パス衝突」を防げる
  • 将来、同種の衝突条件が別経路で発生しても同じガードで吸収できる
  • 既存の project config 仕様への影響が最小

期待挙動

  • cd ~ && takt でも初回セットアップが正常終了する
  • ~/.takt/config.yaml は global config としてのみ扱われる
  • global/project config dir が衝突する場合、project-local .takt 設定は無効化される

再現手順

cd ~
rm -rf ~/.takt
takt

言語とプロバイダーを選択したあと、global config 作成直後に project config validation へ入らず、そのまま続行できること。

Execution Report

Piece takt-default completed successfully.

Closes #541

@nrslib
Copy link
Copy Markdown
Owner Author

nrslib commented Apr 16, 2026

/resolve

@github-actions
Copy link
Copy Markdown
Contributor

🚀 cc-resolve started: View logs

- Resolves all merge conflicts across 6 source files
- Deletes legacy files removed by origin/main (pieceResolver.ts,
  projectConfigFile.ts, pieceLoader.test.ts, project-config-collision-pieceResolver.test.ts)
- Removes deprecated piece-terminology exports (getGlobalPiecesDir,
  getBuiltinPiecesDir) to satisfy terminology guard
- Adds isProjectConfigEnabled guard to loadProjectConfig so collision
  skips the project config file while still applying env overrides
- Restores collision guard in agentLoader.validatePersonaPromptPath
  using literal path check (without symlink resolution) for project config dir
- Adds collision guard to workflowPackageScope.buildCandidateDirsWithPackage
- Updates collision test to import buildCandidateDirsWithPackage from
  workflowPackageScope.js (not resource-resolver.js per API boundary contract)
  and renames pieceDir to workflowDir to fix terminology violations

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

✅ cc-resolve completed. View logs

@nrslib nrslib marked this pull request as ready for review April 26, 2026 05:07
@nrslib
Copy link
Copy Markdown
Owner Author

nrslib commented May 1, 2026

方針は妥当だと思いますが、このままだと project/global .takt 衝突時の扱いが一部だけ残っています。merge 前に追加修正した方がよさそうです。

特に以下が気になります。

  • workflowLookupDirectories.ts: 衝突時でも getProjectWorkflowsDir(cwd) が project lookup dir として入ります。cd ~ 相当では ~/.takt/workflows は global workflow として扱うべきなので、isProjectConfigEnabled(projectCwd) === false のときは project workflow dir を探索対象から外した方がよいです。
  • workflowTrustSource.ts: source === project または isPathWithin(getProjectWorkflowsDir(projectCwd), filePath) により、global workflow が isProjectWorkflowRoot: true になり得ます。これだと privileged system step / runtime.prepare の trust boundary が緩む可能性があります。衝突時は project workflow 判定を無効化し、global workflow 判定を優先するのが安全そうです。
  • workflowPersonaPathPolicy.ts: agentLoader 側はガードされていますが、workflow YAML の persona path 検証では .takt/personas, .takt/agents, .takt/facets/personas がまだ project allowlist に入ります。ここも getProjectConfigDirIfEnabled() で揃える必要があります。

追加テストとしては、以下があると安心です。

  • 衝突時に getNamedWorkflowLookupDirs() / getWorkflowDirs() が project workflow dir を含まない
  • 衝突時に ~/.takt/workflows/foo.yamlsource: user, isProjectWorkflowRoot: false になる
  • 衝突時に workflow persona path policy が project .takt/facets/personas 経路を許可しない

config 本体を読まない・保存しないという中心方針は良いので、workflow/facet/persona の project 扱いも同じ guard に寄せれば筋が通ると思います。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Global config dir と project config dir が衝突する場合は project config を無効化する

1 participant