fix(pull): sync nothing in a project whose config cannot be read (#784) - #792
Conversation
|
|
Findings
Resolved
|
|
Findings
Resolved
Review was read-only; no PR code was executed. |
|
Findings
Resolved
Review was read-only; no PR code was executed. |
…cent#784) Detection skips a project config it cannot read and returns what loads next: a legacy .teamai/ behind a broken partition, which may name another team, or the user scope. pull() deployed and reported for that team, and the session-start hook did so on every session (reports-wt/ and learnings-wt/ appeared in the legacy .teamai/). pull() now listens for the unreadable config, syncs no scope, prints the problem with BROKEN_CONFIG_ADVICE and exits 1. A silent pull (the session-start hook, or a pre-dispatch hook running `teamai pull --silent`) records it in debug.log only. Agent-root seeding and the package hint refuse the same way, so a session start there does nothing. Hooks and usage already follow this rule since Tencent#748. The message trimming detectTeam used moves to config.ts as describeUnreadableConfig so both share it.
- The session-start handler returns when the dispatcher resolved no config for the hook's cwd, which is what an unreadable project config resolves to since Tencent#748. That one guard replaces the unreadable-config sinks added to seedProjectAgentRoot and the package-hint context, and follows the Tencent#769 contract that handlers read their scope from the dispatcher. The handler tests that exercise cwd routing now pass a resolved scope; a new one pins that nothing runs without one. - CHANGELOG and usage guide (en, zh-CN): a session start there runs no pull; only `teamai pull --silent` from a pre-dispatch hook writes the reason to debug.log. - skill-data troubleshooting: what `Nothing was synced` means, and that moving the config aside and re-running init needs the user's consent.
- The session-start pull is registered with `requiresConfig` instead of returning early inside the handler: the dispatcher drops it wherever no config resolves, which covers an unreadable project config (Tencent#748), and spawns no detached pass for it. Where no teamai config exists at all it did nothing on main either (no scope to pull, no project root to seed, no config for a package hint). The Tencent#748 registry test and the docs no longer list it as machine-level work. - `teamai pull --silent` exits 1 on the refusal too. Pre-dispatch hooks run it as `… 2>/dev/null || true` (`; exit 0` on Windows), so hosts still see success. - The dispatch-scope test asserts the pull is skipped and resets the pull mock it queues. - skill-serving design doc: `teamai pull` now reports an unreadable project config too. skill-data troubleshooting: `teamai doctor` can pass there.
…encent#784) A null config from the dispatcher means either "no teamai here" or "the project config cannot be read". Gating the session-start pull on `requiresConfig` stopped it in both; only the second must stop it. The handler now asks `findUnreadableProjectConfig` for the hook's cwd when no config resolved (a cwd that no longer exists holds none) and runs nothing when it reports a file. Everywhere else it runs as on main, so the docs list it as machine-level work again.
b119ec5 to
6836785
Compare
|
Findings
Resolved
Review was read-only; no PR code was executed. |
|
Findings
Resolved
Review was read-only; no PR code was executed. |
Fixes #784
Part of #752
Summary
describeUnreadableConfig(config.ts) builds the one-line detail +BROKEN_CONFIG_ADVICEfor bothpullanddetectTeam. Noteamai doctorpointer: doctor checks the config detection falls back to, not the broken one;skill-datatroubleshooting says so and asks for the user's consent before the config is moved aside. Docs: CHANGELOG, usage guide (en + zh-CN),docs/designs/skill-serving.md.pull --silentexits 1 on the refusal too. Hosts are not affected: pre-dispatch hooks run it asbash -lc "teamai pull --silent" 2>/dev/null || true(; exit 0in the Windows form), so Claude Code, Codex, CodeBuddy and OpenCode still see exit 0, andhook-dispatchnever reaches this path (the handler returns first).Evidence
Real CLI at
b119ec5vsorigin/main(57afe76); the code is unchanged in6836785. Workspace with a broken partitionconfig.yamland, behind it, either a legacy<ws>/.teamai/ofother-teamor only a user scope. Team repos are local bare remotes; the provider axis sets the team'sprovider:togit,github,gitlab.origin/mainb119ec5<ws>/.claude/.codex/.codebuddy/.opencodeseeded;other-team-skilldeployed (Claude, OpenCode);.teamai/gainsreports-wt/ learnings-wt/ state.json search-index.jsonuser-team-skilldeployedteamai pull, user scope / legacy behind —git,github,gitlab✖ Nothing was synced: …/config.yaml: Flow sequence … at line 2, column 1. Fix the file, or move it aside and run `teamai init` to write a new one.github/gitlabteamteamai pull --silent(pre-dispatch hook)debug.logpull(three providers)Tests (each red on
origin/main, green here):Test plan
Head
6836785:b119ec5rebased ontoorigin/main8cee7ab. Only CHANGELOG.md conflicted (kept main's entries plus #784's); every other line of the diff is identical to57afe76..b119ec5, so the real-CLI evidence above still holds.npm run buildnpx vitest run: 4635 passed, 1 skipped, 11 failed, all instats-scope.test.tsnpx tsc --noEmit: 4 errors, all insrc/stats.tsb119ec5:npm run test:e2e229 passed, 26 skipped; the real-CLI matrix aboveThe
stats.ts/stats-scope.test.tsfailures come frommainat 352cfc4 (#795) and appear there without this PR (main CI red on 352cfc4 and 8cee7ab, green on a84bf6f). This PR touches neither file; the fix is tracked separately.Merge Danger
Door: two-way
Blast Radius: narrow
Only projects whose config exists and cannot be read change: they now sync nothing where they used to sync the wrong team. Not changed, and outside #784:
main),teamai pull's pre-command migration keeps a legacy.teamai/while the partitionconfig.yamlcannot be read, sopullitself now reaches the legacy dir behind a broken partition; this PR's refusal is what stops it from syncing that team.readConfigFrom, shared since [bug] TeamAI hooks reach projects that never set it up: Stop nudge, and skill usage pushed to another team's stats #748 by hooks, usage anddetectTeam): a partition directory without search permission, or a danglingconfig.yamlsymlink, still reads as "no config". Changing it changes every caller.isUserTeamaiDir([bug] TeamAI hooks reach projects that never set it up: Stop nudge, and skill usage pushed to another team's stats #748) compares real paths withfs.realpathSync: withgit init ~and aHOMEspelled in a non-canonical case, the user config reads as a project config that is notscope: project. Same predicate every team hook already uses.push,contribute,doctor, …) still fall back past an unreadable one.