Compare commits
3
Commits
bce20d9e4d
...
323f4caa50
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
323f4caa50 | ||
|
|
7defe46de2 | ||
|
|
6b1e3937d7 |
No files matched your search
@@ -38,7 +38,7 @@
|
||||
| 设计有限请求生命周期 | Renderer Workspace JSON 调用 / shared Works token refresh | Main deadline → Electron transport → safe-read-only Node fallback → Host API timeout envelope | 包括取凭据、请求头和响应 body 的完整生命周期最多 30 秒;超时 abort transport 并稳定返回 `504 DESIGN_WORKSPACE_REQUEST_TIMEOUT`;透明 fallback 只允许 `GET`/`HEAD`/`OPTIONS`,mutation 不隐式重放 |
|
||||
| Design Asset binding | 当前 Workspace 已完成图片 / 本地上传 | canonical Asset → typed `asset_binding` input → Current Specification revision | 图片/视频用途由 Specification medium 和 binding role 决定;只提交真实 Workspace Asset identity,不使用本地路径或自然语言占位 |
|
||||
| Design reference alias editing | Active plan 的 final Prompt 与 binding-only reference row | `@图片N` token/add/replace/remove → typed field/collection operations → Current Specification revision | Prompt 决定图片如何参与生成;row 只管理稳定 reference/Asset identity。未绑定 alias 定点要求上传并阻止 Quote;删除时原子移除 binding 并重排后续 alias,既有 alias 不重复插入 |
|
||||
| Design Quote and confirmation | 当前 exact Specification revision | `design.quote.request` → immutable public Quote projection → `design.generation.confirm` with Quote ID | Renderer 只展示 output summary、warnings、expiry、Token Points;Provider Prompt/model/route/storage/internal billing 不下发或编辑 |
|
||||
| Design Quote and confirmation | 当前 exact Specification revision,或同一 accepted chat Run 中服务端识别出的显式完成意图 | `design.quote.request` → immutable public Quote projection → `design.generation.confirm` with Quote ID | 服务端可在同一 chat operation 下先发送 committed chat Direction projection,再发送 offered Quote projection;Store 依次收敛两者,Renderer 不发第二个 mutation。Renderer 只展示 output summary、warnings、expiry、Token Points;Provider Prompt/model/route/storage/internal billing 不下发或编辑,且只有用户显式确认 Quote ID 才授权创建 Task |
|
||||
| Design Task and Asset sync | Direction event stream / Workspace resource events / explicit refresh | Renderer Task/Asset projections | Task/Asset events独立于 Living Form;transport order 和 progress 不改写 Specification,也不授权新生成操作 |
|
||||
| 设计项目删除 | Canvas 侧栏精确项目名确认 | Renderer → Main Host API → Works Square Workspace DELETE | 删除成功后清理当前 Workspace/Direction/resources 并选择最近更新的剩余项目;结算与软删除语义由服务端负责 |
|
||||
| 历史 Prompt Museum URL | `/image-prompts/*` | App replace-redirect → `/image-canvas` | 当前 Canvas 无“获取灵感”入口,App 不挂载或 lazy-load Museum 页面;保留的 Main API/auth/media 与 shared DTO 是 dormant 兼容/安全基础设施 |
|
||||
|
||||
@@ -4,6 +4,17 @@ This file is the integrated default-branch snapshot. Feature tasks record progre
|
||||
|
||||
## Integrated Through
|
||||
|
||||
- AI Design chat-to-Quote client regression source commit
|
||||
`6b1e3937d709b74d407379c210a4bf09e8f4b158` from task
|
||||
`20260907-design-chat-generation-handoff-client-7d3a9c41` is integrated as merge
|
||||
`7defe46de2d4c693a620ca0be10201a18ccd910e` by task
|
||||
`20260908-integrate-design-chat-generation-client-7d3a9c42`. The existing Store
|
||||
contract now has regression coverage for one accepted chat operation receiving its
|
||||
committed chat Direction projection immediately followed by the offered immutable
|
||||
Quote projection. The optimistic user message and activity settle once, while the
|
||||
Quote remains visible without a second Renderer mutation. No client product code,
|
||||
DTO, route, automatic confirmation, Task authorization, package, or deployment
|
||||
changed; generation still begins only after explicit Quote-ID confirmation.
|
||||
- Native text context-menu source frontier
|
||||
`6fbb9c077ecda23e2ee6472631fe374527c49cb7` from task
|
||||
`20260907-input-context-menu-a7c31e` is fast-forwarded onto local `main` by
|
||||
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
# Task: Integrate Design chat generation handoff client
|
||||
|
||||
## Identity
|
||||
|
||||
- Task ID: 20260908-integrate-design-chat-generation-client-7d3a9c42
|
||||
- Mode: Integration
|
||||
- Branch: codex/20260908-integrate-design-chat-generation-client-7d3a9c42-integrate-design-chat-generation-client
|
||||
- Worktree: D:\Datas\OthersProjects\.codex-worktrees\makelore\20260908-integrate-design-chat-generation-client-7d3a9c42
|
||||
- Base commit: bce20d9e4dad99565714bd2c0ca1ef4806426f57
|
||||
- Owner: codex-root
|
||||
- Status: Ready for Integration
|
||||
|
||||
## Scope
|
||||
|
||||
- Integrate exact source commit `6b1e3937d709b74d407379c210a4bf09e8f4b158`
|
||||
from task `20260907-design-chat-generation-handoff-client-7d3a9c41` onto exact local
|
||||
`main` base `bce20d9e4dad99565714bd2c0ca1ef4806426f57`.
|
||||
- Preserve the existing client behavior for two consecutive canonical Direction
|
||||
projections under one accepted chat operation and land the source regression without
|
||||
introducing a second Renderer mutation or phrase recognizer.
|
||||
- Reconcile the accepted implementation fact into canonical current state/data flow,
|
||||
verify the integration tree, and advance local `main` while preserving the three
|
||||
unrelated untracked root task records.
|
||||
|
||||
## Intent And Constraints
|
||||
|
||||
- Electron Main remains the only network authority; generation intent and Quote
|
||||
creation remain server-owned.
|
||||
- One accepted chat Run may settle its optimistic Turn and then expose an immutable
|
||||
Quote under the same client operation identity. The Store must converge both events
|
||||
without duplicating the chat or sending another mutation.
|
||||
- Quote display is not generation authorization. Only explicit Quote-ID confirmation
|
||||
may create a Task or reserve Token Points.
|
||||
- Do not modify, stage, delete, move, stash, reset, or clean the root worktree's
|
||||
untracked `package-122`, `package-123`, or `client-hang-diagnosis` task records.
|
||||
- Source task records remain immutable on their source branches. The integration line
|
||||
owns only this task record and canonical reconciliation.
|
||||
|
||||
## Project Context Loaded
|
||||
|
||||
- Task context: integration task
|
||||
`20260908-integrate-design-chat-generation-client-7d3a9c42` owns the isolated
|
||||
worktree and the sole client Integration lock at base
|
||||
`bce20d9e4dad99565714bd2c0ca1ef4806426f57`.
|
||||
- Read: agent-entry and Planning Gate docs, memory index, project positioning/current
|
||||
state, decision index/system overview, module/data-flow maps, business rules/success
|
||||
criteria, evidence/reflection/commitment/stale indexes, ADR-007, the source task
|
||||
record, and recent activity/repeated-turn peer task records.
|
||||
- Project goal and current focus: a youth-friendly Canvas whose conversation is the
|
||||
primary input while the Current Specification, immutable Quote, confirmed Task, and
|
||||
Assets remain server-authoritative; optimistic chat and operation-scoped activity/
|
||||
assistant projections are already integrated.
|
||||
- Active constraints and decisions: stable operation identity, Main-owned transport,
|
||||
one provisional message per operation, canonical Direction convergence, immutable
|
||||
Quote display, and explicit Quote-ID confirmation.
|
||||
- Evidence, reflections, or commitments: production showed a completed chat Run with
|
||||
no Quote/Task; paired deployed-client confirmation and paid generation remain a
|
||||
separate smoke. The integration workflow must not copy source task records into the
|
||||
final canonical tree.
|
||||
- Likely modules: `tests/unit/image-workspace-store.test.ts`, canonical
|
||||
`current-state.md`, and `data-flow.md`; no client product module changes are expected.
|
||||
- Other active local tasks: the activity task is an integrated predecessor; the
|
||||
repeated-turn task explicitly made no product change; package tasks are isolated and
|
||||
do not overlap this source. No current peer owns this integration slice.
|
||||
- Unknowns, stale docs, or conflicts: template placeholders in project positioning are
|
||||
longstanding canonical debt, not authority for this change. No semantic conflict was
|
||||
found; production deployment remains outside this integration.
|
||||
- Gate result: Passed.
|
||||
|
||||
## Outcome
|
||||
|
||||
- Merged exact source commit `6b1e3937d709b74d407379c210a4bf09e8f4b158`
|
||||
without conflict as two-parent integration merge
|
||||
`7defe46de2d4c693a620ca0be10201a18ccd910e`.
|
||||
- Retained the existing product implementation and added its focused regression:
|
||||
one accepted chat operation may settle the optimistic Turn and then apply a second
|
||||
canonical Direction projection containing the offered immutable Quote. The Store
|
||||
preserves that Quote without issuing another Renderer mutation.
|
||||
- No client product code, shared DTO, route, phrase parser, automatic confirmation,
|
||||
Task authorization, package, deployment, or publication behavior changed.
|
||||
- Promoted the accepted fact into canonical `current-state.md` and `data-flow.md`.
|
||||
Removed only the merged copy of the source task record from the integration tree;
|
||||
the source branch/commit retains its complete immutable record.
|
||||
|
||||
## Verification
|
||||
|
||||
- Source task reported the focused Store suite (`33 passed`), ESLint, TypeScript, and
|
||||
diff checks passing.
|
||||
- On integration merge `7defe46de2d4c693a620ca0be10201a18ccd910e` plus canonical
|
||||
reconciliation:
|
||||
`pnpm exec vitest run tests/unit/image-workspace-store.test.ts --maxWorkers=1`
|
||||
-> `33 passed`.
|
||||
- `pnpm exec eslint tests/unit/image-workspace-store.test.ts` -> passed.
|
||||
- `pnpm run typecheck` -> passed.
|
||||
- Paired Works Square integration verification is recorded in task
|
||||
`20260908-integrate-design-chat-generation-8f4c2a71`.
|
||||
|
||||
## Follow-ups
|
||||
|
||||
- Deploy only with the matching server integration, then run the explicit
|
||||
Quote/confirmation/single-Task smoke recorded by the server task.
|
||||
|
||||
## Promotion Candidates
|
||||
|
||||
- Promoted: canonical client state/data flow now record consecutive committed-chat and
|
||||
offered-Quote Direction projections under one accepted operation, without a second
|
||||
Renderer command or implicit generation authorization.
|
||||
@@ -14,6 +14,7 @@ import { useImageWorkspaceStore } from '@/stores/image-workspace';
|
||||
import {
|
||||
designBootstrapFixture,
|
||||
designFormFixture,
|
||||
designQuoteFixture,
|
||||
designSummaryFixture,
|
||||
designWorkspaceFixture,
|
||||
} from '../fixtures/design-workspace-v2';
|
||||
@@ -688,6 +689,135 @@ describe('V2 Living Form store', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('keeps the Quote created immediately after a committed generation chat', async () => {
|
||||
const source = await loadedStore();
|
||||
const message = '开始生成';
|
||||
const quoteForm = designFormFixture({
|
||||
directionRevision: 6,
|
||||
rawTurnSequence: 2,
|
||||
workspaceViewRevision: 8,
|
||||
activeQuotes: [designQuoteFixture()],
|
||||
});
|
||||
const canonical = designWorkspaceFixture({
|
||||
form: quoteForm,
|
||||
turns: [
|
||||
...designWorkspaceFixture().turns,
|
||||
{
|
||||
turnId: 'turn-2',
|
||||
rawTurnSequence: 2,
|
||||
userMessage: message,
|
||||
assistantMessage: '我先检查制作方案。准备好后需要你确认一次,确认后才会开始生成。',
|
||||
},
|
||||
],
|
||||
});
|
||||
fetchProjectMock.mockResolvedValue(canonical);
|
||||
useImageWorkspaceStore.setState({
|
||||
chatDraft: message,
|
||||
pendingOperations: {
|
||||
'operation-1': {
|
||||
id: 'operation-1',
|
||||
label: '发送创作想法',
|
||||
command: {
|
||||
kind: 'apply_input',
|
||||
workspaceId: 'workspace-1',
|
||||
sessionId: 'session-1',
|
||||
expectedDirectionRevision: 4,
|
||||
clientOperationId: 'operation-1',
|
||||
input: { kind: 'chat', message },
|
||||
},
|
||||
status: 'submitting',
|
||||
error: null,
|
||||
clearDraftPaths: [],
|
||||
clearChatDraft: true,
|
||||
baseRawTurnSequence: 1,
|
||||
},
|
||||
},
|
||||
assistantActivities: {
|
||||
'operation-1': {
|
||||
workspaceId: 'workspace-1',
|
||||
directionId: 'direction-1',
|
||||
status: 'submitting',
|
||||
turnId: null,
|
||||
steps: [],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
source.emit('design.direction.updated', {
|
||||
id: 'session-1:19',
|
||||
type: 'design.direction.updated',
|
||||
clientOperationId: 'operation-1',
|
||||
replayed: false,
|
||||
operation: {
|
||||
operationKind: 'chat',
|
||||
interactionId: 'interaction-2',
|
||||
baseDirectionRevision: 4,
|
||||
newDirectionRevision: 5,
|
||||
rawTurnSequence: 2,
|
||||
specificationRevision: 3,
|
||||
specificationRevisionId: 'specification-revision-3',
|
||||
workspaceViewRevision: 7,
|
||||
specificationRevisionCreated: false,
|
||||
meaningChanged: false,
|
||||
changeSet: { interaction_id: 'interaction-2', changes: [] },
|
||||
turnId: 'turn-2',
|
||||
assistantMessage: '我先检查制作方案。准备好后需要你确认一次,确认后才会开始生成。',
|
||||
createdDecisionPromptIds: [],
|
||||
resolvedDecisionPromptId: null,
|
||||
supersededDecisionPromptIds: [],
|
||||
supersededQuoteCount: 0,
|
||||
quoteId: null,
|
||||
generationTaskId: null,
|
||||
},
|
||||
form: designFormFixture({
|
||||
directionRevision: 5,
|
||||
rawTurnSequence: 2,
|
||||
workspaceViewRevision: 7,
|
||||
}),
|
||||
});
|
||||
source.emit('design.direction.updated', {
|
||||
id: 'session-1:20',
|
||||
type: 'design.direction.updated',
|
||||
clientOperationId: 'operation-1',
|
||||
replayed: false,
|
||||
operation: {
|
||||
operationKind: 'quote_request',
|
||||
interactionId: 'interaction-quote-1',
|
||||
baseDirectionRevision: 5,
|
||||
newDirectionRevision: 6,
|
||||
rawTurnSequence: 2,
|
||||
specificationRevision: 3,
|
||||
specificationRevisionId: 'specification-revision-3',
|
||||
workspaceViewRevision: 8,
|
||||
specificationRevisionCreated: false,
|
||||
meaningChanged: false,
|
||||
changeSet: { interaction_id: 'interaction-quote-1', changes: [] },
|
||||
turnId: null,
|
||||
assistantMessage: null,
|
||||
createdDecisionPromptIds: [],
|
||||
resolvedDecisionPromptId: null,
|
||||
supersededDecisionPromptIds: [],
|
||||
supersededQuoteCount: 0,
|
||||
quoteId: 'quote-1',
|
||||
generationTaskId: null,
|
||||
},
|
||||
form: quoteForm,
|
||||
});
|
||||
|
||||
await vi.waitFor(() => {
|
||||
expect(useImageWorkspaceStore.getState()).toMatchObject({
|
||||
chatDraft: '',
|
||||
pendingOperations: {},
|
||||
workspace: { form: { directionRevision: 6 } },
|
||||
});
|
||||
});
|
||||
expect(useImageWorkspaceStore.getState().workspace?.form.activeQuotes)
|
||||
.toEqual([designQuoteFixture()]);
|
||||
expect(useImageWorkspaceStore.getState().assistantActivities).toMatchObject({
|
||||
'operation-1': { status: 'completed', turnId: 'turn-2' },
|
||||
});
|
||||
});
|
||||
|
||||
it('keeps the optimistic chat until a terminal success is visible in the canonical Workspace', async () => {
|
||||
const source = await loadedStore();
|
||||
const message = '画一只在月球踢球的熊猫';
|
||||
|
||||
Reference in new issue
Block a user