fix(chat): bind project ID through CLI chat + stage dispatch (issue #2)
Root cause: the 2026-09-28 controlled-projection hardening added the ErrUnboundControlledProject guard, and the server path got session project binding backfilled - but two paths missed: - CLI chat mode never called session.SetProjectID (only -project name) - coordinator handleAdvanceStage built StageRunRequest without ProjectID/UserID, so every stage-advance squad task was rejected Fixes: - handleChatMode gains projectID param (wired from -project-id flag); session binding follows the server convention - handleAdvanceStage passes parseDecimalID(UserCtx.Project/User.ID) - CLI chat tests get hermetic env (unreachable DB + ALLOW_IN_MEMORY) so local runs stop accidentally hitting the real dev DB on :5433 - stale test TestBindSessionProjectContext_KeepsExistingProjectID asserted the pre-fix 'switch does not propagate' bug; updated to assert switch propagation + bind no-overwrite Result: go test -short ./... = 75 packages, 0 failures (first time). Short tests promoted from report-only back into the required CI gate.
This commit is contained in:
@@ -291,6 +291,8 @@ func (e *CoordinatorEngine) handleAdvanceStage(ctx context.Context, cand *intent
|
||||
}
|
||||
|
||||
// 3. 调用底层 L3 调度器执行阶段跃迁
|
||||
// 回填数字项目/用户 ID:受控交付物任务按 ProjectID 入账(缺失会被
|
||||
// ErrUnboundControlledProject 拒绝);与 handleTask 派发口径一致。
|
||||
stageRes, err := e.tasks().ExecuteStage(ctx, stageflow.StageRunRequest{
|
||||
Stage: targetStage,
|
||||
ProjectName: userCtx.Project.Name,
|
||||
@@ -300,6 +302,8 @@ func (e *CoordinatorEngine) handleAdvanceStage(ctx context.Context, cand *intent
|
||||
TargetMarket: userCtx.Project.TargetMarket,
|
||||
Fields: userCtx.BlackboardFacts,
|
||||
WorkDir: userCtx.WorkDir,
|
||||
ProjectID: parseDecimalID(userCtx.Project.ID),
|
||||
UserID: parseDecimalID(userCtx.User.ID),
|
||||
})
|
||||
if err != nil {
|
||||
return &CoordinationResult{
|
||||
|
||||
@@ -18,14 +18,19 @@ func TestBindSessionProjectContext_FillsEmptyProjectID(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestBindSessionProjectContext_KeepsExistingProjectID(t *testing.T) {
|
||||
// 2026-09-28 回填会话项目绑定后,SetProjectID 会同步协调器上下文:
|
||||
// 切换项目必须传导(旧断言"保留 9"固化的是切换不生效的缺陷)。
|
||||
func TestBindSessionProjectContext_SwitchPropagates(t *testing.T) {
|
||||
sess := chat.NewSession("sess-keep", &coordinator.UserProjectContext{
|
||||
Project: coordinator.ProjectInfo{ID: "9", Name: "已绑定"},
|
||||
}, nil, nil)
|
||||
sess.SetProjectID(6024)
|
||||
if sess.UserCtx.Project.ID != "6024" {
|
||||
t.Fatalf("project switch must propagate, got %q", sess.UserCtx.Project.ID)
|
||||
}
|
||||
bindSessionProjectContext(sess)
|
||||
if sess.UserCtx.Project.ID != "9" {
|
||||
t.Fatalf("project id=%q", sess.UserCtx.Project.ID)
|
||||
if sess.UserCtx.Project.ID != "6024" {
|
||||
t.Fatalf("bind must not overwrite explicit binding, got %q", sess.UserCtx.Project.ID)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user