@ai-agent-forge/plugin-alignment 0.88.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -0
- package/agent-forge.json +19 -0
- package/dist/baseline.d.ts +12 -0
- package/dist/baseline.d.ts.map +1 -0
- package/dist/baseline.js +68 -0
- package/dist/baseline.js.map +1 -0
- package/dist/engine.d.ts +93 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +634 -0
- package/dist/engine.js.map +1 -0
- package/dist/entry.d.ts +14 -0
- package/dist/entry.d.ts.map +1 -0
- package/dist/entry.js +23 -0
- package/dist/entry.js.map +1 -0
- package/dist/export.d.ts +15 -0
- package/dist/export.d.ts.map +1 -0
- package/dist/export.js +120 -0
- package/dist/export.js.map +1 -0
- package/dist/http-server.d.ts +33 -0
- package/dist/http-server.d.ts.map +1 -0
- package/dist/http-server.js +119 -0
- package/dist/http-server.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +665 -0
- package/dist/index.js.map +1 -0
- package/dist/page.d.ts +15 -0
- package/dist/page.d.ts.map +1 -0
- package/dist/page.js +831 -0
- package/dist/page.js.map +1 -0
- package/dist/render.d.ts +42 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +158 -0
- package/dist/render.js.map +1 -0
- package/dist/types.d.ts +217 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +30 -0
- package/dist/types.js.map +1 -0
- package/package.json +53 -0
- package/plugin.json +12 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Alignment capability plugin (M1 of `docs/design/需求对齐插件设计.md`): a\n * three-step requirement-alignment funnel (objective → detail → design) with\n * block-level bidirectional feedback confirmed on a local HTML page.\n *\n * Persistence protocol, structurally identical to the goal/plan/todo/workflow\n * plugins: append-only `alignment.state` full snapshots (the single rebuild\n * source) plus one `alignment.transition` audit entry per conversion,\n * announced as `alignment.changed` (version 1, correlationId\n * \"alignment.state\", data = the complete AlignmentState snapshot).\n *\n * The round wait is non-blocking (设计 §5 总则 8): alignment_round returns the\n * page URL immediately; page feedback arrives as a `alignment.feedback`\n * custom message injected through SessionAPI.sendMessage (triggerTurn), and a\n * round only closes after the injection succeeded (`round.delivered`,\n * terminal audit D1).\n */\n\nimport type { CapabilityAPI, CapabilityCommandResult, DisposableRegistration } from \"@agent-forge/plugin-sdk\";\nimport { Type } from \"typebox\";\nimport {\n\ttype AdvanceInput,\n\ttype AlignmentSetInput,\n\tactiveStep,\n\tapplyAlignmentAdvance,\n\tapplyAlignmentSet,\n\tapplyRoundPost,\n\tapplyVersionRollback,\n\ttype EngineRun,\n\tfinalBaselineLines,\n\tgate,\n\tmarkDelivered,\n} from \"./engine.ts\";\nimport { exportTargetPath, writeAlignmentExport } from \"./export.ts\";\nimport { type AlignmentServer, startAlignmentServer } from \"./http-server.ts\";\nimport { alignmentToolResultRenderer } from \"./render.ts\";\nimport {\n\tAlignmentError,\n\ttype AlignmentRecord,\n\ttype AlignmentRoundPost,\n\ttype AlignmentRoundResult,\n\ttype AlignmentState,\n\ttype AlignmentTransitionEntry,\n\ttype PendingItem,\n} from \"./types.ts\";\n\nconst STATE_ENTRY = \"alignment.state\";\nconst TRANSITION_ENTRY = \"alignment.transition\";\nconst GOAL_STATE_ENTRY = \"goal.state\";\n/** Round post outcomes cached until delivered — the retry-injection window (终审 D1). */\ninterface CachedRound {\n\tpost: AlignmentRoundPost;\n\trecord: AlignmentRecord;\n\ttransitions: AlignmentTransitionEntry[];\n\tresult: AlignmentRoundResult;\n}\n\nexport interface AlignmentCapabilityOptions {\n\t/** Injection seam for deterministic tests; production binds an OS-assigned port. */\n\tserverPort?: number;\n}\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n\treturn value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\n/**\n * 双调用约定(走查 2026-10-04,goal 插件同款问题的严谨版):会话路径以\n * (toolCallId, params, signal, onUpdate) 调用插件工具——first 是调用 id 字符串;\n * runtime facade 以 (input, context?, signal?) 调用——first 是入参对象。\n * 按 first 的类型区分,两条路径(含 runtime 携带 context)都取到真实入参。\n */\nfunction toolInput(first: unknown, second?: unknown): Record<string, unknown> {\n\tif (typeof first === \"string\") {\n\t\tif (!isObject(second)) return {};\n\t\treturn second;\n\t}\n\tif (!isObject(first)) throw new Error(\"alignment tool input must be an object\");\n\treturn first;\n}\n\nfunction loadState(api: CapabilityAPI): AlignmentState {\n\tconst entries = api.session?.getBranchEntries() ?? [];\n\tconst entry = [...entries].reverse().find((item) => item.customType === STATE_ENTRY);\n\tif (!entry?.data || !isObject(entry.data)) return { alignments: [] };\n\tconst data = entry.data as { alignments?: unknown };\n\treturn { alignments: Array.isArray(data.alignments) ? [...(data.alignments as AlignmentRecord[])] : [] };\n}\n\nfunction loadTransitions(api: CapabilityAPI): AlignmentTransitionEntry[] {\n\tconst entries = api.session?.getBranchEntries() ?? [];\n\treturn entries\n\t\t.filter((item) => item.customType === TRANSITION_ENTRY)\n\t\t.map((item) => item.data as AlignmentTransitionEntry)\n\t\t.filter((item): item is AlignmentTransitionEntry => isObject(item));\n}\n\n/** Advisory goalId check (#10 soft-reference discipline, goal/plan precedent). */\nfunction goalKnownToSession(api: CapabilityAPI, goalId: string): boolean {\n\tconst entries = api.session?.getBranchEntries() ?? [];\n\tfor (let index = entries.length - 1; index >= 0; index -= 1) {\n\t\tconst entry = entries[index];\n\t\tif (entry.customType !== GOAL_STATE_ENTRY) continue;\n\t\tconst data = entry.data;\n\t\tif (!isObject(data)) return false;\n\t\tconst goals = data.goals;\n\t\tif (!Array.isArray(goals)) return false;\n\t\treturn goals.some((goal) => isObject(goal) && goal.id === goalId);\n\t}\n\treturn false;\n}\n\n/** Page projection (state.json): everything the fixed template renders. */\nfunction pageView(\n\trecord: AlignmentRecord,\n\tbaselineFile: string | undefined,\n\tawaitingRevision: boolean,\n): Record<string, unknown> {\n\tconst snapshot = gate(record);\n\t// gate already validated the active step exists (it throws otherwise).\n\tconst blocks = activeStep(record).blocks;\n\t// 终审/终态头部展示跨步总口径(走查 2026-10-03):completed 后仍按当前步\n\t// 计数会显示「已确认 0/1」这类误导数字。\n\tconst countedBlocks = record.status === \"aligning\" ? blocks : record.steps.flatMap((s) => s.blocks);\n\treturn {\n\t\talignmentId: record.id,\n\t\ttitle: record.title,\n\t\tgoalId: record.goalId,\n\t\tstatus: record.status,\n\t\trevision: record.revision,\n\t\tround: record.roundCount,\n\t\tactiveStep: record.activeStep,\n\t\tsteps: record.steps.map((step) => ({\n\t\t\tstep: step.step,\n\t\t\tstatus: step.status,\n\t\t\tblocks: step.blocks.map((block) => ({\n\t\t\t\tid: block.id,\n\t\t\t\tkind: block.kind,\n\t\t\t\tcontent: block.content,\n\t\t\t\trationale: block.rationale,\n\t\t\t\timpact: block.impact,\n\t\t\t\tstatus: block.status,\n\t\t\t\tmodifiedInRound: block.modifiedInRound,\n\t\t\t\tdraftAnswer: block.draftAnswer,\n\t\t\t\tcomments: block.comments,\n\t\t\t})),\n\t\t})),\n\t\tgate: {\n\t\t\t...snapshot,\n\t\t\tapprovedCount: countedBlocks.filter((block) => block.status === \"approved\").length,\n\t\t\tblockCount: countedBlocks.length,\n\t\t},\n\t\tpendingFeedback: record.pendingFeedback,\n\t\t// Version snapshots for the read-only history switcher (走查 2026-10-03).\n\t\tversions: record.versions ?? [],\n\t\tawaitingRevision,\n\t\tbaselineFile,\n\t};\n}\n\nfunction blockStateLine(block: AlignmentRecord[\"steps\"][number][\"blocks\"][number]): string {\n\tconst state = block.status === \"approved\" ? \"已确认\" : \"待确认\";\n\tconst first = block.content.split(\"\\n\")[0]?.slice(0, 80) ?? \"\";\n\tconst notes: string[] = [];\n\tfor (const comment of block.comments) {\n\t\tif (comment.status !== \"open\") continue;\n\t\tnotes.push(\n\t\t\tcomment.author === \"assistant\"\n\t\t\t\t? `AI疑问待回应:${comment.note.slice(0, 40)}`\n\t\t\t\t: `用户批注:${comment.note.slice(0, 40)}`,\n\t\t);\n\t}\n\treturn `- ${block.id}[${block.kind}|${state}] ${first}${notes.length ? `(${notes.join(\";\")})` : \"\"}`;\n}\n\nfunction historyLines(transitions: AlignmentTransitionEntry[]): string {\n\tif (transitions.length === 0) return \"(无)\";\n\treturn transitions\n\t\t.slice(-20)\n\t\t.map((entry) => {\n\t\t\tconst where = entry.step ? `${entry.step} ` : \"\";\n\t\t\treturn `rev${entry.revision} ${where}${entry.event}${entry.reason.detail ? `(${entry.reason.detail.slice(0, 60)})` : \"\"}`;\n\t\t})\n\t\t.join(\"\\n\");\n}\n\nfunction feedbackMessage(\n\trecord: AlignmentRecord,\n\tresult: AlignmentRoundResult,\n\ttransitions: AlignmentTransitionEntry[],\n): string {\n\tconst snapshot = gate(record);\n\tconst lines: string[] = [];\n\tlines.push(\n\t\t`[alignment.feedback] ${result.alignmentId} 第 ${result.round} 轮(${result.step} 步,revision ${result.revision},status ${record.status})`,\n\t);\n\tlines.push(\"== 本轮反馈 ==\");\n\tif (result.approvals.length > 0) lines.push(`确认块:${result.approvals.join(\", \")}`);\n\tfor (const comment of result.comments) {\n\t\tlines.push(\n\t\t\t`用户批注[${comment.blockId}]${comment.escalate ? \"(上游问题)\" : \"\"}:「${comment.quote}」→ ${comment.note}`,\n\t\t);\n\t}\n\tfor (const reply of result.commentReplies) {\n\t\tlines.push(\n\t\t\treply.dismiss\n\t\t\t\t? `AI 疑问 ${reply.commentId}:用户标记不重要`\n\t\t\t\t: `AI 疑问 ${reply.commentId} 的回答:${reply.answer}`,\n\t\t);\n\t}\n\tfor (const answer of result.answers) {\n\t\tlines.push(`补充答案[${answer.blockId}]:${answer.value}`);\n\t}\n\tfor (const addition of result.additions) {\n\t\tlines.push(`自由补充:${addition}`);\n\t}\n\tif (result.stepConfirmed) {\n\t\tif (record.status === \"completed\") {\n\t\t\tlines.push(\"用户已在终审总览确认基线——对齐完成。请输出最终基线总结(plan 输入)。\");\n\t\t\tif (result.finalBaseline) {\n\t\t\t\tlines.push(\"最终基线紧凑清单:\");\n\t\t\t\tfor (const line of result.finalBaseline) {\n\t\t\t\t\tlines.push(` [${line.kind}] ${line.id}: ${line.line}`);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tlines.push(\"用户已确认本步——基线锁定。请 alignment_set 出下一步块集并 alignment_round 刷新。\");\n\t\t}\n\t}\n\tlines.push(\"== 当前块集(全量状态)==\");\n\tif (record.status === \"finalizing\") {\n\t\tlines.push(\"三步基线已全部锁定,等待用户终审总览确认;此阶段无需你操作。\");\n\t} else {\n\t\tfor (const step of record.steps) {\n\t\t\tif (step.blocks.length === 0) continue;\n\t\t\tlines.push(`[${step.step}|${step.status}]`);\n\t\t\tfor (const block of step.blocks) lines.push(blockStateLine(block));\n\t\t}\n\t\tlines.push(\n\t\t\t`待办:${snapshot.unapproved} 块待确认、${snapshot.openComments} 批注未清、${snapshot.pendingAdditions} 补充未落账。`,\n\t\t);\n\t}\n\tlines.push(\"== 历史轮次(revision 锚点)==\");\n\tlines.push(historyLines(transitions));\n\treturn lines.join(\"\\n\");\n}\n\nconst PROMPT_GUIDELINES: readonly string[] = [\n\t\"进入分流(预检规则):用户显式要求对齐时直接进入;否则先做零成本预检——列出缺失信息、被迫假设、矛盾歧义。三项全空则一行结论直接出方案(跳过证据必须可见,禁止静默跳过);有任一项则列出要点并建议对齐,用户说直接做则跳过、但未决假设须在方案中显式标注。预检清单在对齐时直接作为第一轮块种子。\",\n\t\"三步铁律:objective 只谈方向与非目标(≤10 块);detail 只谈业务规则/公式/数据流/异常(禁止技术选型);design 谈技术方案且不得与已锁定基线矛盾,发现矛盾必须停下向用户提出。\",\n\t\"块纪律:假设单独成 assumption 块;缺信息产 missing 块而不是脑补;可自查的先取证落 fact;assistant 批注只用于真实不确定点(公式口径、二义表述、潜在矛盾、与基线冲突)。\",\n\t\"修订纪律:最小改动已确认的块(内容不变即继承确认);每次 alignment_set 之后必须跟 alignment_round 告知用户去看新版;用户批注的 quote 匹配失败时向用户说明而不是猜。\",\n\t\"填空落账:收到补充答案(补充答案[blockId])后,下一次 alignment_set 必须把答案重写进对应块内容并转为 fact/decision(missing 块不得带着未并入的答案被确认锁定);注入消息的「当前块集(全量状态)」是权威现状,以它为准做最小修订。\",\n\t\"终审阶段(status finalizing):三步基线已全部锁定,页面进入只读总览,唯一动作是用户最终确认——此阶段不要调用 alignment_set;收到终审确认消息(alignment completed)即视为开发授权:先输出一行极简基线摘要,然后直接按基线实现——用 plan/todo 把基线拆成可执行任务,实现并自测,完成后向用户报告结果与验收方式。不要停在基线总结等用户再次指令(dogfood 2026-10-04:等指令会打断对齐→开发衔接)。\",\n\t\"页面回退:用户可在页面上把任务回退到更早环节(step.retreated,后续环节作废重走)或把当前步回退到历史版本(version.rolled-back,当前未确认版本丢弃、批注保留)。收到这类消息后,以注入消息里的全量块集为准重新修订,不要复用回退前的块集。\",\n];\n\nconst setSchema = Type.Object({\n\tid: Type.String({ description: \"Stable alignment id; charset [A-Za-z0-9._-], no leading dot\" }),\n\ttitle: Type.Optional(Type.String({ description: \"Human-readable alignment title\" })),\n\tgoalId: Type.Optional(Type.String({ description: \"Soft goal reference; unknown ids only warn\" })),\n\trevision: Type.Optional(Type.Integer({ description: \"Monotonic revision; must exceed the stored one\", minimum: 0 })),\n\tblocks: Type.Array(\n\t\tType.Object({\n\t\t\tid: Type.String({ description: \"Stable block id within the step\" }),\n\t\t\tkind: Type.Union(\n\t\t\t\t[Type.Literal(\"fact\"), Type.Literal(\"assumption\"), Type.Literal(\"decision\"), Type.Literal(\"missing\")],\n\t\t\t\t{ description: \"fact=取证 assumption=假设 decision=决策 missing=待补充\" },\n\t\t\t),\n\t\t\tcontent: Type.String({ description: \"Block content (markdown text, ≤8192 chars)\" }),\n\t\t\trationale: Type.Optional(Type.String({ description: \"Why this decision/assumption (≤2048 chars)\" })),\n\t\t\timpact: Type.Optional(Type.Array(Type.String(), { description: \"Affected modules/files/interfaces\" })),\n\t\t\tcomments: Type.Optional(\n\t\t\t\tType.Array(\n\t\t\t\t\tType.Object({\n\t\t\t\t\t\tid: Type.String(),\n\t\t\t\t\t\tnote: Type.String({ description: \"Assistant question; only real uncertainty\" }),\n\t\t\t\t\t\tquote: Type.Optional(Type.String()),\n\t\t\t\t\t}),\n\t\t\t\t\t{ description: \"New assistant comments (AI 主动标注的不确定点)\" },\n\t\t\t\t),\n\t\t\t),\n\t\t\tcommentResolutions: Type.Optional(\n\t\t\t\tType.Array(\n\t\t\t\t\tType.Object({\n\t\t\t\t\t\tcommentId: Type.String(),\n\t\t\t\t\t\tkind: Type.Union([Type.Literal(\"answered\"), Type.Literal(\"dismissed\"), Type.Literal(\"incorporated\")]),\n\t\t\t\t\t\ttext: Type.Optional(Type.String()),\n\t\t\t\t\t}),\n\t\t\t\t\t{\n\t\t\t\t\t\tdescription:\n\t\t\t\t\t\t\t\"Resolutions for existing comments (user comments may only be resolved, never rewritten)\",\n\t\t\t\t\t},\n\t\t\t\t),\n\t\t\t),\n\t\t}),\n\t\t{ description: \"Full block set of the active step (全量提交;未变块按内容指纹继承确认)\" },\n\t),\n});\n\nconst roundSchema = Type.Object({\n\talignmentId: Type.String({ description: \"Alignment id to open the confirmation page for\" }),\n});\n\nconst advanceSchema = Type.Object({\n\talignmentId: Type.String(),\n\taction: Type.Union([Type.Literal(\"inspect\"), Type.Literal(\"retreat\"), Type.Literal(\"cancel\")]),\n\tstep: Type.Optional(\n\t\tType.Union([Type.Literal(\"objective\"), Type.Literal(\"detail\"), Type.Literal(\"design\")], {\n\t\t\tdescription: \"Retreat target; must be an earlier step\",\n\t\t}),\n\t),\n\tnote: Type.Optional(Type.String({ description: \"Retreat reason (required for retreat)\" })),\n});\n\nfunction pendingText(items: PendingItem[]): string {\n\tif (items.length === 0) return \"nothing pending\";\n\tconst reasons = items.map((item) => `${item.blockId}(${item.reason})`);\n\treturn reasons.join(\" \");\n}\n\nfunction listLines(state: AlignmentState): string {\n\tif (state.alignments.length === 0) return \"no alignments in this session; create one with alignment_set\";\n\tconst lines = [`alignments: ${state.alignments.length}`];\n\tfor (const record of state.alignments) {\n\t\tconst snapshot = gate(record);\n\t\tlines.push(\n\t\t\t`- ${record.id} [${record.status} → ${record.goalId ?? \"-\"}] ${record.title} · ${record.activeStep} r${record.roundCount} · ${snapshot.unapproved} pending / ${snapshot.openComments} open`,\n\t\t);\n\t}\n\treturn lines.join(\"\\n\");\n}\n\nfunction whyLines(record: AlignmentRecord): string {\n\tconst snapshot = gate(record);\n\tconst lines = [`${record.id} · ${record.activeStep} · round ${record.roundCount}`];\n\tif (record.status !== \"aligning\") {\n\t\tlines.push(`status ${record.status} — nothing to wait for`);\n\t\treturn lines.join(\"\\n\");\n\t}\n\tif (snapshot.allGreen) {\n\t\tlines.push(\"ALL GREEN — waiting for the user to click 确认完成 on the page\");\n\t\treturn lines.join(\"\\n\");\n\t}\n\tlines.push(`pending: ${pendingText(snapshot.pending)}`);\n\tif (snapshot.pendingAdditions > 0) {\n\t\tlines.push(`undelivered additions: ${record.pendingFeedback?.additions.join(\" | \")}`);\n\t}\n\treturn lines.join(\"\\n\");\n}\n\nfunction logLines(transitions: AlignmentTransitionEntry[], count: number): string {\n\tif (transitions.length === 0) return \"no alignment transitions recorded\";\n\tconst slice = transitions.slice(-count).reverse();\n\treturn slice\n\t\t.map((entry, index) => {\n\t\t\tconst where = entry.step ? `${entry.step} ` : \"\";\n\t\t\treturn `${slice.length - index}. [r${entry.round ?? \"-\"} rev${entry.revision}] ${where}${entry.event} ${entry.reason.code}${entry.reason.detail ? ` — ${entry.reason.detail}` : \"\"}`;\n\t\t})\n\t\t.join(\"\\n\");\n}\n\nexport function createCapability(\n\tapi: CapabilityAPI,\n\toptions: AlignmentCapabilityOptions = {},\n): readonly DisposableRegistration[] {\n\tlet state = loadState(api);\n\tlet server: AlignmentServer | undefined;\n\tlet cachedRound: CachedRound | undefined;\n\tconst deliveredRoundByAlignment = new Map<string, number>();\n\t/** Revision at last successful injection — awaitingRevision = delivered and not yet superseded by a set. */\n\tconst deliveredRevisionByAlignment = new Map<string, number>();\n\n\tconst persist = (next: AlignmentState, transitions: AlignmentTransitionEntry[]): AlignmentState => {\n\t\tstate = next;\n\t\tapi.session?.appendEntry(STATE_ENTRY, state);\n\t\tfor (const entry of transitions) api.session?.appendEntry(TRANSITION_ENTRY, entry);\n\t\tvoid api.publish({ type: \"alignment.changed\", version: 1, correlationId: STATE_ENTRY, data: state });\n\t\treturn state;\n\t};\n\n\tconst activeRecord = (): AlignmentRecord | undefined =>\n\t\tstate.alignments.find((record) => record.status === \"aligning\") ??\n\t\t[...state.alignments].reverse().find((record) => record.status !== \"aligning\");\n\n\tconst ensureServer = async (): Promise<AlignmentServer> => {\n\t\t// 页面生命周期(走查 2026-10-04 用户裁决):服务随第一个 alignment_round\n\t\t// 启动后常驻到插件 dispose(会话关闭);终态对齐的页面保持可查看,直到\n\t\t// 下一次对齐在同一 URL 上覆盖内容。不再做终态 idle 停服。\n\t\tif (server) return server;\n\t\tserver = await startAlignmentServer(\n\t\t\t{\n\t\t\t\tgetState: () => {\n\t\t\t\t\tconst record = activeRecord();\n\t\t\t\t\tif (!record) return undefined;\n\t\t\t\t\t// awaitingRevision: feedback was delivered and the model has not\n\t\t\t\t\t// bumped the revision yet — the page shows \"AI revising…\".\n\t\t\t\t\tconst awaiting =\n\t\t\t\t\t\trecord.status === \"aligning\" && deliveredRevisionByAlignment.get(record.id) === record.revision;\n\t\t\t\t\treturn pageView(record, undefined, awaiting);\n\t\t\t\t},\n\t\t\t\tonRoundPost: (post) => handleRoundPost(post),\n\t\t\t},\n\t\t\t{ port: options.serverPort },\n\t\t);\n\t\treturn server;\n\t};\n\n\tconst injectFeedback = async (cached: CachedRound): Promise<void> => {\n\t\tconst message = feedbackMessage(cached.record, cached.result, loadTransitions(api));\n\t\tconst send = api.session?.sendMessage;\n\t\tif (!send) {\n\t\t\tthrow new AlignmentError(\n\t\t\t\t\"invalid-input\",\n\t\t\t\t\"host session does not expose sendMessage; feedback cannot be injected\",\n\t\t\t);\n\t\t}\n\t\tawait send({ customType: \"alignment.feedback\", content: message, display: true }, { triggerTurn: true });\n\t};\n\n\tconst handleRoundPost = async (post: AlignmentRoundPost): Promise<{ status: number; body: unknown }> => {\n\t\tconst record = activeRecord();\n\t\tif (!record || (record.status !== \"aligning\" && record.status !== \"finalizing\")) {\n\t\t\treturn { status: 409, body: { error: \"no alignment in progress\" } };\n\t\t}\n\t\tconst samePost = (candidate: CachedRound): boolean =>\n\t\t\tcandidate.result.alignmentId === record.id && JSON.stringify(candidate.post) === JSON.stringify(post);\n\t\t// Delivered idempotency: an identical replay of an already-delivered\n\t\t// round returns the snapshot without re-injecting.\n\t\tconst pending = cachedRound;\n\t\tif (pending && samePost(pending) && deliveredRoundByAlignment.get(record.id) === pending.result.round) {\n\t\t\treturn {\n\t\t\t\tstatus: 200,\n\t\t\t\tbody: {\n\t\t\t\t\tok: true,\n\t\t\t\t\tdelivered: true,\n\t\t\t\t\tstepConfirmed: pending.result.stepConfirmed,\n\t\t\t\t\trevision: pending.record.revision,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\t// Submitted-but-undelivered replay retries only the injection.\n\t\tif (pending && samePost(pending)) {\n\t\t\ttry {\n\t\t\t\tawait injectFeedback(pending);\n\t\t\t\t// 同主路径:注入可能同步驱动模型回合,不回写回合前快照(走查 2026-10-04)。\n\t\t\t\tfor (const entry of markDelivered(pending.record, pending.result.round)) {\n\t\t\t\t\tapi.session?.appendEntry(TRANSITION_ENTRY, entry);\n\t\t\t\t}\n\t\t\t\tvoid api.publish({\n\t\t\t\t\ttype: \"alignment.changed\",\n\t\t\t\t\tversion: 1,\n\t\t\t\t\tcorrelationId: STATE_ENTRY,\n\t\t\t\t\tdata: loadState(api),\n\t\t\t\t});\n\t\t\t\tstate = loadState(api);\n\t\t\t\tdeliveredRoundByAlignment.set(record.id, pending.result.round);\n\t\t\t\t// 重放路径同主路径:纯确认轮不进入\"AI 修订中\"(走查 2026-10-04)。\n\t\t\t\tconst replayHasContent =\n\t\t\t\t\tpending.result.comments.length > 0 ||\n\t\t\t\t\tpending.result.commentReplies.length > 0 ||\n\t\t\t\t\tpending.result.answers.length > 0 ||\n\t\t\t\t\tpending.result.additions.length > 0;\n\t\t\t\tif (replayHasContent) deliveredRevisionByAlignment.set(record.id, pending.record.revision);\n\t\t\t\treturn {\n\t\t\t\t\tstatus: 200,\n\t\t\t\t\tbody: {\n\t\t\t\t\t\tok: true,\n\t\t\t\t\t\tdelivered: true,\n\t\t\t\t\t\tstepConfirmed: pending.result.stepConfirmed,\n\t\t\t\t\t\trevision: pending.record.revision,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\treturn {\n\t\t\t\t\tstatus: 503,\n\t\t\t\t\tbody: {\n\t\t\t\t\t\terror: `feedback delivery failed: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\t\t\tretry: true,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t\t// Page-initiated rollbacks (走查 2026-10-03) share the POST /round\n\t\t// entry so the submission→injection→delivered protocol is identical.\n\t\tlet outcome: ReturnType<typeof applyRoundPost> | undefined;\n\t\tlet runOutcome: ReturnType<typeof applyAlignmentAdvance> | undefined;\n\t\ttry {\n\t\t\tif (post.action === \"retreat\" || post.action === \"rollback\") {\n\t\t\t\tif (post.baseRevision !== record.revision) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: 409,\n\t\t\t\t\t\tbody: { code: \"stale-state\", error: \"page snapshot is stale; reload and retry\" },\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (post.action === \"retreat\") {\n\t\t\t\trunOutcome = applyAlignmentAdvance(state, {\n\t\t\t\t\talignmentId: record.id,\n\t\t\t\t\taction: \"retreat\",\n\t\t\t\t\tstep: post.targetStep,\n\t\t\t\t\tnote: \"回退自确认页:用户在页面上点击了更早的环节\",\n\t\t\t\t});\n\t\t\t} else if (post.action === \"rollback\") {\n\t\t\t\trunOutcome = applyVersionRollback(state, {\n\t\t\t\t\talignmentId: record.id,\n\t\t\t\t\ttargetRevision: post.targetRevision ?? -1,\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\toutcome = applyRoundPost(record, post);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tif (error instanceof AlignmentError) {\n\t\t\t\treturn {\n\t\t\t\t\tstatus: error.code === \"stale-state\" ? 409 : 400,\n\t\t\t\t\tbody: { code: error.code, error: error.message },\n\t\t\t\t};\n\t\t\t}\n\t\t\treturn { status: 500, body: { error: error instanceof Error ? error.message : String(error) } };\n\t\t}\n\t\t// Persist the submission first (append-only fact), then attempt delivery.\n\t\tconst record2 = outcome\n\t\t\t? outcome.record\n\t\t\t: (runOutcome!.state.alignments.find((candidate) => candidate.id === record.id) as AlignmentRecord);\n\t\tconst transitions2 = outcome ? outcome.transitions : runOutcome!.transitions;\n\t\tpersist(\n\t\t\t{\n\t\t\t\talignments: state.alignments.map((candidate) => (candidate.id === record2.id ? record2 : candidate)),\n\t\t\t},\n\t\t\ttransitions2,\n\t\t);\n\t\tconst syntheticResult: AlignmentRoundResult = outcome?.result ?? {\n\t\t\talignmentId: record2.id,\n\t\t\tround: record2.roundCount,\n\t\t\tstep: record2.activeStep,\n\t\t\trevision: record2.revision,\n\t\t\tapprovals: [],\n\t\t\tcomments: [],\n\t\t\tcommentReplies: [],\n\t\t\tanswers: [],\n\t\t\tadditions: [],\n\t\t\tstepConfirmed: false,\n\t\t};\n\t\tlet cached: CachedRound = { post, record: record2, transitions: [], result: syntheticResult };\n\t\tif (outcome?.result.stepConfirmed && outcome.record.status === \"completed\") {\n\t\t\t// 终审确认(走查 2026-10-03):no workspace file is written; the\n\t\t\t// compact listing rides the feedback message and `/alignment\n\t\t\t// export` produces a file only on explicit request.\n\t\t\tconst lines = finalBaselineLines(outcome.record);\n\t\t\toutcome.result.finalBaseline = lines;\n\t\t\tcached = { ...cached, result: outcome.result };\n\t\t}\n\t\tcachedRound = cached;\n\t\ttry {\n\t\t\tawait injectFeedback(cached);\n\t\t\t// injectFeedback 的 sendMessage(triggerTurn) 会同步驱动整个模型回合\n\t\t\t//(agent-session sendCustomMessage → _runAgentPrompt):回合内的\n\t\t\t// alignment_set 已把修订落账 entries。此处若回写回合前快照,会把模型\n\t\t\t// 刚提交的修订整体抹掉(走查 2026-10-04 dogfood:细节步 10 块被还原成\n\t\t\t// 空步)。只追加 round.delivered 审计条目,并从 entries 重建内存态。\n\t\t\tfor (const entry of markDelivered(cached.record, cached.result.round)) {\n\t\t\t\tapi.session?.appendEntry(TRANSITION_ENTRY, entry);\n\t\t\t}\n\t\t\tvoid api.publish({ type: \"alignment.changed\", version: 1, correlationId: STATE_ENTRY, data: loadState(api) });\n\t\t\tstate = loadState(api);\n\t\t\tdeliveredRoundByAlignment.set(cached.record.id, cached.result.round);\n\t\t\t// 只有携带内容反馈(批注/回复/答案/补充)的轮次才进入\"AI 修订中\":\n\t\t\t// 纯确认轮模型正确地不重发块,revision 不变——若也标记 awaiting,\n\t\t\t// 页面会永远钉在机器人等待屏,用户反而无法确认剩余块(走查 2026-10-04)。\n\t\t\tconst hasContentFeedback =\n\t\t\t\tpost.comments.length > 0 ||\n\t\t\t\tpost.commentReplies.length > 0 ||\n\t\t\t\tpost.answers.length > 0 ||\n\t\t\t\tpost.additions.length > 0;\n\t\t\tif (hasContentFeedback) deliveredRevisionByAlignment.set(cached.record.id, cached.record.revision);\n\t\t\treturn {\n\t\t\t\tstatus: 200,\n\t\t\t\tbody: {\n\t\t\t\t\tok: true,\n\t\t\t\t\tdelivered: true,\n\t\t\t\t\tstepConfirmed: cached.result.stepConfirmed,\n\t\t\t\t\trevision: cached.record.revision,\n\t\t\t\t},\n\t\t\t};\n\t\t} catch (error) {\n\t\t\treturn {\n\t\t\t\tstatus: 503,\n\t\t\t\tbody: {\n\t\t\t\t\terror: `feedback delivery failed: ${error instanceof Error ? error.message : String(error)}`,\n\t\t\t\t\tretry: true,\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t};\n\n\tconst runSet = (input: AlignmentSetInput): Record<string, unknown> => {\n\t\tconst run: EngineRun = applyAlignmentSet(state, input);\n\t\tconst record = run.state.alignments.find((candidate) => candidate.id === input.id);\n\t\tpersist(run.state, run.transitions);\n\t\tconst warning =\n\t\t\trecord?.goalId && !goalKnownToSession(api, record.goalId)\n\t\t\t\t? `goalId \"${record.goalId}\" does not match any goal in this session's goal state; the alignment keeps the soft reference`\n\t\t\t\t: undefined;\n\t\treturn { state, alignmentId: input.id, ...(warning ? { warning } : {}) };\n\t};\n\n\tconst setTool = api.registerTool({\n\t\tname: \"alignment_set\",\n\t\tlabel: \"Set alignment\",\n\t\tdescription:\n\t\t\t\"Create or update a requirement alignment task: full block set of the active step (goal→detail→design funnel). Unchanged blocks inherit user approval by content fingerprint\",\n\t\tparameters: setSchema,\n\t\tpromptGuidelines: PROMPT_GUIDELINES,\n\t\trenderResult: alignmentToolResultRenderer,\n\t\t// 双调用约定(goal 插件同款,走查 2026-10-04):会话路径传\n\t\t// (toolCallId, params, signal, onUpdate),runtime facade 路径传\n\t\t// (input, context?, signal?)——second 缺省时取 first。\n\t\texecute: async (first: unknown, second?: unknown) => {\n\t\t\tconst input = toolInput(first, second);\n\t\t\treturn runSet(input as unknown as AlignmentSetInput);\n\t\t},\n\t});\n\n\tconst roundTool = api.registerTool({\n\t\tname: \"alignment_round\",\n\t\tlabel: \"Open alignment page\",\n\t\tdescription:\n\t\t\t\"Open (or refresh) the local confirmation page for the active alignment and return its URL plus progress facts. Non-blocking: feedback arrives later as an alignment.feedback message\",\n\t\tparameters: roundSchema,\n\t\tpromptGuidelines: PROMPT_GUIDELINES,\n\t\trenderResult: alignmentToolResultRenderer,\n\t\texecute: async (first: unknown, second?: unknown) => {\n\t\t\tconst input = toolInput(first, second);\n\t\t\tconst id = typeof input.alignmentId === \"string\" ? input.alignmentId : \"\";\n\t\t\tconst record = state.alignments.find((candidate) => candidate.id === id);\n\t\t\tif (!record) throw new Error(`unknown alignment: ${id}`);\n\t\t\tif (record.status !== \"aligning\") throw new Error(`alignment is ${record.status}: ${id}`);\n\t\t\tif (!api.session?.sendMessage) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"host session does not expose sendMessage; the alignment confirmation page cannot deliver feedback on this host\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tconst running = await ensureServer();\n\t\t\tconst snapshot = gate(record);\n\t\t\treturn {\n\t\t\t\tstate,\n\t\t\t\talignmentId: record.id,\n\t\t\t\turl: running.url,\n\t\t\t\tstep: record.activeStep,\n\t\t\t\tround: record.roundCount,\n\t\t\t\trevision: record.revision,\n\t\t\t\tprogress: {\n\t\t\t\t\tunapproved: snapshot.unapproved,\n\t\t\t\t\topenComments: snapshot.openComments,\n\t\t\t\t\tpendingAdditions: snapshot.pendingAdditions,\n\t\t\t\t\tallGreen: snapshot.allGreen,\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\t});\n\n\tconst advanceTool = api.registerTool({\n\t\tname: \"alignment_advance\",\n\t\tlabel: \"Advance alignment\",\n\t\tdescription:\n\t\t\t\"inspect (read-only status/gate/baseline), retreat (roll back to an earlier step, resets downstream confirmations), or cancel the alignment\",\n\t\tparameters: advanceSchema,\n\t\tpromptGuidelines: PROMPT_GUIDELINES,\n\t\trenderResult: alignmentToolResultRenderer,\n\t\texecute: async (first: unknown, second?: unknown) => {\n\t\t\tconst input = toolInput(first, second) as unknown as AdvanceInput;\n\t\t\tif (input.action === \"inspect\") {\n\t\t\t\tconst record = state.alignments.find((candidate) => candidate.id === input.alignmentId);\n\t\t\t\tif (!record) throw new Error(`unknown alignment: ${input.alignmentId}`);\n\t\t\t\treturn {\n\t\t\t\t\tstate,\n\t\t\t\t\talignmentId: record.id,\n\t\t\t\t\tgate: gate(record),\n\t\t\t\t\tbaseline: record.status === \"completed\" ? finalBaselineLines(record) : undefined,\n\t\t\t\t};\n\t\t\t}\n\t\t\tconst run = applyAlignmentAdvance(state, input);\n\t\t\tpersist(run.state, run.transitions);\n\t\t\treturn { state, alignmentId: input.alignmentId };\n\t\t},\n\t});\n\n\tconst command = api.registerCommand({\n\t\tname: \"alignment\",\n\t\tdescription:\n\t\t\t\"Show this session's alignments (progress, blockers, audit log); `export [id] [path]` writes a self-contained read-only HTML snapshot\",\n\t\texecute: async (args: string, context?: { cwd?: string }): Promise<CapabilityCommandResult> => {\n\t\t\ttry {\n\t\t\t\tconst parts = args\n\t\t\t\t\t.trim()\n\t\t\t\t\t.split(/\\s+/)\n\t\t\t\t\t.filter((part) => part !== \"\");\n\t\t\t\tif (parts.length === 0) return { status: \"success\", message: listLines(state) };\n\t\t\t\tif (parts[0] === \"why\") {\n\t\t\t\t\tconst record =\n\t\t\t\t\t\tstate.alignments.find((candidate) => candidate.status === \"aligning\") ?? state.alignments.at(-1);\n\t\t\t\t\tif (!record) return { status: \"error\", message: \"no alignments in this session\" };\n\t\t\t\t\tconst extra =\n\t\t\t\t\t\tcachedRound && deliveredRoundByAlignment.get(record.id) !== cachedRound.result.round\n\t\t\t\t\t\t\t? `\\nundelivered round: r${cachedRound.result.round} (injection failed; the page can retry)`\n\t\t\t\t\t\t\t: \"\";\n\t\t\t\t\treturn { status: \"success\", message: whyLines(record) + extra };\n\t\t\t\t}\n\t\t\t\tif (parts[0] === \"log\") {\n\t\t\t\t\tconst count = Number.parseInt(parts[1] ?? \"20\", 10);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: \"success\",\n\t\t\t\t\t\tmessage: logLines(loadTransitions(api), Number.isFinite(count) && count > 0 ? count : 20),\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\tif (parts[0] === \"export\") {\n\t\t\t\t\tconst id = parts[1];\n\t\t\t\t\tconst record = id\n\t\t\t\t\t\t? state.alignments.find((candidate) => candidate.id === id)\n\t\t\t\t\t\t: (state.alignments.find((candidate) => candidate.status === \"aligning\") ??\n\t\t\t\t\t\t\tstate.alignments.find((candidate) => candidate.status === \"finalizing\") ??\n\t\t\t\t\t\t\tstate.alignments.at(-1));\n\t\t\t\t\tif (!record) return { status: \"error\", message: `unknown alignment: ${id ?? \"(none in session)\"}` };\n\t\t\t\t\t// Explicit user request — the only path that writes a file.\n\t\t\t\t\tconst target = exportTargetPath(context?.cwd ?? process.cwd(), record, parts[2]);\n\t\t\t\t\tconst written = writeAlignmentExport(record, loadTransitions(api), target);\n\t\t\t\t\treturn {\n\t\t\t\t\t\tstatus: \"success\",\n\t\t\t\t\t\tmessage: `exported: ${written}`,\n\t\t\t\t\t\tlinks: [{ label: written, url: `file:///${written.split(\"\\\\\").join(\"/\")}` }],\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tstatus: \"error\",\n\t\t\t\t\tmessage: \"Usage: /alignment | /alignment why | /alignment log [N] | /alignment export [id] [path]\",\n\t\t\t\t};\n\t\t\t} catch (error) {\n\t\t\t\treturn { status: \"error\", message: error instanceof Error ? error.message : String(error) };\n\t\t\t}\n\t\t},\n\t});\n\n\tconst stopServer = (): void => {\n\t\tconst stopping = server;\n\t\tserver = undefined;\n\t\tif (stopping) void stopping.stop().catch(() => undefined);\n\t};\n\n\t// The command registration doubles as the teardown hook for the local\n\t// confirmation server (plugin dispose must release the port).\n\tconst commandWithTeardown: DisposableRegistration = {\n\t\tid: command.id,\n\t\tkind: command.kind,\n\t\tdispose: () => {\n\t\t\tvoid command.dispose();\n\t\t\tstopServer();\n\t\t},\n\t};\n\n\treturn [setTool, roundTool, advanceTool, commandWithTeardown];\n}\n"]}
|
package/dist/page.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The fixed confirmation-page template (设计 §7 模板契约): a plugin-owned
|
|
3
|
+
* static asset compiled into the package. The model only ever supplies block
|
|
4
|
+
* DATA through alignment.state — it never produces markup, so the same state
|
|
5
|
+
* always renders the same page and there is no model-injection surface
|
|
6
|
+
* (block content is escaped text, never markup).
|
|
7
|
+
*
|
|
8
|
+
* Interaction contract (demo 定稿 2026-10-03): spotlight replays fully on
|
|
9
|
+
* every click, auto-restores after ~4.5s or any click; empty missing blocks
|
|
10
|
+
* show "fill first" instead of an approve button; the annotation popover is
|
|
11
|
+
* immune to its own trailing mouseup; polling never wipes in-progress input.
|
|
12
|
+
*/
|
|
13
|
+
/** The fixed page template: no state, no model input — only the two endpoints above. */
|
|
14
|
+
export declare function renderAlignmentPage(): string;
|
|
15
|
+
//# sourceMappingURL=page.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page.d.ts","sourceRoot":"","sources":["../src/page.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAmwBH,0FAAwF;AACxF,wBAAgB,mBAAmB,IAAI,MAAM,CAiD5C","sourcesContent":["/**\n * The fixed confirmation-page template (设计 §7 模板契约): a plugin-owned\n * static asset compiled into the package. The model only ever supplies block\n * DATA through alignment.state — it never produces markup, so the same state\n * always renders the same page and there is no model-injection surface\n * (block content is escaped text, never markup).\n *\n * Interaction contract (demo 定稿 2026-10-03): spotlight replays fully on\n * every click, auto-restores after ~4.5s or any click; empty missing blocks\n * show \"fill first\" instead of an approve button; the annotation popover is\n * immune to its own trailing mouseup; polling never wipes in-progress input.\n */\n\nconst CSS = `\n:root{--ink:#2a2f45;--ink2:#4c536e;--mut:#8a90a8;--faint:#b6bbce;--line:rgba(120,125,165,.16);\n--grad:linear-gradient(135deg,#6366f1,#a855f7 55%,#ec4899);--green:#10b981;--greensoft:#e7f9f1;\n--amber:#f59e0b;--ambersoft:#fef4e0;--blue:#3b82f6;--bluesoft:#eaf1fe;--pink:#ec4899;--pinksoft:#fdeaf3;\n--card:rgba(255,255,255,.74)}\n*{box-sizing:border-box;margin:0;padding:0}\nbody{font-family:\"SF Pro Display\",-apple-system,\"Segoe UI\",\"PingFang SC\",\"Microsoft YaHei\",sans-serif;\nbackground:#f4f6fd;color:var(--ink);font-size:14px;line-height:1.75}\n::selection{background:#ddd6fe}\ntextarea{background:#fff;border:1.5px solid var(--line);border-radius:16px;color:var(--ink);\nfont:inherit;font-size:13.5px;transition:.15s;scrollbar-width:thin}\ntextarea:focus{outline:none;border-color:#a5b4fc;box-shadow:0 0 0 4px rgba(99,102,241,.12)}\ntextarea::placeholder{color:#b8bdd1}\ntextarea::-webkit-scrollbar{width:6px}textarea::-webkit-scrollbar-button{display:none}\ntextarea::-webkit-scrollbar-thumb{background:rgba(120,125,165,.25);border-radius:6px}\n.blob{position:fixed;border-radius:50%;filter:blur(90px);opacity:.42;z-index:-1}\n.b1{width:480px;height:480px;background:#c7d2fe;top:-160px;left:-90px}\n.b2{width:430px;height:430px;background:#fbcfe8;top:-120px;right:-80px}\n.b3{width:400px;height:400px;background:#fde8c8;bottom:-160px;left:28%}\n.wrap{max-width:1020px;margin:0 auto;padding:32px 22px 190px}\nheader.task{text-align:center}\n.eyebrow{display:inline-flex;align-items:center;gap:7px;font-size:12px;font-weight:700;color:#6366f1;\nbackground:#eef0ff;border-radius:999px;padding:4px 16px}\n.eyebrow::before{content:\"\";width:7px;height:7px;border-radius:50%;background:var(--grad)}\nh1{font-size:24px;font-weight:800;margin-top:12px}\n.meta{font-size:12.5px;color:var(--mut);margin-top:6px}.meta b{color:var(--ink2);font-weight:650}\n.steps{display:flex;gap:10px;justify-content:center;margin-top:18px}\n.step{display:flex;align-items:center;gap:8px;padding:9px 20px;border-radius:999px;\nbackground:rgba(255,255,255,.7);border:1px solid rgba(255,255,255,.9);\nbox-shadow:0 4px 18px rgba(99,102,241,.07);font-size:13.5px;font-weight:600;color:var(--mut)}\n.step .no{width:22px;height:22px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;\nfont-size:11.5px;background:#edeff8;color:var(--mut)}\n.step.done{color:#047857;background:var(--greensoft)}.step.done .no{background:var(--green);color:#fff}\n.step.active{color:#4f46e5;border-color:transparent;\nbackground:linear-gradient(#fff,#fff) padding-box,var(--grad) border-box;box-shadow:0 8px 30px rgba(99,102,241,.15)}\n.step.active .no{background:var(--grad);color:#fff}\n.step .tag{font-size:11px;font-weight:500;opacity:.75}\n.cols{display:flex;gap:20px;align-items:flex-start;margin-top:30px}\naside.locked{width:250px;flex:none;position:sticky;top:14px}\n.glass{background:var(--card);backdrop-filter:blur(16px);border:1px solid rgba(255,255,255,.95);\nborder-radius:22px;box-shadow:0 12px 44px rgba(99,102,241,.08);padding:16px 18px}\n.glass h3{font-size:13.5px;display:flex;align-items:center;gap:7px;color:var(--ink2)}\n.glass .ic{width:22px;height:22px;border-radius:7px;background:var(--greensoft);color:var(--green);\ndisplay:inline-flex;align-items:center;justify-content:center;font-size:12px}\n.lkgrp{margin-top:8px}\n.lkgrp summary{cursor:pointer;font-size:12px;color:var(--mut);padding:4px 0}\n.lkitem{font-size:12px;color:var(--mut);line-height:1.65;padding:5px 0 5px 12px;border-top:1px dashed var(--line)}\n.lkitem .k{font-size:10px;font-weight:700;color:var(--green);margin-right:5px}\n.glass .note{font-size:11px;color:var(--mut);background:#f4f2ff;border-radius:12px;padding:8px 12px;margin-top:10px;line-height:1.6}\n#main{flex:1;min-width:0}\n.stephead{display:flex;align-items:baseline;justify-content:space-between;margin-bottom:16px;padding:0 6px}\n.stephead h2{font-size:18px;font-weight:800}\n.stephead .desc{font-size:12px;color:var(--mut);max-width:440px;text-align:right}\n.block{position:relative;background:var(--card);backdrop-filter:blur(16px);\nborder:1px solid rgba(255,255,255,.95);border-radius:22px;padding:17px 22px 15px;margin-bottom:14px;\nbox-shadow:0 10px 36px rgba(99,102,241,.07);transition:opacity .35s,transform .35s,box-shadow .2s}\n.block .top{display:flex;align-items:center;gap:9px;flex-wrap:wrap}\n.badge{display:inline-flex;align-items:center;gap:6px;font-size:11.5px;font-weight:700;padding:3px 12px;border-radius:999px}\n.badge::before{content:\"\";width:6px;height:6px;border-radius:50%;background:currentColor}\n.badge.decision{color:#4f46e5;background:#eef0ff}.badge.assumption{color:#b45309;background:var(--ambersoft)}\n.badge.fact{color:#047857;background:var(--greensoft)}.badge.missing{color:#db2777;background:var(--pinksoft)}\n.bid{font-size:11px;color:var(--mut);font-weight:600;letter-spacing:.5px}\n.mod{font-size:11px;font-weight:700;color:#7c3aed;background:#f3ecff;border-radius:999px;padding:2px 10px}\n.approvebtn{margin-left:auto;cursor:pointer;font-size:12.5px;font-weight:700;padding:6px 18px;border-radius:999px;\nborder:1.5px solid var(--green);background:#fff;color:var(--green);transition:.18s}\n.approvebtn:hover{background:var(--greensoft)}\n.block.approved .approvebtn{background:linear-gradient(135deg,#34d399,#10b981);border-color:transparent;color:#fff}\n.skiphint{margin-left:auto;font-size:11px;color:var(--faint);background:#f4f5fa;border-radius:999px;padding:4px 13px}\n.content{margin-top:9px;font-size:14.5px;line-height:1.8;white-space:pre-wrap;cursor:text}\n.missinginput textarea{width:100%;margin-top:9px;background:var(--pinksoft);border:1.5px solid #f9c8de;\nborder-radius:14px;padding:9px 14px;font:inherit;font-size:13.5px;color:var(--ink);resize:none;min-height:40px}\n.missinginput textarea:focus{outline:none;border-color:var(--pink);background:#fff}\n.missinginput textarea::placeholder{color:#d98bb1}\ndetails.meta{margin-top:6px;font-size:12px;color:var(--mut)}\ndetails.meta summary{cursor:pointer;width:fit-content}details.meta summary:hover{color:var(--ink2)}\n.prev{background:#f6f5fb;border-radius:10px;padding:7px 12px;margin-top:5px;color:var(--mut);font-size:12px;white-space:pre-wrap}\n.avatar{width:24px;height:24px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;\nfont-size:10px;font-weight:800;flex:none;color:#fff}\n.avatar.ai{background:linear-gradient(135deg,#f59e0b,#f97316)}.avatar.user{background:linear-gradient(135deg,#3b82f6,#6366f1)}\n.comment{margin-top:11px;padding:11px 15px;font-size:13px}\n.comment .who{font-size:11px;font-weight:800;margin-bottom:4px;display:flex;align-items:center;gap:7px}\n.comment .quote{font-size:12px;opacity:.7;padding:1px 0 1px 9px;border-left:2.5px solid currentColor;margin:4px 0}\n.comment.ai{background:#fff8ec;border:1px solid #fbe7c3;border-radius:18px 18px 18px 5px;color:#92580a}\n.comment.ai .who{color:#c2680a}\n.comment.user{background:var(--bluesoft);border:1px solid #cfe0fb;border-radius:18px 18px 5px 18px;color:#1e50af}\n.comment.user .who{color:#2c63c8}\n.comment .actions{margin-top:7px;display:flex;gap:8px}\n.comment .actions button{cursor:pointer;font-size:12px;font-weight:700;padding:3px 14px;border-radius:999px;\nborder:1.5px solid currentColor;background:transparent;color:inherit;opacity:.85;transition:.15s}\n.comment .actions button:hover{opacity:1;background:rgba(255,255,255,.6)}\n.replybox{width:100%;margin-top:8px;background:#fff;border:1.5px solid #fbe7c3;border-radius:12px;\nfont:inherit;font-size:13px;padding:7px 11px;resize:vertical;min-height:40px;color:var(--ink)}\n.replybox:focus{outline:none;border-color:var(--amber)}\n.comment .draftreply{margin-top:6px;font-size:12px;background:rgba(255,255,255,.7);border-radius:10px;\npadding:5px 11px;display:flex;justify-content:space-between;gap:10px;align-items:center}\n.comment .draftreply a{cursor:pointer;text-decoration:underline;color:inherit;opacity:.7;white-space:nowrap}\n.comment.resolved{background:rgba(255,255,255,.55);border:1px dashed var(--line);color:var(--mut);\nfont-size:12px;border-radius:14px;padding:8px 15px}\n#blocks.focusing .block:not(.attention){opacity:.3;transform:scale(.985)}\n.block.attention{animation:wiggle .65s ease;box-shadow:0 0 0 3px var(--kc,#6366f1),0 14px 44px rgba(99,102,241,.2)}\n.block[data-kind=decision]{--kc:#6366f1}.block[data-kind=assumption]{--kc:#f59e0b}\n.block[data-kind=fact]{--kc:#10b981}.block[data-kind=missing]{--kc:#ec4899}\n@keyframes wiggle{0%,100%{transform:rotate(0)}25%{transform:rotate(-.8deg)}50%{transform:rotate(.7deg)}75%{transform:rotate(-.45deg)}}\n.block.attention::after{content:attr(data-reason);position:absolute;top:-12px;right:18px;font-size:11px;\nfont-weight:800;color:#fff;background:var(--kc,#6366f1);padding:3px 13px;border-radius:999px;box-shadow:0 4px 12px rgba(0,0,0,.15)}\nfooter.dock{position:fixed;left:50%;transform:translateX(-50%);bottom:20px;width:min(1000px,calc(100% - 36px));\nbackground:rgba(255,255,255,.88);backdrop-filter:blur(22px);border:1px solid #fff;border-radius:26px;\nbox-shadow:0 22px 70px rgba(80,80,160,.18);z-index:50}\nfooter.dock .inner{padding:14px 18px 12px;display:flex;gap:14px;align-items:flex-end}\n.addbox{flex:1}.addbox label{font-size:11px;font-weight:700;color:var(--mut);display:block;margin-bottom:4px}\n.awaitbar{background:linear-gradient(90deg,#eef2ff,#fdf2f8);border:1px solid #e0e7ff;border-radius:12px;padding:10px 16px;margin:0 0 14px;font-size:13px;color:#4f46e5;font-weight:600}\n.cmask{position:fixed;inset:0;background:rgba(79,70,229,.18);backdrop-filter:blur(6px);z-index:60;display:flex;align-items:center;justify-content:center;animation:cmaskin .18s ease}\n.ccard{background:rgba(255,255,255,.92);backdrop-filter:blur(18px);border:1px solid rgba(148,163,184,.35);border-radius:20px;box-shadow:0 24px 70px -18px rgba(79,70,229,.45);padding:22px 26px 18px;max-width:380px;width:calc(100vw - 48px)}\n.ccard h3{margin:0 0 8px;font-size:15.5px;font-weight:800}\n.ccard p{margin:0 0 16px;font-size:13px;color:var(--mut);line-height:1.7}\n.cbtns{display:flex;gap:10px;justify-content:flex-end}\n.ccancel{border:1px solid var(--line);background:#fff;color:var(--ink2);border-radius:12px;padding:8px 18px;font-size:13px;font-weight:600;cursor:pointer}\n.cok{border:0;background:linear-gradient(135deg,#7c6ff0,#d946ef);color:#fff;border-radius:12px;padding:8px 18px;font-size:13px;font-weight:700;cursor:pointer;box-shadow:0 8px 20px -8px rgba(124,111,240,.6)}\n@keyframes cmaskin{from{opacity:0}to{opacity:1}}\n.botwrap{display:flex;justify-content:center;padding:34px 0 20px}\n.botcard{background:rgba(255,255,255,.75);backdrop-filter:blur(14px);border:1px solid rgba(148,163,184,.3);border-radius:20px;padding:26px 44px 22px;text-align:center;box-shadow:0 18px 44px -20px rgba(99,102,241,.35);animation:botfloat 3.2s ease-in-out infinite}\n.bot{width:64px;height:52px;margin:0 auto 12px;position:relative}\n.bot .antenna{position:absolute;top:-12px;left:50%;transform:translateX(-50%);width:3px;height:12px;background:#c7d2fe;border-radius:2px}\n.bot .antenna:after{content:\"\";position:absolute;top:-7px;left:50%;transform:translateX(-50%);width:9px;height:9px;border-radius:50%;background:#a78bfa;animation:botping 1.6s ease-in-out infinite}\n.bot .face{width:64px;height:52px;border-radius:16px;background:linear-gradient(145deg,#eef2ff,#fdf2f8);border:1.5px solid #c7d2fe;display:flex;align-items:center;justify-content:center;gap:12px}\n.bot .eye{width:8px;height:16px;border-radius:4px;background:#7c6ff0;animation:botblink 2.6s ease-in-out infinite}\n.bot .eye:last-child{animation-delay:.15s}\n.thinkdots{display:flex;gap:7px;justify-content:center;margin:2px 0 10px}\n.thinkdots span{width:8px;height:8px;border-radius:50%;background:#a78bfa;opacity:.45;animation:botdot 1.4s ease-in-out infinite}\n.thinkdots span:nth-child(2){animation-delay:.2s}\n.thinkdots span:nth-child(3){animation-delay:.4s}\n.bottext{font-size:13px;color:#6d28d9;font-weight:600}\n@keyframes botfloat{0%,100%{transform:translateY(0)}50%{transform:translateY(-7px)}}\n@keyframes botblink{0%,88%,100%{transform:scaleY(1)}94%{transform:scaleY(.12)}}\n@keyframes botping{0%,100%{opacity:.5;transform:translateX(-50%) scale(1)}50%{opacity:1;transform:translateX(-50%) scale(1.35)}}\n@keyframes botdot{0%,100%{opacity:.35;transform:translateY(0)}45%{opacity:1;transform:translateY(-6px)}}\n.verbar{font-size:12px;color:var(--mut);margin:0 0 12px}\n.verbar a{cursor:pointer;text-decoration:underline;margin-right:2px}\n.verbar b{color:var(--ink)}\n.verbar .rollbackbtn{margin-left:10px;border:1px solid #fecaca;background:#fff1f2;color:#be123c;border-radius:8px;padding:3px 10px;font-size:12px;cursor:pointer}\n.finhead{margin:6px 0 14px}.finhead h2{font-size:19px;margin:0 0 6px}.finhead p{font-size:13px;color:var(--mut);margin:0}\n.finalview .fingrp{background:rgba(255,255,255,.72);border:1px solid rgba(148,163,184,.28);border-radius:14px;padding:14px 18px;margin-bottom:12px}\n.finalview h3{font-size:14px;margin:0 0 8px}\n.brow{display:flex;gap:8px;align-items:baseline;padding:5px 0;border-bottom:1px dashed rgba(148,163,184,.2);font-size:13px}\n.brow:last-child{border-bottom:0}\n.brow .k{font-size:11px;font-weight:700;flex:none}\n.brow .bid{font-family:ui-monospace,monospace;font-size:12px;color:var(--mut);flex:none}\n.addbox textarea{display:block;width:100%;height:46px;padding:10px 15px;resize:none}\n.mainbtn{cursor:pointer;border:none;border-radius:18px;height:49px;display:inline-flex;align-items:center;\njustify-content:center;padding:0 28px;font-size:14px;font-weight:800;white-space:nowrap;color:#fff;\nbackground:var(--grad);box-shadow:0 10px 30px rgba(139,92,246,.28);transition:.18s}\n.mainbtn:hover:not(:disabled){filter:brightness(1.08);transform:translateY(-1px)}\n.mainbtn.confirm{background:linear-gradient(135deg,#34d399,#0ea573);box-shadow:0 10px 30px rgba(16,185,129,.28)}\n.mainbtn:disabled{background:#e2e5f0;color:#a7adc4;box-shadow:none;cursor:not-allowed;transform:none}\n.gatehint{padding:0 18px 12px;font-size:12px;color:var(--mut)}.gatehint b{color:#db2777}\n.gatehint.ok{color:#047857}\n.selbtn{position:absolute;z-index:40;cursor:pointer;border:none;background:var(--grad);color:#fff;\nfont-size:12.5px;font-weight:700;padding:6px 16px;border-radius:999px;box-shadow:0 8px 24px rgba(139,92,246,.32)}\n.annotpop{position:absolute;z-index:50;width:340px;background:#fff;border:1px solid #e7e9fb;border-radius:20px;\nbox-shadow:0 24px 70px rgba(80,80,160,.22);padding:15px 17px}\n.annotpop .sel{font-size:12px;color:var(--mut);border-left:3px solid var(--blue);padding-left:9px;\nmargin-bottom:9px;max-height:56px;overflow:hidden}\n.annotpop textarea{width:100%;border:1.5px solid var(--line);border-radius:14px;padding:9px 12px;\nresize:vertical;min-height:58px}\n.annotpop .esc{display:flex;gap:7px;align-items:center;font-size:12px;color:var(--mut);margin-top:9px;cursor:pointer}\n.annotpop .esc input{accent-color:#6366f1}\n.annotpop .row{display:flex;gap:9px;justify-content:flex-end;margin-top:11px}\n.annotpop .row button{cursor:pointer;font-size:12.5px;font-weight:700;padding:6px 18px;border-radius:999px;\nborder:1.5px solid var(--line);background:#fff;color:var(--ink2)}\n.annotpop .row button.go{background:var(--grad);border:none;color:#fff;box-shadow:0 6px 18px rgba(139,92,246,.3)}\n#toast{position:fixed;top:18px;left:50%;transform:translateX(-50%) translateY(-80px);color:#fff;\nbackground:var(--grad);font-size:13px;font-weight:700;padding:10px 26px;border-radius:999px;\nbox-shadow:0 12px 36px rgba(139,92,246,.32);transition:transform .3s ease;z-index:100}\n#toast.show{transform:translateX(-50%) translateY(0)}\n.offline{position:fixed;inset:auto 0 0 0;top:0;display:flex;align-items:center;justify-content:center;\nbackground:rgba(90,95,130,.92);color:#fff;font-size:14px;z-index:200;text-align:center;padding:20px}\n.reviving{text-align:center;padding:60px 0;color:var(--mut)}\n.reviving::before{content:\"\";display:block;width:34px;height:34px;margin:0 auto 14px;border-radius:50%;\nbackground:conic-gradient(from 0deg,#6366f1,#ec4899,#6366f1);\n-webkit-mask:radial-gradient(circle 11px,transparent 97%,#000) center/100% 100% no-repeat;\nanimation:spin 1.1s linear infinite}\n@keyframes spin{to{transform:rotate(360deg)}}\n.baseline{margin-top:16px;background:linear-gradient(135deg,#e7f9f1,#eef0ff);border:1px solid #fff;\nborder-radius:24px;padding:20px 24px}\n.baseline h3{color:#047857;font-size:16px}.baseline p{font-size:12px;color:var(--mut);margin:5px 0 10px}\n.brow{display:flex;gap:10px;font-size:13px;padding:6px 2px;border-top:1px dashed var(--line);align-items:baseline}\n.brow .k{font-size:10px;font-weight:800;color:var(--ink2);flex:none}.brow .bid{font-size:10.5px;color:var(--mut);flex:none;font-weight:600}\n@media(max-width:900px){.cols{flex-direction:column}aside.locked{width:100%;position:static}}\n`;\n\nconst SCRIPT = `\n\"use strict\";\nconst KIND_CN={fact:\"取证事实\",assumption:\"假设\",decision:\"决策\",missing:\"待补充\"};\nconst STEP_CN={objective:\"目标\",detail:\"细节\",design:\"设计\"};\nconst STEP_ORDER=[\"objective\",\"detail\",\"design\"];\nconst esc=(s)=>String(s==null?\"\":s).replace(/&/g,\"&\").replace(/</g,\"<\").replace(/>/g,\">\");\nconst el=(id)=>document.getElementById(id);\nconst firstLine=(s)=>String(s).split(\"\\\\n\")[0].slice(0,80);\n\n// page-local drafts: survive re-renders (轮询不丢输入) until submitted\nlet drafts={answers:{},replies:{},dismissed:{},additions:\"\",revised:{}};\n// Version view (走查 2026-10-03): null = latest (interactive); number = archived\n// snapshot revision (read-only).\nlet viewingVersion=null;\n// 完成态的环节查看选择(走查 2026-10-03):null = 全部分组;只读,无回退。\nlet viewingStep=null;\nfunction askConfirm(title,body,okText,onOk){\n // 页内确认弹层(走查 2026-10-03):禁用浏览器原生 confirm。\n const mask=document.createElement(\"div\");\n mask.className=\"cmask\";\n mask.innerHTML='<div class=\"ccard\"><h3>'+esc(title)+'</h3><p>'+esc(body)+'</p>'\n +'<div class=\"cbtns\"><button class=\"ccancel\">取消</button><button class=\"cok\">'+esc(okText)+'</button></div></div>';\n document.body.appendChild(mask);\n const close=()=>mask.remove();\n mask.querySelector(\".ccancel\").addEventListener(\"click\",close);\n mask.querySelector(\".cok\").addEventListener(\"click\",()=>{close();onOk();});\n mask.addEventListener(\"click\",(e)=>{if(e.target===mask)close();});\n}\nfunction botThink(text){\n return '<div class=\"botwrap\"><div class=\"botcard\"><div class=\"bot\"><div class=\"antenna\"></div>'\n +'<div class=\"face\"><span class=\"eye\"></span><span class=\"eye\"></span></div></div>'\n +'<div class=\"thinkdots\"><span></span><span></span><span></span></div>'\n +'<div class=\"bottext\">'+text+'</div></div></div>';\n}\nlet view=null; // last state.json payload\nlet submitting=false;\n\nasync function pull(){\n try{\n const res=await fetch(\"state.json\",{cache:\"no-store\"});\n if(res.status===404){offline(false);return null;}\n if(!res.ok)throw new Error(\"state \"+res.status);\n offline(false);\n return await res.json();\n }catch(e){offline(true);return null;}\n}\nfunction offline(show){\n const banner=el(\"offline\");\n banner.style.display=show?\"flex\":\"none\";\n if(show)banner.textContent=\"会话已断开——回到终端继续(插件服务已停止)\";\n}\n// Local approval mirror: null = follow server state; object after the first\n// local toggle. Every gate/visual read goes through effectiveApproved so a\n// click reacts instantly instead of waiting for the next round trip.\nlet approvals=null; // null = mirror server state; object after local toggles\nfunction effectiveApproved(b){\n if(approvals&&Object.prototype.hasOwnProperty.call(approvals,b.id))return approvals[b.id];\n return b.status===\"approved\";\n}\nfunction gatePendingCount(){\n if(!view)return 0;\n const s=activeStep();\n if(!s)return view.gate.pending.length;\n // Server pending list, discounted by local approvals the page can resolve\n // right now. missing-empty stays pending until an answer exists locally.\n return view.gate.pending.filter((item)=>{\n const b=s.blocks.find((x)=>x.id===item.blockId);\n if(!b)return true;\n if(item.reason===\"unapproved\"||item.reason===\"missing-empty\"){\n if(!effectiveApproved(b))return true;\n return b.kind===\"missing\"&&!(b.draftAnswer||(drafts.answers[b.id]||\"\").trim());\n }\n return true;\n }).length;\n}\nfunction hasContentDrafts(){\n if(drafts.additions.trim())return true;\n const s=activeStep();\n if(!s)return false;\n for(const b of s.blocks){\n if(b.kind===\"missing\"&&!b.draftAnswer&&(drafts.answers[b.id]||\"\").trim())return true;\n if(b.kind===\"missing\"&&b.draftAnswer)return false;\n }\n for(const b of s.blocks)for(const c of b.comments){\n if(c.status===\"open\"&&c.author===\"assistant\"&&(drafts.replies[c.id]||drafts.dismissed[c.id]))return true;\n }\n return !!(selInfo&&selInfo.pendingComments&&selInfo.pendingComments.length);\n}\nfunction hasDrafts(){\n if(hasContentDrafts())return true;\n const s=activeStep();\n if(!s)return false;\n // A local approval that differs from the mirrored state is undelivered\n // feedback and must route the dock button to submit, not spotlight.\n for(const b of s.blocks){\n if(effectiveApproved(b)!==(b.status===\"approved\"))return true;\n }\n return false;\n}\nfunction activeStep(){return view?view.steps.find((s)=>s.step===view.activeStep):null;}\n\nasync function refresh(){\n const next=await pull();\n if(!next)return;\n const focusEditing=document.activeElement&&document.activeElement.tagName===\"TEXTAREA\";\n // 轮询只在状态真正推进时整页重绘(走查 2026-10-03):无条件每 2s 重建\n // innerHTML 会重放入场动画,还会吞掉恰好落在重建窗口里的点击。\n const changed=!view||next.revision!==view.revision||next.round!==view.round\n ||next.status!==view.status||!!next.awaitingRevision!==!!view.awaitingRevision;\n if(changed){approvals=null;viewingVersion=null;}\n view=next;\n if(changed&&!focusEditing)render();\n else renderDock(); // keep the dock fresh while typing\n}\nfunction render(){renderSteps();renderLocked();renderMain();renderDock();}\n\nfunction renderSteps(){\n el(\"title\").textContent=view.title;\n el(\"meta\").innerHTML=view.goalId\n ?(\"goal <b>\"+esc(view.goalId)+\"</b> · 第 <b>\"+view.round+\"</b> 轮 · 已确认 <b>\"+view.gate.approvedCount+\"/\"+view.gate.blockCount+\"</b>\")\n :(\"第 <b>\"+view.round+\"</b> 轮 · 已确认 <b>\"+view.gate.approvedCount+\"/\"+view.gate.blockCount+\"</b>\");\n let tabs=STEP_ORDER.map((id,i)=>{\n const st=view.steps.find((s)=>s.step===id);\n const locked=st.status===\"locked\";\n const cur=view.status===\"completed\"?viewingStep:(view.status===\"finalizing\"?null:view.activeStep);\n const cls=locked?\"done\":(cur===id?\"active\":\"\");\n const tag=locked?(st.blocks.length+\" 块已锁定\"):(view.activeStep===id?\"当前\":\"未解锁\");\n // 已锁定步可点击回退(走查 2026-10-03):后续环节作废重走。\n const terminal=view.status===\"completed\"||view.status===\"cancelled\";\n // 完成态:tab 点击=只读查看该环节(走查 2026-10-03),无回退。\n const viewPick=terminal?' data-viewstep=\"'+id+'\" style=\"cursor:pointer\"':\"\";\n const retreat=(locked&&!terminal)?' data-retreat=\"'+id+'\" style=\"cursor:pointer\" title=\"点击回退到此环节(后面的环节将作废)\"':\"\";\n return '<div class=\"step '+cls+'\"'+viewPick+retreat+'><span class=\"no\">'+(locked?\"✓\":(i+1))+\"</span>\"+STEP_CN[id]\n +'<span class=\"tag\">'+tag+\"</span></div>\";\n }).join(\"\");\n const fin=view.status===\"finalizing\";\n // 完成态:总览 tab = 返回「全部环节」分组视图(走查 2026-10-03)。\n const viewAll=view.status===\"completed\"?' data-viewall=\"1\" style=\"cursor:pointer\"':\"\";\n tabs+='<div class=\"step '+(fin?\"active\":view.status===\"completed\"&&viewingStep===null?\"active\":\"\")+'\"'+(fin||view.status===\"aligning\"?' id=\"finalTab\"':\"\")+viewAll\n +'><span class=\"no\">'+(fin?\"◉\":view.status===\"completed\"&&viewingStep===null?\"◉\":\"4\")+\"</span>总览\"+'<span class=\"tag\">'+(fin?\"终审\":view.status===\"completed\"?\"全部\":\"未到达\")+\"</span></div>\";\n el(\"steps\").innerHTML=tabs;\n}\n\nfunction renderLocked(){\n const aside=el(\"locked\");\n if(view.status===\"finalizing\"||view.status===\"completed\"){aside.style.display=\"none\";return;}\n const locked=view.steps.filter((s)=>s.status===\"locked\");\n if(!locked.length){aside.style.display=\"none\";return;}\n aside.style.display=\"\";\n aside.innerHTML='<div class=\"glass\"><h3><span class=\"ic\">✓</span>已锁定基线 · '\n +locked.map((s)=>STEP_CN[s.step]).join(\" + \")+'</h3>'\n +locked.map((s)=>'<div class=\"lkgrp\"><details><summary>'+STEP_CN[s.step]+' · '+s.blocks.length+' 块</summary>'\n +s.blocks.map((b)=>'<div class=\"lkitem\"><span class=\"k\">'+KIND_CN[b.kind]+'</span>'+esc(firstLine(b.content))+'</div>').join(\"\")\n +'</details></div>').join(\"\")\n +'<div class=\"note\">锁定内容只读——要修改需走回退(批注时勾选「这是上游步骤的问题」)</div></div>';\n}\n\nfunction versionBarHtml(){\n // 版本只作用单节点(走查 2026-10-03):只显示当前步的快照。\n // 完成态跟随正在查看的环节;「全部环节」视图不显示版本条。\n const cur=viewingStep??view.activeStep;\n const versions=(view.versions||[]).filter((v)=>v.step===cur);\n if(view.status===\"completed\"&&viewingStep===null&&viewingVersion===null)return \"\";\n const active=!viewingVersion;\n if(!versions.length)return active?\"\":\"\";\n const chips=versions.slice().reverse().map((v)=>v.revision!==viewingVersion\n ?'<a data-viewver=\"'+v.revision+'\">r'+v.revision+\"</a>\"\n :'<b>r'+v.revision+\"</b>\").join(\" · \");\n const back=viewingVersion!==null?' — <a data-viewver=\"latest\">返回最新版本</a>':\"\";\n // 终态(completed/cancelled)不提供版本回退入口(走查 2026-10-03):对齐结束后只读。\n const rollback=view.status===\"aligning\"&&viewingVersion!==null&&viewingVersion!==undefined\n ?' <button class=\"rollbackbtn\" data-rollback=\"'+viewingVersion+'\">回退到此版本</button>'\n :\"\";\n return '<div class=\"verbar\">版本:'+(active?\"<b>最新 r\"+view.revision+\"</b>\":\"\")+(\" · \"+chips)+back+rollback+\"</div>\";\n}\n\nfunction renderMain(){\n if(view.status===\"finalizing\"){\n el(\"doneBanner\").style.display=\"none\";\n const rows=view.steps.map((st)=>'<div class=\"fingrp\"><h3>'+STEP_CN[st.step]\n +\"(\"+st.blocks.length+\" 块,第 \"+(st.baselineConfirmedAtRound??\"-\")+\" 轮确认)</h3>\"\n +st.blocks.map((b)=>'<div class=\"brow\"><span class=\"k\">'+KIND_CN[b.kind]+'</span><span class=\"bid\">'+esc(b.id)\n +\"</span><span>\"+esc(firstLine(b.content))+\"</span></div>\").join(\"\")+\"</div>\").join(\"\");\n el(\"main\").innerHTML='<div class=\"finhead\"><h2>终审总览——三步基线全部锁定</h2>'\n +'<p>这是完整方案。确认后将生成最终基线并结束对齐;如有问题可点击上方任一已锁定环节回退修改。</p></div>'\n +'<div class=\"finalview\">'+rows+\"</div>\";\n return;\n }\n if(view.status!==\"aligning\"){\n el(\"main\").innerHTML=\"\";\n const banner=el(\"doneBanner\");\n if(view.status===\"completed\"){\n // 完成态(走查 2026-10-03):只读,但可切换环节、切换版本查看。\n banner.style.display=\"\";\n banner.innerHTML='<div class=\"baseline\"><h3>✓ 对齐完成——终审已确认,基线已锁定</h3><p>以下内容只读。可点击环节查看各步详情、切换历史版本;需要留档可在终端执行 <b>/alignment export</b> 导出只读 HTML。实施中改动任一决策须回本插件重新确认。</p></div>';\n const head='<div id=\"pagehead\">'+versionBarHtml()+\"</div>\";\n if(viewingVersion!==null){\n const snap=(view.versions||[]).find((v)=>v.revision===viewingVersion);\n el(\"main\").innerHTML=head+'<div class=\"stephead\"><h2>历史版本 r'+viewingVersion+\"</h2><span class='desc'>只读快照</span></div>\"\n +(snap&&!snap.truncated?snap.blocks.map((b,i)=>blockHtml(b,i,true)).join(\"\"):'<div class=\"empty-hint\">该版本仅存锚点或已不存在。</div>');\n return;\n }\n if(viewingStep!==null){\n const st=view.steps.find((cand)=>cand.step===viewingStep);\n if(!st){viewingStep=null;render();return;}\n el(\"main\").innerHTML=head+'<div class=\"stephead\"><h2>只读查看:'+(STEP_CN[viewingStep]??viewingStep)+'('+st.blocks.length+' 块)</h2><span class=\"desc\">点击上方「总览」返回全部环节。</span></div>'\n +'<div class=\"finalview\"><div class=\"fingrp\">'+st.blocks.map((b,i)=>blockHtml(b,i,true)).join(\"\")+\"</div></div>\";\n return;\n }\n const rows=view.steps.map((st2)=>'<div class=\"fingrp\"><h3>'+(STEP_CN[st2.step]??st2.step)\n +\"(\"+st2.blocks.length+\" 块,第 \"+(st2.baselineConfirmedAtRound??\"-\")+\" 轮确认)</h3>\"\n +'<div class=\"brows\">'+st2.blocks.map((b)=>'<div class=\"brow\"><span class=\"k\">'+KIND_CN[b.kind]\n +'</span><span class=\"bid\">'+esc(b.id)+'</span><span>'+esc(firstLine(b.content))+\"</span></div>\").join(\"\")+\"</div></div>\").join(\"\");\n el(\"main\").innerHTML=head+'<div class=\"stephead\"><h2>全部环节</h2><span class=\"desc\">点击上方环节名可单独查看该步的完整块内容。</span></div>'\n +'<div class=\"finalview\">'+rows+\"</div>\";\n return;\n }\n banner.style.display=\"\";\n banner.innerHTML='<div class=\"baseline\"><h3>对齐已取消</h3><p>现场保留,可在终端查看 /alignment log。</p></div>';\n return;\n }\n el(\"doneBanner\").style.display=\"none\";\n const head='<div id=\"pagehead\">'+versionBarHtml()+\"</div>\";\n if(viewingVersion!==null){\n // 历史版本只读(走查 2026-10-03):无确认/批注/填空入口。\n const snap=(view.versions||[]).find((v)=>v.revision===viewingVersion);\n if(!snap||snap.truncated){\n el(\"main\").innerHTML=head+\"<div class='stephead'><h2>版本 r\"+viewingVersion+\"</h2><span class='desc'>\"\n +(snap?\"该版本超出体积预算,仅保留锚点。\":\"该版本已不存在(可能被滚动淘汰)。\")+\"</span></div>\";\n return;\n }\n const desc=\"历史版本(只读)——确认与批注请返回最新版本。\";\n el(\"main\").innerHTML=head+'<div class=\"stephead\"><h2>'+STEP_CN[snap.step]+\" · r\"+snap.revision+\"</h2><span class='desc'>\"+desc+\"</span></div>\"\n +snap.blocks.map((b,i)=>blockHtml(b,i,true)).join(\"\");\n return;\n }\n // AI 修订中(走查 2026-10-03):内容区换机器人思考效果,顶部进度不动。\n if(view.awaitingRevision){\n el(\"main\").innerHTML=head+botThink(\"AI 正在根据反馈修订……修订版发布后本页自动刷新\");\n return;\n }\n const s=activeStep();\n const desc={objective:\"只对方向:干什么 / 不干什么 / 成功标准。禁止展开实现细节。\",\n detail:\"业务规则、公式、数据流、异常路径。假设必须显式;缺信息挂「待补充」。\",\n design:\"技术选型、模块、接口、文件改动、风险、验收。不得与已锁定基线矛盾。\"}[s.step];\n el(\"main\").innerHTML=head+'<div class=\"stephead\"><h2>'+STEP_CN[s.step]+'</h2><span class=\"desc\">'+desc+\"</span></div>\"\n +s.blocks.map((b,i)=>blockHtml(b,i)).join(\"\");\n}\n\nfunction blockHtml(b,i,readonly){\n if(readonly){\n // 历史版本只读(走查 2026-10-03):无按钮、无输入、批注仅展示。\n return '<article class=\"block '+(b.status===\"approved\"?\"approved\":\"\")+'\" data-kind=\"'+b.kind\n +'\" data-block=\"'+esc(b.id)+'\"><div class=\"top\"><span class=\"badge '+b.kind+'\">'+KIND_CN[b.kind]\n +\"</span>\"+'<span class=\"bid\">'+esc(b.id)+\"</span>\"\n +(b.status===\"approved\"?'<span class=\"skiphint\">已确认</span>':\"\")+\"</div>\"\n +'<div class=\"content\">'+esc(b.content)+\"</div>\"\n +(b.rationale?'<details class=\"meta\"><summary>理由</summary>'+esc(b.rationale)+\"</details>\":\"\")\n +(b.comments||[]).map((c)=>commentHtml(b,c,true)).join(\"\")+\"</article>\";\n }\n const modified=b.modifiedInRound===view.round?'<span class=\"mod\">本轮已修改</span>':\"\";\n return blockHtmlInteractive(b,i,modified);\n}\n\nfunction blockHtmlInteractive(b,i,modified){\n const answered=(b.draftAnswer||\"\").trim()!==\"\";\n const approvedNow=effectiveApproved(b);\n const missingHtml=b.kind===\"missing\"\n ?(b.draftAnswer\n ?'<div class=\"missinginput\"><div class=\"comment resolved\">✓ 已收到你的答案:'+esc(b.draftAnswer)+'(提交后由 AI 并入本块)</div></div>'\n :'<div class=\"missinginput\"><textarea data-answer=\"'+esc(b.id)+'\" placeholder=\"在这里补充你的答案……\">'\n +esc(drafts.answers[b.id]||\"\")+\"</textarea></div>\"):\"\";\n const canApprove=b.kind!==\"missing\"||answered||(drafts.answers[b.id]||\"\").trim()!==\"\";\n const approveHtml=canApprove\n ?'<button class=\"approvebtn\" data-approve=\"'+esc(b.id)+'\">'+(approvedNow?\"已确认\":\"确认\")+\"</button>\"\n :'<span class=\"skiphint\">填写后进入确认</span>';\n const metaHtml=(b.rationale?'<details class=\"meta\"><summary>理由</summary>'+esc(b.rationale)+\"</details>\":\"\")\n +(b.impact?'<details class=\"meta\"><summary>影响范围</summary>'+esc(b.impact.join(\" · \"))+\"</details>\":\"\");\n return '<article class=\"block '+(approvedNow?\"approved\":\"\")+'\" data-kind=\"'+b.kind\n +'\" data-block=\"'+esc(b.id)+'\" style=\"animation-delay:'+Math.min(i*35,280)+'ms\"><div class=\"top\">'\n +'<span class=\"badge '+b.kind+'\">'+KIND_CN[b.kind]+\"</span>\"+'<span class=\"bid\">'+esc(b.id)+\"</span>\"+modified\n +approveHtml+\"</div>\"+'<div class=\"content\" data-content=\"'+esc(b.id)+'\">'+esc(b.content)+\"</div>\"\n +missingHtml+metaHtml+(b.comments||[]).map((c)=>commentHtml(b,c,false)).join(\"\")+\"</article>\";\n}\n\nfunction commentHtml(b,c,readonly){\n if(c.status===\"resolved\"){\n const k={answered:\"已回答\",dismissed:\"已驳回\",incorporated:\"已并入修订\"}[c.resolution.kind];\n return '<div class=\"comment resolved\">✓ '+k+(c.resolution.text?(\":\"+esc(c.resolution.text)):\"\")\n +' — '+(c.author===\"assistant\"?\"AI 疑问\":\"你的批注\")+\": \"+esc((c.note||\"\").slice(0,44))+'</div>';\n }\n if(c.author===\"assistant\"){\n if(readonly)return '<div class=\"comment ai\"><div class=\"who\"><span class=\"avatar ai\">AI</span>AI 疑问</div>'+esc(c.note)+'</div>';\n let body;\n if(drafts.dismissed[c.id])body='<div class=\"draftreply\"><span>你标记了「不重要」(提交后生效)</span><a data-undodismiss=\"'+c.id+'\">撤销</a></div>';\n else if(drafts.revised[c.id])body='<textarea class=\"replybox\" data-reply-input=\"'+c.id+'\" placeholder=\"输入你的回答……\">'\n +esc(drafts.replies[c.id]||\"\")+'</textarea><div class=\"actions\"><button data-reply-save=\"'+c.id+'\">确认回答</button></div>';\n else if(drafts.replies[c.id])body='<div class=\"draftreply\"><span>你的回答:'+esc(drafts.replies[c.id])+'(提交后生效)</span><a data-reply-edit=\"'+c.id+'\">修改</a></div>';\n else body='<div class=\"actions\"><button data-reply=\"'+c.id+'\">回答</button><button data-dismiss=\"'+c.id+'\">不重要</button></div>';\n return '<div class=\"comment ai\"><div class=\"who\"><span class=\"avatar ai\">AI</span>AI 疑问 · 拿不准,需要你裁决</div>'+esc(c.note)+body+'</div>';\n }\n if(readonly)return '<div class=\"comment user\"><div class=\"who\"><span class=\"avatar user\">你</span>你的批注'\n +(c.escalate?\" · 上游问题\":\"\")+'</div>'+(c.quote?'<div class=\"quote\">'+esc(c.quote)+'</div>':\"\")+esc(c.note)+'</div>';\n return '<div class=\"comment user\"><div class=\"who\"><span class=\"avatar user\">你</span>你的批注 · 等待 AI 处理'\n +(c.escalate?\" · 上游问题\":\"\")+'</div>'+(c.quote?'<div class=\"quote\">'+esc(c.quote)+'</div>':\"\")+esc(c.note)+'</div>';\n}\n\nfunction renderDock(){\n const btn=el(\"mainBtn\"),hint=el(\"gateHint\");\n const addbox=document.querySelector(\".addbox\");\n if(!view||view.status!==\"aligning\"&&view.status!==\"finalizing\"){\n // 终态:整个底部操作条隐藏(走查 2026-10-03),对齐结束后页面只读。\n const dock=document.querySelector(\".dock\");\n if(dock)dock.style.display=\"none\";\n return;}\n if(view.status===\"finalizing\"){\n if(addbox)addbox.style.display=\"none\"; // 终审总览无补充输入(走查 2026-10-03)\n btn.textContent=\"确认基线,结束对齐\";btn.className=\"mainbtn confirm\";btn.disabled=false;\n hint.className=\"gatehint ok\";hint.textContent=\"终审总览:查看完整方案后确认;如有问题,点击上方已锁定环节回退。\";return;}\n if(addbox)addbox.style.display=\"\";\n const dockEl=document.querySelector(\".dock\");\n if(dockEl)dockEl.style.display=\"\";\n const n=gatePendingCount(),d=hasDrafts();\n if(n===0&&!d){btn.textContent=view.activeStep===\"design\"?\"确认方案,进入终审总览\":\"确认完成,进入下一步\";\n btn.className=\"mainbtn confirm\";btn.disabled=false;\n hint.className=\"gatehint ok\";hint.textContent=\"门禁三条件满足——全部已确认、批注已清空、无补充。\";return;}\n btn.className=\"mainbtn\";btn.disabled=false;\n if(d){btn.textContent=\"提交本轮反馈\";\n hint.className=\"gatehint\";\n hint.innerHTML=n?(\"已捕获反馈,提交后 AI 修订;尚有 <b>\"+n+\"</b> 处待处理。\"):\"已捕获反馈,提交后 AI 修订并重新等待确认。\";}\n else{btn.textContent=\"定位 \"+n+\" 处待处理\";hint.className=\"gatehint\";\n hint.textContent=\"没有待提交的反馈——点击按钮,页面会指出还有哪里没完成。\";}\n}\n\n// ---------------------------------------------------------------------------\n// interactions\n// ---------------------------------------------------------------------------\ndocument.addEventListener(\"click\",(e)=>{\n const t=e.target;\n // 完成态「总览」tab:返回全部环节分组视图(走查 2026-10-03)。\n if(t.dataset&&t.dataset.viewall){\n viewingStep=null;viewingVersion=null;render();return;\n }\n // 已锁定环节 tab 点击回退(走查 2026-10-03):后续环节作废重走。\n // 完成态环节查看(只读):点击 tab 切换查看该步。\n if(t.dataset&&t.dataset.viewstep){\n viewingStep=t.dataset.viewstep;\n viewingVersion=null;\n render();return;\n }\n if(t.dataset&&t.dataset.retreat){\n const target=t.dataset.retreat;\n askConfirm(\"回退到「\"+STEP_CN[target]+\"」\",\"后面的环节将作废,需要重新确认。\",\"确认回退\",()=>{\n approvals=null;viewingVersion=null;\n postPageAction({action:\"retreat\",baseRevision:view.revision,targetStep:target,approvals:[],comments:[],\n commentReplies:[],answers:[],additions:[],stepConfirmed:false},\"正在回退……\");\n });\n return;\n }\n // 版本切换(走查 2026-10-03):历史版本只读查看。\n if(t.dataset&&t.dataset.viewver){\n viewingVersion=t.dataset.viewver===\"latest\"?null:Number(t.dataset.viewver);\n render();return;\n }\n if(t.dataset&&t.dataset.rollback){\n const targetRevision=Number(t.dataset.rollback);\n askConfirm(\"把当前步回退到版本 r\"+targetRevision,\"当前未确认的修改将丢弃(历史版本中的批注会保留)。\",\"确认回退\",()=>{\n approvals=null;\n postPageAction({action:\"rollback\",baseRevision:view.revision,targetRevision,approvals:[],comments:[],\n commentReplies:[],answers:[],additions:[],stepConfirmed:false},\"正在回退版本……\");\n });\n return;\n }\n if(t.dataset&&t.dataset.approve!==undefined&&t.dataset.approve!==\"\"){toggleApprove(t.dataset.approve);return;}\n if(t.dataset&&t.dataset.reply){drafts.revised[t.dataset.reply]=true;render();return;}\n if(t.dataset&&t.dataset.replyEdit){drafts.revised[t.dataset.replyEdit]=true;render();return;}\n if(t.dataset&&t.dataset.replySave){\n const box=t.closest(\".comment\").querySelector(\".replybox\");\n if(box&&!box.value.trim()){box.focus();return;}\n drafts.replies[t.dataset.replySave]=box.value.trim();delete drafts.revised[t.dataset.replySave];render();return;}\n if(t.dataset&&t.dataset.dismiss){drafts.dismissed[t.dataset.dismiss]=true;render();return;}\n if(t.dataset&&t.dataset.undodismiss){delete drafts.dismissed[t.dataset.undodismiss];render();return;}\n});\ndocument.addEventListener(\"input\",(e)=>{\n const t=e.target;\n if(t.dataset&&t.dataset.answer){drafts.answers[t.dataset.answer]=t.value;renderDock();return;}\n if(t.dataset&&t.dataset.replyInput){drafts.replies[t.dataset.replyInput]=t.value;return;}\n if(t.id===\"additions\"){drafts.additions=t.value;renderDock();}\n});\nfunction toggleApprove(id){\n if(!approvals){\n approvals={};\n for(const b of activeStep().blocks)approvals[b.id]=b.status===\"approved\";\n }\n approvals[id]=!approvals[id];\n render();\n}\n\n// selection annotation (single-block selection only)\nlet selInfo=null,annotGuardUntil=0;\ndocument.addEventListener(\"mouseup\",(e)=>{\n if(e.target.closest&&e.target.closest(\".annotpop\"))return;\n if(e.target.closest&&e.target.closest(\".selbtn\"))return;\n if(Date.now()<annotGuardUntil)return;\n el(\"annotPop\").style.display=\"none\";\n const btn=el(\"selBtn\");\n const sel=window.getSelection();\n if(!sel||sel.isCollapsed){btn.style.display=\"none\";return;}\n const text=sel.toString().trim();\n const range=sel.getRangeAt(0);\n const owner=(range.startContainer.parentElement&&range.startContainer.parentElement.closest)\n ?range.startContainer.parentElement.closest(\".content[data-content]\"):null;\n const ownerEnd=(range.endContainer.parentElement&&range.endContainer.parentElement.closest)\n ?range.endContainer.parentElement.closest(\".content[data-content]\"):null;\n if(!owner||owner!==ownerEnd||!text){btn.style.display=\"none\";return;}\n const rect=range.getBoundingClientRect();\n btn.style.display=\"\";\n btn.className=\"selbtn\";\n btn.style.left=(rect.left+window.scrollX+rect.width/2-46)+\"px\";\n btn.style.top=(rect.top+window.scrollY-40)+\"px\";\n selInfo={blockId:owner.dataset.content,text};\n});\nel(\"selBtn\").addEventListener(\"mousedown\",(e)=>{\n e.preventDefault();\n annotGuardUntil=Date.now()+400;\n const pop=el(\"annotPop\"),btn=el(\"selBtn\");\n el(\"annotQuote\").textContent=\"「\"+(selInfo.text.length>60?selInfo.text.slice(0,60)+\"…\":selInfo.text)+\"」\";\n el(\"annotNote\").value=\"\";el(\"annotEsc\").checked=false;\n pop.style.display=\"\";\n pop.style.left=Math.min(parseFloat(btn.style.left),window.scrollX+window.innerWidth-360)+\"px\";\n pop.style.top=(parseFloat(btn.style.top)+42)+\"px\";\n el(\"annotNote\").focus();\n btn.style.display=\"none\";\n});\nel(\"annotClose\").addEventListener(\"click\",()=>{el(\"annotPop\").style.display=\"none\";window.getSelection().removeAllRanges();});\nel(\"annotGo\").addEventListener(\"click\",()=>{\n const note=el(\"annotNote\").value.trim();\n if(!note){el(\"annotNote\").focus();return;}\n if(!selInfo.pendingComments)selInfo.pendingComments=[];\n selInfo.pendingComments.push({blockId:selInfo.blockId,quote:selInfo.text,note,escalate:el(\"annotEsc\").checked});\n toast(\"批注已暂存(\"+selInfo.pendingComments.length+\" 条)——随本轮反馈一起提交\");\n el(\"annotPop\").style.display=\"none\";window.getSelection().removeAllRanges();\n});\n\n// spotlight: every click replays a full cycle; auto restore ~4.5s or any click\nlet spotSession=0;\nfunction clearSpot(){\n const sec=el(\"main\");\n sec.classList.remove(\"focusing\");\n sec.querySelectorAll(\".block.attention\").forEach((node)=>{node.classList.remove(\"attention\");node.removeAttribute(\"data-reason\");});\n}\nfunction spotlight(msg){\n if(!view||view.status!==\"aligning\")return;\n const items=view.gate.pending;\n if(!items.length){toast(\"当前没有待处理项\");return;}\n const session=++spotSession;\n clearSpot();\n const sec=el(\"main\");\n sec.classList.add(\"focusing\");\n const nodes=items.map((item)=>{\n const node=sec.querySelector('[data-block=\"'+item.blockId+'\"]');\n if(node){\n node.classList.add(\"attention\");\n node.dataset.reason={unapproved:\"未确认\",missing_empty:\"待补充\",\"missing-empty\":\"待补充\",\n assistant_question_open:\"疑问待回应\",\"assistant-question-open\":\"疑问待回应\"}[item.reason]||item.reason;\n }\n return node;\n }).filter(Boolean);\n if(nodes[0])nodes[0].scrollIntoView({behavior:\"smooth\",block:\"center\"});\n toast(msg||(\"还有 \"+nodes.length+\" 处待处理——已为你定位\"));\n const finish=()=>{if(session!==spotSession)return;clearSpot();document.removeEventListener(\"click\",onDoc);};\n const onDoc=(ev)=>{\n if(session!==spotSession){document.removeEventListener(\"click\",onDoc);return;}\n if(ev.target.closest&&ev.target.closest(\"#mainBtn\"))return;\n finish();\n };\n setTimeout(()=>document.addEventListener(\"click\",onDoc),80);\n setTimeout(finish,4500);\n}\n\nlet toastTimer;\nfunction toast(msg){\n const t=el(\"toast\");t.textContent=msg;t.classList.add(\"show\");\n clearTimeout(toastTimer);toastTimer=setTimeout(()=>t.classList.remove(\"show\"),3200);\n}\n\n// ---------------------------------------------------------------------------\n// submit\n// ---------------------------------------------------------------------------\nel(\"mainBtn\").addEventListener(\"click\",async()=>{\n if(!view)return;\n if(view.status===\"finalizing\"){\n // 终审确认(走查 2026-10-03):唯一 completed 路径;文件留档走 /alignment export。\n return postPageAction({action:\"feedback\",baseRevision:view.revision,approvals:[],comments:[],\n commentReplies:[],answers:[],additions:[],stepConfirmed:true},\"正在提交终审确认……\");\n }\n if(view.status!==\"aligning\")return;\n const n=gatePendingCount(),d=hasDrafts();\n if(n===0&&!d){return submitRound(true);}\n if(d){\n // Pure approval diffs with a locally green gate confirm the step in the\n // same round (approvals mirror + stepConfirmed); any content feedback\n // goes as a plain revision round.\n return submitRound(n===0&&!hasContentDrafts());\n }\n spotlight();\n});\n\nasync function postPageAction(payload,submittingText){\n if(submitting)return;\n submitting=true;\n el(\"mainBtn\").disabled=true;\n if(submittingText)el(\"main\").innerHTML='<div class=\"reviving\">'+submittingText+\"</div>\";\n try{\n const res=await fetch(\"round\",{method:\"POST\",headers:{\"content-type\":\"application/json\"},body:JSON.stringify(payload)});\n const out=await res.json().catch(()=>({}));\n if(!res.ok){\n if(out&&out.code===\"stale-state\"){toast(\"页面快照已过期——正在刷新,请重试\");approvals=null;}\n else toast(\"提交失败:\"+((out&&out.error)||res.status));\n }\n }catch(e){toast(\"提交失败:网络错误,请重试\");submitting=false;render();return;}\n submitting=false;\n await refresh();\n}\n\nasync function submitRound(confirmStep){\n if(submitting)return;\n submitting=true;\n el(\"mainBtn\").disabled=true;\n const s=activeStep();\n const approvalsSet={};\n for(const b of s.blocks){\n const locallyToggled=approvals&&Object.prototype.hasOwnProperty.call(approvals,b.id);\n approvalsSet[b.id]=locallyToggled?approvals[b.id]:(b.status===\"approved\");\n }\n const body={\n baseRevision:view.revision,\n approvals:Object.keys(approvalsSet).filter((id)=>approvalsSet[id]),\n comments:(selInfo&&selInfo.pendingComments)||[],\n commentReplies:[],\n answers:[],\n additions:drafts.additions.trim()?[drafts.additions.trim()]:[],\n stepConfirmed:!!confirmStep,\n };\n for(const b of s.blocks){\n if(b.kind===\"missing\"&&!b.draftAnswer&&(drafts.answers[b.id]||\"\").trim())\n body.answers.push({blockId:b.id,value:drafts.answers[b.id].trim()});\n for(const c of b.comments){\n if(c.status!==\"open\"||c.author!==\"assistant\")continue;\n if(drafts.dismissed[c.id])body.commentReplies.push({commentId:c.id,blockId:b.id,dismiss:true});\n else if(drafts.replies[c.id])body.commentReplies.push({commentId:c.id,blockId:b.id,answer:drafts.replies[c.id]});\n }\n }\n el(\"main\").innerHTML='<div class=\"reviving\">正在提交第 '+view.round+' 轮反馈……</div>';\n try{\n const res=await fetch(\"round\",{method:\"POST\",headers:{\"content-type\":\"application/json\"},body:JSON.stringify(body)});\n const payload=await res.json().catch(()=>({}));\n if(!res.ok){\n if(payload&&payload.code===\"stale-state\"){toast(\"页面快照已过期——正在刷新,请基于新版重提\");approvals=null;}\n else toast(\"提交失败:\"+((payload&&payload.error)||res.status));\n }else{\n drafts={answers:{},replies:{},dismissed:{},additions:\"\",revised:{}};\n el(\"additions\").value=\"\";\n if(selInfo)selInfo.pendingComments=[];\n approvals=null;\n toast(payload&&payload.stepConfirmed?\"本步基线已锁定——进入下一步\":\"反馈已送达会话,AI 修订中\");\n }\n }catch(e){toast(\"提交失败:网络错误,请重试\");}\n submitting=false;\n view=null;\n await refresh();\n if(view&&view.status===\"aligning\"&&gatePendingCount()>0)spotlight(\"还有 \"+gatePendingCount()+\" 处待处理——已为你定位\");\n}\n\nel(\"additions\").addEventListener(\"input\",(e)=>{drafts.additions=e.target.value;});\nsetInterval(()=>{void refresh();},2000);\nvoid refresh();\n`;\n\n/** The fixed page template: no state, no model input — only the two endpoints above. */\nexport function renderAlignmentPage(): string {\n\treturn `<!DOCTYPE html>\n<html lang=\"zh-CN\">\n<head>\n<meta charset=\"UTF-8\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"color-scheme\" content=\"light\">\n<title>需求对齐 · Alignment</title>\n<style>${CSS}</style>\n</head>\n<body>\n<div class=\"blob b1\"></div><div class=\"blob b2\"></div><div class=\"blob b3\"></div>\n<div id=\"offline\" class=\"offline\" style=\"display:none\"></div>\n<div class=\"wrap\">\n <header class=\"task\">\n <span class=\"eyebrow\">需求对齐</span>\n <h1 id=\"title\">需求对齐</h1>\n <div class=\"meta\" id=\"meta\"></div>\n <div class=\"steps\" id=\"steps\"></div>\n </header>\n <div id=\"doneBanner\" style=\"display:none\"></div>\n <div class=\"cols\">\n <section id=\"main\"><div class=\"botwrap\"><div class=\"botcard\"><div class=\"bot\"><div class=\"antenna\"></div><div class=\"face\"><span class=\"eye\"></span><span class=\"eye\"></span></div></div><div class=\"thinkdots\"><span></span><span></span><span></span></div><div class=\"bottext\">正在加载对齐状态……</div></div></div></section>\n <aside class=\"locked\" id=\"locked\" style=\"display:none\"></aside>\n </div>\n</div>\n<footer class=\"dock\">\n <div class=\"inner\">\n <div class=\"addbox\">\n <label>补充——想到什么直接写,AI 会结构化为新块,再经你确认</label>\n <textarea id=\"additions\" placeholder=\"例如:对了,退款要支持退运费……\"></textarea>\n </div>\n <button class=\"mainbtn\" id=\"mainBtn\" disabled>连接中</button>\n </div>\n <div class=\"gatehint\" id=\"gateHint\"></div>\n</footer>\n<button id=\"selBtn\" style=\"display:none\">批注此段</button>\n<div class=\"annotpop\" id=\"annotPop\" style=\"display:none\">\n <div class=\"sel\" id=\"annotQuote\"></div>\n <textarea id=\"annotNote\" placeholder=\"这段有问题——指出哪里不对、你期望什么……\"></textarea>\n <label class=\"esc\"><input type=\"checkbox\" id=\"annotEsc\"> 这是上游步骤的问题(触发回退评估)</label>\n <div class=\"row\"><button id=\"annotClose\">取消</button><button id=\"annotGo\" class=\"go\">挂到该块</button></div>\n</div>\n<div id=\"toast\"></div>\n<script>\n${SCRIPT}\n</script>\n</body>\n</html>`;\n}\n"]}
|