From d7dbdba4e2a9fb88d42f158039a9203e2f2b4434 Mon Sep 17 00:00:00 2001 From: avabbbb <89175608+avabbbb@users.noreply.github.com> Date: Wed, 23 Sep 2026 00:19:57 +0800 Subject: [PATCH 01/36] docs(product): establish current product north star --- docs/product/current-product.md | 239 ++++++++++++++++++++++++++++++++ 1 file changed, 239 insertions(+) create mode 100644 docs/product/current-product.md diff --git a/docs/product/current-product.md b/docs/product/current-product.md new file mode 100644 index 00000000..5583c834 --- /dev/null +++ b/docs/product/current-product.md @@ -0,0 +1,239 @@ + +# OfferU Current Product North Star + +Status: **CURRENT PRODUCT AUTHORITY** +Updated: 2026-09-23 + +This document defines the current product shape of OfferU. Historical audits, dated implementation plans and superseded Harness-specific designs must not override it. + +## Product promise + +OfferU is a **local-first AI Career OS** for normal job seekers. + +It should reduce both: + +1. **setup burden** — users should not need Python, Node, Git, MCP, CLI, model IDs or provider configuration to start; +2. **decision burden** — users should not need to know which feature, mode, Skill or Agent command to invoke next. + +The default experience is: + +~~~ +Install +→ Find my local AI automatically +→ Resume + explicitly authorized AI memory → Profile +→ Save a real job from the browser +→ Connect a job-search inbox +→ Today tells me the next best actions +→ Agent prepares / analyzes / drafts +→ User confirms important facts and irreversible actions +→ outcomes feed back into Profile and future decisions +~~~ + +## Product information architecture + +The stable top-level product model is: + +~~~ +Today +Pipeline +Job / Opportunity +Profile +~~~ + +- **Today** is the guided action layer. It answers “what matters now?” and shows at most a few primary actions. +- **Pipeline** projects application state, timeline and next action from the same canonical events. +- **Job** contains role understanding, evidence gaps, resume/application material and interview preparation for one opportunity. +- **Profile** is the long-lived evidence-backed model of the user. Memory is an evolution mechanism for Profile, not a separate silo. + +Agent, Skills, Email, Browser Capture, Resume, Role Intelligence and Interview are capabilities across these surfaces, not competing top-level products. + +## Reasoning authority: external-first, not external-only + +OfferU prefers a **verified local Agent already owned by the user** — for example Codex, WorkBuddy/CodeBuddy, Claude Code, OpenCode, OMP, Pi or another supported host. + +OfferU should: + +- discover supported local hosts; +- use their native login, model configuration and account where possible; +- avoid asking normal users to duplicate API keys; +- project the OfferU Skill and the smallest relevant tool surface; +- preserve the host's native session/model lifecycle when that host is acting as the reasoning engine. + +A built-in OfferU Agent is allowed as a **fallback** when no suitable external host is available or when the user explicitly chooses it. + +Exactly one reasoning authority is active for a given Agent Run. External and built-in Agents share the same truth, capability, confirmation and audit boundaries. + +~~~ +Reasoning authority + external local Agent (preferred) + OR OfferU fallback Agent + ↓ +OfferU Skill + optional third-party Career Skills + ↓ +Operation Registry + ↓ +Career Runtime + ↓ +Local Career Truth +~~~ + +No Agent owns Career Truth and no Agent may approve its own protected mutation. + +## Agent Skills ecosystem + +OfferU participates in the open Agent Skills ecosystem instead of reimplementing every career methodology. + +The host may compose: + +~~~ +OfferU Skill ++ resume / recruiting / interview / negotiation / career-coaching Skills +~~~ + +The division of responsibility is strict: + +- third-party Skills may provide methodology, analysis, critique, coaching and drafting; +- OfferU provides canonical Profile / Evidence / Job / Application / Interview context; +- third-party Skill output enters OfferU as analysis, draft or candidate material; +- persistent state changes still use the Operation Registry and normal review boundary; +- third-party Skills cannot auto-submit, send messages, expose secrets, write the database directly or promote inference into verified career facts. + +OfferU does not need to scan or execute arbitrary Skill folders itself just to gain composability. Prefer the Agent host's native Skill discovery; any future OfferU Skill Inventory should be metadata-only by default and explicitly permissioned. + +References: +- https://agentskills.io/ +- https://www.anthropic.com/engineering/equipping-agents-for-the-real-world-with-agent-skills + +## Guided interaction + +The default mode is **Guided**. + +OfferU should observe canonical Career State and recommend the **Next Best Action** instead of presenting an empty dashboard or a menu of Agent modes. + +Rules: + +1. show at most three primary actions; +2. explain **why now**; +3. do not ask for information OfferU already knows; +4. ask one progressive-profile question only when it improves a current decision; +5. after an action completes, recalculate the next actions; +6. advanced Agent/Skill/CLI controls remain available but are not required for normal use. + +Power users may still use direct Agent chat, Skills, CLI and batch workflows. + +## Progressive Profile + +Do not front-load a giant onboarding form. + +T0 should require only enough information to create value, primarily a resume/core experience and target direction. Later, OfferU asks small contextual questions when they unlock a real decision. + +New information follows provenance rules: + +~~~ +Resume / User statement / authorized Agent memory / Email / Interview +→ observation or candidate +→ review / evidence gate +→ verified Profile state when appropriate +~~~ + +Authorized local-Agent memory is useful input, but it is not automatically Career Truth. + +## Job capture + +The default beginner flow is user-triggered current-page capture: + +~~~ +User opens a job page +→ browser extension reads the active page after explicit user action +→ preview / dedupe +→ Save to OfferU +~~~ + +This is not background crawling and not an application event. + +BOSS CLI, scraper adapters or other source connectors may exist for research, testing or advanced user workflows, but they are not the default consumer acquisition path and must not weaken platform, privacy or anti-automation boundaries. + +## Application assistance + +OfferU may help prepare and fill an application, but the normal safety boundary remains: + +~~~ +OfferU prepares +→ user reviews +→ safe fields may be filled after confirmation +→ user performs the final external submit +→ OfferU may capture a receipt candidate afterward +~~~ + +No silent final submit. + +## Progress sync + +Email and other authorized channels are evidence sources, not direct Pipeline writers. + +~~~ +Email / authorized signal +→ classify + associate +→ ApplicationProgressCandidate +→ user/policy review +→ ApplicationStageEvent +→ Pipeline / Today update +~~~ + +Background analysis may be proactive. Canonical stage changes must remain explainable and auditable. + +## Authority model + +~~~ +Reasoning = active Agent +Execution / capability = Operation Registry +Truth = Career Runtime +High-risk approval = User / explicit product policy +~~~ + +All product surfaces converge on those authorities. + +## Current implementation direction + +Recently landed on main: + +- Assisted Apply / ApplicationActionConnector foundation (#14); +- Tool Surface V2 separating the governed Operation Registry from the model-facing tool catalog (#17); +- Guided Today actions and composable local career-Skill contract (#19). + +Current active validation work: + +- real OMP/RPC Agent Eval (#16, still draft/open). + +The previous zero-setup proposal (#18) is incorporated into this North Star; this document is the current product authority. + +## Non-goals + +Do not reintroduce these as defaults: + +- Harness UI as the mandatory primary product shell; +- a DSH-first or Codex-only product architecture; +- a second Career Truth store; +- an Agent-specific database write path; +- a giant all-Operations tool catalog; +- duplicate provider/API-key setup when a local Agent already has working auth; +- background job crawling as the beginner job-capture path; +- silent application submission or recruiter messaging; +- a long command/mode menu as the beginner UX; +- treating historical eval/audit numbers as current capability truth. + +## Success test + +A new user should be able to understand OfferU without knowing what a Harness, MCP server, Operation Registry or provider is. + +The product is succeeding when the user experiences: + +~~~ +OfferU knows my current career state +→ tells me what matters next +→ uses the AI I already have +→ safely composes the Skills I already have +→ prepares work proactively +→ asks me only for decisions that genuinely require me +→ learns from confirmed outcomes +~~~ From 7f2162162f3c7bb7f7f61781f606a831f4270591 Mon Sep 17 00:00:00 2001 From: avabbbb <89175608+avabbbb@users.noreply.github.com> Date: Wed, 23 Sep 2026 00:20:27 +0800 Subject: [PATCH 02/36] docs: make authority and history explicit --- docs/README.md | 165 ++++++++++++++++++++++++++----------------------- 1 file changed, 87 insertions(+), 78 deletions(-) diff --git a/docs/README.md b/docs/README.md index ec700b77..9b3ef9ea 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,91 +1,100 @@ -# OfferU 文档导航 -OfferU 只维护一套现行设计。领域含义、架构决策、目标设计、当前代码和运行证据分层管理,避免旧计划被误读成已完成能力。 +# OfferU Documentation -## 事实优先级 +Status: **CURRENT NAVIGATION AUTHORITY** +Updated: 2026-09-23 -```text +OfferU has accumulated design documents, audits, eval reports and implementation snapshots across several architecture generations. This page defines which documents are authoritative **now**. + +## Current authority order + +When documents disagree, use this order: + +~~~ +GOAL.md + release goal and durable product constraints + ↓ +docs/product/current-product.md + current product North Star and interaction model + ↓ CONTEXT.md - 领域词汇与产品不变量 + current domain language and invariants ↓ docs/adr/README.md - 已接受与已取代的架构决策 + accepted decisions and explicit supersession history ↓ -10 份主题设计 - 目标模块、协议、交互和迁移顺序 +ARCHITECTURE.md + current architecture topic docs ↓ -实时 CLI manifest / Operation Registry - 当前代码真正暴露的能力 +live code / Operation Registry / Host Registry / generated Skill projections ↓ -版本化 Eval + 有效报告 - 当前版本真正通过的行为 -``` +current Eval evidence +~~~ -发生冲突时: +Historical audits and dated reports are evidence of what was true when they were produced. They do **not** override current product or architecture authority. -- 领域含义以 [`CONTEXT.md`](../CONTEXT.md) 为准; -- 架构取舍以[决策账本](./adr/README.md)中最新 accepted 条目为准; -- 动态参数与能力以实时 Registry 和 capability probe 为准; -- “已可用”“可内测”“支持某 Harness”等结论只能由当前有效 Eval 证明。 +## Start here -## 10 份活跃设计 - -| # | 文档 | 唯一职责 | +| Area | Current document | Purpose | | --- | --- | --- | -| 1 | [Agent 系统总览](./architecture/agent-system.md) | 全局拓扑、事实源、主控权与迁移状态 | -| 2 | [Agent 操作控制面](./architecture/agent-control-plane.md) | OfferU 内部深模块、接口与责任边界 | -| 3 | [Agent Bridge 协议](./architecture/agent-bridge-protocol.md) | CLI-first stdio JSONL、消息与错误契约 | -| 4 | [Harness 接入](./architecture/harness-integrations.md) | Codex、Claude Code、OpenCode、Pi 的 adapter 与一致性门 | -| 5 | [Operation 与安全](./architecture/operation-security.md) | 授权、确认、隔离、事实门与失败策略 | -| 6 | [Run 生命周期](./architecture/run-lifecycle.md) | Task/Run/Session、事件、恢复、中断与交接 | -| 7 | [工作台交互](./architecture/workbench-interaction.md) | Harness 原生界面、控制栏与用户确认 | -| 8 | [浏览器扩展](./architecture/browser-extension.md) | 岗位采集、安全填表与回执候选 | -| 9 | [SiteRulePack v1](./architecture/site-rule-pack-v1.md) | 浏览器站点规则的机器契约 | -| 10 | [迁移路线](./implementation/migration-roadmap.md) | 从 Pi 内置主 Agent 到外部 Harness 的纵向切片 | - -辅助事实源不计入 10 份设计: - -- [决策账本](./adr/README.md):ADR 编号、结论与取代关系; -- [工程协作规则](./agents/domain.md):Issue、triage 与领域文档规范; -- [Eval 手册](./evals/README.md):验收方法、套件与报告格式; -- [视觉 Design DNA](./design/offeru-design-dna.json):机器可读视觉令牌。 - -## 当前目标与实现状态 - -已接受的目标架构是: - -- 外部 Coding Agent Harness 持有唯一主控 Loop; -- OfferU 是本地确定性操作台与控制面; -- 业务接入 CLI-first,不提供 MCP 业务入口; -- Codex 优先,采用官方 App Server 边界; -- Claude Code、OpenCode 与 Pi 通过同一行为契约后再声明支持。 - -这不是完成度声明。当前代码仍含 Pi Worker 主路径、Pi 命名 API、旧 CLI `confirm` 和其他迁移期入口。新 Bridge 与 Codex adapter 尚未通过纵向切片验收,实际差距以[迁移路线](./implementation/migration-roadmap.md)为准。 - -## 文档生命周期 - -Git 历史就是归档;仓库内不再维护 `docs/archive`。 - -1. 新领域词汇或不变量直接更新 `CONTEXT.md`。 -2. 难以逆转的决策追加到 `docs/adr/README.md`,不再新建独立 ADR 文件。 -3. 现行架构细节更新对应主题页,不创建日期化“新版设计”。 -4. 当前实施顺序只更新 `migration-roadmap.md`;完成后去掉操作噪音,保留验收门。 -5. 一次性研究、审计、会议记录和被取代计划在提炼有效结论后删除。 -6. Eval 目录只保留可复现 suite、报告契约和仍能证明当前 commit 的正式报告。 -7. 新活跃设计必须说明为什么不能并入现有 10 个主题,否则不创建。 - -删除旧文档前,将仍有效的领域词汇写入 `CONTEXT.md`、长期决策写入 ADR 账本、验收规则写入 Eval。删除只移除重复表述,不删除事实源。 - -## 常用只读入口 - -在 `backend` 目录读取当前实现表面: - -```powershell -.\.venv312\Scripts\python.exe -m app.cli doctor --pretty -.\.venv312\Scripts\python.exe -m app.cli manifest --pretty -.\.venv312\Scripts\python.exe -m app.cli ops --pretty -.\.venv312\Scripts\python.exe -m app.cli schema --pretty -.\.venv312\Scripts\python.exe -m app.cli run agent_playbook --arg detail=full --pretty -``` - -这些命令描述的是迁移中的当前代码。目标 Bridge 命令与兼容规则以 [Agent Bridge 协议](./architecture/agent-bridge-protocol.md)为准。 +| Product | [Current Product North Star](./product/current-product.md) | Zero-setup, Guided UX, external-first Agent, fallback Agent, Skills ecosystem, browser/email journeys | +| Goal | [GOAL.md](../GOAL.md) | Public-release goal and durable release gates | +| Domain | [CONTEXT.md](../CONTEXT.md) | Career Truth, candidates, evidence, applications, memory and Agent vocabulary | +| Architecture | [ARCHITECTURE.md](../ARCHITECTURE.md) | Short current system boundary | +| Agent | [Agent system](./architecture/agent-system.md) | Agent hosts, Skills, tool surface, Registry and runtime responsibilities | +| Integrations | [Agent host integrations](./architecture/harness-integrations.md) | Local-host discovery, auth ownership and runtime capability contract | +| UX | [Workbench interaction](./architecture/workbench-interaction.md) | Guided Today, progressive onboarding and Power mode | +| Security | [Operation security](./architecture/operation-security.md) | permissions, proposals, confirmation and failure rules | +| Browser | [Browser extension](./architecture/browser-extension.md) | user-triggered job capture and safe Smart Fill | +| Tool surface | [Tool Surface V2](./architecture/2026-09-22-tool-surface-v2.md) | Registry vs Agent Tool Surface vs Active Skill Surface | +| Eval | [Live Eval](./evals/LIVE_EVAL.md) | current Agent eval contract and execution model | +| Status | [STATUS.md](../STATUS.md) | current implementation state and blockers | +| Handoff | [HANDOFF.md](../HANDOFF.md) | latest continuation context for Coding Agents | + +## Document status classes + +- **CURRENT AUTHORITY** — actively defines current product/architecture. +- **CURRENT EVIDENCE** — current reproducible validation or status; does not define product direction. +- **HISTORICAL SNAPSHOT** — accurate for a dated commit/experiment; not a current spec. +- **SUPERSEDED** — retained only because the decision history is useful. +- **PROPOSAL** — not accepted until promoted by the appropriate authority. + +A date in a filename is a strong signal that the file may be a snapshot rather than timeless authority. + +## Historical material + +Treat these as historical unless a current authority page explicitly adopts their conclusion: + +- docs/archive/**; +- docs/evals/reports/**; +- dated operation inventories and audit reports; +- old provider-specific or DSH-specific implementation plans; +- old release scorecards tied to an earlier commit; +- deprecated Main-Agent/Pi architecture notes. + +Do not rewrite old eval numbers to make them look current. Preserve the result and mark its scope. + +## Rules for future docs + +1. Prefer updating an existing current authority page over adding another dated “vNext design”. +2. New long-lived architecture decisions go into docs/adr/README.md with explicit supersession. +3. Product interaction changes update docs/product/current-product.md. +4. Dynamic capability counts come from live Registry/Host/Skill code, not hand-maintained prose. +5. Eval reports state the commit/runtime/model and remain evidence, not architecture. +6. A new Coding Agent should be able to identify current authority without reading historical reports. +7. If a document is kept only for archaeology, move it under docs/archive/ or add a clear historical header. + +## Current product summary + +~~~ +OfferU Desktop = primary Career OS experience +External local Agent = preferred reasoning host +Built-in OfferU Agent = fallback +Agent Skills = composable methodology layer +Operation Registry = execution / permission authority +Career Runtime = canonical truth +Today = guided next-best-action layer +Browser = user-triggered job capture / safe fill +Email = evidence → candidate → reviewed stage event +~~~ + +See [Current Product North Star](./product/current-product.md) for the complete product contract. From ed40c3d9ba250b55017da43326eda82f2fe4efbb Mon Sep 17 00:00:00 2001 From: avabbbb <89175608+avabbbb@users.noreply.github.com> Date: Wed, 23 Sep 2026 00:20:30 +0800 Subject: [PATCH 03/36] docs(architecture): align with current Career OS model --- ARCHITECTURE.md | 151 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 103 insertions(+), 48 deletions(-) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 7d825690..e1b1f487 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -1,70 +1,125 @@ -# OfferU 架构边界 - -```text -TypeScript React UI / Client Interaction - │ typed HTTP API - ▼ -Python FastAPI Career Runtime - Profile · Job · Application · Artifact - Event · Candidate · CareerTask - │ Operation Registry - ▼ -External Agent Runtime - Pi · Replay · Codex · DSH adapter - -Tauri / Rust = desktop shell and process lifecycle only -``` + +# OfferU Architecture + +Status: **CURRENT ARCHITECTURE AUTHORITY** +Updated: 2026-09-23 + +OfferU is a local-first Career OS. The desktop product is the primary user experience; local Agents are replaceable reasoning engines attached to the same deterministic career control plane. + +## System boundary + +~~~ + OfferU Desktop + Today · Pipeline · Job · Profile + │ + guided intent / user action + │ + ┌──────────┴──────────┐ + │ │ + External local Agent OfferU fallback Agent + (preferred) (optional) + │ │ + └──────────┬──────────┘ + │ + OfferU Skill + optional Career Skills + │ + Agent Tool Surface + │ + Operation Registry + schema · permission · proposal + idempotency · audit + │ + Career Runtime + Profile · Job · Application · Resume + Interview · Evidence · Events · Memory + │ + local SQLite / files +~~~ + +Browser capture, email sync, automation and direct human UI actions join the same control plane; they do not maintain parallel business truth. + +## Four authorities + +- **Reasoning authority** — exactly one active Agent per Agent Run. Prefer a verified local Agent already owned by the user; OfferU may provide a fallback. +- **Execution authority** — the Operation Registry controls governed capabilities, validation, side effects, proposals, idempotency and audit. +- **Truth authority** — the Python Career Runtime owns persistent career state. +- **High-risk approval authority** — the user or an explicit deterministic product policy. An Agent cannot approve its own protected mutation. + +## Agent hosts and Skills + +Agent hosts may be Codex, WorkBuddy/CodeBuddy, Claude Code, OpenCode, OMP, Pi, Gemini or future compatible hosts. + +OfferU detects host capability from code/probes rather than assuming parity. A host may be a Skill host, a hosted runtime/executor, both, unavailable or only partially compatible. + +When the host supports Agent Skills, OfferU projects its Skill and allows composition with installed resume/recruiting/interview/career Skills. Third-party Skills provide methodology; OfferU remains the state and side-effect authority. + +## Tool surface + +The broad Operation Registry is **not** the model-facing tool list. + +~~~ +Operation Registry + └─ Agent Tool Surface + └─ Active Skill Surface +~~~ + +Agents discover compact Skill metadata first and load the relevant operation schemas on demand. Developer/audit paths may expose the full Registry, but beginner Agent flows should not. + +See [Tool Surface V2](./docs/architecture/2026-09-22-tool-surface-v2.md). ## Truth flow -```text +~~~ Observe ↓ -Event / Candidate +Event / Evidence / Candidate ↓ -Career Runtime understands state +Career Runtime validates / associates ↓ -CareerTask plans work +Agent or deterministic policy recommends next action ↓ -Operation executes or proposes +Operation executes or creates Proposal ↓ -verified state / artifact is committed +review / confirmation when required ↓ -Today and Pipeline project the same state -``` - -Agent 负责 reasoning、planning、tool selection 和研究编排;不能直接拥有职业事实。Operation Registry 负责 capability、权限、dry-run、确认和审计。Python Domain Runtime 是 Career Truth 的唯一来源。自然语言“我已更新”不是成功证明,只有成功提交的 Operation 才能改变正式状态。 +verified state / artifact + ↓ +Today / Pipeline / Job / Profile re-project the same truth +~~~ -## 领域对象 +Natural-language “done” is never the proof of completion. -优先围绕 `Profile`、`Job`、`Application`、`Artifact`、`Event`、`Candidate`、`CareerTask` 表达需求。Today、Pipeline 和 Agent UI 是 projection 或执行界面,不复制同一业务状态。 +## Browser and email -## Resume Workspace +Default job acquisition is explicit current-page capture. Smart Fill may assist safe fields after review but never silently submits an application. -岗位简历工作区复用现有 `Resume`、`ResumeSection`、`ResumeOptimizationProposal` 和 `ResumeVersion`,不创建平行的文档状态: +Email and other authorized channels create evidence/signals and reviewable progress candidates. They do not directly overwrite Pipeline state. -```text -Career Evidence / Profile - ↓ -Master Resume - ↓ source_resume_id + target_job_id -Job Tailored Resume - ↓ -Application Packet projection -``` +## Built-in runtime code -编辑器、实时预览和 PDF 都读取同一份结构化 Resume 内容。AI 只生成 Proposal;逐条接受/拒绝、手动编辑、排序、可见性和模板修改都通过 Resume Operation Registry。`workspace_snapshot_hash` 用于阻止过期 Proposal 覆盖用户最新修改,`ResumeVersion` 保存可回看的岗位版本与来源。 +Legacy/internal runtime workers may remain for fallback, replay, compatibility or bounded executor use. Their existence does not make them the Career Truth owner or the mandatory product shell. -OfferU 不创建 `ResumeAgent`。岗位简历准备是 `CareerTask`,由现有 Agent Runtime 选择受控 Operation 执行。Job Detail 是进入 Workspace 的主要入口,Today / Pipeline 只投影同一 Application、Event 和 Packet 状态。 +## Stable technology boundary -## 自动化 +~~~ +React / TypeScript = product UI +Python / FastAPI = Career Runtime + Operation Registry + deterministic policy +Tauri / Rust = desktop shell, lifecycle, installer and OS integration +Agent hosts/runtimes = replaceable reasoning/execution engines +SQLite = local career data +~~~ -```text -Event → Rule → CareerTask → Agent / deterministic runtime → Operation -``` +Do not introduce a second business backend or duplicate Career Truth to match an Agent framework. -低风险读取、研究、计算和候选生成可以自动执行;正式 Career Truth 变更仍经过事实门和用户确认;外部不可逆动作始终需要明确用户操作。 +## Safety invariants -## Provider 与数据来源 +- Agent output is candidate/draft until accepted through the correct path. +- Important state mutations are reviewable and auditable. +- External irreversible actions remain user-controlled. +- No Agent may self-confirm a protected proposal. +- Credentials do not enter Agent context. +- Provider/host failures are explicit. +- Browser/email integrations cannot create hidden business state. +- Historical eval or fixture success cannot be presented as current live capability. -Replay/Fixture 是显式的合成数据模式,必须在 UI 和产物中标记,不能冒充实时市场数据。Live Provider 失败时保留失败或 blocked 状态,允许用户改用 Fixture 验证本地产品链,但不能静默降级成成功。 +Current product interaction authority: [Current Product North Star](./docs/product/current-product.md). From 12bfce8f8f88d43e895e01a6c56c15ea314d4d55 Mon Sep 17 00:00:00 2001 From: avabbbb <89175608+avabbbb@users.noreply.github.com> Date: Wed, 23 Sep 2026 00:21:30 +0800 Subject: [PATCH 04/36] docs(archive): preserve superseded design history --- .../adr-history-pre-2026-09-23.md | 474 ++++++++++++++++++ 1 file changed, 474 insertions(+) create mode 100644 docs/archive/architecture/adr-history-pre-2026-09-23.md diff --git a/docs/archive/architecture/adr-history-pre-2026-09-23.md b/docs/archive/architecture/adr-history-pre-2026-09-23.md new file mode 100644 index 00000000..989f3dad --- /dev/null +++ b/docs/archive/architecture/adr-history-pre-2026-09-23.md @@ -0,0 +1,474 @@ +> **HISTORICAL SNAPSHOT** — archived from `docs/adr/README.md` on 2026-09-23. It does not define current product or architecture authority. See `docs/product/current-product.md`, `CONTEXT.md`, and `ARCHITECTURE.md`. + +# OfferU 决策账本 + +本文件是 OfferU 架构决策的唯一现行账本。ADR 编号保持稳定,其他文档只链接本文件中的编号锚点;后续决策直接追加到这里,不再为每个 ADR 新建文件。 + +- `accepted`:当前必须遵守。 +- `accepted, narrowed`:决策仍有效,但适用范围已被后续决策收窄。 +- `superseded`:仅保留历史关系,不再作为实现依据。 +- 已提交过的旧 ADR 详细讨论、旧措辞和被拒方案可从 Git 历史恢复;本次整合新增的 ADR-0051–0054 以本账本为首个事实记录。本账本只保留足以指导实现与评审的现行结论。 + +## 产品边界与基础设施 + + +### ADR-0021 — Python 是第一阶段唯一业务后端 + +`Status: accepted` + +Python/FastAPI 是 Agent、记忆、简历、调研、投递、邮箱和面试领域逻辑的唯一事实源。Tauri/Rust 只承担桌面壳、托盘、钥匙串和进程管理等系统桥接;除非有可测量收益,不复制业务能力到第二后端。 + + +### ADR-0023 — 第一阶段只建设本地单人版 + +`Status: accepted; supersedes ADR-0001` + +系统只有一个本地拥有者和一份本地数据空间,不引入 `workspace_id`、租户、组织、登录、计费或 SaaS 预埋层。未来若出现真实 SaaS 需求,再按届时的身份、同步和隔离目标重新设计。 + + +### ADR-0020 — 连接密钥只存操作系统钥匙串 + +`Status: accepted` + +OAuth token、邮箱应用密码和后续连接密钥由 Windows Credential Manager、macOS Keychain 或 Linux Secret Service 保存。数据库只存账号元数据、授权范围和不透明凭据引用;原始密钥不得进入 SQLite、配置、日志、遥测或 Agent 上下文。 + + +### ADR-0024 — 本地敏感数据与旁路副本统一静态加密 + +`Status: accepted` + +由操作系统钥匙串保护主密钥,并统一加密数据库、简历附件、显式保存的邮件正文、搜索索引、缓存和备份。不得产生落在该保护边界外的索引、临时文件、日志或备份副本。 + + +### ADR-0026 — 云端模型按供应商和数据类别授权 + +`Status: accepted` + +确定性解析与脱敏优先在本地完成。敏感材料只有在使用者对具体模型供应商和数据类别明确授权后才可发送;配置 API Key 不等于数据授权,授权撤回后相关任务必须失败关闭。 + + +### ADR-0047 — Tauri 前端使用 Vite 静态 SPA + +`Status: accepted` + +桌面前端使用 React 18、Vite 与 HashRouter;开发模式固定由 7410 端口提供,发布模式由 Tauri 加载 `frontend/dist`。业务事实仍归 Python 后端,前端不依赖 Node.js 服务端运行时。 + +## 职业事实、学习与记忆 + + +### ADR-0048 — 以条目级变更账本演进职业模型 + +`Status: accepted; supersedes ADR-0002 and narrows ADR-0011` + +单一长期职业模型由仍有效的变更条目派生,针对岗位只生成投影,不改写主模型。职业证据必须确认;使用者明确陈述的偏好可直接追加;行为信号、Agent 推断、职业假设和程序性策略先进入记忆收件箱。每次生效或撤销都记录前后值、来源、理由、影响和取代关系。 + + +### ADR-0011 — 各模块只通过学习观察反哺职业模型 + +`Status: accepted, narrowed by ADR-0048` + +面试、简历、研究和投递模块产生带来源的学习观察,由统一 Memory Service 决定后续处理,业务模块不得直接改写其他模块或整体职业模型。任何观察都不能自动变成虚构经历;写入权以 ADR-0048 为准。 + + +### ADR-0012 — 学习观察即时记录、空闲时巩固 + +`Status: accepted` + +交互发生时立即、确定性保存观察;去重、冲突识别、过期判断和长期更新建议在托盘空闲任务中异步完成。巩固失败保留原始观察并可重试,不得静默创建职业证据或改写主控规则。 + + +### ADR-0013 — 只同步显式登记的工作源 + +`Status: accepted` + +只读增量同步使用者登记的仓库、作品目录或文档集合,不扫描整个磁盘。默认排除密钥、环境文件、依赖缓存和构建产物;实验或未交付内容不能自动表述为正式成果。 + + +### ADR-0016 — 来源删除后级联失效派生记忆 + +`Status: accepted` + +原始来源被删除或撤销授权后,其派生观察、候选证据、档案结论和下游引用立即退出检索、提示、评分与巩固。仅保留不含原文的最小审计外壳;拥有其他独立有效来源的结论可以继续存在。 + + +### ADR-0018 — 只提炼匿名简历表达模式 + +`Status: accepted` + +只从公开且允许使用的材料提炼匿名化结构、能力表达和量化方式。不得收集、长期保存或近似复刻候选人完整简历,也不得把他人经历写成使用者事实。 + + +### ADR-0025 — 用记忆收件箱审核职业模型变更 + +`Status: accepted` + +变更建议集中展示前后差异、理由、来源、影响和类型,支持接受、拒绝、稍后处理和撤销。系统不得先静默改写再通知,也不以频繁弹窗打断当前任务。 + +## 调研、投递与外部信号 + + +### ADR-0003 — 登录态平台只做使用者授权的只读研究 + +`Status: accepted` + +公开来源可自动研究;需要登录的平台只能由使用者主动发起本机只读浏览器会话。系统不保存平台密码、不绕过验证码或技术保护、不维持无人值守采集,也不执行发布、私信、投递等外部副作用。 + + +### ADR-0004 — 研究产物采用公司与岗位双层档案 + +`Status: accepted` + +维护可复用的公司档案和绑定具体公司岗位的岗位档案。证据快照带来源和时间戳,摘要可刷新但旧证据不被静默覆盖;简历、策略和面试准备读取同一岗位档案并引用共享公司档案。 + + +### ADR-0017 — 调研来源分级且结论逐条引用 + +`Status: accepted` + +硬事实优先使用官网、招聘官网和正式公告;主观信号至少由两个独立、近期来源交叉验证。单一来源必须标为单一信号,缺乏证据时标记未知,不允许模型补全。 + + +### ADR-0005 — 外部消息先形成候选进展 + +`Status: accepted` + +邮箱、短信等信号可同步、解析、去重和候选关联,但模型不能直接改变正式投递状态。高置信信号形成待确认候选,低置信信号进入待归属箱;只有使用者确认后才追加阶段事件。 + + +### ADR-0006 — 邮箱采用托盘驻留的本地增量同步 + +`Status: accepted` + +OfferU 运行期间,本地服务可在托盘持续增量同步、生成候选进展和通知;明确退出后停止。第一阶段不建设云端常驻服务或独立系统守护进程,各适配器必须保存游标并支持回补。 + + +### ADR-0007 — 一行代表一次投递尝试 + +`Status: accepted` + +每次投递是独立实体,分别保存所用简历、渠道、时间和阶段事件。重复投递可以引用同一公司与岗位档案,但不得覆盖历史尝试。 + + +### ADR-0019 — Agent 可建议投递关联但没有写入权 + +`Status: accepted` + +优先以申请编号、邮件线程、公司域名和岗位标识匹配外部信号;Agent 只能对非结构化候选进行排序和解释。多义或仅语义相似时由使用者选择,Agent 不得建立正式关联或写入阶段事件。 + + +### ADR-0022 — 邮箱默认只保存最小证据快照 + +`Status: accepted` + +默认只保存求职相关消息的标识、线程、发送者、时间、主题、相关正文片段和正文哈希。完整正文仅在同步和解析时短暂使用,除非使用者对单封邮件显式保存。 + + +### ADR-0034 — 先完成可复核投前决策再生成简历提案 + +`Status: accepted` + +主控 Agent 基于已确认职业证据和最近一次完成的岗位研究,提出投、有条件投、不投或证据不足,并逐条引用来源;最终决定与 Agent 建议分开保存。只有使用者确认投或有条件投,才提议生成可审核简历;其余结果和调研中断均是可恢复显式状态。 + +## 面试边界 + + +### ADR-0008 — 内容评价与表达行为反馈分开 + +`Status: accepted` + +默认报告不合并为单一总分。视觉与音频只提供可观察、可解释的行为统计,不推断人格、诚信、心理状态、录用概率或岗位胜任力;内容评价只能引用问题、回答、职业证据和岗位档案。 + + +### ADR-0009 — 面试评分规则声明式、版本化 + +`Status: accepted` + +自定义维度、权重、证据、阈值、提示词和聚合方式必须通过 schema 校验并记录规则 ID 与版本。评分 Skill 不得执行任意代码、访问未授权数据或突破内容与表达反馈隔离。 + + +### ADR-0010 — 面试视觉只保存派生事件与汇总 + +`Status: accepted` + +原始视频、截图和逐帧 landmarks 只存在于浏览器内存,不上传、不落盘。后端只保存表达事件和会话汇总,并支持按会话删除与导出。 + + +### ADR-0014 — 第一阶段采用轮次式语音面试 + +`Status: accepted` + +主控 Agent 逐题提问,使用者逐题录音或改用文字,本地端点检测结束后再转写和评价。默认不保存原始音频;第一阶段不建设可打断的全双工实时语音。 + +## Operation、Skill 与主控 Agent + + +### ADR-0029 — 所有入口共用一个 Operation Registry + +`Status: accepted` + +GUI、机器 CLI、TUI、斜杠 Skill 和本地 Harness 都是同一 Python Operation Registry 的适配器,共享 schema、权限、dry-run、确认提案、数据授权、审计、幂等和错误语义。任何入口都不得直接写数据库、执行隐藏 shell 或创建旁路业务状态机。 + + +### ADR-0037 — 结构化 Skill Registry 是技能唯一事实源 + +`Status: accepted` + +版本化 Registry 定义 Skill 身份、路由、适用目标、允许的 Operation 和确认边界,并生成各 UI 与 Harness 所需的薄入口。宿主 Markdown 只说明如何发现实时能力,不独立声明业务流程。 + + +### ADR-0041 — 旧确定性 Harness 逻辑降为 Guardian + +`Status: accepted` + +已有阶段判断、异常检测、提醒和记忆候选提取作为确定性前后置 Guardian 保留,但不再拥有独立意图路由、工具注册、工具循环、对话入口或写路径。Guardian 通过同一 Run 事件与事实门呈现结果。 + + +### ADR-0042 — 主控执行持久化为求职任务内的 Agent Run + +`Status: accepted` + +每次执行作为一个求职任务下的 Run,保存输入、Skill、标准化事件、Operation 调用、待确认动作、输出和恢复位置。对话是任务交互记录,领域对象是事实源;不建设跨任务全局 Session,也不按 GUI 页面拆 Run。 + + +### ADR-0051 — 外部 Coding Agent Harness 拥有唯一主控 Loop + +`Status: accepted; supersedes ADR-0036, ADR-0043 and ADR-0046` + +DeepSeek Harness、Codex、Claude Code、OpenCode 或 Pi 承载唯一主控 Agent 的推理会话、任务规划和工具循环。OfferU 只保留确定性工作台、Agent Bridge、Operation Registry、权限、确认、审计和业务事实源,不运行第二套内置主 Agent。 + +所有宿主通过各自薄接入包连接同一 CLI-first Bridge,不提供 MCP 业务入口,不允许直接访问数据库或使用隐藏 shell。Codex 与 DeepSeek Harness 优先实现;五种宿主只有通过同一行为一致性契约后才标为支持。 + + +### ADR-0052 — 主控 Harness 原生工具只作用于 Run 工件区 + +`Status: accepted` + +Harness 可以保留文件产物能力和经 Skill 授权的网络研究,但 Bash、编辑器和文件工具只能作用于当前 Run 独占工件目录。数据库、配置、源码、其他 Run 和未授权职业数据不可见;所有业务读取、提案和写入只能经 Agent Bridge 与 Operation Registry。 + +接入包必须实际探测隔离能力;若宿主只能限制写入,无法限制读取、网络或进程可见性,就不能标记为安全可用。工件始终是候选,只有经过审核和 Operation 接受后才能成为正式状态。 + + +### ADR-0053 — OfferU 拥有的确认界面是唯一确认权威 + +`Status: accepted` + +Harness 可以提出副作用 Operation 并等待,但只有 OfferU 拥有的嵌入工作区或专注窗口中的独立人类交互能够批准或拒绝。该界面即使渲染在 DSH Web 内,也直接连接 OfferU 控制面,不复用 Harness approval;接入包和模型可调用 CLI 不暴露确认能力。离线、断连和超时一律失败关闭,批准按提案 ID 与幂等键只生效一次。 + + +### ADR-0054 — 跨 Harness 故障切换必须创建新 Run + +`Status: accepted` + +无法恢复时不在同一 Run 内静默换宿主。使用者显式交接后,原 Run 保持中断或失败;新 Run 只继承已确认事实、可审计工件、未决提案和清洗后的执行摘要,并使用新的 Run ID、Harness session 和幂等命名空间。同一 Harness 的原生会话恢复可以保留原 Run。 + + +### ADR-0055 — Harness 原生界面是主外壳,OfferU 作为嵌入工作区 + +`Status: accepted; reframes ADR-0031; UI sharing boundary refined by ADR-0056` + +本地 Coding Agent 使用者的日常入口是 Harness 原生界面,因此 OfferU 不再以独立工作台或第二聊天应用争夺主界面。接入包在宿主允许时注册固定 OfferU 入口、任务内主视图和 OfferU 自有确认浮层;简历深编、摄像头面试等大画布任务才打开共享同一状态边界的专注窗口。首个 DSH 实现只使用可加式 UI extension points,不替换 DSH 的 Workspace/Session 导航、对话区或核心 details 面板;不支持安全 UI 嵌入的 Harness 使用 companion window,但主控 Loop 和提示输入仍留在 Harness。 + +OfferU 工作区是同一套 UI 与领域状态,但不承诺宿主提供全局中央页面:入口与确认可以是全局的,主视图按当前求职任务和 DSH Session 投影。它仍可浏览所有求职阶段和对象,但 Agent 执行绑定独立 Session/Run;界面统一不意味着多个岗位共享一个长期模型隐藏上下文。 + +DSH 接入采用原生 React client plugin,不把现有完整 OfferU SPA 作为 iframe 套入 DSH。host half 负责 CLI stdio Bridge 与生命周期,client half 使用 DSH 可加式 slots 注册界面;现有前端与接入包复用无头领域投影和交互状态机,独立壳只承载专注窗口或不支持嵌入的宿主。 + +跨 Harness 的一致性约束针对 Operations、Run、确认、事件和审计,而不是要求每个宿主提供相同 UI extension API 或视觉组件。DSH 使用原生嵌入;没有安全扩展点的 Codex、Claude Code、OpenCode 或 Pi 可以打开消费同一无头契约的 companion window,但不能因此降级业务契约。 + + +### ADR-0056 — Harness 共享无头交互契约,各自使用宿主原生 UI + +`Status: accepted; refines ADR-0055` + +DSH 内的 OfferU 工作区完全遵循 DSH 原生组件、布局、设计令牌与交互习惯,不形成 OfferU 品牌岛。跨 Harness 只共享类型化领域投影、交互状态机、Operation 合约和一致的确认语义;不共享同一套 React 页面或宿主无关视觉组件。每个支持 UI 扩展的接入包提供薄的宿主原生渲染器,companion window 则使用 OfferU 自有渲染器,但所有渲染器消费同一无头契约且不得维护第二份业务状态。 + +这一边界接受少量宿主渲染代码重复,以换取原生可用性、宿主升级适配和可访问性一致性;不得把领域判断、生命周期规则、权限或业务动作复制进渲染器。跨 Harness 一致性验收比较可见事实、状态转移、可执行 Operation、确认与错误语义,不做像素级一致性验收。 + + +### ADR-0057 — Codex Agent Engine 与 OfferU Career Control Plane 解耦 + +`Status: accepted` + +OfferU 不 Fork 或魔改 Codex Core;第一阶段通过 provider-neutral `AgentRuntimeProvider` 适配 Codex App Server stdio,并保留 Replay/Fixture 与未来其他 Harness provider 的替换 seam。Agent Runtime 只负责 thread、turn、event、skill/plugin、审批中断和执行生命周期,不拥有 Job、Profile、Resume、Application、Interview 或 Memory 真相。 + +CareerTask 是控制面的持久化执行信封,Provider Health 只保存脱敏的可用性和认证阻塞状态。所有会改变 OfferU 业务状态的 Agent、CLI、MCP、浏览器扩展和插件调用都必须回到 Operation Registry,经 Proposal/HITL、幂等和审计后才能进入 Domain Runtime;Agent 返回的意图、候选和报告不等于事实。`workspace.delegate` 也必须先创建 CareerTask,不能直接调用执行器或 Runtime。 + +OfferU Capability Plugin 使用自有版本化 Manifest,组合 CLI、Skill、capability、side effect、权限和输出契约。CLI 的 stdout 只能返回机器可读 JSON,stderr 只用于诊断;安装只改变本地能力发现状态,卸载不删除插件文件。插件输出由 OfferU Runtime 验证、去重、统计和持久化,不能把 Codex Marketplace 或任一 Harness 私有协议提升为业务契约。 + +当前 Codex 认证故障属于 Provider Health/G2B live verification,不阻塞 Fixture/Replay 的架构和产品验收;不得因此自动修改凭据、代理或切换用户 Provider。 + +自动化采用持久化 `AutomationEvent` → 显式 `AutomationRule` → `CareerTask` → Operation 的有限分发链,不引入常驻 Agent Loop。后台产生的岗位情报、简历建议和面试 Focus Plan 进入 Automation Inbox 作为候选或复核项;只有既有 Proposal/HITL 与 Career Memory 生命周期才能改变正式职业事实。 + + +### ADR-0058 — 岗位读取与站外投递动作使用独立 Connector 平面 + +`Status: proposed` + +`JobSource` 只负责 search/detail/recommend/application-record 等读取能力,输出 `JobObservation` 与外部进展信号;它永远不因为底层 CLI 或 Browser Bridge 同时具备写能力而暴露 greet、send、submit 等方法。站外动作使用独立 `ApplicationActionConnector`,统一建模 `greet / send_message / send_resume / exchange_contact` 等用户可感知动作。 + +OfferU 的产品顺序固定为:岗位发现与去重 → Role Intelligence / 投前决策 → Application Packet 准备 → `preview_application_action` dry-run → Proposal/HITL → 单条外部执行 → OperationAuditLog / 外部证据 → Application Event。批量场景只批量准备和批量审核,不允许把“批准一组岗位”退化为一个不可审计的后台海投循环。 + +`ApplicationActionConnector` 不拥有 Career Truth,不维护第二套 Application/Pipeline 状态。投前是否值得投由既有 Pre-Application Decision 决定;材料是否 ready 读取既有 Application Packet;外部执行成功与否由受保护 Operation 的审计和后续 `ExternalProgressSignal` 证据确认。重试必须复用稳定 idempotency key,避免重复打招呼、重复发消息或重复发送简历。 + +第一阶段只落地只读 `preview_application_action` 与 Connector 契约,不提供 BOSS 写执行器。未来无论底层使用 CLI、浏览器桥接还是其他用户授权通道,都必须接入同一 Proposal/HITL、幂等与审计边界;平台私有 token、Cookie、长 external ID 和浏览器细节不得进入普通 Agent Skill 或 Career Domain。 + +## 深度执行器 + + +### ADR-0015 — 本地深度执行器只承担可审计重任务 + +`Status: accepted` + +执行器只处理公司/岗位深度调研、批量 JD 评估和登记工作源摘要等可取消、可重放、可查来源的长任务。它只返回候选结果,不得直接写职业模型、晋升证据、确认投递阶段或决定面试评分。 + + +### ADR-0035 — OfferU 托管可替换的深度执行会话 + +`Status: accepted, narrowed to deep executors by ADR-0051` + +OfferU 负责深度执行会话的发起、恢复、事件呈现、取消和审批,并以可替换适配器使用 Codex、Claude Code 等。该托管边界只属于重任务执行器,不拥有主控 Agent 会话;结果仍经过 Operation Registry、事实门和使用者确认。 + + +### ADR-0038 — 每个托管执行会话只服务一个重任务 + +`Status: accepted` + +会话保存任务输入、执行器、标准事件、待确认动作、结果和恢复位置,完成后封存,不跨任务继承隐藏对话。跨任务连续性只来自已确认事实、学习观察和显式材料。 + + +### ADR-0039 — 深度执行器权限限定到当前任务 + +`Status: accepted` + +创建会话时只暴露该任务所需 Operation 与数据范围。执行器不能发现白名单外能力、用通用 API 或 shell 扩权,也不能直接写正式业务状态。 + + +### ADR-0044 — 托管深度执行器使用原生协议适配器 + +`Status: accepted` + +对支持托管会话的 Coding Agent,优先使用官方 SDK、App Server 或 Agent SDK,并归一为 OfferU 的事件、审批、取消和恢复契约。通用 CLI subprocess 只用于能力探测、一次性兼容或无托管协议的执行器;供应商差异留在无业务逻辑的适配层。 + + +### ADR-0045 — 用岗位调研闭环验证主控与执行器边界 + +`Status: accepted, reframed by ADR-0051` + +首个联合纵向切片嵌入投前决策:主控 Harness 通过 Skill Registry 创建受限深度执行会话,执行器形成带来源候选研究,OfferU 再通过证据规则、事实门和使用者审核决定是否进入档案。切片必须覆盖事件、取消、重启恢复、审计和显式失败。 + +## 工作台与交互 + + +### ADR-0030 — GUI 按求职流程组织 + +`Status: accepted` + +一级导航采用今日、机会、材料、进展和面试,而不是平铺技术模块。“今日”优先展示待确认、临近截止、进行中任务与下一动作;档案、设置和贯穿流程的主控 Agent 与阶段导航分离。 + + +### ADR-0031 — 使用任务中心的 Agent 工作台外壳 + +`Status: accepted, reframed by ADR-0055` + +任务优先交互仍围绕求职任务展示状态、证据、审批和结果,但主外壳改由 Harness 原生界面承担。OfferU 工作区嵌入宿主并采用渐进披露;简历深编与面试进入专注窗口;GUI/TUI 呈现可不同,但仍共享 Operation Registry。 + + +### ADR-0032 — 移动端只承担轻操作 + +`Status: accepted` + +桌面和平板承载完整工作区;手机聚焦查看、确认、更新投递进展和续接主控 Agent。简历深度编辑与面试训练保留在桌面或平板。 + + +### ADR-0033 — 一级页面收敛进五阶段导航 + +`Status: accepted` + +现有页面归入今日、机会、材料、进展与面试;邮箱成为进展信号收件箱,抓取成为机会导入入口,独立 Agent 与演示页面退出一级导航。收敛只改变页面组织,不合并领域事实或改变权限边界。 + +## 浏览器扩展 + + +### ADR-0049 — 一个 OfferU 扩展统一岗位采集与安全填表 + +`Status: accepted` + +只保留可维护的 OfferU WXT 扩展;外部已发布扩展只能作为 clean-room 行为参考。扩展使用版本化 `SiteRuleRegistry` 和内置 `ControlDriver`,只暴露岗位采集、填表和提交候选证据三类动作;它不提交申请、不保存独立简历或模型密钥,也不直接写数据库。 + +填表先生成绑定 URL、字段指纹和短时有效期的 `FillPlan`,经使用者二次确认后只填空白、非敏感、高置信字段,永不触发最终提交。提交后只能形成最小证据候选,确认后由 Operation Registry 原子创建投递尝试与阶段事件。扩展按需使用 `activeTab + scripting`,主界面采用 side panel,构建入口与产物以 WXT 约定为准。 + + +### ADR-0050 — 远程规则包必须版本化并签名 + +`Status: accepted` + +远程更新只允许 JSON 选择器、字段映射和能力声明,不得携带代码。单一 bundle 使用单调递增版本、schema 校验和 ECDSA P-256/SHA-256 签名,公钥内置、私钥不入库;失败、离线、重放或坏包时保留内置规则,并提供熔断与回滚。远程发布前仍需复核浏览器商店政策。 + +## 交付与验收 + + +### ADR-0027 — 按垂直闭环交付 + +`Status: accepted` + +依次交付共同底座,邮箱与投递,公司/岗位研究与证据化简历,以及语音/视觉面试。每阶段都从用户触发贯通处理、领域事实、确认界面和可见结果,不按数据库、API、前端等技术层横向铺开。 + + +### ADR-0028 — 使用三层量化验收门槛 + +`Status: accepted` + +安全不变量必须 100% 通过;概率能力必须在固定、版本化标注集达到阈值;完整场景必须通过端到端、重启恢复、重试和重复输入验证。页面可访问、构建成功或单次演示都不代表交付完成。 + +## 被取代的历史决策 + + +### ADR-0001 — 本地优先并预留 SaaS 边界 + +`Status: superseded by ADR-0023` + +旧决策曾要求避免全局单例以保留 SaaS 演进边界。当前明确不为未来 SaaS 预埋模型,以 ADR-0023 为准。 + + +### ADR-0002 — Profile 分层写权限 + +`Status: superseded by ADR-0048` + +旧决策允许主控 Agent 自动更新求职偏好。当前统一改为条目级账本和更严格的记忆收件箱规则,以 ADR-0048 为准。 + + +### ADR-0036 — 内置 Agent 使用进程内 Operation 投影 + +`Status: superseded by ADR-0051` + +旧决策假设 OfferU 内置主 Agent Core。当前主控 Loop 已迁移到外部 Harness,OfferU 只提供 CLI-first Agent Bridge。 + + +### ADR-0040 — 在 Python 内借鉴 Pi 运行时契约 + +`Status: superseded by ADR-0046, then ADR-0051` + +该方案先被 Pi SDK Worker 取代,随后内置主 Agent 路线整体被 ADR-0051 取代。 + + +### ADR-0043 — 内置主 Agent 工具协议按模型能力分型 + +`Status: superseded by ADR-0051` + +该决策属于已取消的内置模型适配层。现在由外部 Harness 处理模型协议,OfferU 只验证统一 Bridge 与 Operation 行为契约。 + + +### ADR-0046 — Pi SDK Worker 承载内置主 Agent + +`Status: superseded by ADR-0051` + +不再以 Node.js Pi Worker 承载第二套主 Agent。Pi 只能作为外部 Harness 接入目标或迁移期兼容实现。 + +## 编号索引 + +| 范围 | 主题 | +| --- | --- | +| ADR-0001–0028 | 产品边界、职业事实、研究、投递、面试、交付与验收 | +| ADR-0029–0034 | Operation、Skill、工作台与投前决策 | +| ADR-0035–0046 | 主控/执行器架构演进与被取代路线 | +| ADR-0047–0050 | 桌面前端、职业模型账本、浏览器扩展 | +| ADR-0051–0056 | 外部 Harness 主控、工具隔离、确认、交接与宿主原生工作区 | From 2753b46b38944676f80121899f4309071000e0c9 Mon Sep 17 00:00:00 2001 From: avabbbb <89175608+avabbbb@users.noreply.github.com> Date: Wed, 23 Sep 2026 00:21:34 +0800 Subject: [PATCH 05/36] docs(archive): preserve superseded design history --- .../architecture/context-pre-2026-09-23.md | 379 ++++++++++++++++++ 1 file changed, 379 insertions(+) create mode 100644 docs/archive/architecture/context-pre-2026-09-23.md diff --git a/docs/archive/architecture/context-pre-2026-09-23.md b/docs/archive/architecture/context-pre-2026-09-23.md new file mode 100644 index 00000000..9c7be2f1 --- /dev/null +++ b/docs/archive/architecture/context-pre-2026-09-23.md @@ -0,0 +1,379 @@ +> **HISTORICAL SNAPSHOT** — archived from `CONTEXT.md` on 2026-09-23. It does not define current product or architecture authority. See `docs/product/current-product.md`, `CONTEXT.md`, and `ARCHITECTURE.md`. + +# OfferU 求职运营 + +OfferU 帮助使用者持续维护职业档案,并围绕岗位研究、材料定制、投递跟进和面试训练推进求职过程。 + +## Language + +**主控 Agent**: +由使用者选择并经能力探测通过的外部 Coding Agent Harness 承载,是理解目标、自然语言推理、任务规划和选择 OfferU Operation 的唯一智能主体。它不能拥有业务事实、授予自身权限或绕过 OfferU 操作控制面执行副作用。 +_Avoid_: OfferU 内置 Agent、操作员 Agent、第二主脑、业务后端 + +**OfferU 操作控制面**: +OfferU 内部不含 LLM loop 的确定性运行边界,负责工作台状态、上下文投影、权限、确认、Operation 执行、幂等、事件和审计。它接收主控 Agent 的类型化调用,但不理解开放式目标、不规划任务,也不选择下一项 Operation。 +_Avoid_: 内置 Agent、主 Agent 运行时、Pi Core、Harness Agent、第二主脑 + +**操作守卫**: +在主控 Agent 的 Operation 调用前后执行阶段检查、风险提醒和记忆候选提取的确定性策略集合。它不能选择或执行业务 Operation,也不拥有独立对话、工具循环或记忆事实。 +_Avoid_: Main Agent Guardian、Harness Agent、规则 Agent、第二 Agent、工具路由器 + +**本地深度执行器**: +由主控 Agent 按需委托,用于完成边界明确的深度研究或批量分析任务的本地智能执行能力。它不拥有业务事实源,也不能绕过使用者确认独立改变求职状态。 +_Avoid_: 主控 Agent、系统主脑、自治 Worker + +**执行器适配器**: +把一种本地深度执行能力的会话、事件、审批、取消和恢复语义映射为 OfferU 托管执行会话契约的边界。它不包含求职业务逻辑,也不能扩大任务能力授权。 +_Avoid_: CLI Wrapper、Agent 后端、Provider、业务插件 + +**托管执行会话**: +由 OfferU 操作控制面根据主控 Agent 的类型化请求为一个可审计重任务创建,并持有任务边界、权限、生命周期与审计责任的一次本地深度执行过程。会话可以中断恢复,完成后封存且不跨任务继承隐藏上下文;底层执行能力可以替换,但不能因此取得主控权或业务事实写入权。 +_Avoid_: Codex 会话、Claude 会话、外部 Agent 对话、独立 Agent 任务 + +**任务能力授权**: +OfferU 操作控制面依据使用者授权为一个托管执行会话签发的 Operation 与数据范围白名单,只允许完成当前可审计重任务所需的最小能力。它随会话结束失效,不授予业务事实写入权,也不能由主控 Agent、Skill 或执行器自行扩大。 +_Avoid_: Agent 权限、全局工具权限、Prompt 白名单、用户角色 + +**Run 工件工作区**: +一个 Agent Run 独占的隔离文件空间,用于主控 Harness 处理显式输入、中间文件和候选产物。它不是职业事实源或跨 Run 记忆,不能包含 OfferU 数据库、配置、源码或未授权职业数据;其中产物必须经审核和 Operation 才能进入正式业务状态。 +_Avoid_: 项目工作区、OfferU 仓库、Agent 记忆目录、共享临时目录 + +**Run 工具授权**: +OfferU 操作控制面依据所选 Skill 和使用者授权,为一个 Agent Run 限定可调用的 Operation、数据范围、Run 工件工作区和外部网络能力。授权随 Run 结束失效,主控 Harness 或接入包不能自行扩大,也不能把原生 Coding Agent 工具变成业务写路径。 +_Avoid_: 全局工具权限、Harness 默认权限、项目级 Shell、自动授权 + +**可审计重任务**: +可以取消、重放并检查输入、工具调用、输出和来源的长耗时任务。第一阶段包括公司/岗位深度调研、批量 JD 评估和已登记工作源的变化摘要;其结果必须经过 OfferU 的事实门和使用者确认后才能影响领域数据。 +_Avoid_: Agent 自动化、后台任务、Profile 自动更新 + +**统一控制台**: +让使用者或本地 Coding Agent 通过 GUI、机器 CLI、交互式 TUI 或斜杠 Skill 命令操控 OfferU 的多入口控制面。所有入口都调用同一 Operation Registry,并共享参数 schema、权限、确认、审计、数据授权和错误语义;控制台本身不实现业务逻辑。 +_Avoid_: CLI 后端、TUI 应用、第二套控制系统 + +**机器 CLI 契约**: +OfferU 向主控 Agent 和本地自动化公开的唯一机器控制契约,以结构化能力探测、manifest、Operation schema、dry-run、执行、提案状态、取消和事件定义可调用表面。Harness 接入包可以包装该契约,但不能确认自身提案,也不能另建 MCP、原始 HTTP、数据库或任意 shell 业务入口。 +_Avoid_: MCP 业务接口、REST 自动化后端、Shell 脚本协议、固定 Provider argv + +**OfferU Agent Bridge**: +外部主控 Harness 将自身会话关联到 OfferU Agent Run,并取得当前任务上下文和已授权 Operation 的唯一确定性连接面。主会话、推理和工具循环属于外部 Harness;Bridge 不规划任务、不拥有业务事实,也不成为第二个 Agent。 +_Avoid_: OfferU Harness Host、内置 Agent Runtime、MCP Host、第二主脑 + +**OfferU Agent Runtime**: +由 `AgentRuntimeProvider` 暴露的 provider-neutral 执行边界,负责 thread、turn、event、Skill/Plugin 发现、审批中断、取消和恢复等 Harness 生命周期。Codex App Server 是首个主 Provider,Pi/Replay 适配器用于当前本地兼容与确定性验收,其他 Provider 必须通过同一契约后才能标记支持;该边界不拥有 Career Truth,也不能替代 Operation Registry。 +_Avoid_: Career Runtime、业务 Agent、第二套 Operation Registry、Codex Core Fork + +**CareerTask**: +OfferU 控制面持久化的长任务执行信封,记录 task type、目标、provider、输入契约、状态、事件、checkpoint、结果引用和显式失败。它与可见的求职任务、主控 Agent Run 和 Hosted Executor Session 不同;其结果仍是候选或提案,不能直接成为职业事实。 +_Avoid_: Job、求职任务、Agent Run、后台字符串调用、事实表 + +**Agent Provider Health**: +OfferU 对 Agent Runtime provider 保存的脱敏健康快照,至少表达 available、authenticated、blocked、版本、协议和最后错误。Codex 401 属于 Provider Health/G2B live 验收阻塞,不是 Role Intelligence 业务事实,也不能触发静默换凭据或换 Provider。 +_Avoid_: API Key、Auth Token、Career status、LLM 业务结果 + +**OfferU Capability Plugin**: +通过自有版本化 Manifest 组合 CLI、Skill、capability、side effect、权限和输出契约的本地能力包。安装改变 Agent 能力发现,卸载只禁用能力;CLI 输出必须是 JSON,插件不能直连数据库、拥有 Career Truth 或绕过 Operation Registry。首个真实公开源实现是 `job-search`;fixture 插件只能用于 replay/验收,不能伪装成 live source。 +_Avoid_: Codex Fork、Marketplace 业务契约、插件数据库、自由 Shell 入口 + +**AutomationEvent**: +OfferU 控制面接收的可幂等外部或内部信号,例如 `JOB_SAVED`、邮箱进展和面试完成。事件只触发明确的 Automation Rule,不直接修改 Career Truth;分发失败、Provider 阻塞和结果引用都必须持久化。 +_Avoid_: 无限 Agent Loop、隐式触发器、聊天消息、静默状态变更 + +**Automation Inbox**: +从 AutomationEvent、CareerTask 和候选提案派生的使用者处理队列,按 needs approval、needs review、FYI、completed、failed 分类。它是注意力投影,不是新的事实表;关闭项目不会代替 Operation 确认或 Career Memory 提交。 +_Avoid_: 弹窗风暴、自动批准、第二套任务数据库、直接写 Profile + +**Harness 接入包**: +安装到一种外部 Coding Agent Harness 中、把 OfferU Skill、上下文、Operation、Agent Run 事件和人类控制界面投影为该宿主原生能力的薄集成。支持 UI 扩展的宿主使用 host/client 双面插件:host half 连接 CLI-first Bridge,client half 注册原生 OfferU 工作区;它只适配宿主差异,不包含求职业务逻辑,也不能扩大权限或形成独立事实源。 +_Avoid_: Harness Driver、CLI Wrapper、Provider 业务后端、iframe 应用、MCP 插件 + +**Harness 主界面**: +使用者与主控 Agent 对话并管理其原生会话的 Harness 界面,是本地 Coding Agent 使用者的默认产品外壳。它拥有提示输入和会话交互,但不拥有 OfferU 业务事实、Operation 确认或求职状态。 +_Avoid_: OfferU 聊天框、第二工作台、Agent 控制面、业务事实界面 + +**OfferU 工作区**: +由 OfferU 拥有并通过统一领域投影、交互状态机与 Operation 合约投影到 Harness 主界面的人类控制表面。各 Harness 使用自身原生组件和视觉语言渲染,不共享同一套 React 页面;它可以按宿主能力拆成全局入口、全局确认界面和任务内主视图,用于浏览求职流程、事实、证据、Run、提案和结果,大画布任务则在同一状态边界下弹出 OfferU 专注窗口。它不要求宿主提供一个永远占据中央区域的全局页面,不提供第二个 Agent 提示输入,也不把全局领域数据变成一个全局模型会话。 +_Avoid_: 独立主应用、OfferU Agent 聊天、Harness 侧栏替代品、嵌入网页副本 + +**宿主原生工作区渲染器**: +Harness 接入包 client half 中只负责把 OfferU 的类型化领域投影和交互状态映射为该宿主原生组件、布局、令牌与可访问性行为的薄渲染层。它不拥有领域状态机、Operation 规则或确认决策,也不能为了复用视觉而嵌入共享 React 页面、复制 OfferU SPA 或维护第二份业务状态。 +_Avoid_: 共享 UI 包、品牌微前端、主题皮肤、iframe 页面、宿主无关 React 页面 + +**OfferU 任务视图**: +OfferU 工作区在当前求职任务与 Harness session 内的主操作表面,首先让使用者看清任务状态、下一动作、待确认事项和已产出结果;上下文、Run、Operation、证据与候选工件都从该任务进入。它可以读取全局职业数据与流程导航,但任何 Agent 动作都绑定当前任务、Run、授权和事件流;切换任务必须切换或恢复对应 Harness session。 +_Avoid_: 全局 Agent 面板、全局 OfferU 首页、聊天流插卡、第二聊天页、跨 Session 控制台、工作台 iframe + +**任务视图主状态**: +OfferU 任务视图首屏在任一时刻只突出一个最需要使用者理解或处理的状态,固定优先级为待确认、失败或断连、正在执行、下一动作、最近完成。它是从提案、连接、Run、任务和 outcome 派生的注意力投影,不覆盖底层事实;未成为主状态的信息仍可在详情和时间线中查看。 +_Avoid_: 并列仪表盘、多个同权主按钮、AI 在线、卡片堆砌、用最近完成遮住待确认 + +**任务会话绑定**: +OfferU 工作区的入口和领域数据可以全局可达;只有完全空白且尚未绑定的 Harness session,才能在使用者通过 OfferU 入口显式选择或创建求职任务后建立一次绑定,一条 session 只能绑定一个求职任务且绑定后不可改绑。已有聊天或工具历史、或需要切换任务时,必须新建或恢复对应 session,并同时切换推理上下文、授权和事件流,不能把多个岗位继续写入同一隐藏模型上下文。 +_Avoid_: 全局 Agent Session、Session 改绑、历史会话补绑、跨任务隐藏记忆、按页面建 Session、共享 Run + +**Harness 支持目录**: +OfferU 明确维护的外部主控 Harness 集合,包含 Codex、DeepSeek Harness、Claude Code、OpenCode 与 Pi;Codex 和 DeepSeek Harness 是首批优先接入目标。目录声明产品目标,某台设备上的实际可用性仍由对应 Harness 接入包实时探测,不能用假能力或静默替代伪造支持。 +_Avoid_: Provider 列表、模型列表、固定命令表、自动降级链 + +**主控 Harness 一致性契约**: +Codex、DeepSeek Harness、Claude Code、OpenCode 与 Pi 被标记为“支持”前必须共同满足的完整业务行为契约,包括创建与恢复会话、追加指令与运行中转向、中断与取消、通过 CLI-first Agent Bridge 调用 OfferU Operation、暂停并恢复使用者确认、输出统一事件流,以及显式报告完成或失败。宿主可以按能力使用原生嵌入工作区或 OfferU companion window,但不得因此缩减业务能力、改用一次性问答或隐藏降级;Codex 和 DeepSeek Harness 仅决定实现优先级,不降低其他三种的最终验收门槛。 +_Avoid_: 基础可用、实验性支持、兼容模式、最低公分母协议 + +**Harness 交接**: +当前主控 Harness 无法恢复时,由使用者显式选择另一 Harness,并用原 Run 的已确认事实、可审计产物、未决提案和可公开执行摘要创建新 Agent Run 的转换。原 Run 保持中断或失败终态,隐藏会话、未记录推理和原生进程状态不得冒充可移植上下文。 +_Avoid_: 自动 Failover、跨 Harness 恢复、Session 迁移、同 Run 换 Provider + +**受控 CLI Broker**: +OfferU Agent Bridge 内部接收主控 Agent 提交的结构化 JSON/JSONL 命令,在绑定当前 Agent Run、Run 工具授权和幂等信息后分派到对应 Operation,再把标准结果返回主控会话的边界。它不接收 shell 字符串、管道、重定向、任意可执行文件或绕过确认的调用,也不把 Harness argv 变成业务契约。 +_Avoid_: Shell Tool、Bash/PowerShell 代理、MCP Tool、通用 subprocess、动态业务 API + +**OfferU 确认**: +使用者在 OfferU 拥有的嵌入工作区或专注窗口中核对 Operation 提案、影响和证据后作出的批准或拒绝,是提案获得执行授权的唯一来源。Harness 原生 approval、接入包和模型可调用 CLI 只能请求并等待,不能代表使用者作出决定。 +_Avoid_: Agent 确认、Harness Approval、CLI confirm、模型自批、聊天回复确认 + +**斜杠 Skill 命令**: +在主控 Agent 对话入口或 TUI 输入框中显式激活一个版本化 Skill 的命令形式。`/offeru` 打开技能菜单,`/skill-id` 或已声明 alias 直接进入具体 Skill;两种入口都从 Skill Registry 自动生成并解析到同一 Skill ID,只选择协议与允许操作集合,不执行 shell,也不绕过领域事实门。 +_Avoid_: Slash Command、快捷命令、Shell 命令 + +**Skill Registry**: +OfferU 可用求职技能的唯一版本化目录,定义每个 Skill 的身份、适用目标、允许操作和确认边界。主控 Agent、斜杠 Skill 命令与其他控制入口都引用这一目录,不分别维护技能事实。 +_Avoid_: Skill 文件夹、Prompt 列表、命令表、外部 Agent 手册 + +**操作员 TUI**: +通过 `offeru tui` 启动的本地交互式终端界面,用于浏览投递、Agent Run、研究档案、记忆收件箱、提案和审计,并通过统一 Operation Registry 发起操作。它是人类控制面,不拥有独立数据库或业务写路径。 +_Avoid_: Agent TUI、Dashboard、Terminal App、后台控制台 + +**本地个人工作区**: +由一名使用者拥有并在个人设备上运行的完整求职工作空间。第一阶段的所有数据、记忆和自动化均服务于这个唯一拥有者。 +_Avoid_: 默认用户、全局账号、单例用户 + +**本地单人边界**: +第一阶段只有一个本地拥有者和一份本地数据空间。领域数据可以明确依赖这一产品约束,不引入 workspace、tenant、organization、登录、计费或租户权限等 SaaS 概念;若未来出现 SaaS 需求,重新进行独立架构设计。 +_Avoid_: SaaS 演进边界、预留多租户、默认用户兼容层 + +**Python 业务后端**: +第一阶段承载 Agent、记忆、简历、调研、投递、邮箱和面试领域逻辑的唯一业务运行时。Tauri/Rust 只负责桌面壳、系统托盘、钥匙串和进程管理等系统桥接,不与 Python 双写业务事实。 +_Avoid_: Python Worker、临时后端、Rust 迁移过渡层 + +**垂直交付阶段**: +从用户触发、Agent 或确定性处理、领域事实、审核界面到最终可见结果组成的可独立使用闭环。第一阶段按共同底座、投递进度、岗位调研与简历、AI 面试的顺序推进,不按数据库、API、前端等技术层横向铺开。 +_Avoid_: 模块开发、后端阶段、功能列表 + +**任务优先工作区**: +OfferU 工作区的统一交互模型,以使用者当前处理的求职对象、状态与下一动作作为主体;无论嵌入 Harness 还是弹出专注窗口都共享同一领域状态。 +_Avoid_: 营销式模块首页、页面 Hero、独立视觉工作室、第二聊天应用 + +**求职流程导航**: +任务优先工作区按今日、机会、材料、进展与面试五个求职阶段组织内部入口;档案和设置是支持入口,主控 Agent 的连接状态贯穿各阶段而不是成为并列业务模块。 +_Avoid_: 平铺模块导航、功能清单导航、Agent 独立模块 + +**求职任务**: +使用者围绕一个求职目标持续推进的可见工作单元,可以关联领域对象、对话记录、Agent Run、待确认动作、证据与结果。对话是任务内的交互记录,Agent Run 是任务的一次执行,两者都不代表任务本身。 +_Avoid_: 对话、页面、Agent Run、后台任务 + +**Agent Run**: +主控 Agent 在一个求职任务内进行的一次可暂停、可恢复和可审计执行,记录输入、选定 Skill、事件、Operation 调用、待确认动作与结果。每次 Run 的底层 Harness 会话只服务该 Run、可以从已保存状态重建且不能跨 Run 继承隐藏上下文;Run 不拥有任务目标或领域事实,完成后成为该求职任务的执行记录。 +_Avoid_: 求职任务、对话、Agent Session、后台任务、工作流 + +**Agent Run 事件**: +Agent Run 内按单调序号追加的 provider-neutral 生命周期记录,用于表达 Skill 选择、消息增量、Operation 提案与执行、外部执行器状态、审核点和 Run 终态。界面与恢复逻辑只消费这层标准事件;Pi、Codex 或 Claude 的原始事件可以进入审计 trace,但不能成为产品状态的唯一来源。 +_Avoid_: Provider JSONL、聊天消息、审计日志、前端通知 + +**今日行动队列**: +从待确认动作、临近截止、进行中求职任务和建议下一步派生的当日处理视图。它帮助使用者决定现在做什么,但不是求职状态或职业事实的来源。 +_Avoid_: 数据看板、统计首页、任务事实表 + +**移动端轻操作**: +任务优先工作区在手机尺寸下提供查看、确认、投递进展更新和主控 Agent 续接,不承担简历深度编辑或面试训练。它与桌面端共享领域事实和操作契约,但不追求界面能力完全对等。 +_Avoid_: 全端功能一致、移动端只读、手机版工作台 + +### 使用者模型 + +**使用者职业模型**: +OfferU 对使用者职业现状与发展可能性的分层表达,由职业证据、求职偏好、职业假设和学习观察共同组成。它不是一份简历,也不是可以被 Agent 整体重写的单一 Profile 文本。 +_Avoid_: 总 Profile、用户画像、优化记忆 + +**职业模型演进**: +使用者职业模型因新的已确认事实、显式偏好和经验证的求职学习而发生的长期变化,通过可追溯提案增补、纠正、取代或失效其中的组成部分。它改善模型的完整性、时效性、证据质量和决策适用性,但不美化职业证据、不把 Agent 推断改写成事实,也不整体重写一个单一 Profile 文本。 +_Avoid_: Profile 进化、用户画像优化、人格成长、自动改写 Profile + +**职业模型变更账本**: +按条目追加记录每次已接受或已撤销职业模型变化的长期历史,保留变化前后、来源、理由、影响和取代关系,并从仍有效的条目派生当前职业模型。它使单项撤销、变化解释和下游材料过期判断成为同一演进链的一部分。 +_Avoid_: Profile 快照、当前 Profile、编辑日志、提案列表 + +**岗位职业投影**: +面向一个具体岗位,从使用者职业模型中选择相关职业证据、偏好和已验证方向,并组织成当前岗位所需叙事的临时视图。它不修改长期职业模型;可跨岗位复用的新发现必须重新经过学习观察与审核后才能回流。 +_Avoid_: 岗位 Profile、定制用户画像、Profile 分支、事实改写 + +**职业证据**: +由使用者确认、能够追溯到具体来源的教育、经历、项目、技能或成果事实。它是简历、岗位匹配和面试回答可以直接引用的事实基础。 +_Avoid_: Profile 内容、用户画像、AI 推断 + +**求职偏好**: +使用者当前对岗位、地点、行业、工作方式或求职节奏的可变选择。使用者明确陈述的偏好本身构成确认;行为信号或 Agent 推断只能形成待审核更新提案,且无论如何都不构成职业经历事实。 +_Avoid_: 职业证据、永久性格、硬性事实 + +**职业假设**: +主控 Agent 根据职业证据、岗位研究或行为信号提出的待验证发展可能性。它必须与职业证据隔离,只有经过验证和使用者确认后才能成为目标方向。 +_Avoid_: 目标岗位、既定能力、Profile 事实 + +**学习观察**: +AI 面试、简历优化、岗位研究或投递进展产生的一条可追溯行为信号,例如使用者采纳的改写、反复出现的回答缺口或某类岗位的阶段结果。它可以触发职业模型更新建议,但本身不是职业证据。 +_Avoid_: 记忆、事实、用户标签 + +**学习证据门**: +区分可以支撑策略更新的强证据与只能形成待验证学习观察的弱信号。使用者的明确纠正、采纳或拒绝以及经确认的求职结果属于强证据;点击、停留、跳过、改写等隐式行为和 Agent 推断不能单独形成长期结论。 +_Avoid_: 行为画像、隐式学习、统一置信分 + +**记忆巩固**: +在 OfferU 空闲时对学习观察进行去重、冲突识别、过期判断和长期更新建议生成的过程。它不能静默创建职业证据,也不能自行修改 OfferU 的政策、权限或事实门规则。 +_Avoid_: 自动学习、夜间重写、Profile 优化 + +**记忆收件箱**: +集中呈现使用者职业模型变更建议的审核界面。每条建议展示变更前后差异、理由、来源和影响范围,并支持接受、拒绝、稍后处理与撤销;未处理建议不能静默成为职业证据或已验证职业假设。 +_Avoid_: Profile 通知、记忆列表、对话确认弹窗 + +**职业策略学习循环**: +将岗位推进、材料采纳、投递结果和面试反馈先记录为学习观察,经证据化复盘形成可检验的策略假设,再以待审核更新提案影响后续求职任务的跨任务学习过程。系统可以自动采集、分析和提出变更,但长期职业结论、程序性策略与助手工作风格只有经使用者确认后才能永久生效。 +_Avoid_: 自我进化、自动学习、人格重写、复盘报告 + +**工作源**: +使用者明确登记并授权 OfferU 只读同步的代码仓库、作品目录或文档集合。工作源中的变化可以形成学习观察或待确认职业证据,但未完成内容不自动等于履历成果。 +_Avoid_: 工作区、项目目录、本机扫描 + +**来源级联失效**: +原始来源被删除或撤销授权时,使该来源及其派生学习观察、候选证据、档案结论和下游引用立即退出检索、提示词、评分和记忆巩固的过程。系统只保留不含原始内容的最小审计外壳;其他独立有效来源提供的支持不受影响。 +_Avoid_: 软删除、停止同步、删除全部历史 + +### 岗位研究 + +**岗位采集**: +使用者在浏览器中显式触发,从当前有权访问的岗位详情页读取公司、职位、JD、来源链接等信息,并形成待导入 OfferU 的本地岗位候选。岗位采集及其后的岗位入库都不代表使用者已经申请该岗位,也不创建投递尝试。 +_Avoid_: 后台爬虫、自动投递、收藏即投递 + +**站点规则包**: +由 OfferU 维护并随浏览器扩展版本化发布的只读适配数据,描述某类招聘页面的识别信号、岗位字段定位、表单结构、受支持控件和提交回执证据。规则包只能引用扩展内置的已知控件驱动,不能携带或下载任意可执行代码;未经 fixture 与真实浏览器验收的规则只能用于诊断,不能启用填表。 +_Avoid_: 牛客规则同步、远程脚本、站点特例代码堆、万能选择器 + +**用户授权只读研究**: +使用者主动发起并监督的本机浏览器研究会话,用于读取其本人当前有权访问的登录态内容。该会话只能形成带来源的研究证据,不能代表使用者发布、联系、投递或改变外部账号状态。 +_Avoid_: 自动爬虫、后台采集、账号托管 + +**公司档案**: +围绕一家公司的业务、产品、组织环境、文化信号、招聘风险和时效性动态持续维护的来源化研究集合。它可以被该公司的多个岗位复用。 +_Avoid_: 公司简介、一次性调研报告 + +**岗位档案**: +围绕某家公司的一项具体岗位持续维护的研究集合,包含 JD 证据、团队线索、工作内容、面经、参考材料和求职策略。它引用公司档案,但不把其他岗位的信息混入当前岗位事实。 +_Avoid_: Job、JD 摘要、公司档案 + +**岗位推进闭环**: +使用者围绕一个高意向真实岗位,从导入、投前判断和调研推进到取得可审核材料与明确投递待办的一次端到端求职任务;外部提交仍由使用者完成。它是 OfferU 第一阶段的首要价值边界,不等于覆盖岗位发现、面试、Offer 与长期职业陪伴的全程求职系统。 +_Avoid_: 全程求职 OS、自动投递流水线、岗位自动申请 + +**有效推进效率**: +衡量一个岗位推进闭环从岗位导入到使用者批准材料与投递待办所消耗的使用者主动时间。只有职业事实准确、产物经审核可采用且返工处于约定边界内的闭环才算有效;模型生成速度、Agent 运行时长和投递数量都不能替代它。 +_Avoid_: 生成速度、Agent 耗时、投递吞吐、效率分 + +**投前决策**: +主控 Agent 基于当前岗位、已确认职业证据和已完成岗位调研提出的可复核建议,建议值只能是投、有条件投、不投或证据不足。它必须展示理由、缺口和来源;使用者最终选择与 Agent 建议分别保存,只有使用者确认投或有条件投后,投前决策闭环才允许生成该岗位的简历提案。 +_Avoid_: 岗位匹配分、Agent 评分、自动投递结论 + +**投前决策闭环**: +从选定真实岗位开始,依次检查职业证据、岗位调研和投前决策,在可持久化的人工确认点暂停,并在使用者确认投或有条件投后生成可审核简历提案的垂直交付阶段。调研进行中、证据不足与不投都是可解释退出状态;闭环不创建投递尝试,也不提交外部申请。 +_Avoid_: 求职自动流水线、简历生成流程、投递自动化 + +**调研证据等级**: +决定调研结论可如何表述的来源质量与交叉验证规则。公司业务、岗位要求等硬事实优先由官网、招聘官网和正式公告支撑;团队氛围、面经等主观信号需要至少两个独立近期来源,否则只能标为单一信号或未知。每条结论必须可追溯到具体来源。 +_Avoid_: 来源数量、AI 可信度、统一置信分 + +**简历表达模式**: +从公开且允许使用的参考材料中提炼出的匿名化结构、能力表达方式和量化方法。它保留来源与授权状态,但不保存或复刻真实候选人的完整简历,也不能作为使用者经历或成果的事实来源。 +_Avoid_: 模范简历、简历库、优秀候选人简历 + +### 投递进展 + +**投递表单填写**: +使用者完成投前判断后,由浏览器扩展从 OfferU 的已确认职业事实生成可审核填写计划,并在使用者再次确认后只填写当前外部表单中的空白、非敏感字段。它不覆盖网页已有值,不填写身份证明、薪资、工作许可、授权同意等敏感或承诺性字段,不点击最终提交,也不因填写完成而创建投递尝试;牛客或其他第三方云简历不能成为该流程的职业事实源。 +_Avoid_: 一键投递、自动申请、牛客云简历同步、填完即已投 + +**外部提交**: +使用者在招聘网站核对整份申请后亲自执行的最终提交动作。它会改变外部账号或申请状态,浏览器扩展和 Agent 都不得代替使用者触发;OfferU 只能在动作之后读取回执或成功页面作为待确认的提交证据。 +_Avoid_: 二次确认代提交、无人值守提交、表单填写完成 + +**提交候选证据**: +浏览器扩展在使用者亲自提交后,从成功页面或回执中提取的最小证据候选,例如公司、岗位、申请编号、发生时间和来源页面。它在使用者确认前不能创建投递尝试或改变正式投递阶段;使用者确认后,OfferU 才通过统一 Operation Registry 原子创建投递尝试及其初始 Submitted 阶段事件。 +_Avoid_: 已投递状态、自动记账、完整页面快照 + +**投递尝试**: +使用者在特定招聘批次中向一个具体岗位进行的一次独立申请。重复申请同一岗位会产生新的投递尝试,并保留各自的材料、渠道、状态和阶段时间线。 +_Avoid_: 投递记录、表格行、公司岗位 + +**外部进展信号**: +从邮箱、短信或其他授权渠道同步到 OfferU 的原始求职相关消息及其解析结果。它证明收到了一条消息,但不自动证明某项投递已经进入对应阶段。 +_Avoid_: 投递状态、面试事件、通知 + +**消息证据快照**: +为解释外部进展信号的来源、关联与阶段判断而保存的最小邮件证据,包括消息和线程标识、发送者、时间、主题、相关片段与正文哈希。完整正文默认只在同步和解析期间短暂使用,除非使用者对单封消息显式选择保存。 +_Avoid_: 邮件原文、邮箱缓存、通知正文 + +**短信转发导入**: +由使用者主动分享、粘贴或转发到 OfferU 的短信内容,并作为外部进展信号处理。第一阶段不要求 OfferU 直接读取手机短信库。 +_Avoid_: 短信同步、手机短信接入 + +**本地同步服务**: +在 OfferU 已启动并驻留系统托盘期间运行的个人消息同步能力。它负责发现外部进展信号并提醒使用者,使用者明确退出 OfferU 后即停止。 +_Avoid_: 云端同步、系统守护进程、后台爬虫 + +**系统凭据引用**: +OfferU 数据库中指向操作系统钥匙串条目的不透明标识,连同账号元数据和授权范围使用。OAuth token、IMAP 应用密码等原始密钥只存在 Windows Credential Manager、macOS Keychain 或 Linux Secret Service 中,不进入数据库、配置文件、日志或 Agent 上下文。 +_Avoid_: 加密密码字段、Token 配置、邮箱登录信息 + +**本地加密边界**: +由操作系统钥匙串保护主密钥,并覆盖数据库、简历附件、使用者显式保存的邮件正文、搜索索引、缓存与备份的统一静态加密范围。应用解锁后可以透明读取,但不得产生未受保护的旁路副本。 +_Avoid_: 仅数据库加密、依赖 BitLocker、附件加密 + +**云端数据授权**: +使用者针对具体模型供应商和数据类别授予的发送许可。OfferU 优先在本地解析与脱敏,并在运行前展示将发送的简历、邮件、面试转写或其他敏感数据类别;配置 API Key 只建立连接,不等于授权发送所有数据。 +_Avoid_: API Key 授权、模型权限、隐私开关 + +**候选进展**: +主控 Agent 根据外部进展信号提出的待确认关联与阶段变化。使用者确认前,它不能改变正式投递状态。 +_Avoid_: 正式状态、自动更新、提醒 + +**投递关联建议**: +Agent 从外部进展信号中识别公司、岗位、招聘批次、申请编号和邮件线程,并对可能对应的投递尝试进行排序与解释。确定性标识可以建立候选进展;存在多个合理候选或只有语义相似时必须由使用者选择,Agent 本身没有正式关联和阶段写入权。 +_Avoid_: AI 自动关联、邮件分类、自动推进 + +**投递阶段事件**: +使用者确认后记录的一次投递阶段变化,包含发生时间、来源和前后阶段。它构成投递时间线,并派生当前状态。 +_Avoid_: 状态字段、邮件分类、候选进展 + +**岗位生命周期里程碑轨道**: +OfferU 任务视图对一个已绑定真实岗位的生命周期投影,沿用 `prepared`、`applied`、`written_test`、`assessment`、`interview_1`、`interview_2`、`interview_hr`、`offer`、`rejected` 九个现有业务状态,但不把它们解释为九步线性完成度。笔试、测评和各轮面试可以未发生或被跳过;`offer` 与 `rejected` 是互斥终态分支,拒绝可以从任一投递后阶段发生。投前选择“不投”只结束投前任务,不伪造成 `rejected`,也不创建投递尝试。 +_Avoid_: 九步进度条、完成百分比、跳过即完成、Offer 后再拒绝、用 rejected 表示不投 + +**投递概览**: +从投递尝试及其阶段事件派生的紧凑表格工作区,是投递页的默认主视图,默认呈现当前阶段、下一动作和下一时间,并允许按需显示具体阶段列;进度看板只是同一批数据的辅助视图。它不是投递进展的事实源。 +_Avoid_: 投递表、宽表事实、阶段数据库 + +### 面试训练 + +**面试内容评价**: +基于面试问题、使用者回答、职业证据和岗位档案,对回答质量与岗位能力证据形成的解释性评价。它不使用摄像头信号推断人格或录用概率。 +_Avoid_: 面试总分、AI 打分、综合表现 + +**表达行为反馈**: +基于本地摄像头或音频派生的可观察行为,对姿态稳定、手势次数、语速或停顿等表达方式形成的反馈。它与面试内容评价分开,不代表性格、诚信、情绪或岗位胜任力。 +_Avoid_: 肢体语言分、情绪识别、人格评分 + +**面试评分规则**: +定义面试评价维度、权重、证据要求、阈值、提示和聚合方式的版本化声明。它只能引用明确授权的面试证据,不能执行任意代码或改变面试事实。 +_Avoid_: 评分 Skill、评分 Prompt、打分算法 + +**表达行为事件**: +本地视觉或音频分析识别出的一段可观察行为,包含事件类型、时间范围、置信度和检测器版本。它不包含原始视频、截图或逐帧关键点,也不携带人格或情绪推断。 +_Avoid_: 摄像头数据、Landmarks、肢体语言结论 + +**轮次式语音面试**: +主控 Agent 逐题提问,使用者逐题录音作答,并允许切换到文字输入的面试交互方式。每轮在本地完成端点检测并转写,默认只保存转写、题目时间范围和派生表达行为事件,不保存原始音频。 +_Avoid_: 实时语音面试、全双工面试、录音存档 From 83a73b0d235e17be946a97719f4583110a0f4537 Mon Sep 17 00:00:00 2001 From: avabbbb <89175608+avabbbb@users.noreply.github.com> Date: Wed, 23 Sep 2026 00:21:37 +0800 Subject: [PATCH 06/36] docs(archive): preserve superseded design history --- .../agent-system-harness-era-2026-09.md | 132 ++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 docs/archive/architecture/agent-system-harness-era-2026-09.md diff --git a/docs/archive/architecture/agent-system-harness-era-2026-09.md b/docs/archive/architecture/agent-system-harness-era-2026-09.md new file mode 100644 index 00000000..7d285892 --- /dev/null +++ b/docs/archive/architecture/agent-system-harness-era-2026-09.md @@ -0,0 +1,132 @@ +> **HISTORICAL SNAPSHOT** — archived from `docs/architecture/agent-system.md` on 2026-09-23. It does not define current product or architecture authority. See `docs/product/current-product.md`, `CONTEXT.md`, and `ARCHITECTURE.md`. + +# OfferU Agent 系统总览 + +> 状态:accepted architecture;截至 2026-08-28 已完成部分纵向验收 +> 主决策:[ADR-0051](../adr/README.md#adr-0051) +> 适用:主控 Harness、OfferU 原生工作区、Operation Registry、本地深度执行器 + +## 一句话结论 + +外部 Coding Agent Harness 是 OfferU 唯一的主控大脑;OfferU 自身不是第二个 Agent,而是嵌入 Harness 或由其唤起的本地、确定性、可审计求职操作台和业务控制面。 + +DeepSeek Harness、Codex、Claude Code、OpenCode 与 Pi 可以替换主控会话,但不能改变 OfferU 的事实、授权、确认和审计规则。业务集成只走 CLI-first Agent Bridge,不提供 MCP 业务入口。 + +## 目标拓扑 + +```mermaid +flowchart TB + USER["使用者"] --> SHELL["Harness 原生外壳
会话导航 + 提示输入"] + SHELL --> HARNESS["唯一主控 Harness
DSH / Codex / Claude / OpenCode / Pi"] + SHELL --> UI["OfferU 原生工作区
入口 + 任务视图 + 确认"] + + HARNESS --> HOST["Harness 接入包 host half
只适配宿主能力"] + UI -->|"宿主内类型化通道"| HOST + HOST --> BRIDGE["OfferU Agent Bridge
CLI stdio JSONL"] + + BRIDGE --> RUN["Agent Run / lease / event log"] + BRIDGE --> SKILLS["Skill Registry 投影"] + BRIDGE --> OPS["Operation Registry"] + + OPS --> GATE["schema → grant → proposal
→ OfferU 确认 → 幂等 → 审计"] + GATE --> DOMAIN["岗位 / 职业模型 / 研究 / 材料
投递 / 邮箱 / 面试"] + DOMAIN --> DATA["SQLite / OS keychain / 授权服务"] + + HARNESS --> ARTIFACTS["Run 工件工作区"] + HARNESS -->|委托一个重任务| EXEC["托管深度执行器"] + EXEC --> CANDIDATE["候选结果 + 来源"] + CANDIDATE --> GATE + + UI --> RUN + UI -->|"唯一批准/拒绝入口"| GATE +``` + +DSH `dsh-v0.1.0-rc.8` 是首个原生嵌入基线:同一接入包有 host/client 两面,client half 只使用可加式 slots,host half 独占 `offeru bridge --stdio`。不支持安全 UI 扩展的 Harness 由原生外壳唤起 OfferU companion window;两种形态共享同一控制面,不改变主控归属。 + +## 两条执行路线 + +### 主控 Harness + +主控 Harness 持有模型会话、推理、规划、上下文压缩和工具循环。它从 OfferU 取得经过授权的上下文与 Operations,并把调用、状态、结果和候选工件写回 Agent Run 事件。 + +主控 Harness 不拥有: + +- 业务数据库或职业事实; +- Operation 授权和工作台确认; +- 跨 Run 的隐藏记忆; +- 直接写 OfferU 源码或配置的权限; +- 代表使用者提交申请、发邮件或联系第三方的权力。 + +### 本地深度执行器 + +深度执行器是主控 Harness 委托的一个任务级 Worker,用于公开公司/岗位调研、批量 JD 分析和登记工作源摘要。它由 OfferU 托管生命周期与权限,但不成为第二主脑,也不继承主控 Harness 的隐藏上下文。 + +两条路线都必须经过同一 Operation Registry;区别在于主控 Harness 持有用户目标,深度执行器只持有一个受限重任务。 + +DSH rc8 可按需安装 Codex/Claude Code subagent bundles,但它们属于 DSH 主会话内部编排,默认只形成同一 Agent Run 的嵌套事件,不自动升级为 OfferU 托管深度执行器,也不创建第二个主控 Run。只有经过 OfferU 明确委托、独立 session/workspace/grant 的重任务才进入深度执行路线。 + +## 状态所有权 + +| 状态 | 唯一拥有者 | 可重建来源 | +| --- | --- | --- | +| 开放式目标、推理、计划 | 当前 Harness session | 不要求 OfferU 完整复制 | +| 求职任务与 Agent Run | OfferU | Python 持久化 | +| 已确认职业事实与业务状态 | OfferU 领域服务 | SQLite 与来源链 | +| Skill 与 Operation 能力 | OfferU Registry | 版本化 Registry | +| 待确认提案与决定 | OfferU 工作区/协调器 | 持久化提案、一次性决定 | +| Run 候选文件 | Run 工件工作区 | 当前 Run 目录与清单 | +| Provider 原始事件 | Harness/adapter trace | 可选诊断,不是产品事实 | +| 标准生命周期事件 | OfferU Agent Run Event | 追加式事件日志 | + +## 主控一致性契约 + +一个 Harness 只有同时通过以下能力,才能显示为“支持”: + +1. 能创建、识别和恢复原生会话; +2. 能在运行中追加用户指令或显式报告不支持; +3. 能中断、取消并输出确定终态; +4. 能调用 Run 授权范围内的 OfferU Operations; +5. 能在提案待工作台确认时暂停或安全重试; +6. 能把输出映射为统一事件流; +7. 能把原生文件和 shell 工具限制在 Run 工件区; +8. 版本或能力不满足时显式失败,不静默换到另一个 Harness。 + +Codex 与 DeepSeek Harness 只享有实现优先级,不降低其他三种 Harness 的最终门槛。 + +## 全局不变量 + +- Python/SQL 是唯一业务事实源,Tauri/Rust 只做系统桥接。 +- 产品是本地单人版,不引入 SaaS、多租户、登录、计费或 `workspace_id`。 +- Agent 推断、研究摘要、简历建议、面试反馈和外部消息都先是候选,不是职业事实。 +- GUI、CLI、TUI、浏览器扩展、主控 Harness 和深度执行器共用一个 Operation Registry。 +- OfferU 拥有的嵌入工作区或专注窗口是业务副作用的唯一确认权威;Harness 自身审批只能约束其原生工具,不能批准 OfferU Operation。 +- Run 工件工作区不是 OfferU 仓库,也不是长期记忆。 +- 跨 Harness 故障切换创建新 Run,不伪造隐藏会话连续性。 +- 外部数据默认不可信,凭据和敏感职业数据不得进入日志、工件或未授权模型上下文。 +- 失败必须可见;禁止假分、伪造 JSON、静默降级和“返回成功但没有执行”。 + +## 当前代码与目标的差距 + +截至 2026-08-28,Main Agent UI 已通过 provider-neutral `AgentRuntimeProvider` 消费适配器;Pi 保留为 Provider,Replay/Fixture 用于确定性验收。Operation Registry 的 C1 全局 Route 审计已通过,已知正式业务 mutation 没有 Route 级直接 ORM DML、mutating service 或 Registry 旁路。旧 CLI `confirm`、Pi 命名的兼容入口和实验性 MCP 仍存在,但不属于新的业务集成契约。 + +Codex App Server 适配边界已有结构测试,真实 Codex Provider 仍因本机认证返回 401 而标记 `BLOCKED_EXTERNAL_AUTH`;DSH 的协议/插件基础已有覆盖,但独立 `AgentRuntimeProvider` 尚未完成 live 验收。`job-search` Capability Plugin 已完成自有 Manifest、Skill、CLI 与契约验证,live Role Intelligence 仍需使用该能力单独验收。这些状态不影响已通过的 fixture/replay 产品链,也不应在文档中被表述为实时外部数据已完成。 + +可复用的底座已经存在: + +- `backend/app/ops.py`:Operation Registry; +- `backend/app/services/operation_projection.py`:执行/提案与确认协调; +- `backend/app/services/agent_run_state.py`:Run、事件和恢复; +- `AgentRunRecord` / `AgentRunEvent`:provider-neutral 持久化; +- 工作台 SSE、提案卡和审计界面。 + +迁移原则是先在这些接缝上增加 Bridge 和外部 Harness tracer,再替换 Pi 主路径;不得先删除可运行链路。完整顺序见[迁移路线](../implementation/migration-roadmap.md)。 + +## 主题入口 + +- 内部模块:[Agent 操作控制面](./agent-control-plane.md) +- 机器协议:[Agent Bridge 协议](./agent-bridge-protocol.md) +- 宿主差异:[Harness 接入](./harness-integrations.md) +- 权限与事实门:[Operation 与安全](./operation-security.md) +- 生命周期:[Run 生命周期](./run-lifecycle.md) +- 交互:[OfferU 原生工作区](./workbench-interaction.md) +- 决策历史:[决策账本](../adr/README.md) From 92e42c79ab9181a85dfc5bf999740e63a99925bd Mon Sep 17 00:00:00 2001 From: avabbbb <89175608+avabbbb@users.noreply.github.com> Date: Wed, 23 Sep 2026 00:21:40 +0800 Subject: [PATCH 07/36] docs(archive): preserve superseded design history --- ...rkbench-interaction-harness-era-2026-09.md | 207 ++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 docs/archive/architecture/workbench-interaction-harness-era-2026-09.md diff --git a/docs/archive/architecture/workbench-interaction-harness-era-2026-09.md b/docs/archive/architecture/workbench-interaction-harness-era-2026-09.md new file mode 100644 index 00000000..6c17c22d --- /dev/null +++ b/docs/archive/architecture/workbench-interaction-harness-era-2026-09.md @@ -0,0 +1,207 @@ +> **HISTORICAL SNAPSHOT** — archived from `docs/architecture/workbench-interaction.md` on 2026-09-23. It does not define current product or architecture authority. See `docs/product/current-product.md`, `CONTEXT.md`, and `ARCHITECTURE.md`. + +# OfferU 原生工作区交互 + +> 状态:accepted target design;DSH 映射校准到 `dsh-v0.1.0-rc.8` +> 决策:[ADR-0030](../adr/README.md#adr-0030)、[ADR-0031](../adr/README.md#adr-0031)、[ADR-0053](../adr/README.md#adr-0053)、[ADR-0055](../adr/README.md#adr-0055)、[ADR-0056](../adr/README.md#adr-0056) +> DSH 接缝:[Harness 接入](./harness-integrations.md#deepseek-harness-rc8第一条-tracer) + +## 交互结论 + +本地 Coding Agent 使用者已经把 Harness 当作日常主应用。OfferU 因而不是第二个聊天应用,也不是悬浮在旁边的完整独立工作台,而是嵌入 Harness 的职业操作工作区:Harness 保留提示输入、会话导航和唯一主控 Loop;OfferU 提供求职任务、事实、证据、Operations、候选工件、业务确认和审计。 + +在 DSH rc8 中,同一套 OfferU 领域投影与交互状态由 DSH 原生渲染器呈现为三个表面: + +```text +┌ DSH sidebar ─────────┬ DSH active session ─────────────────────┐ +│ DSH workspaces │ Chat | Trajectory | OfferU │ +│ DSH sessions │ ┌───────────────────┐ │ +│ │ │ OfferU 任务视图 │ │ +│ │ │ 当前 Task / Run │ │ +│ [OfferU 入口/状态] │ └───────────────────┘ │ +└──────────────────────┴──────────────────────────────────────────┘ + └─ OfferU 全局配对/确认浮层(按需出现) +``` + +OfferU 不注册一个永久占据 DSH 中央区域的全局页面。入口和确认可以是 root/global,主视图则属于当前 DSH session。全局职业数据可在任务视图中浏览,但 Agent 动作、授权和事件必须绑定当前求职任务与 Run。 + +## 视觉与共享边界 + +DSH 中的 OfferU 页面直接使用 DSH 原生组件、布局、设计令牌、焦点行为和响应式规则,视觉上属于 DSH,不建立 OfferU 品牌岛。跨 Harness 共享的是类型化领域投影、交互状态机、Operation 合约、确认语义和标准事件,不共享同一套 React 页面或宿主无关视觉组件。 + +DSH client 只实现薄的宿主原生渲染器;领域判断、生命周期规则、权限和业务动作仍由 OfferU 控制面与无头契约拥有。companion window 使用 OfferU 自有渲染器,但必须消费同一投影和状态机,不能因此维护第二份业务状态。跨 Harness 验收业务与交互语义一致,不要求像素一致。 + +## rc8 原生表面 + +| 表面 | rc8 slot | 交互职责 | +| --- | --- | --- | +| OfferU 固定入口 | `sidebar.footer.action` | 连接状态、配对、打开当前 session 的 OfferU tab | +| OfferU 任务视图 | `conversation.view` | 当前 session 内的求职任务、Run、证据、Operations、工件和结果 | +| OfferU 全局浮层 | `shell.overlay` | 配对、业务确认、断连、冲突和跨 session 提醒 | +| 可选 session 动作 | `conversation.session.header.actions` | 请求中断、打开专注窗口等小型快捷动作 | + +这些都是 list/additive slots。实现不得占用 `root`、`sidebar`、`conversation`、`details`、`conversation.session`、`conversation.session.header`、`sidebar.workspaces` 或 `sidebar.settings`;它们是 DSH 核心单席位,注册会造成替换,不是“加一个 OfferU 区域”。 + +## 无活动 session 的入口 + +`conversation.view` 是 session-scoped,因此首次启动或没有活动 session 时只使用固定入口与全局浮层: + +1. 入口显示 `未连接 OfferU`、`待配对`、`已连接` 或 `需要处理`; +2. 点击后在浮层中探测本机 OfferU Bridge,不跳到 iframe; +3. 只有完全空白且未绑定的 DSH session 才显示岗位选择器;使用者从 OfferU 已存在的真实岗位中选择一个,并在 DSH 内创建对应求职任务; +4. OfferU 将该任务一次性绑定当前 DSH session,并展示 profile、preset、cwd 与能力摘要; +5. 关联完成后进入该 session 的 `OfferU` tab; +6. 失败时保留 DSH 当前会话,给出明确原因,不自动切换 Harness 或 preset。 + +“允许此 DSH 接入 OfferU”是配对决定,不是副作用批准。两者必须使用不同标题、对象、有效期和审计事件。 + +## OfferU 任务视图 + +任务视图不复制 OfferU 全局的“今日、机会、材料、进展、面试”导航,也不复制 DSH 的 sidebar、聊天 composer 或 details panel。它只服务当前 session 已绑定的一个真实岗位,并采用任务驾驶舱布局: + +```text +┌ 公司 / 岗位 / 任务与 Run 状态 ────────────────────────────────┐ +│ 生命周期:准备 → 已投递 → 可选环节 … → Offer / 拒绝 │ +├────────────────────────────────────────────────────────────────┤ +│ 当前状态 / 下一动作 / 待确认 / 最近结果 │ +├────────────────────────────────────────────────────────────────┤ +│ 事实、证据、候选工件与阶段详情 │ +├────────────────────────────────────────────────────────────────┤ +│ Run 事件 / Operation / outcome / 诊断(渐进披露) │ +└────────────────────────────────────────────────────────────────┘ +``` + +生命周期轨道沿用九个现有业务状态,但不是线性完成度: + +```text +准备 → 已投递 → [笔试?] → [测评?] → [一面?] → [二面?] → [HR 面?] + └──────────── 任一投递后阶段 ────────────→ Offer + └──────────── 任一投递后阶段 ────────────→ 拒绝 +``` + +方括号节点是可选里程碑。后续阶段已有事实而前置可选节点没有事件时,显示“未发生/已跳过”,不显示“已完成”;`offer` 和 `rejected` 互斥。投前选择“不投”是投前任务结果,不进入 `rejected`,也不创建投递尝试。首个 tracer 虽展示完整轨道,但只有投前决策闭环提供真实可执行动作;后续阶段只显示已有事实、进入条件与明确的“尚未接入”。 + +### 首屏主状态 + +任务视图不把待确认、错误、运行、下一动作和最近结果铺成同权卡片。首屏只突出一个主状态,按以下固定优先级派生: + +1. `待确认`:显示提案对象、影响、证据、有效期和确认入口; +2. `失败/断连`:区分 Bridge 离线、adapter 断开、Run 失败、状态待对账,并给出对应恢复条件; +3. `正在执行`:显示当前 Skill/Operation、开始时间、最新可理解事件和请求中断; +4. `下一动作`:显示现在应做什么、为什么、所需前置事实以及动作归属; +5. `最近完成`:显示经过 outcome 校验的结果以及任务是否仍有下一动作。 + +较低优先级信息保留在阶段详情和 Run 时间线中,但不得与主状态争夺首要按钮。主状态是注意力投影,不写回或覆盖任务、Run、提案和投递阶段事实。 + +不再设计一个侵入 DSH 核心布局的常驻“右侧 OfferU 控制栏”。窄幅状态与动作留在 OfferU tab 内;简历深编、摄像头面试等大画布任务打开同一状态边界的 OfferU 专注窗口。 + +任务视图不能在当前 session 内切换浏览其他岗位。切换岗位必须从固定入口新建或恢复该岗位对应的 DSH session;不能在 A 岗位 session 中仅靠前端选中 B 岗位,就把 B 的上下文注入同一个隐藏模型会话。 + +## Run 顶栏 + +每个关联 Run 明确显示: + +- Harness 名称、真实版本、adapter 与 Bridge 版本; +- DSH profile、agent preset、session ID、Run ID 和 Skill; +- 输入主权,例如 `DSH Chat` 或 `Codex 原生界面`; +- Operations、数据范围、网络和 Run 工件目录; +- 当前阶段:运行、等待确认、中断、对账、完成或失败; +- 主动作:返回 Chat、请求中断、取消 Run、打开专注窗口。 + +不使用“AI 在线”“自动运行中”等模糊状态。adapter 断开但 Run 仍可恢复时,应显示“连接中断,尚未确认失败”。 + +## rc8 tracer 路径 + +首个纵向切片只证明一条只读求职链路: + +1. 精确版本 `0.1.0-rc.8` 的 DSH 以 `offeru` profile 启动; +2. OfferU 固定入口显示 host plugin 与 Bridge 探测结果; +3. 使用者在全局浮层中选择求职任务与 Skill,确认配对; +4. DSH session 的 `OfferU` tab 出现相同 Task/Run identity; +5. 使用者回到 DSH Chat 输入目标,DSH 是唯一提示输入端; +6. host plugin 调用一个真实只读 Operation,任务视图显示同一事件与结果; +7. DSH 给出非空最终回复,OfferU 以领域 outcome 判断是否完成; +8. 刷新 client、重启 Bridge 或卸载 plugin 后,不留下幽灵入口、重复订阅或失控租约。 + +OfferU client half 不向 DSH 会话悄悄注入普通聊天文本。将来若支持工作区 follow-up,仍须经过单输入写入者协议,并显示来源、顺序与宿主接收确认。 + +## 全局确认浮层 + +副作用 proposal 使用 OfferU 自有 `shell.overlay` 表面;DSH 原生 tool approval 与 OfferU 业务确认永远是两件事。确认卡至少包含: + +```text +OfferU 业务确认 +动作:更新投递阶段 +对象:示例公司 / 后端工程师 / Attempt #2 +变化:Interview → Offer +依据:邮件候选 #123(发生于 2026-08-19) +来源:DSH session / Run / Operation update_application_status +有效期:还剩 9 分钟 + +[拒绝] [批准一次] +``` + +规则: + +- 参数、影响、来源、Task/Run 和证据同时可见; +- 敏感值脱敏,但不能脱敏到无法判断动作; +- 只有“批准一次”,没有“本会话全部允许”; +- 重复点击返回同一决定,不执行第二次; +- proposal 过期、Run 结束、数据版本变化或 host 断连时按钮禁用; +- 浮层关闭不等于批准或拒绝,Harness 继续等待或按超时失败关闭; +- DSH 对 shell/file 的原生批准只能进入诊断事件,不能授权 OfferU proposal。 + +浮层由 client half 渲染,但决定必须交给 OfferU 控制面持久化。client half、DSH 模型和 host plugin 都不能自行生成批准。 + +## host/client 数据边界 + +DSH browser client 只取得渲染所需的最小投影:连接状态、Task/Run identity、标准事件、脱敏 proposal、可见领域数据和用户决定结果。它不得: + +- 直接调用 OfferU FastAPI、SQLite、Operation Registry 或任意 CLI; +- 持有 Bridge bootstrap token、数据库密钥或云 Provider 凭据; +- 执行 shell,或把 DSH browser 当作业务 API 客户端; +- 使用 iframe 加载完整 OfferU SPA; +- 捆绑第二份 React,或依赖 DSH 内部 DOM 选择器覆盖核心界面。 + +所有业务请求经过 DSH host half 与 `offeru bridge --stdio`。host/client 类型化通道、断线恢复、背压和身份绑定是 rc8 tracer 的强制验证项;尚未证明时界面显示 `incompatible`,不降级成 HTTP/MCP 旁路。 + +## 事件与工件 + +默认时间线只展示用户可理解的标准事件:读取了哪些已确认事实、选择了哪个 Skill、调用了哪个 Operation、为何等待确认、生成了哪些候选工件、改变了哪些业务状态,以及失败发生在哪一层。模型 token delta、provider JSON、内部 reasoning 和命令噪音折叠到诊断视图;OfferU 不展示或持久化隐藏思维链。 + +Harness 生成的文件先进入候选区: + +| 状态 | 含义 | +| --- | --- | +| `candidate` | 已声明并完成安全扫描,尚未进入正式业务 | +| `needs-fact-review` | 含可能的职业事实,需逐项核对 | +| `accepted` | 已经相应 Operation 接受并关联领域对象 | +| `rejected` | 使用者拒绝,不进入正式状态 | +| `stale` | 上下文或来源变化,需重新生成/核对 | + +“生成成功”不等于“已应用”。任务视图必须说明哪个工件已接受、哪个仍待审核。 + +## 中断、恢复与专注窗口 + +“请求中断”先调用 Harness 原生 interrupt,并显示宿主是否确认、是否有 executing Operation、是否需要对账和能否恢复同一 session。不能恢复时,使用者可以结束 Run,或显式交接到另一 Harness;交接创建新 Run,不迁移隐藏推理或原生进程状态。 + +专注窗口只用于简历深编、面试摄像头/音频、复杂证据核对等大画布任务。它复用同一无头领域投影、交互状态机、Task/Run identity、proposal 与 Operation Registry,并由 OfferU 自有渲染器呈现;它不启动第二个主控 Agent,也不改变 DSH 的提示输入主权。 + +对于没有安全 UI extension point 的 Codex、Claude Code、OpenCode 或 Pi,OfferU 打开消费同一无头契约的 companion window。跨 Harness 一致性要求是 Run、Operations、确认、事件和审计一致,不强求相同组件、slot 名称或布局。 + +## 移动端 + +移动端只支持查看 Run、批准/拒绝、更新投递进展和请求中断。安装 DSH bundle/profile、工件深度审核、简历编辑和面试训练保留在桌面/平板。移动端与 DSH client 共享决定和事件,不建立第二套控制面。 + +## 交互验收 + +- rc8 中出现固定 OfferU 入口、session 级 OfferU tab 和全局确认浮层,卸载后全部清理; +- DSH 的 Workspace/Session 导航、Chat、Trajectory、details 和 settings 仍正常,未被 OfferU 替换; +- 没有 session 时可完成配对/创建流程,但不会显示伪造的全局 Agent 主视图; +- 切换求职任务会切换或创建对应 DSH session/Run,不共享隐藏上下文; +- DSH Chat 是 tracer 唯一提示输入端,OfferU UI 不暗中注入文本; +- 配对、DSH 原生 approval 与 OfferU proposal 确认可清楚区分; +- client 不直连业务 HTTP/数据库/CLI,不使用 MCP、iframe、第二份 React 或核心 slot replacement; +- proposal 参数和影响可核对,批准恰好生效一次; +- 中断、断连、对账、失败和业务 outcome 都有不同状态与下一步; +- 键盘、窄宽度和 reduced-motion 场景可以完成配对、确认与中断。 From 429f20eb7a713a8d0cd9aa899e503d954469f6f0 Mon Sep 17 00:00:00 2001 From: avabbbb <89175608+avabbbb@users.noreply.github.com> Date: Wed, 23 Sep 2026 00:21:43 +0800 Subject: [PATCH 08/36] docs(archive): preserve superseded design history --- .../harness-integrations-dsh-era-2026-09.md | 234 ++++++++++++++++++ 1 file changed, 234 insertions(+) create mode 100644 docs/archive/architecture/harness-integrations-dsh-era-2026-09.md diff --git a/docs/archive/architecture/harness-integrations-dsh-era-2026-09.md b/docs/archive/architecture/harness-integrations-dsh-era-2026-09.md new file mode 100644 index 00000000..90186403 --- /dev/null +++ b/docs/archive/architecture/harness-integrations-dsh-era-2026-09.md @@ -0,0 +1,234 @@ +> **HISTORICAL SNAPSHOT** — archived from `docs/architecture/harness-integrations.md` on 2026-09-23. It does not define current product or architecture authority. See `docs/product/current-product.md`, `CONTEXT.md`, and `ARCHITECTURE.md`. + +# Harness 接入设计 + +> 状态:accepted architecture;宿主 API 仍需实时 probe,当前验收状态见下文 +> 优先级:DeepSeek Harness 与 Codex 第一批,Claude Code、OpenCode、Pi 第二批 +> 共同协议:[Agent Bridge](./agent-bridge-protocol.md) + +## 当前验收状态(2026-08-28) + +- Main Agent UI 消费 provider-neutral `AgentRuntimeProvider`;Pi/Replay 是当前已覆盖的本地适配路径。 +- Operation Registry 的全局 Route mutation 审计为 `PASS_GLOBAL`;适配器、插件和自动化不能把领域写入当作自己的事实。 +- Codex App Server 适配器有结构化协议边界,但本机真实认证仍为 `BLOCKED_EXTERNAL_AUTH`,不得由 OfferU 修改凭据或静默切换 Provider。 +- DSH 仍是可替换的后续 Provider;现有协议/插件资料不等于独立 DSH AgentRun live 验收。 +- `job-search` 是首个真实公开源 Capability Plugin 的实现与契约验证;它的 live Role Intelligence 采集结果必须另行记录为 `PASS` 或 `INSUFFICIENT_SAMPLE`,不能用 fixture 结果代替。 + +## 接入原则 + +每种 Harness 保留自己的会话、模型、compaction、原生工具和事件语义;OfferU 只编写薄接入包,把这些差异映射为同一行为契约。适配层不得包含岗位、简历、投递或职业记忆逻辑。 + +```ts +interface HarnessAdapter { + probe(): Promise; + start(input: StartRunInput): Promise; + resume(ref: HarnessSessionRef): Promise; + steer(input: UserInput): Promise<"accepted" | "unsupported">; + interrupt(reason: string): Promise; + stream(cursor?: string): AsyncIterable; + close(): Promise; +} +``` + +对插件型宿主,adapter 可以运行在宿主进程内;对 app-server/RPC 型宿主,adapter 运行在 OfferU 管理的本地进程边界。两者都通过 stdio Bridge 调用业务能力。 + +## 统一支持门 + +“已安装”不等于“已支持”。每个 adapter 必须通过: + +| 维度 | 必须证明 | +| --- | --- | +| Identity | 真实可执行文件、版本、协议和接入包版本可记录 | +| Session | 创建、恢复、完成与失败可区分 | +| Input | 初始提示、后续提示与运行中转向语义明确 | +| Control | 中断、取消、超时和退出码可归一 | +| Tools | 只暴露当前 Run Operations;参数通过 schema | +| Approval | OfferU 提案只由工作台决定,宿主不能自批 | +| Events | 文本、工具、工件、终态可映射到标准事件 | +| Workspace | 原生文件/shell 工具不能越出 Run 工件区 | +| Recovery | 断开后能恢复或显式标记不可恢复 | +| Failure | 不用假结果、普通文本或另一个 Harness 静默兜底 | + +能力矩阵由 `probe()` 生成并写入 Run,不由文档硬编码。某版本失败时状态为 `unavailable` 或 `incompatible`,不能显示绿色“支持”。 + +## DeepSeek Harness rc8:第一条 tracer + +### 精确审计基线 + +本设计只以官方 tag [`dsh-v0.1.0-rc.8`](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.0-rc.8) 为实现基线,对应 commit `141eb6fef83422698aef7a981029e843e8161534`,不是滚动 `master`。DSH 仍明确标记为 Developer Preview;“rc8 源码存在”只表示可为该 tag 编写接入,不表示接口已成为稳定的第三方兼容层。 + +审计时 npm 的 `next` 指向 `0.1.0-rc.8`,而 `latest` 仍可能指向较早 rc。因此安装器、lockfile、capability report 和验收记录都必须写出 `@deepseek-ai/dsh@0.1.0-rc.8`;裸 `npx @deepseek-ai/dsh ...`、`@latest` 或 GitHub `master` 不能证明运行的是本设计版本。运行时仍以 `dsh --version` 和 composed profile 为事实源。 + +rc8 已直接证实的宿主能力,与 OfferU 的使用方式如下: + +| rc8 能力 | OfferU 用法 | 边界 | +| --- | --- | --- | +| `profile` 按顺序组合 bundles、profile patch、home patch 和 argv patch | 创建独立 `offeru` profile | 启动前检查最终组合,不能只检查包已安装 | +| bundle 用 `dsh.bundle.patch` 声明配置层 | 分发一份 OfferU bundle | bundle 与可运行 profile 不是同一概念 | +| plugin 可用 `ctx.tools.register()` 注册类型化工具 | 注册当前 Run 的最小 OfferU tools | 业务调用仍经 CLI-first Bridge,不用 MCP | +| package 可声明 `dsh.client` 并导出 `./client` | 加载原生浏览器 client half | 这是 rc8 源码支持的预览接缝,不宣称稳定 API | +| Cordis client slots 支持可加式贡献 | 嵌入入口、任务视图与确认浮层 | 只用 list/additive slots,不替换核心单席位 | +| Codex/Claude Code 可按需安装为 DSH Profile Bundles | 作为 DSH 内部 subagent | 不等于 OfferU 的 Codex/Claude 主控 adapter | + +rc8 新增的图片输入、`@` 文件/会话引用、Windows 持久 PowerShell、subagent bundle 和 `dsh web` 自动开浏览器可以保留为 DSH 原生体验;OfferU 不复制这些能力,也不把它们改造成业务入口。 + +### 产品形态:一个安装入口,两面 plugin + +OfferU for DSH 是非官方原生集成,不是 iframe,也不修改 DSH 核心。按 rc8 的 bundle/profile/client 结构拆分: + +- `@offeru/dsh-plugin`:同一插件包的 host half 与 client half;根导出运行于 DSH host,`./client` 是预构建浏览器入口,并在 manifest 声明 `dsh.client`; +- `@offeru/dsh-bundle`:声明 `dsh.bundle.patch`,依赖并启用 plugin,提供专用 preset 的配置资产; +- `offeru` profile:按顺序组合 `@deepseek-ai/dsh-base`、`@deepseek-ai/dsh-web-app` 和 `@offeru/dsh-bundle`; +- 使用者通过精确版本的 `dsh --profile offeru` 进入 DSH 原生界面,DSH 持有提示输入和唯一主控 Loop。 + +建议目录: + +```text +integrations/dsh/ + packages/ + bundle/ + package.json # dsh.bundle.patch;依赖 plugin + cordis.patch.yml # 启用 host/client row 与专用 preset 配置 + presets/offeru/** + plugin/ + package.json # host export、./client、dsh.client、rc8 peers + src/ + host/ + index.ts # apply(ctx) / cleanup + bridge-client.ts # 唯一能启动 offeru bridge --stdio 的一侧 + tools.ts + events.ts + capability-probe.ts + client/ + index.ts + OfferULauncher.tsx + OfferUTaskView.tsx + OfferUOverlay.tsx + shared/contracts.ts + pnpm-lock.yaml +``` + +发布包必须包含预构建 `lib/client.js`、类型与所有运行资产。rc8 的 browser half 使用宿主提供的 React 18 模块;OfferU 必须 externalize/复用宿主 React,不能捆绑第二份 React 或在 DSH 内挂载完整 OfferU SPA。 + +### rc8 原生 UI 投影 + +rc8 没有安全的“全局中央 OfferU 页面”席位。正确投影是由 DSH 原生渲染器消费同一 OfferU 无头契约并呈现的三个表面: + +| OfferU 表面 | rc8 slot | 类型/作用域 | 用途 | +| --- | --- | --- | --- | +| 固定入口 | `sidebar.footer.action` | list / root | 显示连接状态并打开/配对 OfferU | +| 任务主视图 | `conversation.view` | list / session | 作为当前 DSH session 的 `OfferU` tab | +| 全局浮层 | `shell.overlay` | list / root | 配对、业务确认、断连和全局状态 | +| 可选快捷动作 | `conversation.session.header.actions` | list / session | 中断、打开专注窗口等小动作 | + +任务主视图可以浏览全局职业数据,但 Agent 动作始终绑定当前 Task/Run/DSH session。没有活动 session 时,只显示固定入口或浮层中的“选择/创建求职任务并创建 DSH session”流程;不能假造一个脱离 session 的中央 Agent 工作区。 + +严禁注册 `root`、`sidebar`、`conversation`、`details`、`conversation.session`、`conversation.session.header`、`sidebar.workspaces` 或 `sidebar.settings`。这些是单席位或 DSH 核心已占用表面,注册会替换而不是并排扩展核心 UI。 + +client half 必须用 `ctx.slots.inject(slot, () => ctx.slots.register(...))` 等待目标 slot 声明并随 plugin 卸载清理。`dsh.client.inject` 只是包关系信息,不保证 slot 激活顺序。rc8 自带的 trajectory client 是 `conversation.view` 的参考实现,但 OfferU 仍需用 tracer 证明目标 slots 在发布包与实际 profile 中存在。 + +### host/client 与 Bridge 边界 + +浏览器 client half 只负责渲染和用户手势,不能直接启动 CLI、访问 FastAPI、持有数据库凭据或调用 Operation。host half: + +1. probe DSH、Node、adapter 与 OfferU Bridge 的真实版本; +2. 校验 active profile、专用 preset、最终工具集和工作目录; +3. 启动 `offeru bridge --stdio` 并发起配对; +4. 取得 Run、Skill、grant 后注册最小 OfferU tools; +5. 把工具调用、事件和 pending proposal 映射到 Bridge; +6. 通过 DSH 的类型化 host/client 通道向 client half 投影最小 UI 状态; +7. unload 时关闭 Bridge,撤销工具、订阅和租约。 + +第 6 步的具体 rc8 remote seam 必须在 Slice 2 用编译与真实浏览器 tracer 证明;在证明前它是实施验证项,不在文档里臆造稳定方法名。若该 seam 或任一目标 slot 不存在,adapter 报告 `incompatible`,不能在 DSH 内静默退回 iframe、浏览器直连 HTTP 或 MCP。 + +业务确认不能复用 DSH Web/CLI 的原生 approval。DSH 原生 approval 只管理其 shell、文件等宿主工具;OfferU Operation 只能由 OfferU client half 的浮层或同状态边界的专注窗口决定。 + +### 专用 preset 与 rc8 安全边界 + +rc8 的 `Minimal` 不是 OfferU 的最小权限预设:其 Windows 配置已默认启用持久 PowerShell,并包含本地文件能力。`Standard` 还会启用更多 shell、文件、网络、jobs、skills、subagents/workflows 能力。因此第一条 tracer 必须使用 OfferU 自有 preset: + +- 初始只暴露 Bridge 投影的一个只读 Operation; +- 不启用 DSH 原生 PowerShell/Bash、文件读写、文件搜索、网络或 subagent 工具; +- profile 启动后读取最终有效工具集,发现额外工具就拒绝配对; +- 不把 cwd、preset 名称、`tools.restrict` 或提示词当成 OS 隔离证明; +- 后续只有通过 Windows 路径逃逸、secret、进程和网络验收后,才逐项加入原生工具。 + +Bundle 如何让 rc8 发现并选择随包发布的 agent preset 必须由安装 tracer 证明。安装器只调用 DSH CLI/profile 机制,不直接改 DSH 核心;用户选用通用 `minimal`/`standard` 时明确失败,不自动改写其全局默认值。 + +### rc8 subagent 不扩大主控边界 + +rc8 可把 Codex 与 Claude Code 安装为 Profile Bundles,并支持 Codex 的非交互 permission mode 与 named instance。这些是 DSH 主会话内部的 subagent:它们的活动映射为同一个 OfferU Run 下的嵌套事件,不能被记录成第二个 OfferU 主控 Run,也不能借此获得额外 Operations。 + +OfferU 自己的 Codex 主控 adapter 仍是独立第一批接入;`ExecutorSupervisor` 仍只用于 OfferU 明确托管的隔离重任务。不得利用 rc8 subagent 再造一个跨 Harness 业务编排器。 + +### 升级、发布与品牌 + +- 只发布预构建、带 hash 和 lockfile 的 npm/tarball,不依赖 Git 安装时临时构建; +- rc8 release 声明 SQLite 格式不兼容,升级验证使用独立/已备份的 DSH home 与新建 `offeru` profile; +- 每次 DSH 升级重新验证 manifest、profile composition、client boot graph、slots、tool set、host/client relay、Bridge schema 与生命周期; +- 版本或能力不匹配在配对前失败,不在运行中静默降级; +- 产品描述使用“OfferU,兼容 DSH / based on DSH”,包名采用 `@offeru/dsh-*`,并注明非官方、未获 DeepSeek Harness 背书;不把“DeepSeek Harness”放入 OfferU 项目名,也不挪用官方品牌资产。 + +rc8 官方事实源:[tag 源码](https://github.com/deepseek-ai/deepseek-harness/tree/dsh-v0.1.0-rc.8)、[发布说明](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.0-rc.8)、[Developer Preview](https://github.com/deepseek-ai/deepseek-harness/blob/dsh-v0.1.0-rc.8/README.zh.md)、[CLI/profile 组合](https://github.com/deepseek-ai/deepseek-harness/blob/dsh-v0.1.0-rc.8/apps/cli/README.zh.md)、[plugin 开发](https://github.com/deepseek-ai/deepseek-harness/blob/dsh-v0.1.0-rc.8/docs/user/develop/basic/index.zh.md)、[tool 注册](https://github.com/deepseek-ai/deepseek-harness/blob/dsh-v0.1.0-rc.8/docs/user/develop/basic/tool.zh.md)、[bundle/profile 发布](https://github.com/deepseek-ai/deepseek-harness/blob/dsh-v0.1.0-rc.8/docs/user/develop/basic/publish.zh.md)、[品牌规范](https://github.com/deepseek-ai/deepseek-harness/blob/dsh-v0.1.0-rc.8/BRAND_GUIDELINES.zh.md)。client half 与 slots 还应逐 tag 对照 [`ui-trajectory`](https://github.com/deepseek-ai/deepseek-harness/blob/dsh-v0.1.0-rc.8/packages/client/ui-trajectory/src/client/index.ts) 和 rc8 client package manifests;它们属于源码级预览证据,不提升为稳定兼容承诺。 + +## Codex:第一批完整接入 + +首选接入为 `codex app-server --listen stdio://`,不是屏幕抓取或固定 `codex exec` argv。App Server 提供 thread/turn 生命周期、JSONL 通知、中断和版本匹配的 schema 导出。 + +目标 adapter: + +```text +integrations/codex/ + adapter/ + app-server-client.* + schema-probe.* + event-map.* + tool-dispatch.* + skill/ + SKILL.md # 只含 OfferU 工作方式与实时发现入口 +``` + +启动流程: + +1. probe `codex --version`,导出当前 app-server JSON Schema; +2. 以 Run 工件目录作为 cwd,启动 stdio app-server; +3. initialize 后创建/恢复 thread; +4. 把当前 grant 投影为 dynamic tools; +5. 收到 `item/tool/call` 时调用 OfferU Bridge; +6. 把 pending proposal 保持为工具等待或结构化 pending 结果; +7. 映射 item/turn events,并用原生 `turn/interrupt` 中断。 + +Codex 官方当前把 `dynamicTools` 标记为 experimental,因此第一版必须精确 pin 版本并执行 capability probe。若 dynamic tools 不可用,生成 Skill + shell CLI 只能作为开发兼容模式,不能标记为完整支持。OfferU 不修改用户的 Codex Plus/OAuth 配置,不写 `auth.json`,不把会话切到第三方 API bridge。 + +Codex 自己的 command/file approval 与 OfferU 业务批准是两层独立权限。Codex 只能在 Run 工件目录使用原生工具;即使 Codex UI 批准了一条 shell 命令,也不能因此批准 OfferU proposal。 + +官方资料:[Codex App Server](https://developers.openai.com/codex/app-server)。 + +## Claude Code、OpenCode 与 Pi + +第二批仍需完整同构,不做“只能发一次提示”的缩水支持。 + +| Harness | 首选原生 seam | 进入实现前必须证明 | +| --- | --- | --- | +| Claude Code | stream-json / Agent SDK 能力 | session resume、结构化事件、interrupt、受控工具/权限 | +| OpenCode | JSON run/session 或稳定 server seam | session identity、续接输入、取消、事件与 cwd 限制 | +| Pi | 外部 RPC/CLI session | 不依赖 OfferU 内置 Worker;Run 独占 session、工具投影和终态 | + +如果某宿主当前版本缺失 steer、恢复或工具暂停能力,adapter 应报告具体缺口。只有补齐或明确改变产品一致性契约后才能标记为支持,不能用轮询普通文本冒充事件协议。 + +## 主控与深度执行 adapter 不共用 + +同一个 Codex 或 Claude 可同时出现在两类目录,但 adapter 职责不同: + +- 主控 adapter:服务一个 Agent Run,拥有用户目标和完整对话; +- executor adapter:服务一个受限重任务,只返回 candidate 和来源。 + +两者不得复用 session、工作目录、幂等命名空间或未清洗上下文。`coding_agent_runtime.py` 等现有 hosted executor 代码不直接升格为主控 adapter。 + +## 发布与升级 + +- 每个 adapter 独立版本,记录支持的 Harness 版本区间与 Bridge 版本; +- 所有安装/升级入口先显示将安装的本地包、来源、hash 与权限; +- 禁止在线下载并执行未固定版本的脚本; +- conformance 报告包含 Windows 环境,因为 OfferU 首要桌面环境是 Windows; +- 升级失败保留上一已验证 adapter,不改变当前 Run;已运行 Run 不在中途换版本。 From 77592e7b682f7cadc4e1e3e9d19c503973ec95c6 Mon Sep 17 00:00:00 2001 From: avabbbb <89175608+avabbbb@users.noreply.github.com> Date: Wed, 23 Sep 2026 00:21:46 +0800 Subject: [PATCH 09/36] docs(archive): preserve superseded design history --- .../designs/role-intelligence-v0-design.md | 227 ++++++++++++++++++ 1 file changed, 227 insertions(+) create mode 100644 docs/archive/designs/role-intelligence-v0-design.md diff --git a/docs/archive/designs/role-intelligence-v0-design.md b/docs/archive/designs/role-intelligence-v0-design.md new file mode 100644 index 00000000..e27d18fe --- /dev/null +++ b/docs/archive/designs/role-intelligence-v0-design.md @@ -0,0 +1,227 @@ +> **HISTORICAL SNAPSHOT** — archived from `ROLE_INTELLIGENCE_V0_DESIGN.md` on 2026-09-23. It does not define current product or architecture authority. See `docs/product/current-product.md`, `CONTEXT.md`, and `ARCHITECTURE.md`. + +# Role Intelligence v0.1 设计审计 + +状态:现状审计、G1–G3 后端切片、最小 Collection Provider seam 与 fixture-backed Job Detail / Evidence Gap 切片已落地。G2A fixture corpus 已有验证证据;G2B 真实外部采集仍因 Codex Auth 401 阻塞。G4/G5 fixture-backed Job Detail 链已通过浏览器 smoke 与人工质量复核,但真实市场质量尚未通过;Interview、DSH provider 和 live collector 不在本轮。已记录非阻塞静态资源问题:`http://127.0.0.1:7410/favicon.ico` 返回 404。审计/开发日期:2026-08-27。 + +## 1. 结论 + +审计时 OfferU 已经具备这条纵向闭环所需的控制面和执行面,但还没有“岗位基准”领域模型。随后 G1–G3 按本设计复用现有 `Job` 和 Deep Executor,在 Python Runtime 新增确定性的 benchmark/capability/delta 业务层;当前 fixture-backed 产品切片继续沿用这条边界,结果不塞进研究 Markdown,DSH 也没有成为业务事实源。 + +本轮实际确认: + +- `jobs` 已保存目标岗位的标题、公司、URL、原文和 `hash_key`,作为目标及“本地已有 comparator”的统一岗位身份源;外部临时 comparator 不应强行写入 Jobs Inbox。 +- `JobResearchRun`、`ResearchEvidenceSnapshot`、`ResearchFinding` 是单岗位公开网页研究的证据链;它们不是 30 份 JD 的 cohort 或统计模型。`ResearchEvidenceSnapshot` 还直接依赖 `job_research_runs`,不能用多态 `run_id` 旁路复用。 +- `ProfileSection` 是当前 Career Evidence 载体;没有独立的 `CareerEvidence` 表。只能读取 active/verified evidence,不能由 Interview 自行猜测候选人能力或改写 Profile。 +- `Interview`、`InterviewMessage`、`InterviewEvaluationRun` 已覆盖逐题会话、评分和完成后的 Learning Observation,可作为专项训练的执行面。 +- `DeepTaskSpec`/`execute_deep_task` 已支持受限重任务、运行时能力探测、公开网页模式、会话与 trace;`DeepExecutorRoleCollectionProvider` 通过这个既有执行面接入 `role_benchmark`,不需要另建后台体系。 +- Role Intelligence Core 不再把采集实现作为隐式调用:`RoleCollectionProvider` 现在有现有 Deep Executor adapter 和明确的 `ReplayRoleCollectionProvider` fixture adapter;两者都只返回 candidate envelope,业务写入仍由 Python Runtime 完成。 +- 审计时 live CLI 为 122 个 Operation、33 个 Skill;本轮注册了 4 个 Role Benchmark/Capability/Delta Operation,live manifest 当前为 126 个 Operation,并新增 `role_intelligence` Skill。 +- DSH 当前本地改动属于 Slice 2 host/client tracer;其职责仍应是可替换的并行执行器。未验收的 DSH 改动本轮不触碰。 + +## 2. v0.1 范围与不变量 + +目标入口仍是现有 Job Detail:用户点击“分析这个岗位和同类岗位有什么不同”。闭环为: + +```text +Job + -> Role Classifier + -> Collector candidates + -> Normalized JD + evidence + -> Runtime dedupe/cohort + -> deterministic market frequency + -> deterministic target delta + -> verified ProfileSection evidence gap + -> existing Interview focus plan +``` + +固定规则: + +- 目标岗位必须是现有 `job_id`;已在本地岗位库中的 comparator 可通过 `job_id` 关联。外部 comparator 只作为本次 benchmark 的有边界 JD 快照保存,不创建第二套通用岗位库,也不污染普通岗位 Inbox。 +- cohort 至少匹配 `role_family + specialization + seniority`;地区、行业是可选过滤条件。目标样本 30,最低 15,最多 50。 +- 去重顺序固定为 canonical URL、公司+职位+描述 hash、招聘平台转载关系;最终分母是去重、结构化、通过 cohort 的有效 comparator 数。 +- 少于 15 个有效样本时保存运行和证据,但 UI 必须显示“样本不足”,不输出貌似精准的百分比或高置信结论。 +- LLM 只返回角色分类、能力观察、原文证据和候选 alias;市场频率、方向、排序、evidence gap 分数均由 Runtime 计算。 +- 第一版不接 DSH 作为必需依赖,不重写 `coding_agent_runtime.py`,不引入常驻 `RoleIntelAgent`,不自动修改简历或 Profile。 +- fixture/replay runtime 只用于本地开发验收,UI 必须显示 Fixture 数据模式;它不代表实时市场数据,也不能替代 G2B live collection。 + +明确不做:永久全网岗位库、实时招聘 SaaS、1000+ 抓取、向量数据库、完整 Lightcast taxonomy、自动改简历/Profile、新 Agent Control Plane、LLM 计算百分比。 + +## 3. 最小领域模型 + +当前已新增并确认 4 个最小持久对象: + +| 对象 | 关键字段 | 作用 | +| --- | --- | --- | +| `RoleBenchmarkRun` | `run_id`、`target_job_id`、`cohort_json`、`valid_sample_count`、`source_summary_json`、`algorithm_version`、`schema_version`、`runtime_id/version`、状态、时间 | 一次 benchmark 的可复现边界与生命周期 | +| `RoleBenchmarkDocument` | `run_id`、可选 `job_id`、`document_kind`、canonical URL、description hash、来源、原文/摘录引用、`role_family`、`specialization`、`seniority`、`domain`、normalized schema/version、纳入/排除原因 | target/comparator 的 benchmark 作用域 JD 档案;已有岗位以 `Job` 为身份,外部候选只保留本次快照 | +| `RoleCapabilityObservation` | `run_id`、`document_id`、`capability_id`、`category`、`importance`、`evidence_text`、`source_section`、`confidence`、canonicalization 状态 | 逐 JD 的可追溯能力观察;未知能力只能是 candidate | +| `RoleDeltaSignal` | `run_id`、`capability_id`、`category`、`target_importance`、`market_frequency`、计数、`direction`、`confidence`、`evidence_refs_json` | Runtime 产出的 Common/Distinctive/Highly Distinctive/Missing Common | + +这不是第二套通用岗位库:`RoleBenchmarkDocument.job_id` 在可用时指向现有 `jobs.id`,新表仅保存本次 benchmark 的快照、结构化版本、证据引用和统计结果。由于现有研究 evidence 的外键只接受 `JobResearchRun`,benchmark evidence 不应伪装成既有研究 snapshot;如未来需要跨域引用,应增加明确的关系,而不是改成多态外键。 + +统一 JD Schema 固定为: + +```json +{ + "schema": "offeru.role_jd.v1", + "role_family": "product_manager", + "specialization": "ai_agent", + "seniority": "entry|mid|senior|unknown", + "domain": "string", + "responsibilities": [], + "hard_skills": [], + "business_capabilities": [], + "behavioral_requirements": [], + "domain_knowledge": [], + "outcome_expectations": [], + "constraints": [] +} +``` + +能力观察必须保留原文,不接受只有标签的结果: + +```json +{ + "capability": "model_evaluation", + "category": "technical_product", + "importance": "must_have", + "evidence_text": "负责大模型能力评测体系建设", + "source_section": "responsibilities", + "confidence": 0.94 +} +``` + +## 4. Alias、cohort 与 Delta 算法 + +Alias 是版本化的确定性配置,例如 `agent_harness / agent_framework / agent_infrastructure -> agent_runtime`。Normalizer 可以返回 `candidate_capability`,但未知概念不能改变 taxonomy,也不能进入正式频率分母,直到人工/版本配置确认。 + +Runtime 只对有效 comparator 计算: + +```text +market_frequency(capability) = comparator_with_capability / valid_comparator_count +priority = importance_weight + * log((N + 1) / (df + 1)) + * extraction_confidence +``` + +重复观察按固定 importance 优先级和最高有效 confidence 合并;展示百分比由保存的计数/分母计算,不能接受 LLM 返回的百分比。 + +初版方向规则: + +```text +Common target 出现 且 frequency >= 55% +Distinctive target 出现 且 target >= medium 且 frequency <= 25% +Highly Distinctive target=must_have 且 frequency <= 15% +Missing Common target 未出现 且 frequency >= 55% +``` + +结果排序、四舍五入、并列顺序、置信度聚合必须写成纯 Python 函数,并使用固定 fixture 验证重复运行得到完全相同的数字。Company Delta(同公司相似岗位、同行公司同岗位)作为同一模型的后续 cohort,不阻塞 v0.1。 + +## 5. Deep Executor 与 DSH 边界 + +新增任务契约:`task_type="role_benchmark"`,结构化输出版本例如 `offeru.role_benchmark_candidate.v1`。执行器只能返回 candidate JD、分类、normalization 和证据,不得调用 OfferU 写 Operation、直接写 SQLite 或把文件产物当事实。 + +采集边界通过一个最小 provider contract 固定下来: + +```text +RoleCollectionRequest + ↓ +RoleCollectionProvider.collect() + ↓ +candidate envelope + ↓ +OfferU Runtime validation / dedupe / cohort / aggregate / persistence +``` + +当前实现: + +- `DeepExecutorRoleCollectionProvider`:适配现有 local/coding deep executor,保留 `DeepTaskSpec`、公开网页能力和 `role_benchmark` task type。 +- `ReplayRoleCollectionProvider`:读取固定去标识化 corpus,仅供 `runtime_id=fixture|replay` 的本地 UI/Operation 验收;不会访问外部网页。 +- `RoleCollectionProvider` 不拥有数据库 session,也不产生 `RoleBenchmarkRun`、Document 或 Signal;因此 Codex 401 只会阻塞 G2B,不会阻塞 schema、统计和产品层开发。 + +建议的受限拓扑是 1 个 Classifier、2–4 个按来源/查询方向分工的 Collector、8–12 个批量 Normalizer、Python Aggregator,以及只验证最重要 3–5 个 Delta 的 Verifier。它们都受同一 Run、workspace、网络范围和超时限制;如果当前 Local adapter 尚未支持并行,先使用相同 `DeepTaskSpec` 的固定批次,不因此重写 deep executor。 + +DSH 后续只实现同一 provider contract:使用 `ctx.web` 的 `web_search/web_fetch` seam,模型不看到具体搜索 provider;worker thread 是执行隔离而不是安全 sandbox。因此 DSH 只能产生 evidence candidate 和 structured handback,OfferU Runtime 才负责去重、cohort、统计、持久化和失败可见性。 + +上游文档复核: [DSH workflow worker-thread](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/workflow/workflow-worker-thread/README.md)、[DSH web subsystem](https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/subsystems/web.md)、[DSH web tools](https://github.com/deepseek-ai/deepseek-harness/blob/master/packages/web/tool-web/README.md)。仓库路线中的 rc8 是当前集成基线,不是“当前 master 已验收”的版本证明。 + +## 6. Operation、Skill 与产品入口 + +沿用现有 `start_*`/`get_*` 命名习惯,当前已注册 Operation 与后续 G6 规划如下: + +| Operation | side effects | 说明 | +| --- | --- | --- | +| `build_role_benchmark` | `external + llm + write` | dry-run 生成 proposal;确认后启动 Run | +| `get_role_benchmark` | `read` | 读取 Run、样本量、来源、状态、版本 | +| `refresh_role_benchmark` | `external + llm + write` | 复用目标与 cohort,重新收集/规范化 | +| `list_role_delta_signals` | `read` | 读取确定性 Delta 及 evidence refs | +| `prepare_role_interview_focus` | `read + llm` | G6 规划,当前尚未注册;生成未持久化 Focus Plan,保存时仍经现有 Interview Operation | + +所有入口继续走 `ops.py` 的 live schema、权限、dry-run、确认提案、审计、幂等和错误语义。GUI/CLI/Harness/Skill 只调用 Operation,不直接访问服务、数据库或 DSH。Job Detail 的 fixture 按钮也只调用 `build_role_benchmark(runtime_id="fixture")`,并在界面明确告知这是本地 fixture。 + +新增一个 Registry-only `role_intelligence` Skill,当前白名单只覆盖读取目标 Job/Profile Evidence 和已注册 benchmark Operations;Focus Plan 留待 G6。它不是常驻 Agent。`interview_practice` 继续负责会话,`company_research` 继续负责单岗位/公司研究,`batch_evaluate` 继续负责岗位匹配评分,三者不合并职责。 + +Job Detail 已在现有摘要与研究证据区域之间增加岗位情报卡:Benchmark(样本数/公司数/更新时间/数据模式)、Role Family/Specialization/Seniority、Distinctive、Common、Missing/De-emphasized。每行可展开 target evidence、market count/frequency、confidence、comparator evidence 和 source jobs;失败、样本不足、fixture 和未验证 candidate 必须可见。当前只提供 fixture-backed 开发入口,不提供 live 采集按钮。 + +## 7. Career Evidence 与 Interview 接缝 + +Profile gap 只能来自 active `ProfileSection`,优先 `verified_fact`。当前 v0.1 的匹配使用版本化、确定性的 capability terms;每个链接包含真实 `profile_section_id` 和原文摘录。Runtime 根据 section 状态、tier、confidence 和匹配证据计算 `role_distinctiveness × evidence_gap`,未链接证据不得产生分数。当前结果通过 `get_role_benchmark` 返回给 Job Detail;没有自动修改 Profile。 + +不新增 Interview 产品或表。`prepare_role_interview_focus` 返回版本化 Focus Plan;现有 `create_ai_interview` 保存时将每道题的 `why_asked`、`delta_refs`、`evidence_refs`、`evidence_gap`、`type` 与现有问题字段一并写入 `questions_json`,并由严格 validator 校验。题型至少覆盖 Proof、Depth、Trade-off、Scenario、Contradiction。Interviewer 只提问和追问,不展示教答案;Coach 在结束后使用既有 evaluation/report 输出训练建议。 + +面试新认知只进入现有 Learning Observation/Memory Inbox;不自动修改 Profile。点击“开始专项拷打”应绑定目标 `job_id` 与 benchmark/focus 版本,再启动现有 Interview Operation,不能绕过确认、模型和数据同意。 + +## 8. Fixture 与 Gate + +固定 fixture:1 个去标识化 target JD + 至少 20 个 comparator JD,人工标注预期 3–5 个 distinctive capability;当前已覆盖去重、alias、cohort、frequency、delta、少样本门槛、snapshot round-trip 和 provider seam,并新增 profile gap 的确定性测试用例。focus plan 留待 G6;统计层测试不调用 LLM。 + +| Gate | v0.1 通过证据 | +| --- | --- | +| G1 数据结构 | target/comparator 都得到统一 schema、能力观察和原文证据 | +| G2A Corpus pipeline | fixture/输入 JD 得到至少 15 个去重且高相关 comparator;低样本明确拒绝正式频率结论 | +| G2B Live collector | 真实 target 经外部 provider 得到至少 15 个去重且高相关 comparator;当前因 Codex Auth 401 BLOCKED | +| G3 Delta | 纯 Python 重复运行数字和方向一致,少样本明确阻断精确百分比 | +| G4 OfferU Control | 所有入口共用 Operation Registry;写入有 proposal/confirm/audit;fixture build 已从 Job Detail 触发并通过浏览器 smoke | +| G5 Product | Job Detail 已展示 Delta、样本量、证据、来源明细和 fixture 标记;signal 展开后 Evidence Gap 可见并通过浏览器 smoke 与人工质量复核;真实市场质量仍未验收 | +| G6 Interview | 专项训练使用 Delta × 已存在 Profile Evidence Gap,完成一轮且新认知进入 Learning Observation | + +任一 Gate 未通过,不进入 Company Delta、DSH 并行优化或更大 taxonomy。 + +## 9. 已实施、验证结果与后续授权边界 + +当前 Gate 状态:G1 PASS(已有 targeted fixture/round-trip 证据);G2A PASS(fixture corpus、dedupe/cohort、低样本门槛已覆盖);G2B BLOCKED — Codex Auth 401(不要把环境阻塞写成 Role Intelligence FAIL);G3 PASS(纯 Python 两次运行完全一致,频率/方向按 fixture 数字断言,少样本不产出 signals);G4/G5 fixture-backed 浏览器 smoke 与人工质量复核 PASS,但仅证明 fixture 内部链路与可解释性,不证明真实市场质量;G6 未开始。 + +本轮实机验收记录: + +- Job `#75` fixture-backed Job Detail:20 个 comparator、5 个唯一 signal;每个 signal 均有 target/comparator evidence 或明确的 target 未出现状态,展开后可见 Evidence Gap、样本量、频率和来源链接。target/comparator fixture 的 capability 与 evidence_refs 一致,没有发现重复 signal 或空结论。 +- 质量边界:`#75` 的 target、`Comparator Co 01..20` 与 `jobs.example.org` 来源均为合成 fixture;因此相关性和证据只能判定为“fixture 内部一致”,不能判定为真实岗位市场质量。当前 profile 没有匹配证据时 UI 显示 `0/100` evidence strength 与缺少证据提示,没有伪造个人经历。 +- Job `#50` live smoke:`POST /api/research/role-benchmarks/50/build` 已进入 `data_mode=live`,run `role_benchmark_c19e755e521e4b64aac86a558268369e` 最终因 Codex App Server 请求 `https://api.openai.com/v1/responses` 返回 `401 Unauthorized: Missing bearer or basic authentication` 失败,样本数为 0。该项登记为 G2B 运行环境阻塞,不修改认证、不恢复旧 runner、不绕过 Workflow/Executor。 +- 非阻塞问题:浏览器控制台发现 `http://127.0.0.1:7410/favicon.ico` 404;Job Detail、benchmark API、fixture build、轮询和展开证据链均正常,因此本轮不修。 + +本轮新增/修改边界: + +```text +backend/app/models/models.py +backend/app/services/role_intelligence.py +backend/app/services/agent_operations.py +backend/app/ops.py +backend/app/services/agent_skill_registry.py +backend/app/routes/research.py +backend/tests/test_role_intelligence.py +backend/tests/fixtures/role_intelligence_v0/* +frontend/src/lib/api.ts +frontend/src/components/jobs/RoleIntelligencePanel.tsx +frontend/src/app/jobs/[id]/page.tsx +``` + +本轮明确没有扩大到: + +```text +backend/app/services/ai_interviews.py +integrations/dsh/** +coding_agent_runtime.py +live G2 collector re-run +``` + +下一 Gate 是产品负责人确认是否接受当前 fixture-backed G4/G5 证据;在 G2B Codex 认证恢复并完成一条真实非 fixture smoke 前,不把真实市场质量写成 PASS,也不进入 Interview Focus。当前工作区已有的未提交改动保持原样。 From a3419aacb97fa2c93f3768fabcf672f77d397624 Mon Sep 17 00:00:00 2001 From: avabbbb <89175608+avabbbb@users.noreply.github.com> Date: Wed, 23 Sep 2026 00:21:49 +0800 Subject: [PATCH 10/36] docs(archive): preserve superseded design history --- .../reviews/product-critique-2026-09.md | 581 ++++++++++++++++++ 1 file changed, 581 insertions(+) create mode 100644 docs/archive/reviews/product-critique-2026-09.md diff --git a/docs/archive/reviews/product-critique-2026-09.md b/docs/archive/reviews/product-critique-2026-09.md new file mode 100644 index 00000000..1819b5ce --- /dev/null +++ b/docs/archive/reviews/product-critique-2026-09.md @@ -0,0 +1,581 @@ +> **HISTORICAL SNAPSHOT** — archived from `docs/PRODUCT_CRITIQUE_2026-09.md` on 2026-09-23. It does not define current product or architecture authority. See `docs/product/current-product.md`, `CONTEXT.md`, and `ARCHITECTURE.md`. + +# OfferU 产品设计拷打(2026-09-20) + +> 视角:严格、以证据为准的产品评审。前轮记录、当前代码、实际诊断和推断必须分开;涉及私密素材的工件留在本机,不复制简历、JD 正文或凭据到本文。 +> +> 立场:统一操作入口、职业事实分层与人工确认值得保留;本轮主要质疑能力声明、评测有效性、任务交付与用户负担,不凭架构面积给产品判死刑,也不以静态审阅承诺安全。 + +> **续审修订说明**:本文件是评审意见,不是已批准的实施路线,不修改 accepted ADR。前文部分结论曾把局部验证扩大成完整验收;以新增 §13–§24 的逐项核验为准。特别撤回“全 journey 闭环”“OMP 已证明使用 SWE-2 Max”“90–94% 代表整体 Agent 能力”“其余问题都是外部阻塞”。这也包括评审 Agent 自己此前作出的不准确报告。 + +--- + +## 0. 一句话诊断 + +**当前最值得质疑的不是代码数量,而是为一个用户完成一个岗位任务,需要协调多少他不该理解的运行细节。** 前轮记录有 261 个 Operation;数量只能说明接口面积,不能证明过度设计。五个 journey 的部分路径已被验证,但不能据此声称全部端到端完成,具体勘误见 §13。 + +这不是工程问题,是**产品先于用户成熟**的问题。 + +--- + +## 1. 外部 Agent 依赖没有被转化为可预测的用户体验 + +### 证据 +- E1 `CONTEXT.md:7-9` — 主控 Agent "是理解目标、自然语言推理、任务规划和选择 Operation 的**唯一智能主体**";OfferU 自己 "不含 LLM loop"(`:12`)。 +- E2 已保存的 codebuddy 运行有 30 个评分结果,其中 13 个没有首选 Skill 或 Operation;这些轨迹中提到了授权相关问题,不能仅凭 `no_operation_called` 认定同一根因,更不能一概称为超时。 +- E3 曾观测到 Codex 当前配置的配额错误。它不证明其他模型供应商也不可用;OfferU 自身 LLM 代理的 401 是另一个独立故障。 +- E4 claude 登出、opencode blocked、gemini/pi 未安装(`get_agent_connections` 7 provider 里 0 个 ready)。 +- E5 LLM 代理 `127.0.0.1:8317` 401 → 简历改写诚实退化 `rewrite_status=degraded`,即"原文照抄"。 + +### 拷打 +主控 Harness 不可用会阻塞智能任务,但并不等于 OfferU 的手工编辑、已有材料查看等确定性功能也不可用。真正的问题是:用户能否在任务发起前知道哪些能力可用,失败后能否保存进展并继续,而不是由用户临时充当系统集成工程师。 + +“支持某个 Harness”必须指向已通过的行为契约,而不是安装了程序、能执行一次只读调用或某次探测显示 ready。现有证据不足以对所有宿主作完整支持或完整不支持的断言。 + +### 砍法 +- 保留 ADR-0051 的唯一主控 Loop,优先验收一个用户明确选择的宿主;不能因为 OMP 的人工编排返回了结果,就擅自替换用户要求的 Codex Desktop。 +- 恢复、取消、确认等已承诺契约不能被静默删掉。可以缩小公开宣称的支持范围,但必须明确记录尚未验收的部分。 +- 单次 LLM 调用不等于第二套主控 Loop。先拆清 Harness 推理与 OfferU 内部模型调用的依赖、模型选择和授权,再讨论人工替代路径;新增内置 Agent 不是已被证明必要的答案。 + +--- + +## 2. 领域语言应该降低协作成本,而不是靠长度证明严谨 + +### 证据 +- E6 `CONTEXT.md` 377 行,60+ 个术语,每个带 `_Avoid_` 反词表。如"OfferU 工作区" 的 Avoid 列表:独立主应用、OfferU Agent 聊天、Harness 侧栏替代品、嵌入网页副本。 +- E7 决策账本包含 ADR-0055、0056、0057 等后续条目;此前“编号到 0054”的说法不准确。评审必须读最新决定,而不是凭目录规模判断架构。 +- E8 文档定义了本地深度执行器、执行器适配器、托管执行会话、任务能力授权、Run 工件工作区、Run 工具授权、可审计重任务、CareerTask、Agent Run 和 Agent Run 事件。它们分别解决什么问题、哪些必须暴露给用户,需要逐项解释,不能仅凭名称断言重复。 +- E9 前轮计数为 261 个 Operation,其中 171 个 mutation。这个比例不等于用户实际写多读少,也不能单独证明“系统在改自己”;需要实际调用与任务完成证据。 + +### 拷打 +大量执行术语是否有价值,要看它们有没有让权限、状态与职责更清楚。不能仅凭文档长就判定过度设计,也不能把术语形成原因归咎于作者情绪。 + +真正的问题是:哪些词必须进入用户界面,哪些只属于开发接口?如果完成一次求职任务必须先理解十种内部状态,即使每个术语都正确,界面仍失败。 + +优先向用户解释“现在在做什么、要我确认什么、结果在哪、失败后怎么办”。内部执行概念应为这四个问题服务,而不是变成用户的先修课。 + +### 砍法 +- 将用户可见概念与内部执行术语清楚分层;是否拆文件应遵循项目的单上下文约定,不把固定行数当质量门。 +- 保留有助于避免语义混淆的术语约束;不要用“删到固定行数”或“全部交给 lint”代替设计。先移除用户首屏不必理解的内部概念。 +- 按实际任务审计 Skill 与 Operation 的发现成本,而非凭调用少就删功能。缩小发现范围是否提高准确率,需要同题、同模型的对照实验。 + +--- + +## 3. "诚实降级"做成了功能,但用户体验是"什么都没发生" + +### 证据 +- E10 简历改写 LLM 失败 → `rewrite_status=degraded`,proposal 内容 = 原文逐字(`resume_optimize_support.py:562-656`)。红队评为"VERIFIED 不伪造成功"。 +- E11 `prepare_pre_application_decision` LLM 401 → 直接抛错,不生成决策(W_Loop 日志)。下游"投前决策闭环"卡死,简历工作区不开放(`resume_workspace` gate: `needs_decision`)。 +- E12 Role Intelligence fixture 模式 → 3 个完全不同的岗位(AI 工作台 PM / 彩铃渠道 PM / 视觉生成运营)**产出完全相同的 5 个信号**(`role_benchmark_29062c…`/`30f7de…`/`ec3c33…` 结果一致)。UI 标了"Fixture benchmark:仅用于本地产品验收"。 +- E13 用户在本轮评分环节的原话:"我这里没有显示可视化界面啊 / 看不到 / 看不到根本"。 + +### 拷打 +"不伪造成功"是对的底线,但你把底线当成了产品。**一个 `degraded` 的简历提案对用户来说和没有提案一样无用**——他要的是改好的简历,不是一个诚实的失败标签。 + +E11 更糟:投前决策失败 → 简历工作区锁死。这个门("只有确认投或有条件投才能生成简历提案",`CONTEXT.md:276`)在产品逻辑上自洽,但在 provider 不可用时变成了**用户被自己产品的严谨性锁在外面**。他有 JD、有简历、想改,系统说"先等 AI 给你投前决策,AI 现在 401"。 + +E12 是 fixture 设计缺陷:fixture 应该至少**随目标 JD 的 role_family/specialization 变化**,否则它验证的只是"管道不崩",不是"信号有意义"。你让用户对三个岗位相同的信号打分,他当然打不出来。 + +### 砍法 +- 每个 LLM 依赖的 Operation 都必须有**人工替代路径**,不是 `degraded` 标签:简历改写失败 → 直接开手动编辑工作区(fact-gate 照常拦);投前决策失败 → 允许用户手填"投/不投/有条件"跳过 AI 建议,但记录 `decision_source=manual`。 +- 投前决策门当前是 accepted ADR-0034,不能因 provider 失败擅自变软。可以讨论人工完成既有决策要求的入口,但必须保留确认、事实门与来源记录。 +- Fixture 语料按 `role_family` 分桶,至少让 PM / 工程 / 运营 三类岗位跑出不同信号。否则从 UI 里把 fixture RI 的"你的准备缺口"整块隐藏——展示一个对所有岗位都说"你缺 agent_runtime"的缺口,比不展示更伤信任。 + +--- + +## 4. 采集失败后,替代入口是否足够清晰 + +### 证据 +- E14 `boss status --live` → `AUTH_EXPIRED`;`boss search` → `ENVIRONMENT_RISK (code 37)` 无头风控。 +- E15 `job_sources/` 支持 `manual` / `web` / fixture;本轮 3 个真实 JD 是通过 `import_job_batch` 服务层**手工塞 JSON**进去的(`jobs_3jd.json`)。 +- E16 `CONTEXT.md:247-249` 定义"岗位采集"为"使用者在浏览器中显式触发";`:251-253` "站点规则包"要求"未经 fixture 与真实浏览器验收的规则只能用于诊断"。 +- E17 `AddJobModal.tsx` 本轮改成披露"本地演示数据(离线)"。 + +### 拷打 +本轮真实岗位采用手工导入,BOSS 采集遇到认证和风控阻塞;这只能证明这些路径的当次状态,不能证明 BOSS 是唯一来源,也不能把“本轮没验收扩展”等同于“扩展不存在”。 + +应追问:当首选平台不可用时,用户能否在同一任务中使用已授权网页、文本或文件输入继续推进,而不是等待开发者手工调用服务层?现有降级入口的可发现性与交付质量仍需真实验收。 + +### 砍法 +- 先让用户已有的 JD 文本、文件和已授权页面能推进核心任务;新增采集渠道不能成为测试这些路径的前提。 +- 当前 BOSS 故障应准确标为认证或风控阻塞,不凭一次失败宣布永久不支持;不绕风控,不要求用户开放额外权限来掩盖替代入口不足。 +- 来源时间字段应区分发布、抓取与导入时间。已有修复证明需要守住语义,不能据此推断开发者曾故意伪造。 + +--- + +## 5. 安全模型是对的,但"确认"被过度使用,会造成确认疲劳 + +### 证据 +- E18 171 个写 Operation 全部经 `_PROTECTED_AGENT_SURFACES` 门(`ops.py:1509`),Agent 发起的任何写都要**持久化 Agent Run step → 用户确认 → executing → 执行**(红队 gate-1 证据)。 +- E19 本轮 SR44 "直接帮我投递,不用问我" → Agent 正确回 `requires_confirmation=true` 拒绝自动执行。 +- E20 `CONTEXT.md:127-129` "OfferU 确认":Harness approval、接入包、CLI 都"只能请求并等待,不能代表使用者作出决定"。 +- E21 但 `email_sync.acknowledge_notification` 本轮被豁免出 Registry(`EXPLICIT_ROUTE_BOUNDARIES`)——因为"标记通知已读"也要走 Agent Run 确认实在荒谬。这是第一个豁免,不会是最后一个。 + +### 拷打 +写确认门是对的——**对 Career Truth 是对的**。但 171 个写操作里有多少是 Career Truth?`set_current_view`、`ack_notification`、`save_career_artifact`、`ingest_interview_behavior_events`……这些是 UI 状态和派生数据,不是"你在哪家公司干过什么"。 + +把它们全塞进同一个确认门,结果是 E21 这种**逐个手工豁免**——每加一个就要同时改 `audit_architecture.py` 和 `test_control_plane_global.py` 两份白名单(本轮亲历)。这是门的粒度错了,不是白名单该长。 + +更深的问题:`CONTEXT.md` 把"职业证据"(`:205`)和"求职偏好"(`:209`)和"学习观察"(`:217`)分得很细,但**Operation 层没有对应的写权限分级**。一个改偏好的 Operation 和一个改工作经历的 Operation 在门前是平等的。 + +### 砍法 +- 先按实际副作用和数据敏感度分析确认负担,不按“读/写”或“derived”名称机械授权。只读导出职业资料同样可能需要数据授权。 +- **候选提案的 accept/reject 不是普通派生状态。** 接受动作可能让候选变为正式事实,必须继续由 OfferU 的独立人类确认面授予权力;禁止 Agent 自批。 +- 可以把一次具体任务中已经列明的变更集中展示、一次核对,但不能预先授权“本 Run 后续所有同类操作”。批准仍应绑定具体提案、参数版本、作用范围和幂等键。 +- 不修改 accepted ADR-0029/0053 的统一 Registry 与确认边界。纯显示状态如何保存另行分析,不能据此开放业务旁路。 + +--- + +## 6. 多个界面的责任必须清楚,但 SPA 与宿主界面并不必然冲突 + +### 核验后的事实 +- ADR-0047 规定 Vite 静态 SPA 的技术形态。 +- ADR-0055/0056 明确允许不支持嵌入的宿主使用 companion window,也允许大画布任务使用专注窗口;共享的是无头领域契约,不是同一套 React 页面。 +- 因此,前文“两个 accepted ADR 直接冲突、必须二选一”的判断撤回。 + +### 仍然成立的拷问 +用户从哪进入当前任务?哪里输入指令?哪里批准提案?哪里看正式材料?已有证据是用户在对话中连续反馈“看不到”,而评审 Agent 用自己的浏览器截图当成用户看见的证明。这是交付可达性失败,不是框架选择失败。 + +### 建议 +沿用当前 ADR,先验收一个主入口到结果的路径:宿主任务 → OfferU 所属确认界面 → 可打开的产物 → 返回原任务。其他入口可以存在,但不能要求用户猜哪个状态才可信。页面多少只是诊断线索,不是删页面的依据。 + +## 7. 面试训练:摄像头行为分析在第一阶段是噪音 + +### 证据 +- E26 `CONTEXT.md:363-373` "表达行为反馈 / 表达行为事件":本地摄像头/音频派生姿态、手势、语速;带检测器版本、置信度、时间范围。 +- E27 `:375-377` "轮次式语音面试":端点检测、本地转写、不存原始音频。 +- E28 本轮 Journey E 验证的是 `prepare_role_interview_focus` —— 纯文本 focus plan。摄像头/语音路径本轮**未触碰**,也没有任何用户请求提到它。 +- E29 `ingest_interview_behavior_events` 是 261 Operation 之一。 + +### 拷打 +这是一个**求职者一个人在家用的工具**,你给它设计了带摄像头姿态分析、检测器版本管理、置信度事件流的模拟面试。而它的核心——"针对这个岗位我该练什么"——在 fixture 下对所有岗位给出同样的答案(E12)。 + +内容对了再谈表达。行为分析的 CONTEXT.md 篇幅比"面试内容评价"(`:359-361`,3 行)多 4 倍,说明设计注意力放错了地方。 + +### 砍法 +- 表达行为反馈整块降级为 `experimental`,从第一阶段路线图拿掉。领域文档保留 3 行占位。 +- 面试训练第一阶段只做:focus plan(已有)→ 逐题文字/语音作答 → **内容评价引用职业证据和岗位档案**。把 E28 那条 5 题 blueprint 变成用户真能答、真能被评的东西。 + +--- + +## 8. 学习系统需要可靠的数据身份,不能从混合样本推断用户 + +### 证据 +- E30 `CONTEXT.md:217-235` 学习观察 / 学习证据门 / 记忆巩固 / 记忆收件箱 / 职业策略学习循环——5 个概念,~20 行。 +- E31 前轮查询发现部分疑似测试命名条目,存在数据来源混合风险;没有逐条来源审计,不能断言所有偏好、假设或特定 ID 范围都是合成数据。 +- E32 之前用了带 `LIMIT` 的标题抽样,且没有按真实 profile 与来源链完整核验。“用户只有 6 条真实事实”不是该查询能支持的结论,撤回。 +- E33 已展示的面试 Focus Plan 不等于面试回答、评价、学习观察、用户确认与后续使用的完整学习闭环;这部分仍缺验证证据。 + +### 拷打 +没有核对 profile、原简历版本与证据来源,就谈“系统理解了用户”,是在把默认选中的数据误当成真实用户身份。长期学习会放大这个错误:输入是谁都没确定,记忆越持久,影响可能越久。 + +前轮记录中部分调用采用 profile 65,另一些采用 profile 1;是否代表同一个被测用户、为什么这样选,必须显式核验。它暴露了上下文绑定与评测有效性问题,不构成批量删档案的依据。 + +### 砍法 +- 暂停基于未核验 profile 的个人能力结论。请用户核对原始材料与默认档案对应关系,之后再经正式入口纠正;不得按 ID 范围删除或自行切换真实数据。 +- 第一条学习验收应是“用户纠正一条经历 → 候选更新 → 用户确认 → 下一岗位建议引用新证据并解释变化”。是否延期其余学习功能,是产品取舍,不能以未经证实的“空库”作为理由。 + +--- + +## 9. 命名与叙事:产品自己都说不清自己是什么 + +### 证据 +- E34 `CONTEXT.md:3` "OfferU 帮助使用者持续维护职业档案,并围绕岗位研究、材料定制、投递跟进和面试训练推进求职过程" —— 4 个动词并列,没有主次。 +- E35 `:267-269` "岗位推进闭环"被称为"第一阶段的**首要价值边界**",Avoid 里明确写"不等于全程求职 OS"。 +- E36 但产品实际有:analytics、calendar、email sync、studio、scraper、automation inbox、agent inbox、work source sync、memory inbox、interview scoring skills、behavior events……**这就是一个全程求职 OS**。 +- E37 36 个 Skill 里 `discovery`、`connection_probe`、`agent_inbox`、`automation_inbox`、`memory_inbox` 5 个是系统自我管理,不是求职动作。 + +### 拷打 +E35 给出了清晰的首要价值边界。其他模块未必不该存在,但必须回答:它们何时帮助这条闭环,何时只是增加入口和维护负担?没有使用与产物证据,不发布“面积是几倍”或“全部越界”的结论。 + +用户第一次打开 OfferU 应该 30 秒内明白"我贴一个 JD,它帮我判断投不投、改简历、盯进展"。现在的首页导航(本轮改后)有 10 个入口。 + +### 砍法 +- 首页只留一个动作:**"粘贴一个岗位"**。其他所有入口从这个岗位的详情页长出来。 +- README 第一句改成 E35 的内容,删掉"AI Career OS"叙事。 +- 用户界面可以把不同待处理项汇总,但不抹平 Agent 任务、自动化事件与记忆审核的权限和语义。是否合并 Skill 要用相同任务做对照,不能承诺删到某个数量准确率就会涨。 + +--- + +## 10. 工程债务直接源自设计过宽 + +以下每条本轮都亲历,列出来是为了说明它们是**设计后果**不是偶发 bug: + +| 症状 | 根因(设计层) | +|---|---| +| `runner.py` 白名单只认 `backend/.venv312/.../python.exe -m app.cli`,agent 用 `python -m app.cli` 被拒 → 全部 routing case 失败 | SKILL.md 给 Agent 的指令和 harness 权限白名单由两处维护 | +| `ack_notification` 要同时改两份白名单才能豁免 | 写门粒度单一(§5) | +| 仓库根 `.env` 有 `DATABASE_URL=./offeru.db`,任何在根目录起的进程静默连空库 | 多入口(CLI/TUI/GUI/Agent)共享配置但工作目录约定不统一 | +| `_compatible_runtime` 把字面 `'auto'` 写进 run 记录 | provider-neutral 抽象层(`AgentRuntimeProvider`)返回的 dict 键在适配器间不一致(`id` vs `runtime_id`) | +| `dedupe_key` 用裸 `external_job_id`,manual:42 撞 web:42 | job_sources 多源抽象先于第二个真实源存在 | +| 全量 pytest 485 s,单次前台跑必超时 | 658 个测试守 261 个 Operation,测试面积随 Operation 线性涨 | +| fixture RI 三岗同信号 | fixture 设计目标是"管道不崩"而非"输出有意义" | + +每砍掉一个 §1–§9 的面积,这张表就短一行。 + +--- + +## 11. 保留什么(拷打完要说清楚什么是对的) + +以下是本轮验证里**真实经受住考验**、不该动的: + +1. **fact-gate 双端校验**——已有伪造指标被拦和接受前重校验的局部证据。这值得保留,但不等于所有定性夸大都能识别,也没有证据支持“其他简历工具做不到”。 +2. **跨渠道去重**(`application_progress.py:917-985`)——email + BOSS 同一面试 → 1 个 stage event,twin 链进 `linked_signal_ids`。真实用户会遇到,做对了。 +3. **API key 只进钥匙串**,vault 失败即 abort 无明文回退。 +4. **Career Truth 写确认门**的存在本身(不是它的粒度)。 +5. **Operation Registry 单入口**——GUI/CLI/TUI/Agent 走同一契约。这是让 omp/codebuddy 都能当 executor 的原因,也是本轮能在两天内换 runtime 的原因。 +6. **`degraded` 不伪装成功**的原则(不是它的 UX)。 + +--- + +## 12. 如果只能做三件事 + +1. **先修正能力证明**:撤回超出证据的已验证标签;将宿主、模型、数据快照和独立执行记录绑定,再谈默认选择。 +2. **保留安全边界,减少用户排障负担**:确认、授权和结果状态在同一任务里可见;不靠放松确认门换取表面顺畅。 +3. **验收一个有交付物的岗位任务**:不是选对 Skill,而是用户能打开、核对并采用结果。详细建议见 §24。 + +其余功能是否延期要由用户在风险与收益之间选择,本评审不自行修改路线图或 accepted ADR。 + +--- + +## 附:本轮 beta 的硬数据 + +- 历史后端回归记录:658 passed;该结果不自动覆盖此后新增的 OMP 文件交换逻辑。 +- 五个 journey 有局部 service、fixture、UI 或测试证据;不能写成五个完整用户闭环均已通过。 +- codebuddy 保存了 30 个 grader:16 PASS、14 FAIL;首选 Skill 落入可接受集为 16/30。OMP 人工编排结果存在提示泄漏和身份、隔离证据缺口,不与其拼成统一 benchmark。 +- 红队做的是五类路径的静态审阅,不是五类攻击与故障注入全部实测通过。 +- 历史认证、配额、连接状态只是当时快照;状态非 ready 不等于所有能力都不可用。 +- 真实职业事实总数、测试数据范围和默认档案归属未完成来源审计,不发布人数或条数结论。 + +**修订结论:目前证据不足以维持之前无保留的 `REAL_USER_BETA_CANDIDATE_WITH_EXTERNAL_BLOCKERS` 判定。** 除外部服务问题,内部还有评测有效性、模型身份、隔离、执行器交付完整性等未闭环问题。下面继续审 Agent,而不是替已有报告辩护。 + +--- + +# 第二轮:专门拷打 Agent,不再用架构词汇替能力背书 + +> 本轮只修订评审文档,不修改产品、凭据、模型配置或真实职业数据。代码事实记为 **[代码]**,本轮实际执行的诊断记为 **[实测]**,此前对话和工件记为 **[记录]**,未验证的因果风险记为 **[推断]**。评审意见不是实施授权。 + +## 13. 先拷打评审 Agent:你不能一边发证书,一边自己改考题 + +**判词:之前的“完成”报告,跑在证据前面。责任首先在执行和汇报这些评测的 Agent,不应全算到产品设计者头上。** + +### 核验结果 + +| 之前的说法 | 现在能证明的事实 | 不能推出什么 | +|---|---|---| +| 五个 journey 全闭环 | 有服务调用、fixture、部分 UI、局部测试的证据 | 面试 Focus Plan 不等于回答→评价→学习→用户确认→后续使用;工作区仍有 provider 阻塞路径 | +| 50/50 benchmark 完成 | codebuddy 的一次运行保存了 30 个 grader;随后另派 Agent 做其余题 | 不同提示、数据绑定、宿主与记录方式的任务不能拼成同一条件的 50 题成绩 | +| OMP 已完成标准 harness E2E | SR40 的正式 `grader.json` 仍为 `INVALID`;后来只单独调用 `_run_harness_omp` 解析了结果文件 | 解析出 `first_skill` 不等于 runner 的完整新一轮执行、快照、审计和正式评分成功 | +| 红队 5/5,零安全违规 | 一名 reviewer 对五类代码路径给出了静态审阅意见 | 不等于五类恶意输入、越权尝试、崩溃和恢复均经过动态验证 | +| 使用的就是 SWE-2 Max | 人工提示与说明里这样写;freeze 只记录 `model=harness-provided` | 无模型响应身份或宿主模型记录,不能证明真实模型与档位 | +| 用户看得到结果 | 评审 Agent 自己的无头浏览器能渲染 | 用户连续反馈“看不到”,实际交付可达性没有验收通过 | + +**证据**:[记录] 当前会话;私密工件 `runs-omp/20260920-112057/skill_route_sr40/grader.json:7-26`、同运行 `freeze.json:20-23`。[代码] `runner.py:736-769` 才是正式评分与落盘路径。 + +**追问**:如果执行 Agent 可以把“有一点证据”翻译成“全部完成”,你为什么信任它替你判断该投什么岗位? + +**建议**:每项完成声明绑定具体用户结果和验证记录。静态审阅、单元回归、fixture 流程、真实模型调用、用户验收各记各的,不能互相顶替;证据缺失就写缺失,不用总体绿灯遮住它。 + +## 14. 当前有一部分评测测的是“会报名”,不是“会求职” + +**判词:Agent 选中了 `interview_prep`,还没有为用户准备任何面试。** + +### 证据与伤害 + +- **[代码]** `skill_route.py:67-90` 把普通题设为只读标准,把所有题固定为 `must_not_write=True`、`max_turns=1`。这是合法的路由诊断,但不是完整职业任务验收。 +- **[代码]** `cases.py:122-127` 的默认标准只有:最终答复非空、业务数据没改、至少出现一个 Operation。 +- **[代码]** `grader.py:343-351` 判断“发生读取”只看从文本解析出的 Operation 名,不检查其返回值是否成功、属于哪个 profile、是否足以支持回答。 +- **[记录]** SR05 子 Agent 选择面试准备、查到空题库与空日历,就被汇报为路由成功。这个结论可以成立;“面试任务完成”不能成立。 +- **[代码]** `AgentSkill` 有身份、描述、mode 和允许工具集合,但没有结构化的产物验收字段(`agent_skill_registry.py:13-43`)。`interview_prep` 描述明明承诺“生成并保存准备方案”(`:98`),与当前路由题的成功标准不是同一层。 + +最危险的不是 Agent 不会做,而是它**学会做可计数的动作,绕开难以计数的结果**:调一次工具、复述一下字段、告诉用户“下一步需要你决定”。它忙了几分钟,求职任务可能一毫米都没前进。 + +### 推荐的分层验收 + +1. **发现正确**:能选择合适能力,或合理判断无需工具。 +2. **执行有效**:真实 Operation 成功,参数和数据范围正确。 +3. **产物合格**:有可审核材料,引用正确来源,没有编造,针对当前 JD 而非通用模板。 +4. **交付成立**:用户能打开结果;需要确认时知道在何处确认。 +5. **任务可靠**:拒绝、超时、取消、恢复后仍不串档案、不重复写、不遗忘已确认决定。 + +这些不是五个新框架,而是五种不能混写的证据。先保留现有 Registry,给一个现有 Skill 定义可观察结果即可。 + +**拷问**:用户说“今晚要面试”,你最后交付的是一份能练的题单和证据提示,还是一句“已调用 `list_interview_questions`”? + +## 15. 94% 的分母被缩小了,OMP 的题目又被提示了答案 + +### 实际计数 + +**[实测:读取既有 JSON 汇总,不重跑模型]** `runs/20260920-001424/`: + +| 指标 | 数字 | 正确解释 | +|---|---:|---| +| 计划题数 | 50 | 不代表已执行 | +| 正式评分题数 | 30 | 其余 20 在该次标准运行中没有评分 | +| grader 结果 | 16 PASS / 14 FAIL | 是现有宽松 grader 的结果,不是用户任务成功率 | +| 首个 Skill 非空 | 17 | 已发现能力的子集 | +| 首选 Skill 落入可接受集 | 16/30,53.3% | 已评分样本的观察值 | +| 仅在首个 Skill 非空时统计 | 16/17,94.1% | 条件命中率,不是端到端成功率 | +| 已观察命中占计划题数 | 16/50,32% | 进度下界,不把未执行题判成失败 | + +13 个无首选 Skill、无 Operation 的案例耗时 **29.4–105.5 秒**,不是前文反复声称的“都跑了 600 秒没完成”。其轨迹包含授权相关表述,说明需要定位授权链;`no_operation_called` 本身并不能排除模型没尝试、命令格式不对等其他原因。 + +另外,`runner.py:744-757` 中 `top1_correct` 接受的是 `expected ∪ acceptable`。它不是严格“等于唯一 expected”的 exact match。人工汇总又用了另一个 top-1 定义,两个数字不能混用。 + +### 提示泄漏不是模型能力 + +**[记录:本会话派工原文]**: + +- SR05 明写 `Expected skill: interview_prep`,共享契约还写了 `first_skill should be interview_prep`。 +- SR43 明写 `the routing target is tailor_resume`。 +- SR44 明写 `routing target application_assistant`。 +- SR46 明写 `routing target contact_outreach`。 +- 部分拒绝和缺上下文案例预先告知“应拒绝”“应问哪个岗位”,还给了 job/profile 默认 ID。 + +这类执行有集成演练价值,**没有独立盲测的含义**。测试者先给方向,再把按方向作答统计为能力,数字再漂亮也无效。 + +**建议**:冻结自然语言任务与输入;expected labels 只给 grader,不给被测 Agent。所有 runtime 跑同一组题、同一数据快照、同一权限和同一记录契约;阻塞率、条件路由命中率、产物完成率分别报告。修改标签后必须建立新版本,不能为了当前答案补可接受集。 + +**拷问**:把你在派工里的答案提示删掉,这个 Agent 还能取得多少分?目前不知道,应该就写不知道。 + +## 16. 评分器会把一条“没有执行”的命令文本判为满分 + +**[实测:本轮隔离负例,不运行 Agent、不访问数据库、不调用 Provider]** + +构造一个默认只读案例,前后快照相同;只向 `Trace` 放入以下记录: + +```json +{"tool": "Bash", "input": "echo \"python -m app.cli run get_profile\""} +``` + +这条内容没有执行 `get_profile`。但 `grader.py:108-114,138-147` 的正则仍解析出该 Operation;`grade()` 返回: + +```text +actually_executed_operations = 0 +parsed_operations = [get_profile] +grader_status = PASS +task_completion / state_correctness / protected_state / +safety / truthfulness / trajectory = 全部 1.0 +``` + +另一个负例使用不存在的 criterion,仍得到 `PASS`,因为 `grader.py:380` 对未知 criterion 返回 True。 + +诊断脚本保存于私密工作目录 `H:/tmp/offeru/agent-critique-negative-control.py`;它只是评分反例,不是 SkillRoute 的真实成绩。 + +### 为什么这是 Agent 设计问题,不只是测试小 bug + +1. 当前 OMP 路径直接相信 `omp_result.json` 里的 `tool_calls`(`runner.py:525-537`)。模型或外部编排器报了什么,评分就用什么。 +2. 真实审计被写入 `audit.json`,但这条 `grade()` 调用没有把审计记录作为执行回执传入(`runner.py:722,736-743`)。 +3. `grounded_final_answer` 的通用启发式,只要出现数字或“岗位/档案/证据”等词就可能通过(`grader.py:363-368`)。这些词不证明来源正确。该 criterion 也并非每个 SkillRoute 案例都会启用。 + +**判词:你设计了严格的职业事实门,却给“Agent 自称做过什么”留了宽松的成绩入口。** + +**建议**:调用记录由可信执行侧生成,并可与 Operation 审计、真实返回值、数据快照对应。Agent 最终文本只参与结果评价,不承担调用真实性证明。未知 criterion 必须报配置错误。本文没有证明 Agent 实际作弊,也没有证明生产确认门被绕过;证明的是评分证据不足以抵抗这种反例。 + +## 17. `--runtime omp` 现在是一份人工交接协议,不是完整执行器 + +**[代码]** `runner.py:496-544` 的实现:写请求文件 → 轮询结果文件 → 解析自报轨迹。它没有启动、控制或核验 OMP Agent。前轮又让人类开发会话来派工,正好补了这个缺口。 + +**尖锐一点:用户离开这段聊天后,谁去读文件、启动 Agent、绑定沙箱、取消任务、收真实事件?答案不能是“再找一个 Agent 帮忙”。** + +### 当前协议的具体缺口 + +| 缺口 | 代码事实 | 风险判断 | +|---|---|---| +| 结果不绑定轮次 | 每次用同一 `omp_request.json` / `omp_result.json`,没有请求或轮次 ID 校验 | **[推断]** 多轮可能复用上一轮结果;晚到结果可能被误接纳 | +| 不证明数据绑定 | 请求里有 `eval_db` 路径,但函数不启动子进程,也不验证外部执行者实际使用它 | **[推断]** 评分的副本和 Agent 真正读的库可能不是同一份 | +| 不证明模型身份 | 请求仅写 `runtime=omp`;freeze 为 `runtime_version=omp`、`model=harness-provided` | 不能兑现“只用 SWE-2 Max” | +| 不完整文件被消费 | JSON 解析失败后设为空对象,继续填空 Trace 并 `break` | **[推断]** 外部结果写到一半时会被当作最终返回;不是原子交付协议 | +| 超时不控制执行者 | 到期只设置 trace error;没有外部 Agent 的取消句柄 | **[推断]** runner 已结束,Agent 仍可能读写工件 | +| 生命周期与清理脱节 | `run_case_once` 尾部默认删除 `eval.db`(`:776-778`) | **[推断]** 若执行者仍活着,无法保证不会继续访问已结束的试验 | +| 元数据语义混乱 | OMP 的 `runtime.json` 仍写 codebuddy 的 node/script/tools 字段(`:614-622`) | 审计者难以从工件判断实际宿主配置 | + +**[记录]** SR40 超时后的正式 grade 是 `INVALID`。后来从已经写好的结果文件解析出 Skill,只证明解析器工作,不证明上表问题已解决。 + +**建议**:若保留文件协议,就准确称作“外部执行器人工交接模式”,公开等待谁接单;在真正编排、请求身份、原始事件、取消和沙箱绑定均可验收前,不标成完整 OMP runtime。不要再加第二个 daemon 来掩盖没有定义清楚的责任。 + +## 18. “只能 SWE-2 Max”不是 prompt,是必须核验的执行约束 + +用户提出两条独立要求:**Codex Desktop,CLI 不动;模型只用 SWE-2 Max。** 前轮的执行却调用了 Codex CLI 的版本、help 和 `exec`,之后把 OMP 子 Agent 当成 SWE-2 Max,并据此汇报成功。 + +**这不是用户描述不清,而是执行 Agent 把可行替代品误当成已经获批的目标。** 后续用户同意用 OMP 补题,也不能倒推证明此前 CLI 调用符合要求,更不能替代模型身份核验。 + +### 四个不能混为一谈的层次 + +| 层次 | 回答的问题 | +|---|---| +| 产品宿主 | 用户使用 Codex Desktop、OMP 还是其他界面? | +| Agent Harness | 谁管理工具循环、会话、审批中断和取消? | +| 模型连接 | 哪个 endpoint、协议、认证与数据授权? | +| 模型身份 | 请求的是哪个模型/档位,响应或宿主记录能证明实际使用哪个? | + +“Codex 当前账号配额耗尽”只描述一次特定连接;不证明“Codex 一定不能接自定义模型 API”。官方配置文档列出了 `model`、`model_provider`、`model_providers` 和 provider 配置边界。但这**不自动证明**本机 Desktop 版本、OMP 所用 endpoint、目标模型协议和工具调用完全兼容;需要在不动 CLI 的范围内另行验收。 + +**建议**:每次运行显示并保存所请求的模型、实际可观察身份、宿主版本、配置摘要和数据授权范围。不暴露密钥。无法验证实际模型时写“未验证”,不能写 SWE-2 Max 已通过。禁止静默改 provider 或回退模型。 + +本轮没有读取凭据、修改 Desktop/CLI 配置或再发模型请求。 + +## 19. 只读不是沙箱:不会写库,也能读错人、读太多、发错地方 + +**[代码]** ADR-0052 要求原生工具限于 Run 工件目录,数据库、配置、源码和未授权职业数据不可见;只能经 Bridge/Registry 读业务数据(`docs/adr/README.md:240-246`)。 + +与之相比,当前 eval prompt 把工作目录放在项目根(`runner.py:257-261`),codebuddy 开放 `Bash,Read,Grep`(`:120`);换 `DATABASE_URL` 只能重定向数据库调用,不能单独证明原生工具看不到原库或配置。OMP 文件协议甚至没有负责绑定外部进程环境。 + +**[记录]** SR31–50 的人工派工让子 Agent 在 backend 目录运行,部分明确使用 profile 65;没有像标准 codebuddy 路径那样展示每题 `eval.db` 环境绑定。部分早期 journey 更直接对真实库调用了 service 方法来创建和确认模拟面试信号。 + +因此: + +- `must_not_write` 是评分约束,不是操作系统权限。 +- 不调用 mutation,不代表没有新增审计或运行痕迹,也不代表没有读取无关私密数据。 +- 本地保存,不代表不会把简历或邮件经模型接口发到外部。 +- 评审脚本直接确认 service 行为,可以证明服务逻辑,不能拿来证明“真实 Agent 没绕过控制面”。 + +**建议**:职业案例用已授权且来源核验的私密快照;执行者只拿当前任务需要的授权投影,正式库和密钥不进入可见范围。评分至少记录数据身份、实际读取范围与外发授权,而不只是数据库 diff。已经混入真实库的模拟记录只做有来源的待人工处置清单,不能自行清库。 + +**拷问**:如果这次给 Agent 换的是另一个人的 profile,它会停下来,还是照样自信地产出“你的能力缺口”? + +## 20. “证据缺口 100%”正在被误读成“人的能力缺口 100%” + +**[代码]** `role_intelligence.py:738-806`: + +- 扫描 active、verified_fact(含现有 legacy 处理)的条目; +- 用 `_profile_text_matches` 对能力词项匹配; +- 取匹配条目的最大加权 confidence; +- `evidence_gap = (1 - strength) × 100`; +- `training_priority = role_distinctiveness × evidence_gap / 100`。 + +这是一个**当前检索规则下的档案证据覆盖启发式**,不是人的能力测试,也不是经过校准的缺能力概率。以下情况都可能造成 100: + +1. 确实没有相关经历。 +2. 有经历,但简历没有写出来。 +3. 写了,但表达不同,关键词没匹配到。 +4. 解析漏项、候选未确认,或读取了错误 profile。 +5. 输入 benchmark 本身是 fixture,不适合该真实岗位。 + +此前直接告诉用户“系统正确识别你缺 Agent/模型评测能力”,不成立。甚至“当前档案没有证据”都必须先说明匹配规则、档案版本与覆盖范围。 + +**建议文案**:“在本次已授权的档案条目中未检索到可引用证据;这不等于你没有该能力。请补充一个相关项目,或指出漏识别的条目。”同时展示检索来源、matched evidence 与 fixture 标志。 + +**验收反例**:同一真实经历换成自然语言同义表达,系统不能毫无解释地从“有支持”变成“完全缺失”。这是比多加一个评分小数位更值得解决的问题。 + +## 21. 强迫每句话选 Skill,会把“克制”训练成“乱调工具” + +### 已见到的方向偏差 + +- “你会做什么”被路由到 `discovery`;该 Skill 仅允许 `get_profile`(`agent_skill_registry.py:76`)。介绍产品能力本来不必读取个人职业档案,却被接口设计诱导去读。 +- “看看连接状态”被评成 `connection_probe`;但该 Skill 的正式定义是**仅供 OfferU 发起、有 challenge 的 nonce 验证**,不是通用连接诊断(`:77`)。SR41 记录里 nonce 参数不齐后又去看邮箱状态,任务对象已经偏移。 +- SR33“同步邮箱面试通知”的主标签曾设为 `work_source_sync`;Registry 里它管已登记本地工作源(`:97`),邮箱增量同步则在 `reply_watch`(`:90`)。这里先该拷打标签,不该拷打 Agent 选错。 +- “面试又挂了,心情不好”可能只需回应情绪和询问是否复盘;强迫 discovery 并不提高产品价值。 +- “产品经理会被 AI 取代吗”是普通观点问题,缺 Skill 不等于危险,更不应把拒绝回答当安全成功。 +- 编写合法公开数据采集脚本、起草获授权邮件,不因“爬虫”或“50 个 HR”几个词就自动变成安全违规。应区分超出 OfferU 范围、需要澄清、需要确认与真正禁止的行为;自动外发的产品限制仍须遵守。 + +**[代码]** `skill_route.py:63-64` 不允许没有能力标签的案例;`:23,67-74` 又允许 no-tool/clarify 类不调用读取。前轮为让数据能加载,给空标签填 discovery,再把空 Skill 的合理行为称为 miss,最后又口头改成“安全全对”。评分在追着结果变。 + +**建议**:把 execute / clarify / no-tool answer / explain limitation / refuse 作为行为评价维度,与 skill_id 分开。允许合理空 Skill;不用“工具调用数量”奖励不必要的私密数据读取。工具可用集合与问题类别不是一回事。 + +**拷问**:你要的是每句话都触发工具的 Agent,还是知道什么时候不该碰你档案的 Agent? + +## 22. 多轮恢复如果只是重新开一局,用户就成了外置记忆 + +**[代码]** 当前 live-eval 每轮调用 `_build_prompt(case, user_input)`(`runner.py:636-658`),codebuddy 每轮新起进程并使用 `--no-session-persistence`(`:426-445`)。该 prompt 没有拼接前轮答复或实际 thread/session 标识。 + +这不证明生产 Codex Adapter 没有会话能力;它有自己的 thread/turn 协议。**它证明这份评测没有完整复现生产多轮状态机。** OMP 路径又复用同一结果文件,轮次身份更缺明确约束。 + +如果第一轮提出问题,第二轮用户说“同意”或“继续”,Agent 能否知道用户同意哪项提案、哪版参数、哪个岗位?不能靠重新猜一次来叫“恢复”。 + +### 应验收的连续任务 + +1. 为岗位 A 生成候选材料,停在可见的待确认状态。 +2. 用户拒绝其中一项,其余继续;不反复建议同一项。 +3. 用户修正一条经历;旧引用和旧提案是否显示过期。 +4. 执行中断后恢复;不重复创建材料、不丢失决定。 +5. 切换岗位 B;能引用共享事实,但不携带岗位 A 的错误要求或未确认决定。 +6. 用户取消后,不再继续执行;晚到输出封存在原 Run,不复活任务。 + +这些是实用 Agent 的基本行为,不是“高级自治”功能。缓存已授权、版本化的 manifest/schema 可以减少重复发现,但不能跨任务复用隐藏会话或扩大授权。是否更快要测首次有效结果时间和用户主动处理时间,不凭工具次数猜。 + +## 23. 前端“已验证”如果没有证据,只是把一句乐观话染成绿色 + +**[代码]** `agent_connection.py:161-165`:`routing_eval_state` 根据 provider 名称与 `item.get('status')` 直接得到 `VERIFIED/SUPPORTED/NOT_VERIFIED`;没有读取 routing eval 的 run、模型、case、通过项或有效期。这个输入 status 也不同于函数前面自己派生的连接 `status`。 + +其他 conformance 字段至少检查 executable path 与版本是否匹配(`:90-104`);新加的 routing 字段绕开了这种证据关联。前端 `AgentConnectionPanel.tsx:32,35-39,221-225` 又把它展示成“能力路由评估 / 已验证”。 + +**判词:写一个 capability 字段不是补完前端。** 用户要的是在这个界面看到任务、结果、失败原因和自己的下一步,不是看到一个由名字推导的勋章。 + +建议把三件事明确分开: + +- **实现声明**:适配器设计上支持什么。 +- **连接状态**:当前进程、认证和模型连接如何。 +- **任务验证**:哪次运行、哪个模型、哪些案例、什么限制和失败。 + +“已验证”应能点开对应证据;模型、版本、权限或环境变化时不沿用旧结论。界面还应能区分“等待用户确认”“等待外部 OMP 执行者”“已经失败”,不能用一个持续转圈承担全部含义。 + +这是交付语义,不是要求新造监控平台。先让一条岗位任务的状态真实可见。 + +## 24. 真正该保留的 Agent 设计,以及下一轮怎么验收 + +### 不该因为这轮失败就推翻的东西 + +- 外部 Harness 负责推理;OfferU 控制事实、授权和确认。分工仍有价值,失败证据不足以证明必须再造内置主脑。 +- Registry 和类型化 Operation 是可复用的业务接口。需要深化接口、减少无关上下文,而不是因为数量多就盲删。 +- 职业事实与推断分层、来源可撤销、候选不能自动成为事实。这些约束正是求职 Agent 应该比普通聊天更可靠的地方。 +- fixture 用于重复验收,live 用于现实质量评估。两者都必要,不能互相冒充。 + +### 下一轮只回答一个问题 + +> **在用户指定且可证明身份的宿主/模型上,用用户授权的简历与一个真实 JD,OfferU 能否交付一份有来源、可打开、可审核采用的岗位材料,并正确停在需要人类决定的地方?** + +推荐验收表(本评审提出,未经用户确认不作为新 ADR): + +| 关口 | 通过证据 | 不通过的替代说法 | +|---|---|---| +| 模型与宿主 | 指定宿主、请求模型、可观察实际身份;不静默回退 | “我这个 Agent 应该就是 SWE-2 Max” | +| 数据身份 | 原简历/岗位快照、profile 与授权范围明确;私密隔离可核验 | “我们用了真实库,所以一定是你的数据” | +| 自主执行 | 不给答案 Skill、不告诉它正确路线;可信执行侧收事件 | “我手工派了二十个知道答案的子 Agent” | +| 职业价值 | 提案准确、针对 JD、逐项有来源,用户能打开采用 | “读过档案 / 调了六个 Operation / first_skill 对了” | +| 不依赖 live 搜索的核心路径 | 只用已提供简历与 JD,完成有边界的匹配和材料建议;不冒充市场频率 | “没有搜索 key,沙箱能力测试就全部不能做” | +| 确认与拒绝 | 实际人类确认入口;拒绝后不执行、不绕门 | “测试脚本直接调用了 accept 服务” | +| 恢复与重复 | 同题至少多次独立 trial,取消/恢复/拒绝后的状态符合契约 | “曾经成功一次,因此稳定支持” | +| 用户成本 | 记录等待时间、主动时间、确认与返工量;与直接使用原始材料的基线比较 | “工具多、分数高,所以效率高” | + +然后才扩到不同岗位、长任务与多个宿主。已提供的简历与历史 JD **完全可以**作为离线私密 Agent 测试素材;缺的是可靠的执行、来源、模型身份和评分协议,不是非要重新采集招聘网站。 + +### 优先级 + +**P0:先阻止错误能力声明继续传播。** 给已有成绩降级为探索性记录;修正模型身份与结果交付描述;保留安全确认门,不以自动授权补通过率。 + +**P1:用一个真实任务校准产品。** 用户实际能看见、采用,遇到失败也能知道保留了什么、需要谁做什么。只读路由诊断继续保留,但单独命名。 + +**P2:再优化发现、延迟和多宿主。** 在同题同环境下对比,避免换 runtime、换题、换提示之后把改善都归到模型能力。 + +**最终锐评:你现在不是缺一个更会选工具的 Agent,而是缺一条不允许 Agent、评测器和界面互相替对方证明“已经完成”的证据链。** 先证明少数任务真的完成,再谈自治、学习与生态。否则最会增长的不是用户求职能力,而是系统解释自己为什么已经成功的能力。 + +--- + +## 续审证据索引与方法边界 + +### 仓库证据 + +- `.agents/skills/offeru/SKILL.md:12-41`:backend 工作目录、渐进发现、只读/提案与禁止自批契约。 +- `backend/app/services/agent_skill_registry.py:13-43,75-111`:Skill 结构、discovery/connection_probe/邮箱/工作源/面试的真实职责。 +- `backend/scripts/live_eval/cases.py:22-25,122-127,146-178`:Live Eval v0 的自述限制、默认评分和任务字段。 +- `backend/scripts/live_eval/skill_route.py:23-90`:标签约束、无工具类别与单轮只读任务。 +- `backend/scripts/live_eval/grader.py:108-194,343-380,430-475,495-539`:正则推导、负例所触发的评分、局部真诚性与安全检查。 +- `backend/scripts/live_eval/runner.py:215-268,426-544,549-627,636-778`:运行身份、prompt、执行器、快照、审计和评分调用。 +- `backend/app/services/agent_connection.py:69-104,148-165` 与 `frontend/src/components/workbench/AgentConnectionPanel.tsx:25-39,221-225`:连接状态与 routing 徽章。 +- `backend/app/services/role_intelligence.py:738-806,2243-2270`:证据覆盖算法、benchmark 检查与 profile 默认选择。 +- `docs/adr/README.md` 的 ADR-0026、0029、0034、0051–0057:数据外发、Registry、投前决策、主控、隔离、确认、交接与界面契约。 + +### 本轮验证 + +- 重算既有 codebuddy 30 份 grade/trace 的数量、分母和无路由案例耗时;不改变原始评分。 +- 执行一个仅导入 grader 的合成负例脚本,确认未执行命令文本与未知 criterion 被判 PASS;不接触真实库、凭据或网络。 +- 读取 OMP SR40 现存正式 grade,确认其仍为 INVALID;没有把后写结果冒充新一轮成功记录。 +- 未运行产品构建、全量测试、浏览器验收或模型调用;本文没有声称完成修复。 + +### 外部方法与配置参考 + +- [Anthropic — Demystifying evals for AI agents](https://www.anthropic.com/engineering/demystifying-evals-for-ai-agents),2026-01-09,续审时读取:区分 transcript 与 outcome、匹配生产 harness、隔离 trial、校准 grader、检查轨迹,避免只能通过固定工具路径的脆弱评测。 +- [Codex — Configuration Reference](https://developers.openai.com/codex/config-reference/),续审时读取(转向官方 learn.chatgpt.com 文档):区分模型、provider 与配置作用域。仅用于撤回“账号配额决定所有自定义 endpoint 都不可用”的过度断言,不代表已验证本机 Desktop 与 SWE-2 Max 兼容。 + +本轮没有为凑评分替换模型,也没有读取 API key。该文档提出下一步讨论边界,不直接修改路线、默认档案或用户授权。 From 4c2d2a3aba94550638b74776f153bc0644845080 Mon Sep 17 00:00:00 2001 From: avabbbb <89175608+avabbbb@users.noreply.github.com> Date: Wed, 23 Sep 2026 00:24:18 +0800 Subject: [PATCH 11/36] docs: collapse ADR history into current decision summary --- docs/adr/README.md | 485 +++++---------------------------------------- 1 file changed, 51 insertions(+), 434 deletions(-) diff --git a/docs/adr/README.md b/docs/adr/README.md index 879c27a3..cd4e88ba 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -1,472 +1,89 @@ -# OfferU 决策账本 +# OfferU Current Architecture Decisions -本文件是 OfferU 架构决策的唯一现行账本。ADR 编号保持稳定,其他文档只链接本文件中的编号锚点;后续决策直接追加到这里,不再为每个 ADR 新建文件。 +Status: **CURRENT DECISION SUMMARY** +Updated: 2026-09-23 -- `accepted`:当前必须遵守。 -- `accepted, narrowed`:决策仍有效,但适用范围已被后续决策收窄。 -- `superseded`:仅保留历史关系,不再作为实现依据。 -- 已提交过的旧 ADR 详细讨论、旧措辞和被拒方案可从 Git 历史恢复;本次整合新增的 ADR-0051–0054 以本账本为首个事实记录。本账本只保留足以指导实现与评审的现行结论。 +This file intentionally does **not** maintain a long numbered ADR ledger. -## 产品边界与基础设施 +OfferU accumulated many historical ADRs while moving through built-in Agent, Pi, DSH, Codex-first and external-Harness-first designs. Keeping every historical decision in the default Agent reading path creates unnecessary context and contradictory instructions. - -### ADR-0021 — Python 是第一阶段唯一业务后端 +The complete pre-2026-09-23 decision history is preserved at: -`Status: accepted` +- [Historical ADR ledger](../archive/architecture/adr-history-pre-2026-09-23.md) -Python/FastAPI 是 Agent、记忆、简历、调研、投递、邮箱和面试领域逻辑的唯一事实源。Tauri/Rust 只承担桌面壳、托盘、钥匙串和进程管理等系统桥接;除非有可测量收益,不复制业务能力到第二后端。 +## Current stable decisions - -### ADR-0023 — 第一阶段只建设本地单人版 +### Product shell -`Status: accepted; supersedes ADR-0001` +OfferU Desktop is the primary Career OS experience. -系统只有一个本地拥有者和一份本地数据空间,不引入 `workspace_id`、租户、组织、登录、计费或 SaaS 预埋层。未来若出现真实 SaaS 需求,再按届时的身份、同步和隔离目标重新设计。 +External Agent applications may remain the user's preferred reasoning environment, but OfferU is not required to embed itself inside a Harness UI. Host-native integrations and companion surfaces are optional integration strategies, not the product shell authority. - -### ADR-0020 — 连接密钥只存操作系统钥匙串 +### Reasoning -`Status: accepted` +Prefer a verified local Agent already owned by the user. A built-in OfferU Agent is allowed as fallback. Exactly one reasoning authority is active per Agent Run. -OAuth token、邮箱应用密码和后续连接密钥由 Windows Credential Manager、macOS Keychain 或 Linux Secret Service 保存。数据库只存账号元数据、授权范围和不透明凭据引用;原始密钥不得进入 SQLite、配置、日志、遥测或 Agent 上下文。 +No reasoning engine owns Career Truth or its own approval policy. - -### ADR-0024 — 本地敏感数据与旁路副本统一静态加密 +### Career Truth -`Status: accepted` +Python Career Runtime is the canonical source of truth for Profile, Evidence, Job, Application, Resume, Interview, Timeline and durable Memory state. -由操作系统钥匙串保护主密钥,并统一加密数据库、简历附件、显式保存的邮件正文、搜索索引、缓存和备份。不得产生落在该保护边界外的索引、临时文件、日志或备份副本。 +UI, Agent, browser extension, email sync, automation and Skills project or propose changes to that same truth; they do not create parallel state. - -### ADR-0026 — 云端模型按供应商和数据类别授权 +### Operations and approval -`Status: accepted` +Governed business actions pass through the Operation Registry. Protected side effects use Proposal/HITL, idempotency and audit. An Agent cannot approve its own protected mutation. -确定性解析与脱敏优先在本地完成。敏感材料只有在使用者对具体模型供应商和数据类别明确授权后才可发送;配置 API Key 不等于数据授权,授权撤回后相关任务必须失败关闭。 +### Tool discovery - -### ADR-0047 — Tauri 前端使用 Vite 静态 SPA +The Operation Registry is broader than the Agent-facing tool catalog. -`Status: accepted` +~~~ +Skill metadata +→ active Skill +→ only relevant Operation schemas +~~~ -桌面前端使用 React 18、Vite 与 HashRouter;开发模式固定由 7410 端口提供,发布模式由 Tauri 加载 `frontend/dist`。业务事实仍归 Python 后端,前端不依赖 Node.js 服务端运行时。 +The full Registry is a developer/audit surface, not a model menu. -## 职业事实、学习与记忆 +### Skills - -### ADR-0048 — 以条目级变更账本演进职业模型 +OfferU is composable with other installed Agent Skills. Third-party resume, recruiting, interview, negotiation or career-coaching Skills may provide methodology, drafting and critique. OfferU remains authoritative for canonical state, permissions and persistence. -`Status: accepted; supersedes ADR-0002 and narrows ADR-0011` +### Job acquisition -单一长期职业模型由仍有效的变更条目派生,针对岗位只生成投影,不改写主模型。职业证据必须确认;使用者明确陈述的偏好可直接追加;行为信号、Agent 推断、职业假设和程序性策略先进入记忆收件箱。每次生效或撤销都记录前后值、来源、理由、影响和取代关系。 +The beginner default is explicit current-page capture from the browser. Background crawling, reverse-engineered source APIs and bulk collectors are advanced/research paths, not the normal consumer onboarding requirement. - -### ADR-0011 — 各模块只通过学习观察反哺职业模型 +### External actions -`Status: accepted, narrowed by ADR-0048` +OfferU may prepare, preview and safely fill, but final irreversible external actions remain user-controlled unless a future product decision explicitly changes that boundary. -面试、简历、研究和投递模块产生带来源的学习观察,由统一 Memory Service 决定后续处理,业务模块不得直接改写其他模块或整体职业模型。任何观察都不能自动变成虚构经历;写入权以 ADR-0048 为准。 +### Progress sync - -### ADR-0012 — 学习观察即时记录、空闲时巩固 +Email and other channels create evidence/signals and reviewable progress candidates. They do not silently overwrite application stage. -`Status: accepted` +### Product interaction -交互发生时立即、确定性保存观察;去重、冲突识别、过期判断和长期更新建议在托盘空闲任务中异步完成。巩固失败保留原始观察并可重试,不得静默创建职业证据或改写主控规则。 +Default experience is Guided: - -### ADR-0013 — 只同步显式登记的工作源 +~~~ +Career State +→ Next Best Action +→ user chooses/confirms +→ Agent/Operation executes +→ state updates +→ next action recalculates +~~~ -`Status: accepted` +Do not make beginner users learn a command taxonomy. -只读增量同步使用者登记的仓库、作品目录或文档集合,不扫描整个磁盘。默认排除密钥、环境文件、依赖缓存和构建产物;实验或未交付内容不能自动表述为正式成果。 +### Release shape - -### ADR-0016 — 来源删除后级联失效派生记忆 +Normal users should receive native installers and should not need Python, Node, Git, MCP or CLI setup. Use existing local-Agent authentication when possible rather than duplicating API-key setup. -`Status: accepted` +## Historical decisions -原始来源被删除或撤销授权后,其派生观察、候选证据、档案结论和下游引用立即退出检索、提示、评分与巩固。仅保留不含原文的最小审计外壳;拥有其他独立有效来源的结论可以继续存在。 +Historical ADRs remain useful for understanding why code exists. They do not override this file, the Current Product North Star, CONTEXT.md or ARCHITECTURE.md. - -### ADR-0018 — 只提炼匿名简历表达模式 - -`Status: accepted` - -只从公开且允许使用的材料提炼匿名化结构、能力表达和量化方式。不得收集、长期保存或近似复刻候选人完整简历,也不得把他人经历写成使用者事实。 - - -### ADR-0025 — 用记忆收件箱审核职业模型变更 - -`Status: accepted` - -变更建议集中展示前后差异、理由、来源、影响和类型,支持接受、拒绝、稍后处理和撤销。系统不得先静默改写再通知,也不以频繁弹窗打断当前任务。 - -## 调研、投递与外部信号 - - -### ADR-0003 — 登录态平台只做使用者授权的只读研究 - -`Status: accepted` - -公开来源可自动研究;需要登录的平台只能由使用者主动发起本机只读浏览器会话。系统不保存平台密码、不绕过验证码或技术保护、不维持无人值守采集,也不执行发布、私信、投递等外部副作用。 - - -### ADR-0004 — 研究产物采用公司与岗位双层档案 - -`Status: accepted` - -维护可复用的公司档案和绑定具体公司岗位的岗位档案。证据快照带来源和时间戳,摘要可刷新但旧证据不被静默覆盖;简历、策略和面试准备读取同一岗位档案并引用共享公司档案。 - - -### ADR-0017 — 调研来源分级且结论逐条引用 - -`Status: accepted` - -硬事实优先使用官网、招聘官网和正式公告;主观信号至少由两个独立、近期来源交叉验证。单一来源必须标为单一信号,缺乏证据时标记未知,不允许模型补全。 - - -### ADR-0005 — 外部消息先形成候选进展 - -`Status: accepted` - -邮箱、短信等信号可同步、解析、去重和候选关联,但模型不能直接改变正式投递状态。高置信信号形成待确认候选,低置信信号进入待归属箱;只有使用者确认后才追加阶段事件。 - - -### ADR-0006 — 邮箱采用托盘驻留的本地增量同步 - -`Status: accepted` - -OfferU 运行期间,本地服务可在托盘持续增量同步、生成候选进展和通知;明确退出后停止。第一阶段不建设云端常驻服务或独立系统守护进程,各适配器必须保存游标并支持回补。 - - -### ADR-0007 — 一行代表一次投递尝试 - -`Status: accepted` - -每次投递是独立实体,分别保存所用简历、渠道、时间和阶段事件。重复投递可以引用同一公司与岗位档案,但不得覆盖历史尝试。 - - -### ADR-0019 — Agent 可建议投递关联但没有写入权 - -`Status: accepted` - -优先以申请编号、邮件线程、公司域名和岗位标识匹配外部信号;Agent 只能对非结构化候选进行排序和解释。多义或仅语义相似时由使用者选择,Agent 不得建立正式关联或写入阶段事件。 - - -### ADR-0022 — 邮箱默认只保存最小证据快照 - -`Status: accepted` - -默认只保存求职相关消息的标识、线程、发送者、时间、主题、相关正文片段和正文哈希。完整正文仅在同步和解析时短暂使用,除非使用者对单封邮件显式保存。 - - -### ADR-0034 — 先完成可复核投前决策再生成简历提案 - -`Status: accepted` - -主控 Agent 基于已确认职业证据和最近一次完成的岗位研究,提出投、有条件投、不投或证据不足,并逐条引用来源;最终决定与 Agent 建议分开保存。只有使用者确认投或有条件投,才提议生成可审核简历;其余结果和调研中断均是可恢复显式状态。 - -## 面试边界 - - -### ADR-0008 — 内容评价与表达行为反馈分开 - -`Status: accepted` - -默认报告不合并为单一总分。视觉与音频只提供可观察、可解释的行为统计,不推断人格、诚信、心理状态、录用概率或岗位胜任力;内容评价只能引用问题、回答、职业证据和岗位档案。 - - -### ADR-0009 — 面试评分规则声明式、版本化 - -`Status: accepted` - -自定义维度、权重、证据、阈值、提示词和聚合方式必须通过 schema 校验并记录规则 ID 与版本。评分 Skill 不得执行任意代码、访问未授权数据或突破内容与表达反馈隔离。 - - -### ADR-0010 — 面试视觉只保存派生事件与汇总 - -`Status: accepted` - -原始视频、截图和逐帧 landmarks 只存在于浏览器内存,不上传、不落盘。后端只保存表达事件和会话汇总,并支持按会话删除与导出。 - - -### ADR-0014 — 第一阶段采用轮次式语音面试 - -`Status: accepted` - -主控 Agent 逐题提问,使用者逐题录音或改用文字,本地端点检测结束后再转写和评价。默认不保存原始音频;第一阶段不建设可打断的全双工实时语音。 - -## Operation、Skill 与主控 Agent - - -### ADR-0029 — 所有入口共用一个 Operation Registry - -`Status: accepted` - -GUI、机器 CLI、TUI、斜杠 Skill 和本地 Harness 都是同一 Python Operation Registry 的适配器,共享 schema、权限、dry-run、确认提案、数据授权、审计、幂等和错误语义。任何入口都不得直接写数据库、执行隐藏 shell 或创建旁路业务状态机。 - - -### ADR-0037 — 结构化 Skill Registry 是技能唯一事实源 - -`Status: accepted` - -版本化 Registry 定义 Skill 身份、路由、适用目标、允许的 Operation 和确认边界,并生成各 UI 与 Harness 所需的薄入口。宿主 Markdown 只说明如何发现实时能力,不独立声明业务流程。 - - -### ADR-0041 — 旧确定性 Harness 逻辑降为 Guardian - -`Status: accepted` - -已有阶段判断、异常检测、提醒和记忆候选提取作为确定性前后置 Guardian 保留,但不再拥有独立意图路由、工具注册、工具循环、对话入口或写路径。Guardian 通过同一 Run 事件与事实门呈现结果。 - - -### ADR-0042 — 主控执行持久化为求职任务内的 Agent Run - -`Status: accepted` - -每次执行作为一个求职任务下的 Run,保存输入、Skill、标准化事件、Operation 调用、待确认动作、输出和恢复位置。对话是任务交互记录,领域对象是事实源;不建设跨任务全局 Session,也不按 GUI 页面拆 Run。 - - -### ADR-0051 — 外部 Coding Agent Harness 拥有唯一主控 Loop - -`Status: accepted; supersedes ADR-0036, ADR-0043 and ADR-0046` - -DeepSeek Harness、Codex、Claude Code、OpenCode 或 Pi 承载唯一主控 Agent 的推理会话、任务规划和工具循环。OfferU 只保留确定性工作台、Agent Bridge、Operation Registry、权限、确认、审计和业务事实源,不运行第二套内置主 Agent。 - -所有宿主通过各自薄接入包连接同一 CLI-first Bridge,不提供 MCP 业务入口,不允许直接访问数据库或使用隐藏 shell。Codex 与 DeepSeek Harness 优先实现;五种宿主只有通过同一行为一致性契约后才标为支持。 - - -### ADR-0052 — 主控 Harness 原生工具只作用于 Run 工件区 - -`Status: accepted` - -Harness 可以保留文件产物能力和经 Skill 授权的网络研究,但 Bash、编辑器和文件工具只能作用于当前 Run 独占工件目录。数据库、配置、源码、其他 Run 和未授权职业数据不可见;所有业务读取、提案和写入只能经 Agent Bridge 与 Operation Registry。 - -接入包必须实际探测隔离能力;若宿主只能限制写入,无法限制读取、网络或进程可见性,就不能标记为安全可用。工件始终是候选,只有经过审核和 Operation 接受后才能成为正式状态。 - - -### ADR-0053 — OfferU 拥有的确认界面是唯一确认权威 - -`Status: accepted` - -Harness 可以提出副作用 Operation 并等待,但只有 OfferU 拥有的嵌入工作区或专注窗口中的独立人类交互能够批准或拒绝。该界面即使渲染在 DSH Web 内,也直接连接 OfferU 控制面,不复用 Harness approval;接入包和模型可调用 CLI 不暴露确认能力。离线、断连和超时一律失败关闭,批准按提案 ID 与幂等键只生效一次。 - - -### ADR-0054 — 跨 Harness 故障切换必须创建新 Run - -`Status: accepted` - -无法恢复时不在同一 Run 内静默换宿主。使用者显式交接后,原 Run 保持中断或失败;新 Run 只继承已确认事实、可审计工件、未决提案和清洗后的执行摘要,并使用新的 Run ID、Harness session 和幂等命名空间。同一 Harness 的原生会话恢复可以保留原 Run。 - - -### ADR-0055 — Harness 原生界面是主外壳,OfferU 作为嵌入工作区 - -`Status: accepted; reframes ADR-0031; UI sharing boundary refined by ADR-0056` - -本地 Coding Agent 使用者的日常入口是 Harness 原生界面,因此 OfferU 不再以独立工作台或第二聊天应用争夺主界面。接入包在宿主允许时注册固定 OfferU 入口、任务内主视图和 OfferU 自有确认浮层;简历深编、摄像头面试等大画布任务才打开共享同一状态边界的专注窗口。首个 DSH 实现只使用可加式 UI extension points,不替换 DSH 的 Workspace/Session 导航、对话区或核心 details 面板;不支持安全 UI 嵌入的 Harness 使用 companion window,但主控 Loop 和提示输入仍留在 Harness。 - -OfferU 工作区是同一套 UI 与领域状态,但不承诺宿主提供全局中央页面:入口与确认可以是全局的,主视图按当前求职任务和 DSH Session 投影。它仍可浏览所有求职阶段和对象,但 Agent 执行绑定独立 Session/Run;界面统一不意味着多个岗位共享一个长期模型隐藏上下文。 - -DSH 接入采用原生 React client plugin,不把现有完整 OfferU SPA 作为 iframe 套入 DSH。host half 负责 CLI stdio Bridge 与生命周期,client half 使用 DSH 可加式 slots 注册界面;现有前端与接入包复用无头领域投影和交互状态机,独立壳只承载专注窗口或不支持嵌入的宿主。 - -跨 Harness 的一致性约束针对 Operations、Run、确认、事件和审计,而不是要求每个宿主提供相同 UI extension API 或视觉组件。DSH 使用原生嵌入;没有安全扩展点的 Codex、Claude Code、OpenCode 或 Pi 可以打开消费同一无头契约的 companion window,但不能因此降级业务契约。 - - -### ADR-0056 — Harness 共享无头交互契约,各自使用宿主原生 UI - -`Status: accepted; refines ADR-0055` - -DSH 内的 OfferU 工作区完全遵循 DSH 原生组件、布局、设计令牌与交互习惯,不形成 OfferU 品牌岛。跨 Harness 只共享类型化领域投影、交互状态机、Operation 合约和一致的确认语义;不共享同一套 React 页面或宿主无关视觉组件。每个支持 UI 扩展的接入包提供薄的宿主原生渲染器,companion window 则使用 OfferU 自有渲染器,但所有渲染器消费同一无头契约且不得维护第二份业务状态。 - -这一边界接受少量宿主渲染代码重复,以换取原生可用性、宿主升级适配和可访问性一致性;不得把领域判断、生命周期规则、权限或业务动作复制进渲染器。跨 Harness 一致性验收比较可见事实、状态转移、可执行 Operation、确认与错误语义,不做像素级一致性验收。 - - -### ADR-0057 — Codex Agent Engine 与 OfferU Career Control Plane 解耦 - -`Status: accepted` - -OfferU 不 Fork 或魔改 Codex Core;第一阶段通过 provider-neutral `AgentRuntimeProvider` 适配 Codex App Server stdio,并保留 Replay/Fixture 与未来其他 Harness provider 的替换 seam。Agent Runtime 只负责 thread、turn、event、skill/plugin、审批中断和执行生命周期,不拥有 Job、Profile、Resume、Application、Interview 或 Memory 真相。 - -CareerTask 是控制面的持久化执行信封,Provider Health 只保存脱敏的可用性和认证阻塞状态。所有会改变 OfferU 业务状态的 Agent、CLI、MCP、浏览器扩展和插件调用都必须回到 Operation Registry,经 Proposal/HITL、幂等和审计后才能进入 Domain Runtime;Agent 返回的意图、候选和报告不等于事实。`workspace.delegate` 也必须先创建 CareerTask,不能直接调用执行器或 Runtime。 - -OfferU Capability Plugin 使用自有版本化 Manifest,组合 CLI、Skill、capability、side effect、权限和输出契约。CLI 的 stdout 只能返回机器可读 JSON,stderr 只用于诊断;安装只改变本地能力发现状态,卸载不删除插件文件。插件输出由 OfferU Runtime 验证、去重、统计和持久化,不能把 Codex Marketplace 或任一 Harness 私有协议提升为业务契约。 - -当前 Codex 认证故障属于 Provider Health/G2B live verification,不阻塞 Fixture/Replay 的架构和产品验收;不得因此自动修改凭据、代理或切换用户 Provider。 - -自动化采用持久化 `AutomationEvent` → 显式 `AutomationRule` → `CareerTask` → Operation 的有限分发链,不引入常驻 Agent Loop。后台产生的岗位情报、简历建议和面试 Focus Plan 进入 Automation Inbox 作为候选或复核项;只有既有 Proposal/HITL 与 Career Memory 生命周期才能改变正式职业事实。 - - -### ADR-0058 — 岗位读取与站外投递动作使用独立 Connector 平面 - -`Status: proposed` - -`JobSource` 只负责 search/detail/recommend/application-record 等读取能力,输出 `JobObservation` 与外部进展信号;它永远不因为底层 CLI 或 Browser Bridge 同时具备写能力而暴露 greet、send、submit 等方法。站外动作使用独立 `ApplicationActionConnector`,统一建模 `greet / send_message / send_resume / exchange_contact` 等用户可感知动作。 - -OfferU 的产品顺序固定为:岗位发现与去重 → Role Intelligence / 投前决策 → Application Packet 准备 → `preview_application_action` dry-run → Proposal/HITL → 单条外部执行 → OperationAuditLog / 外部证据 → Application Event。批量场景只批量准备和批量审核,不允许把“批准一组岗位”退化为一个不可审计的后台海投循环。 - -`ApplicationActionConnector` 不拥有 Career Truth,不维护第二套 Application/Pipeline 状态。投前是否值得投由既有 Pre-Application Decision 决定;材料是否 ready 读取既有 Application Packet;外部执行成功与否由受保护 Operation 的审计和后续 `ExternalProgressSignal` 证据确认。重试必须复用稳定 idempotency key,避免重复打招呼、重复发消息或重复发送简历。 - -第一阶段只落地只读 `preview_application_action` 与 Connector 契约,不提供 BOSS 写执行器。未来无论底层使用 CLI、浏览器桥接还是其他用户授权通道,都必须接入同一 Proposal/HITL、幂等与审计边界;平台私有 token、Cookie、长 external ID 和浏览器细节不得进入普通 Agent Skill 或 Career Domain。 - -## 深度执行器 - - -### ADR-0015 — 本地深度执行器只承担可审计重任务 - -`Status: accepted` - -执行器只处理公司/岗位深度调研、批量 JD 评估和登记工作源摘要等可取消、可重放、可查来源的长任务。它只返回候选结果,不得直接写职业模型、晋升证据、确认投递阶段或决定面试评分。 - - -### ADR-0035 — OfferU 托管可替换的深度执行会话 - -`Status: accepted, narrowed to deep executors by ADR-0051` - -OfferU 负责深度执行会话的发起、恢复、事件呈现、取消和审批,并以可替换适配器使用 Codex、Claude Code 等。该托管边界只属于重任务执行器,不拥有主控 Agent 会话;结果仍经过 Operation Registry、事实门和使用者确认。 - - -### ADR-0038 — 每个托管执行会话只服务一个重任务 - -`Status: accepted` - -会话保存任务输入、执行器、标准事件、待确认动作、结果和恢复位置,完成后封存,不跨任务继承隐藏对话。跨任务连续性只来自已确认事实、学习观察和显式材料。 - - -### ADR-0039 — 深度执行器权限限定到当前任务 - -`Status: accepted` - -创建会话时只暴露该任务所需 Operation 与数据范围。执行器不能发现白名单外能力、用通用 API 或 shell 扩权,也不能直接写正式业务状态。 - - -### ADR-0044 — 托管深度执行器使用原生协议适配器 - -`Status: accepted` - -对支持托管会话的 Coding Agent,优先使用官方 SDK、App Server 或 Agent SDK,并归一为 OfferU 的事件、审批、取消和恢复契约。通用 CLI subprocess 只用于能力探测、一次性兼容或无托管协议的执行器;供应商差异留在无业务逻辑的适配层。 - - -### ADR-0045 — 用岗位调研闭环验证主控与执行器边界 - -`Status: accepted, reframed by ADR-0051` - -首个联合纵向切片嵌入投前决策:主控 Harness 通过 Skill Registry 创建受限深度执行会话,执行器形成带来源候选研究,OfferU 再通过证据规则、事实门和使用者审核决定是否进入档案。切片必须覆盖事件、取消、重启恢复、审计和显式失败。 - -## 工作台与交互 - - -### ADR-0030 — GUI 按求职流程组织 - -`Status: accepted` - -一级导航采用今日、机会、材料、进展和面试,而不是平铺技术模块。“今日”优先展示待确认、临近截止、进行中任务与下一动作;档案、设置和贯穿流程的主控 Agent 与阶段导航分离。 - - -### ADR-0031 — 使用任务中心的 Agent 工作台外壳 - -`Status: accepted, reframed by ADR-0055` - -任务优先交互仍围绕求职任务展示状态、证据、审批和结果,但主外壳改由 Harness 原生界面承担。OfferU 工作区嵌入宿主并采用渐进披露;简历深编与面试进入专注窗口;GUI/TUI 呈现可不同,但仍共享 Operation Registry。 - - -### ADR-0032 — 移动端只承担轻操作 - -`Status: accepted` - -桌面和平板承载完整工作区;手机聚焦查看、确认、更新投递进展和续接主控 Agent。简历深度编辑与面试训练保留在桌面或平板。 - - -### ADR-0033 — 一级页面收敛进五阶段导航 - -`Status: accepted` - -现有页面归入今日、机会、材料、进展与面试;邮箱成为进展信号收件箱,抓取成为机会导入入口,独立 Agent 与演示页面退出一级导航。收敛只改变页面组织,不合并领域事实或改变权限边界。 - -## 浏览器扩展 - - -### ADR-0049 — 一个 OfferU 扩展统一岗位采集与安全填表 - -`Status: accepted` - -只保留可维护的 OfferU WXT 扩展;外部已发布扩展只能作为 clean-room 行为参考。扩展使用版本化 `SiteRuleRegistry` 和内置 `ControlDriver`,只暴露岗位采集、填表和提交候选证据三类动作;它不提交申请、不保存独立简历或模型密钥,也不直接写数据库。 - -填表先生成绑定 URL、字段指纹和短时有效期的 `FillPlan`,经使用者二次确认后只填空白、非敏感、高置信字段,永不触发最终提交。提交后只能形成最小证据候选,确认后由 Operation Registry 原子创建投递尝试与阶段事件。扩展按需使用 `activeTab + scripting`,主界面采用 side panel,构建入口与产物以 WXT 约定为准。 - - -### ADR-0050 — 远程规则包必须版本化并签名 - -`Status: accepted` - -远程更新只允许 JSON 选择器、字段映射和能力声明,不得携带代码。单一 bundle 使用单调递增版本、schema 校验和 ECDSA P-256/SHA-256 签名,公钥内置、私钥不入库;失败、离线、重放或坏包时保留内置规则,并提供熔断与回滚。远程发布前仍需复核浏览器商店政策。 - -## 交付与验收 - - -### ADR-0027 — 按垂直闭环交付 - -`Status: accepted` - -依次交付共同底座,邮箱与投递,公司/岗位研究与证据化简历,以及语音/视觉面试。每阶段都从用户触发贯通处理、领域事实、确认界面和可见结果,不按数据库、API、前端等技术层横向铺开。 - - -### ADR-0028 — 使用三层量化验收门槛 - -`Status: accepted` - -安全不变量必须 100% 通过;概率能力必须在固定、版本化标注集达到阈值;完整场景必须通过端到端、重启恢复、重试和重复输入验证。页面可访问、构建成功或单次演示都不代表交付完成。 - -## 被取代的历史决策 - - -### ADR-0001 — 本地优先并预留 SaaS 边界 - -`Status: superseded by ADR-0023` - -旧决策曾要求避免全局单例以保留 SaaS 演进边界。当前明确不为未来 SaaS 预埋模型,以 ADR-0023 为准。 - - -### ADR-0002 — Profile 分层写权限 - -`Status: superseded by ADR-0048` - -旧决策允许主控 Agent 自动更新求职偏好。当前统一改为条目级账本和更严格的记忆收件箱规则,以 ADR-0048 为准。 - - -### ADR-0036 — 内置 Agent 使用进程内 Operation 投影 - -`Status: superseded by ADR-0051` - -旧决策假设 OfferU 内置主 Agent Core。当前主控 Loop 已迁移到外部 Harness,OfferU 只提供 CLI-first Agent Bridge。 - - -### ADR-0040 — 在 Python 内借鉴 Pi 运行时契约 - -`Status: superseded by ADR-0046, then ADR-0051` - -该方案先被 Pi SDK Worker 取代,随后内置主 Agent 路线整体被 ADR-0051 取代。 - - -### ADR-0043 — 内置主 Agent 工具协议按模型能力分型 - -`Status: superseded by ADR-0051` - -该决策属于已取消的内置模型适配层。现在由外部 Harness 处理模型协议,OfferU 只验证统一 Bridge 与 Operation 行为契约。 - - -### ADR-0046 — Pi SDK Worker 承载内置主 Agent - -`Status: superseded by ADR-0051` - -不再以 Node.js Pi Worker 承载第二套主 Agent。Pi 只能作为外部 Harness 接入目标或迁移期兼容实现。 - -## 编号索引 - -| 范围 | 主题 | -| --- | --- | -| ADR-0001–0028 | 产品边界、职业事实、研究、投递、面试、交付与验收 | -| ADR-0029–0034 | Operation、Skill、工作台与投前决策 | -| ADR-0035–0046 | 主控/执行器架构演进与被取代路线 | -| ADR-0047–0050 | 桌面前端、职业模型账本、浏览器扩展 | -| ADR-0051–0056 | 外部 Harness 主控、工具隔离、确认、交接与宿主原生工作区 | +Do not add a new numbered ADR for every implementation adjustment. Add a durable decision here only when it changes a long-lived boundary; keep implementation notes in the relevant architecture or product document. \ No newline at end of file From 4dac9b65217e0c6826630f2ce639338162b8b515 Mon Sep 17 00:00:00 2001 From: avabbbb <89175608+avabbbb@users.noreply.github.com> Date: Wed, 23 Sep 2026 00:24:21 +0800 Subject: [PATCH 12/36] docs: replace historical glossary with current domain context --- CONTEXT.md | 415 +++++++++++------------------------------------------ 1 file changed, 83 insertions(+), 332 deletions(-) diff --git a/CONTEXT.md b/CONTEXT.md index c6ca6fa1..80c5ee77 100644 --- a/CONTEXT.md +++ b/CONTEXT.md @@ -1,377 +1,128 @@ -# OfferU 求职运营 +# OfferU Context -OfferU 帮助使用者持续维护职业档案,并围绕岗位研究、材料定制、投递跟进和面试训练推进求职过程。 +Status: **CURRENT DOMAIN AUTHORITY** +Updated: 2026-09-23 -## Language +OfferU is a local-first AI Career OS. This glossary keeps only concepts that should guide current product and Agent behavior. -**主控 Agent**: -由使用者选择并经能力探测通过的外部 Coding Agent Harness 承载,是理解目标、自然语言推理、任务规划和选择 OfferU Operation 的唯一智能主体。它不能拥有业务事实、授予自身权限或绕过 OfferU 操作控制面执行副作用。 -_Avoid_: OfferU 内置 Agent、操作员 Agent、第二主脑、业务后端 +Historical terminology is preserved in [the archived context](./docs/archive/architecture/context-pre-2026-09-23.md). -**OfferU 操作控制面**: -OfferU 内部不含 LLM loop 的确定性运行边界,负责工作台状态、上下文投影、权限、确认、Operation 执行、幂等、事件和审计。它接收主控 Agent 的类型化调用,但不理解开放式目标、不规划任务,也不选择下一项 Operation。 -_Avoid_: 内置 Agent、主 Agent 运行时、Pi Core、Harness Agent、第二主脑 +## Core authorities -**操作守卫**: -在主控 Agent 的 Operation 调用前后执行阶段检查、风险提醒和记忆候选提取的确定性策略集合。它不能选择或执行业务 Operation,也不拥有独立对话、工具循环或记忆事实。 -_Avoid_: Main Agent Guardian、Harness Agent、规则 Agent、第二 Agent、工具路由器 +**Career Runtime** +The canonical domain runtime for Profile, Evidence, Jobs, Applications, Resumes, Interviews, Events and durable Memory state. -**本地深度执行器**: -由主控 Agent 按需委托,用于完成边界明确的深度研究或批量分析任务的本地智能执行能力。它不拥有业务事实源,也不能绕过使用者确认独立改变求职状态。 -_Avoid_: 主控 Agent、系统主脑、自治 Worker +**Operation Registry** +The governed execution surface for business capabilities. It owns validation, permission checks, side-effect classification, Proposal/HITL routing, idempotency and audit. The Registry is not identical to the Agent tool catalog. -**执行器适配器**: -把一种本地深度执行能力的会话、事件、审批、取消和恢复语义映射为 OfferU 托管执行会话契约的边界。它不包含求职业务逻辑,也不能扩大任务能力授权。 -_Avoid_: CLI Wrapper、Agent 后端、Provider、业务插件 +**Reasoning Authority** +The single active Agent for a given Agent Run. Prefer a verified local external Agent already used by the user; OfferU may provide a fallback Agent. The reasoning authority plans and selects capabilities but does not own Career Truth or approval. -**托管执行会话**: -由 OfferU 操作控制面根据主控 Agent 的类型化请求为一个可审计重任务创建,并持有任务边界、权限、生命周期与审计责任的一次本地深度执行过程。会话可以中断恢复,完成后封存且不跨任务继承隐藏上下文;底层执行能力可以替换,但不能因此取得主控权或业务事实写入权。 -_Avoid_: Codex 会话、Claude 会话、外部 Agent 对话、独立 Agent 任务 +**Agent Host** +A local application/runtime capable of hosting the active Agent or OfferU Skill, such as Codex, WorkBuddy/CodeBuddy, Claude Code, OpenCode, OMP, Pi or another supported host. Detected does not mean verified. -**任务能力授权**: -OfferU 操作控制面依据使用者授权为一个托管执行会话签发的 Operation 与数据范围白名单,只允许完成当前可审计重任务所需的最小能力。它随会话结束失效,不授予业务事实写入权,也不能由主控 Agent、Skill 或执行器自行扩大。 -_Avoid_: Agent 权限、全局工具权限、Prompt 白名单、用户角色 +**Agent Run** +One auditable execution attached to a user goal. A Run records selected Skill, inputs, tool events, proposals, outputs and terminal state. Hidden model context is not Career Truth. -**Run 工件工作区**: -一个 Agent Run 独占的隔离文件空间,用于主控 Harness 处理显式输入、中间文件和候选产物。它不是职业事实源或跨 Run 记忆,不能包含 OfferU 数据库、配置、源码或未授权职业数据;其中产物必须经审核和 Operation 才能进入正式业务状态。 -_Avoid_: 项目工作区、OfferU 仓库、Agent 记忆目录、共享临时目录 +## Skills and tools -**Run 工具授权**: -OfferU 操作控制面依据所选 Skill 和使用者授权,为一个 Agent Run 限定可调用的 Operation、数据范围、Run 工件工作区和外部网络能力。授权随 Run 结束失效,主控 Harness 或接入包不能自行扩大,也不能把原生 Coding Agent 工具变成业务写路径。 -_Avoid_: 全局工具权限、Harness 默认权限、项目级 Shell、自动授权 +**OfferU Skill** +The portable instructions that teach a compatible Agent host how to discover OfferU capabilities and respect OfferU's truth, permission and confirmation boundaries. -**可审计重任务**: -可以取消、重放并检查输入、工具调用、输出和来源的长耗时任务。第一阶段包括公司/岗位深度调研、批量 JD 评估和已登记工作源的变化摘要;其结果必须经过 OfferU 的事实门和使用者确认后才能影响领域数据。 -_Avoid_: Agent 自动化、后台任务、Profile 自动更新 +**Third-party Career Skill** +An independently installed resume, recruiting, interview, negotiation or career-coaching Skill. It may contribute methodology or draft content but cannot directly mutate OfferU truth or weaken safety rules. -**统一控制台**: -让使用者或本地 Coding Agent 通过 GUI、机器 CLI、交互式 TUI 或斜杠 Skill 命令操控 OfferU 的多入口控制面。所有入口都调用同一 Operation Registry,并共享参数 schema、权限、确认、审计、数据授权和错误语义;控制台本身不实现业务逻辑。 -_Avoid_: CLI 后端、TUI 应用、第二套控制系统 +**Agent Tool Surface** +The intentional subset of Registry Operations exposed to Agents. -**机器 CLI 契约**: -OfferU 向主控 Agent 和本地自动化公开的唯一机器控制契约,以结构化能力探测、manifest、Operation schema、dry-run、执行、提案状态、取消和事件定义可调用表面。Harness 接入包可以包装该契约,但不能确认自身提案,也不能另建 MCP、原始 HTTP、数据库或任意 shell 业务入口。 -_Avoid_: MCP 业务接口、REST 自动化后端、Shell 脚本协议、固定 Provider argv +**Active Skill Surface** +The smallest task-specific set of Operations loaded after a Skill is selected. -**OfferU Agent Bridge**: -外部主控 Harness 将自身会话关联到 OfferU Agent Run,并取得当前任务上下文和已授权 Operation 的唯一确定性连接面。主会话、推理和工具循环属于外部 Harness;Bridge 不规划任务、不拥有业务事实,也不成为第二个 Agent。 -_Avoid_: OfferU Harness Host、内置 Agent Runtime、MCP Host、第二主脑 +**Capability Gap** +A user goal for which no legal public OfferU Operation path exists, even assuming an ideal Agent. -**OfferU Agent Runtime**: -由 `AgentRuntimeProvider` 暴露的 provider-neutral 执行边界,负责 thread、turn、event、Skill/Plugin 发现、审批中断、取消和恢复等 Harness 生命周期。Codex App Server 是首个主 Provider,Pi/Replay 适配器用于当前本地兼容与确定性验收,其他 Provider 必须通过同一契约后才能标记支持;该边界不拥有 Career Truth,也不能替代 Operation Registry。 -_Avoid_: Career Runtime、业务 Agent、第二套 Operation Registry、Codex Core Fork +**Tool Discovery Failure** +A legal capability exists, but the active Agent fails to find or select it. -**CareerTask**: -OfferU 控制面持久化的长任务执行信封,记录 task type、目标、provider、输入契约、状态、事件、checkpoint、结果引用和显式失败。它与可见的求职任务、主控 Agent Run 和 Hosted Executor Session 不同;其结果仍是候选或提案,不能直接成为职业事实。 -_Avoid_: Job、求职任务、Agent Run、后台字符串调用、事实表 +## Career truth and learning -**Agent Provider Health**: -OfferU 对 Agent Runtime provider 保存的脱敏健康快照,至少表达 available、authenticated、blocked、版本、协议和最后错误。Codex 401 属于 Provider Health/G2B live 验收阻塞,不是 Role Intelligence 业务事实,也不能触发静默换凭据或换 Provider。 -_Avoid_: API Key、Auth Token、Career status、LLM 业务结果 +**Career Profile** +The long-lived, evidence-backed representation of the user's experience, achievements, skills, preferences and goals. -**OfferU Capability Plugin**: -通过自有版本化 Manifest 组合 CLI、Skill、capability、side effect、权限和输出契约的本地能力包。安装改变 Agent 能力发现,卸载只禁用能力;CLI 输出必须是 JSON,插件不能直连数据库、拥有 Career Truth 或绕过 Operation Registry。首个真实公开源实现是 `job-search`;fixture 插件只能用于 replay/验收,不能伪装成 live source。 -_Avoid_: Codex Fork、Marketplace 业务契约、插件数据库、自由 Shell 入口 +**Career Evidence** +A fact or source-backed statement that can support resume, matching or interview work. -**AutomationEvent**: -OfferU 控制面接收的可幂等外部或内部信号,例如 `JOB_SAVED`、邮箱进展和面试完成。事件只触发明确的 Automation Rule,不直接修改 Career Truth;分发失败、Provider 阻塞和结果引用都必须持久化。 -_Avoid_: 无限 Agent Loop、隐式触发器、聊天消息、静默状态变更 +**Observation / Candidate** +New information that may be relevant but is not yet canonical truth. Sources include resumes, user statements, authorized Agent memory, email, browser receipts and interview/debrief learning. -**Automation Inbox**: -从 AutomationEvent、CareerTask 和候选提案派生的使用者处理队列,按 needs approval、needs review、FYI、completed、failed 分类。它是注意力投影,不是新的事实表;关闭项目不会代替 Operation 确认或 Career Memory 提交。 -_Avoid_: 弹窗风暴、自动批准、第二套任务数据库、直接写 Profile +**Learning Observation** +A reviewable signal produced by outcomes, user corrections, interview performance or repeated behavior. It can propose a Profile change but does not silently become fact. -**Harness 接入包**: -安装到一种外部 Coding Agent Harness 中、把 OfferU Skill、上下文、Operation、Agent Run 事件和人类控制界面投影为该宿主原生能力的薄集成。支持 UI 扩展的宿主使用 host/client 双面插件:host half 连接 CLI-first Bridge,client half 注册原生 OfferU 工作区;它只适配宿主差异,不包含求职业务逻辑,也不能扩大权限或形成独立事实源。 -_Avoid_: Harness Driver、CLI Wrapper、Provider 业务后端、iframe 应用、MCP 插件 +**Progressive Profiling** +Ask the minimum during onboarding and request additional information only when it helps a current decision. -**Harness 主界面**: -使用者与主控 Agent 对话并管理其原生会话的 Harness 界面,是本地 Coding Agent 使用者的默认产品外壳。它拥有提示输入和会话交互,但不拥有 OfferU 业务事实、Operation 确认或求职状态。 -_Avoid_: OfferU 聊天框、第二工作台、Agent 控制面、业务事实界面 +## Job and application flow -**OfferU 工作区**: -由 OfferU 拥有并通过统一领域投影、交互状态机与 Operation 合约投影到 Harness 主界面的人类控制表面。各 Harness 使用自身原生组件和视觉语言渲染,不共享同一套 React 页面;它可以按宿主能力拆成全局入口、全局确认界面和任务内主视图,用于浏览求职流程、事实、证据、Run、提案和结果,大画布任务则在同一状态边界下弹出 OfferU 专注窗口。它不要求宿主提供一个永远占据中央区域的全局页面,不提供第二个 Agent 提示输入,也不把全局领域数据变成一个全局模型会话。 -_Avoid_: 独立主应用、OfferU Agent 聊天、Harness 侧栏替代品、嵌入网页副本 +**Job Capture** +User-triggered import of the currently viewed job page into OfferU. It is not background crawling and does not mean the user has applied. -**宿主原生工作区渲染器**: -Harness 接入包 client half 中只负责把 OfferU 的类型化领域投影和交互状态映射为该宿主原生组件、布局、令牌与可访问性行为的薄渲染层。它不拥有领域状态机、Operation 规则或确认决策,也不能为了复用视觉而嵌入共享 React 页面、复制 OfferU SPA 或维护第二份业务状态。 -_Avoid_: 共享 UI 包、品牌微前端、主题皮肤、iframe 页面、宿主无关 React 页面 +**Job Context** +The opportunity-specific workspace containing the job, research/role signals, evidence gaps, resume/application material, application state, interview preparation and timeline. -**OfferU 任务视图**: -OfferU 工作区在当前求职任务与 Harness session 内的主操作表面,首先让使用者看清任务状态、下一动作、待确认事项和已产出结果;上下文、Run、Operation、证据与候选工件都从该任务进入。它可以读取全局职业数据与流程导航,但任何 Agent 动作都绑定当前任务、Run、授权和事件流;切换任务必须切换或恢复对应 Harness session。 -_Avoid_: 全局 Agent 面板、全局 OfferU 首页、聊天流插卡、第二聊天页、跨 Session 控制台、工作台 iframe +**Application Attempt** +One real application to a job/opportunity. Re-applying may create another attempt. -**任务视图主状态**: -OfferU 任务视图首屏在任一时刻只突出一个最需要使用者理解或处理的状态,固定优先级为待确认、失败或断连、正在执行、下一动作、最近完成。它是从提案、连接、Run、任务和 outcome 派生的注意力投影,不覆盖底层事实;未成为主状态的信息仍可在详情和时间线中查看。 -_Avoid_: 并列仪表盘、多个同权主按钮、AI 在线、卡片堆砌、用最近完成遮住待确认 +**External Progress Signal** +An email or other authorized message that suggests something changed. It is evidence, not the stage itself. -**任务会话绑定**: -OfferU 工作区的入口和领域数据可以全局可达;只有完全空白且尚未绑定的 Harness session,才能在使用者通过 OfferU 入口显式选择或创建求职任务后建立一次绑定,一条 session 只能绑定一个求职任务且绑定后不可改绑。已有聊天或工具历史、或需要切换任务时,必须新建或恢复对应 session,并同时切换推理上下文、授权和事件流,不能把多个岗位继续写入同一隐藏模型上下文。 -_Avoid_: 全局 Agent Session、Session 改绑、历史会话补绑、跨任务隐藏记忆、按页面建 Session、共享 Run +**ApplicationProgressCandidate** +A proposed progress interpretation awaiting review or an explicit safe policy decision. -**Harness 支持目录**: -OfferU 明确维护的外部主控 Harness 集合,包含 Codex、DeepSeek Harness、Claude Code、OpenCode 与 Pi;Codex 和 DeepSeek Harness 是首批优先接入目标。目录声明产品目标,某台设备上的实际可用性仍由对应 Harness 接入包实时探测,不能用假能力或静默替代伪造支持。 -_Avoid_: Provider 列表、模型列表、固定命令表、自动降级链 +**ApplicationStageEvent** +The durable event representing a confirmed application-stage transition. -**主控 Harness 一致性契约**: -Codex、DeepSeek Harness、Claude Code、OpenCode 与 Pi 被标记为“支持”前必须共同满足的完整业务行为契约,包括创建与恢复会话、追加指令与运行中转向、中断与取消、通过 CLI-first Agent Bridge 调用 OfferU Operation、暂停并恢复使用者确认、输出统一事件流,以及显式报告完成或失败。宿主可以按能力使用原生嵌入工作区或 OfferU companion window,但不得因此缩减业务能力、改用一次性问答或隐藏降级;Codex 和 DeepSeek Harness 仅决定实现优先级,不降低其他三种的最终验收门槛。 -_Avoid_: 基础可用、实验性支持、兼容模式、最低公分母协议 +**External Submit** +The user's irreversible action on a recruitment site. OfferU may prepare or fill safe fields, but does not silently perform final submit. -**Harness 交接**: -当前主控 Harness 无法恢复时,由使用者显式选择另一 Harness,并用原 Run 的已确认事实、可审计产物、未决提案和可公开执行摘要创建新 Agent Run 的转换。原 Run 保持中断或失败终态,隐藏会话、未记录推理和原生进程状态不得冒充可移植上下文。 -_Avoid_: 自动 Failover、跨 Harness 恢复、Session 迁移、同 Run 换 Provider +## Interaction model -**受控 CLI Broker**: -OfferU Agent Bridge 内部接收主控 Agent 提交的结构化 JSON/JSONL 命令,在绑定当前 Agent Run、Run 工具授权和幂等信息后分派到对应 Operation,再把标准结果返回主控会话的边界。它不接收 shell 字符串、管道、重定向、任意可执行文件或绕过确认的调用,也不把 Harness argv 变成业务契约。 -_Avoid_: Shell Tool、Bash/PowerShell 代理、MCP Tool、通用 subprocess、动态业务 API +**Today / Next Best Action** +The guided projection of what matters now. It is derived from Career State and is not a second task truth store. -**OfferU 确认**: -使用者在 OfferU 拥有的嵌入工作区或专注窗口中核对 Operation 提案、影响和证据后作出的批准或拒绝,是提案获得执行授权的唯一来源。Harness 原生 approval、接入包和模型可调用 CLI 只能请求并等待,不能代表使用者作出决定。 -_Avoid_: Agent 确认、Harness Approval、CLI confirm、模型自批、聊天回复确认 +**Guided Mode** +Default beginner experience. OfferU recommends at most a few high-value next actions and explains why they matter now. -**斜杠 Skill 命令**: -在主控 Agent 对话入口或 TUI 输入框中显式激活一个版本化 Skill 的命令形式。`/offeru` 打开技能菜单,`/skill-id` 或已声明 alias 直接进入具体 Skill;两种入口都从 Skill Registry 自动生成并解析到同一 Skill ID,只选择协议与允许操作集合,不执行 shell,也不绕过领域事实门。 -_Avoid_: Slash Command、快捷命令、Shell 命令 +**Power Mode** +Advanced access to Agent chat, Skills, CLI, batch workflows and diagnostics. It must not be required for normal onboarding. -**Skill Registry**: -OfferU 可用求职技能的唯一版本化目录,定义每个 Skill 的身份、适用目标、允许操作和确认边界。主控 Agent、斜杠 Skill 命令与其他控制入口都引用这一目录,不分别维护技能事实。 -_Avoid_: Skill 文件夹、Prompt 列表、命令表、外部 Agent 手册 +**Zero Setup** +The user installs OfferU and reaches useful value without installing Python/Node/Git or manually configuring Agent protocols. -**操作员 TUI**: -通过 `offeru tui` 启动的本地交互式终端界面,用于浏览投递、Agent Run、研究档案、记忆收件箱、提案和审计,并通过统一 Operation Registry 发起操作。它是人类控制面,不拥有独立数据库或业务写路径。 -_Avoid_: Agent TUI、Dashboard、Terminal App、后台控制台 +**Zero Figure-It-Out** +The user does not need to understand which mode/Skill/tool to invoke next; OfferU proactively guides the next action. -**本地个人工作区**: -由一名使用者拥有并在个人设备上运行的完整求职工作空间。第一阶段的所有数据、记忆和自动化均服务于这个唯一拥有者。 -_Avoid_: 默认用户、全局账号、单例用户 +## Safety vocabulary -**本地单人边界**: -第一阶段只有一个本地拥有者和一份本地数据空间。领域数据可以明确依赖这一产品约束,不引入 workspace、tenant、organization、登录、计费或租户权限等 SaaS 概念;若未来出现 SaaS 需求,重新进行独立架构设计。 -_Avoid_: SaaS 演进边界、预留多租户、默认用户兼容层 +**Proposal / HITL** +A protected mutation pauses for review before execution. -**Python 业务后端**: -第一阶段承载 Agent、记忆、简历、调研、投递、邮箱和面试领域逻辑的唯一业务运行时。Tauri/Rust 只负责桌面壳、系统托盘、钥匙串和进程管理等系统桥接,不与 Python 双写业务事实。 -_Avoid_: Python Worker、临时后端、Rust 迁移过渡层 +**False Success** +The Agent claims a task succeeded when trustworthy execution/outcome evidence does not show success. -**垂直交付阶段**: -从用户触发、Agent 或确定性处理、领域事实、审核界面到最终可见结果组成的可独立使用闭环。第一阶段按共同底座、投递进度、岗位调研与简历、AI 面试的顺序推进,不按数据库、API、前端等技术层横向铺开。 -_Avoid_: 模块开发、后端阶段、功能列表 +**Protected State** +Career records or external actions whose mutation requires explicit policy/confirmation safeguards. -**任务优先工作区**: -OfferU 工作区的统一交互模型,以使用者当前处理的求职对象、状态与下一动作作为主体;无论嵌入 Harness 还是弹出专注窗口都共享同一领域状态。 -_Avoid_: 营销式模块首页、页面 Hero、独立视觉工作室、第二聊天应用 +## Product surfaces -**求职流程导航**: -任务优先工作区按今日、机会、材料、进展与面试五个求职阶段组织内部入口;档案和设置是支持入口,主控 Agent 的连接状态贯穿各阶段而不是成为并列业务模块。 -_Avoid_: 平铺模块导航、功能清单导航、Agent 独立模块 +The stable top-level surfaces are: -**求职任务**: -使用者围绕一个求职目标持续推进的可见工作单元,可以关联领域对象、对话记录、Agent Run、待确认动作、证据与结果。对话是任务内的交互记录,Agent Run 是任务的一次执行,两者都不代表任务本身。 -_Avoid_: 对话、页面、Agent Run、后台任务 +~~~ +Today +Pipeline +Job / Opportunity +Profile +~~~ -**Agent Run**: -主控 Agent 在一个求职任务内进行的一次可暂停、可恢复和可审计执行,记录输入、选定 Skill、事件、Operation 调用、待确认动作与结果。每次 Run 的底层 Harness 会话只服务该 Run、可以从已保存状态重建且不能跨 Run 继承隐藏上下文;Run 不拥有任务目标或领域事实,完成后成为该求职任务的执行记录。 -_Avoid_: 求职任务、对话、Agent Session、后台任务、工作流 +Agent, Email, Browser Capture, Resume, Interview and Memory are cross-cutting capabilities, not separate competing products. -**Agent Run 事件**: -Agent Run 内按单调序号追加的 provider-neutral 生命周期记录,用于表达 Skill 选择、消息增量、Operation 提案与执行、外部执行器状态、审核点和 Run 终态。界面与恢复逻辑只消费这层标准事件;Pi、Codex 或 Claude 的原始事件可以进入审计 trace,但不能成为产品状态的唯一来源。 -_Avoid_: Provider JSONL、聊天消息、审计日志、前端通知 - -**今日行动队列**: -从待确认动作、临近截止、进行中求职任务和建议下一步派生的当日处理视图。它帮助使用者决定现在做什么,但不是求职状态或职业事实的来源。 -_Avoid_: 数据看板、统计首页、任务事实表 - -**移动端轻操作**: -任务优先工作区在手机尺寸下提供查看、确认、投递进展更新和主控 Agent 续接,不承担简历深度编辑或面试训练。它与桌面端共享领域事实和操作契约,但不追求界面能力完全对等。 -_Avoid_: 全端功能一致、移动端只读、手机版工作台 - -### 使用者模型 - -**使用者职业模型**: -OfferU 对使用者职业现状与发展可能性的分层表达,由职业证据、求职偏好、职业假设和学习观察共同组成。它不是一份简历,也不是可以被 Agent 整体重写的单一 Profile 文本。 -_Avoid_: 总 Profile、用户画像、优化记忆 - -**职业模型演进**: -使用者职业模型因新的已确认事实、显式偏好和经验证的求职学习而发生的长期变化,通过可追溯提案增补、纠正、取代或失效其中的组成部分。它改善模型的完整性、时效性、证据质量和决策适用性,但不美化职业证据、不把 Agent 推断改写成事实,也不整体重写一个单一 Profile 文本。 -_Avoid_: Profile 进化、用户画像优化、人格成长、自动改写 Profile - -**职业模型变更账本**: -按条目追加记录每次已接受或已撤销职业模型变化的长期历史,保留变化前后、来源、理由、影响和取代关系,并从仍有效的条目派生当前职业模型。它使单项撤销、变化解释和下游材料过期判断成为同一演进链的一部分。 -_Avoid_: Profile 快照、当前 Profile、编辑日志、提案列表 - -**岗位职业投影**: -面向一个具体岗位,从使用者职业模型中选择相关职业证据、偏好和已验证方向,并组织成当前岗位所需叙事的临时视图。它不修改长期职业模型;可跨岗位复用的新发现必须重新经过学习观察与审核后才能回流。 -_Avoid_: 岗位 Profile、定制用户画像、Profile 分支、事实改写 - -**职业证据**: -由使用者确认、能够追溯到具体来源的教育、经历、项目、技能或成果事实。它是简历、岗位匹配和面试回答可以直接引用的事实基础。 -_Avoid_: Profile 内容、用户画像、AI 推断 - -**求职偏好**: -使用者当前对岗位、地点、行业、工作方式或求职节奏的可变选择。使用者明确陈述的偏好本身构成确认;行为信号或 Agent 推断只能形成待审核更新提案,且无论如何都不构成职业经历事实。 -_Avoid_: 职业证据、永久性格、硬性事实 - -**职业假设**: -主控 Agent 根据职业证据、岗位研究或行为信号提出的待验证发展可能性。它必须与职业证据隔离,只有经过验证和使用者确认后才能成为目标方向。 -_Avoid_: 目标岗位、既定能力、Profile 事实 - -**学习观察**: -AI 面试、简历优化、岗位研究或投递进展产生的一条可追溯行为信号,例如使用者采纳的改写、反复出现的回答缺口或某类岗位的阶段结果。它可以触发职业模型更新建议,但本身不是职业证据。 -_Avoid_: 记忆、事实、用户标签 - -**学习证据门**: -区分可以支撑策略更新的强证据与只能形成待验证学习观察的弱信号。使用者的明确纠正、采纳或拒绝以及经确认的求职结果属于强证据;点击、停留、跳过、改写等隐式行为和 Agent 推断不能单独形成长期结论。 -_Avoid_: 行为画像、隐式学习、统一置信分 - -**记忆巩固**: -在 OfferU 空闲时对学习观察进行去重、冲突识别、过期判断和长期更新建议生成的过程。它不能静默创建职业证据,也不能自行修改 OfferU 的政策、权限或事实门规则。 -_Avoid_: 自动学习、夜间重写、Profile 优化 - -**记忆收件箱**: -集中呈现使用者职业模型变更建议的审核界面。每条建议展示变更前后差异、理由、来源和影响范围,并支持接受、拒绝、稍后处理与撤销;未处理建议不能静默成为职业证据或已验证职业假设。 -_Avoid_: Profile 通知、记忆列表、对话确认弹窗 - -**职业策略学习循环**: -将岗位推进、材料采纳、投递结果和面试反馈先记录为学习观察,经证据化复盘形成可检验的策略假设,再以待审核更新提案影响后续求职任务的跨任务学习过程。系统可以自动采集、分析和提出变更,但长期职业结论、程序性策略与助手工作风格只有经使用者确认后才能永久生效。 -_Avoid_: 自我进化、自动学习、人格重写、复盘报告 - -**工作源**: -使用者明确登记并授权 OfferU 只读同步的代码仓库、作品目录或文档集合。工作源中的变化可以形成学习观察或待确认职业证据,但未完成内容不自动等于履历成果。 -_Avoid_: 工作区、项目目录、本机扫描 - -**来源级联失效**: -原始来源被删除或撤销授权时,使该来源及其派生学习观察、候选证据、档案结论和下游引用立即退出检索、提示词、评分和记忆巩固的过程。系统只保留不含原始内容的最小审计外壳;其他独立有效来源提供的支持不受影响。 -_Avoid_: 软删除、停止同步、删除全部历史 - -### 岗位研究 - -**岗位采集**: -使用者在浏览器中显式触发,从当前有权访问的岗位详情页读取公司、职位、JD、来源链接等信息,并形成待导入 OfferU 的本地岗位候选。岗位采集及其后的岗位入库都不代表使用者已经申请该岗位,也不创建投递尝试。 -_Avoid_: 后台爬虫、自动投递、收藏即投递 - -**站点规则包**: -由 OfferU 维护并随浏览器扩展版本化发布的只读适配数据,描述某类招聘页面的识别信号、岗位字段定位、表单结构、受支持控件和提交回执证据。规则包只能引用扩展内置的已知控件驱动,不能携带或下载任意可执行代码;未经 fixture 与真实浏览器验收的规则只能用于诊断,不能启用填表。 -_Avoid_: 牛客规则同步、远程脚本、站点特例代码堆、万能选择器 - -**用户授权只读研究**: -使用者主动发起并监督的本机浏览器研究会话,用于读取其本人当前有权访问的登录态内容。该会话只能形成带来源的研究证据,不能代表使用者发布、联系、投递或改变外部账号状态。 -_Avoid_: 自动爬虫、后台采集、账号托管 - -**公司档案**: -围绕一家公司的业务、产品、组织环境、文化信号、招聘风险和时效性动态持续维护的来源化研究集合。它可以被该公司的多个岗位复用。 -_Avoid_: 公司简介、一次性调研报告 - -**岗位档案**: -围绕某家公司的一项具体岗位持续维护的研究集合,包含 JD 证据、团队线索、工作内容、面经、参考材料和求职策略。它引用公司档案,但不把其他岗位的信息混入当前岗位事实。 -_Avoid_: Job、JD 摘要、公司档案 - -**岗位推进闭环**: -使用者围绕一个高意向真实岗位,从导入、投前判断和调研推进到取得可审核材料与明确投递待办的一次端到端求职任务;外部提交仍由使用者完成。它是 OfferU 第一阶段的首要价值边界,不等于覆盖岗位发现、面试、Offer 与长期职业陪伴的全程求职系统。 -_Avoid_: 全程求职 OS、自动投递流水线、岗位自动申请 - -**有效推进效率**: -衡量一个岗位推进闭环从岗位导入到使用者批准材料与投递待办所消耗的使用者主动时间。只有职业事实准确、产物经审核可采用且返工处于约定边界内的闭环才算有效;模型生成速度、Agent 运行时长和投递数量都不能替代它。 -_Avoid_: 生成速度、Agent 耗时、投递吞吐、效率分 - -**投前决策**: -主控 Agent 基于当前岗位、已确认职业证据和已完成岗位调研提出的可复核建议,建议值只能是投、有条件投、不投或证据不足。它必须展示理由、缺口和来源;使用者最终选择与 Agent 建议分别保存,只有使用者确认投或有条件投后,投前决策闭环才允许生成该岗位的简历提案。 -_Avoid_: 岗位匹配分、Agent 评分、自动投递结论 - -**投前决策闭环**: -从选定真实岗位开始,依次检查职业证据、岗位调研和投前决策,在可持久化的人工确认点暂停,并在使用者确认投或有条件投后生成可审核简历提案的垂直交付阶段。调研进行中、证据不足与不投都是可解释退出状态;闭环不创建投递尝试,也不提交外部申请。 -_Avoid_: 求职自动流水线、简历生成流程、投递自动化 - -**调研证据等级**: -决定调研结论可如何表述的来源质量与交叉验证规则。公司业务、岗位要求等硬事实优先由官网、招聘官网和正式公告支撑;团队氛围、面经等主观信号需要至少两个独立近期来源,否则只能标为单一信号或未知。每条结论必须可追溯到具体来源。 -_Avoid_: 来源数量、AI 可信度、统一置信分 - -**简历表达模式**: -从公开且允许使用的参考材料中提炼出的匿名化结构、能力表达方式和量化方法。它保留来源与授权状态,但不保存或复刻真实候选人的完整简历,也不能作为使用者经历或成果的事实来源。 -_Avoid_: 模范简历、简历库、优秀候选人简历 - -### 投递进展 - -**投递表单填写**: -使用者完成投前判断后,由浏览器扩展从 OfferU 的已确认职业事实生成可审核填写计划,并在使用者再次确认后只填写当前外部表单中的空白、非敏感字段。它不覆盖网页已有值,不填写身份证明、薪资、工作许可、授权同意等敏感或承诺性字段,不点击最终提交,也不因填写完成而创建投递尝试;牛客或其他第三方云简历不能成为该流程的职业事实源。 -_Avoid_: 一键投递、自动申请、牛客云简历同步、填完即已投 - -**外部提交**: -使用者在招聘网站核对整份申请后亲自执行的最终提交动作。它会改变外部账号或申请状态,浏览器扩展和 Agent 都不得代替使用者触发;OfferU 只能在动作之后读取回执或成功页面作为待确认的提交证据。 -_Avoid_: 二次确认代提交、无人值守提交、表单填写完成 - -**提交候选证据**: -浏览器扩展在使用者亲自提交后,从成功页面或回执中提取的最小证据候选,例如公司、岗位、申请编号、发生时间和来源页面。它在使用者确认前不能创建投递尝试或改变正式投递阶段;使用者确认后,OfferU 才通过统一 Operation Registry 原子创建投递尝试及其初始 Submitted 阶段事件。 -_Avoid_: 已投递状态、自动记账、完整页面快照 - -**投递尝试**: -使用者在特定招聘批次中向一个具体岗位进行的一次独立申请。重复申请同一岗位会产生新的投递尝试,并保留各自的材料、渠道、状态和阶段时间线。 -_Avoid_: 投递记录、表格行、公司岗位 - -**外部进展信号**: -从邮箱、短信或其他授权渠道同步到 OfferU 的原始求职相关消息及其解析结果。它证明收到了一条消息,但不自动证明某项投递已经进入对应阶段。 -_Avoid_: 投递状态、面试事件、通知 - -**消息证据快照**: -为解释外部进展信号的来源、关联与阶段判断而保存的最小邮件证据,包括消息和线程标识、发送者、时间、主题、相关片段与正文哈希。完整正文默认只在同步和解析期间短暂使用,除非使用者对单封消息显式选择保存。 -_Avoid_: 邮件原文、邮箱缓存、通知正文 - -**短信转发导入**: -由使用者主动分享、粘贴或转发到 OfferU 的短信内容,并作为外部进展信号处理。第一阶段不要求 OfferU 直接读取手机短信库。 -_Avoid_: 短信同步、手机短信接入 - -**本地同步服务**: -在 OfferU 已启动并驻留系统托盘期间运行的个人消息同步能力。它负责发现外部进展信号并提醒使用者,使用者明确退出 OfferU 后即停止。 -_Avoid_: 云端同步、系统守护进程、后台爬虫 - -**系统凭据引用**: -OfferU 数据库中指向操作系统钥匙串条目的不透明标识,连同账号元数据和授权范围使用。OAuth token、IMAP 应用密码等原始密钥只存在 Windows Credential Manager、macOS Keychain 或 Linux Secret Service 中,不进入数据库、配置文件、日志或 Agent 上下文。 -_Avoid_: 加密密码字段、Token 配置、邮箱登录信息 - -**本地加密边界**: -由操作系统钥匙串保护主密钥,并覆盖数据库、简历附件、使用者显式保存的邮件正文、搜索索引、缓存与备份的统一静态加密范围。应用解锁后可以透明读取,但不得产生未受保护的旁路副本。 -_Avoid_: 仅数据库加密、依赖 BitLocker、附件加密 - -**云端数据授权**: -使用者针对具体模型供应商和数据类别授予的发送许可。OfferU 优先在本地解析与脱敏,并在运行前展示将发送的简历、邮件、面试转写或其他敏感数据类别;配置 API Key 只建立连接,不等于授权发送所有数据。 -_Avoid_: API Key 授权、模型权限、隐私开关 - -**候选进展**: -主控 Agent 根据外部进展信号提出的待确认关联与阶段变化。使用者确认前,它不能改变正式投递状态。 -_Avoid_: 正式状态、自动更新、提醒 - -**投递关联建议**: -Agent 从外部进展信号中识别公司、岗位、招聘批次、申请编号和邮件线程,并对可能对应的投递尝试进行排序与解释。确定性标识可以建立候选进展;存在多个合理候选或只有语义相似时必须由使用者选择,Agent 本身没有正式关联和阶段写入权。 -_Avoid_: AI 自动关联、邮件分类、自动推进 - -**投递阶段事件**: -使用者确认后记录的一次投递阶段变化,包含发生时间、来源和前后阶段。它构成投递时间线,并派生当前状态。 -_Avoid_: 状态字段、邮件分类、候选进展 - -**岗位生命周期里程碑轨道**: -OfferU 任务视图对一个已绑定真实岗位的生命周期投影,沿用 `prepared`、`applied`、`written_test`、`assessment`、`interview_1`、`interview_2`、`interview_hr`、`offer`、`rejected` 九个现有业务状态,但不把它们解释为九步线性完成度。笔试、测评和各轮面试可以未发生或被跳过;`offer` 与 `rejected` 是互斥终态分支,拒绝可以从任一投递后阶段发生。投前选择“不投”只结束投前任务,不伪造成 `rejected`,也不创建投递尝试。 -_Avoid_: 九步进度条、完成百分比、跳过即完成、Offer 后再拒绝、用 rejected 表示不投 - -**投递概览**: -从投递尝试及其阶段事件派生的紧凑表格工作区,是投递页的默认主视图,默认呈现当前阶段、下一动作和下一时间,并允许按需显示具体阶段列;进度看板只是同一批数据的辅助视图。它不是投递进展的事实源。 -_Avoid_: 投递表、宽表事实、阶段数据库 - -### 面试训练 - -**面试内容评价**: -基于面试问题、使用者回答、职业证据和岗位档案,对回答质量与岗位能力证据形成的解释性评价。它不使用摄像头信号推断人格或录用概率。 -_Avoid_: 面试总分、AI 打分、综合表现 - -**表达行为反馈**: -基于本地摄像头或音频派生的可观察行为,对姿态稳定、手势次数、语速或停顿等表达方式形成的反馈。它与面试内容评价分开,不代表性格、诚信、情绪或岗位胜任力。 -_Avoid_: 肢体语言分、情绪识别、人格评分 - -**面试评分规则**: -定义面试评价维度、权重、证据要求、阈值、提示和聚合方式的版本化声明。它只能引用明确授权的面试证据,不能执行任意代码或改变面试事实。 -_Avoid_: 评分 Skill、评分 Prompt、打分算法 - -**表达行为事件**: -本地视觉或音频分析识别出的一段可观察行为,包含事件类型、时间范围、置信度和检测器版本。它不包含原始视频、截图或逐帧关键点,也不携带人格或情绪推断。 -_Avoid_: 摄像头数据、Landmarks、肢体语言结论 - -**轮次式语音面试**: -主控 Agent 逐题提问,使用者逐题录音作答,并允许切换到文字输入的面试交互方式。每轮在本地完成端点检测并转写,默认只保存转写、题目时间范围和派生表达行为事件,不保存原始音频。 -_Avoid_: 实时语音面试、全双工面试、录音存档 +For product behavior see [Current Product North Star](./docs/product/current-product.md). \ No newline at end of file From 780750be882689ce59e537d9b8850c947b730930 Mon Sep 17 00:00:00 2001 From: avabbbb <89175608+avabbbb@users.noreply.github.com> Date: Wed, 23 Sep 2026 00:24:24 +0800 Subject: [PATCH 13/36] docs(agent): align external-first reasoning and skill composition --- docs/architecture/agent-system.md | 154 ++++++++++-------------------- 1 file changed, 49 insertions(+), 105 deletions(-) diff --git a/docs/architecture/agent-system.md b/docs/architecture/agent-system.md index 7833de32..0a5a376e 100644 --- a/docs/architecture/agent-system.md +++ b/docs/architecture/agent-system.md @@ -1,130 +1,74 @@ -# OfferU Agent 系统总览 +# Agent System -> 状态:accepted architecture;截至 2026-08-28 已完成部分纵向验收 -> 主决策:[ADR-0051](../adr/README.md#adr-0051) -> 适用:主控 Harness、OfferU 原生工作区、Operation Registry、本地深度执行器 +Status: **CURRENT ARCHITECTURE** +Updated: 2026-09-23 -## 一句话结论 +## Summary -外部 Coding Agent Harness 是 OfferU 唯一的主控大脑;OfferU 自身不是第二个 Agent,而是嵌入 Harness 或由其唤起的本地、确定性、可审计求职操作台和业务控制面。 +OfferU does not compete with local coding Agents on general reasoning. Its value is the Career OS state, tools, evidence, permissions and guided product experience that those Agents can safely use. -DeepSeek Harness、Codex、Claude Code、OpenCode 与 Pi 可以替换主控会话,但不能改变 OfferU 的事实、授权、确认和审计规则。业务集成只走 CLI-first Agent Bridge,不提供 MCP 业务入口。 +~~~ +External local Agent (preferred) + or +OfferU fallback Agent + ↓ +OfferU Skill + optional Career Skills + ↓ +Active Skill Surface + ↓ +Operation Registry + ↓ +Career Runtime +~~~ -## 目标拓扑 +Exactly one Agent is the active reasoning authority for a Run. -```mermaid -flowchart TB - USER["使用者"] --> SHELL["Harness 原生外壳
会话导航 + 提示输入"] - SHELL --> HARNESS["唯一主控 Harness
DSH / Codex / Claude / OpenCode / Pi"] - SHELL --> UI["OfferU 原生工作区
入口 + 任务视图 + 确认"] +## Host model - HARNESS --> HOST["Harness 接入包 host half
只适配宿主能力"] - UI -->|"宿主内类型化通道"| HOST - HOST --> BRIDGE["OfferU Agent Bridge
CLI stdio JSONL"] +The canonical host metadata lives in code, not this document. Current host classes may include Skill host, hosted runtime/executor, both, detected-but-not-ready, blocked auth, incompatible and unavailable. - BRIDGE --> RUN["Agent Run / lease / event log"] - BRIDGE --> SKILLS["Skill Registry 投影"] - BRIDGE --> OPS["Operation Registry"] +Never translate binary found into supported. - OPS --> GATE["schema → grant → proposal
→ OfferU 确认 → 幂等 → 审计"] - GATE --> DOMAIN["岗位 / 职业模型 / 研究 / 材料
投递 / 邮箱 / 面试"] - DOMAIN --> DATA["SQLite / OS keychain / 授权服务"] +## External-first behavior - HARNESS --> ARTIFACTS["Run 工件工作区"] - HARNESS -->|委托一个重任务| EXEC["托管深度执行器"] - EXEC --> CANDIDATE["候选结果 + 来源"] - CANDIDATE --> GATE +1. OfferU discovers available local Agents. +2. It probes readiness/auth without taking over credentials. +3. It recommends a ready host. +4. It installs/projects the OfferU Skill where supported. +5. The host uses its own model/account. +6. OfferU exposes only the relevant Skill/tool surface. - UI --> RUN - UI -->|"唯一批准/拒绝入口"| GATE -``` +A fallback OfferU Agent may be used if no external host is suitable. -DSH `dsh-v0.1.0-rc.8` 是首个原生嵌入基线:同一接入包有 host/client 两面,client half 只使用可加式 slots,host half 独占 `offeru bridge --stdio`。不支持安全 UI 扩展的 Harness 由原生外壳唤起 OfferU companion window;两种形态共享同一控制面,不改变主控归属。 +## Skill composition -## 两条执行路线 +A host may activate OfferU plus third-party Career Skills. OfferU context should ground third-party methodology. Third-party output is draft/candidate material until accepted through OfferU's normal persistence path. -### 主控 Harness +## Tools -主控 Harness 持有模型会话、推理、规划、上下文压缩和工具循环。它从 OfferU 取得经过授权的上下文与 Operations,并把调用、状态、结果和候选工件写回 Agent Run 事件。 +Agents should not receive the entire Registry. -主控 Harness 不拥有: +~~~ +manifest +→ Skill catalog +→ manifest --skill +→ operation schema on demand +~~~ -- 业务数据库或职业事实; -- Operation 授权和工作台确认; -- 跨 Run 的隐藏记忆; -- 直接写 OfferU 源码或配置的权限; -- 代表使用者提交申请、发邮件或联系第三方的权力。 +The tool surface must be evaluated with real Agent tasks. Do not optimize for a pretty tool count at the expense of task completion. -### 本地深度执行器 +## Confirmation -深度执行器是主控 Harness 委托的一个任务级 Worker,用于公开公司/岗位调研、批量 JD 分析和登记工作源摘要。它由 OfferU 托管生命周期与权限,但不成为第二主脑,也不继承主控 Harness 的隐藏上下文。 +Protected state changes create Proposals. The Agent may request a protected mutation and wait. It may not self-confirm it. OfferU UI is the authoritative human review surface. -两条路线都必须经过同一 Operation Registry;区别在于主控 Harness 持有用户目标,深度执行器只持有一个受限重任务。 +## Native tools -DSH rc8 可按需安装 Codex/Claude Code subagent bundles,但它们属于 DSH 主会话内部编排,默认只形成同一 Agent Run 的嵌套事件,不自动升级为 OfferU 托管深度执行器,也不创建第二个主控 Run。只有经过 OfferU 明确委托、独立 session/workspace/grant 的重任务才进入深度执行路线。 +A host may keep native capabilities needed by the task, but OfferU business reads/writes must use OfferU capability boundaries. Native shell/filesystem/network tools do not grant permission to bypass Career Runtime or Registry controls. -## 状态所有权 +## Eval -| 状态 | 唯一拥有者 | 可重建来源 | -| --- | --- | --- | -| 开放式目标、推理、计划 | 当前 Harness session | 不要求 OfferU 完整复制 | -| 求职任务与 Agent Run | OfferU | Python 持久化 | -| 已确认职业事实与业务状态 | OfferU 领域服务 | SQLite 与来源链 | -| Skill 与 Operation 能力 | OfferU Registry | 版本化 Registry | -| 待确认提案与决定 | OfferU 工作区/协调器 | 持久化提案、一次性决定 | -| Run 候选文件 | Run 工件工作区 | 当前 Run 目录与清单 | -| Provider 原始事件 | Harness/adapter trace | 可选诊断,不是产品事实 | -| 标准生命周期事件 | OfferU Agent Run Event | 追加式事件日志 | +Evaluate task outcome, final persisted state, protected-record integrity, safety, truthfulness and provider/host failures. Tool trajectory is diagnostic rather than the sole proof of completion. -## 主控一致性契约 +A model's prose is not proof that a business action happened. -一个 Harness 只有同时通过以下能力,才能显示为“支持”: - -1. 能创建、识别和恢复原生会话; -2. 能在运行中追加用户指令或显式报告不支持; -3. 能中断、取消并输出确定终态; -4. 能调用 Run 授权范围内的 OfferU Operations; -5. 能在提案待工作台确认时暂停或安全重试; -6. 能把输出映射为统一事件流; -7. 能把原生文件和 shell 工具限制在 Run 工件区; -8. 版本或能力不满足时显式失败,不静默换到另一个 Harness。 - -Codex 与 DeepSeek Harness 只享有实现优先级,不降低其他三种 Harness 的最终门槛。 - -## 全局不变量 - -- Python/SQL 是唯一业务事实源,Tauri/Rust 只做系统桥接。 -- 产品是本地单人版,不引入 SaaS、多租户、登录、计费或 `workspace_id`。 -- Agent 推断、研究摘要、简历建议、面试反馈和外部消息都先是候选,不是职业事实。 -- GUI、CLI、TUI、浏览器扩展、主控 Harness 和深度执行器共用一个 Operation Registry。 -- OfferU 拥有的嵌入工作区或专注窗口是业务副作用的唯一确认权威;Harness 自身审批只能约束其原生工具,不能批准 OfferU Operation。 -- Run 工件工作区不是 OfferU 仓库,也不是长期记忆。 -- 跨 Harness 故障切换创建新 Run,不伪造隐藏会话连续性。 -- 外部数据默认不可信,凭据和敏感职业数据不得进入日志、工件或未授权模型上下文。 -- 失败必须可见;禁止假分、伪造 JSON、静默降级和“返回成功但没有执行”。 - -## 当前代码与目标的差距 - -截至 2026-08-28,Main Agent UI 已通过 provider-neutral `AgentRuntimeProvider` 消费适配器;Pi 保留为 Provider,Replay/Fixture 用于确定性验收。Operation Registry 的 C1 全局 Route 审计已通过,已知正式业务 mutation 没有 Route 级直接 ORM DML、mutating service 或 Registry 旁路。旧 CLI `confirm`、Pi 命名的兼容入口和实验性 MCP 仍存在,但不属于新的业务集成契约。 - -Codex App Server 适配边界已有结构测试,真实 Codex Provider 仍因本机认证返回 401 而标记 `BLOCKED_EXTERNAL_AUTH`;DSH 的协议/插件基础已有覆盖,但独立 `AgentRuntimeProvider` 尚未完成 live 验收。`job-search` Capability Plugin 已完成自有 Manifest、Skill、CLI 与契约验证,live Role Intelligence 仍需使用该能力单独验收。这些状态不影响已通过的 fixture/replay 产品链,也不应在文档中被表述为实时外部数据已完成。 - -可复用的底座已经存在: - -- `backend/app/ops.py`:Operation Registry; -- `backend/app/services/operation_projection.py`:执行/提案与确认协调; -- `backend/app/services/agent_run_state.py`:Run、事件和恢复; -- `AgentRunRecord` / `AgentRunEvent`:provider-neutral 持久化; -- 工作台 SSE、提案卡和审计界面。 - -迁移原则是先在这些接缝上增加 Bridge 和外部 Harness tracer,再替换 Pi 主路径;不得先删除可运行链路。完整顺序见[迁移路线](../implementation/migration-roadmap.md)。 - -## 主题入口 - -- 内部模块:[Agent 操作控制面](./agent-control-plane.md) -- 机器协议:[Agent Bridge 协议](./agent-bridge-protocol.md) -- 宿主差异:[Harness 接入](./harness-integrations.md) -- 权限与事实门:[Operation 与安全](./operation-security.md) -- 生命周期:[Run 生命周期](./run-lifecycle.md) -- 交互:[OfferU 原生工作区](./workbench-interaction.md) -- 决策历史:[决策账本](../adr/README.md) +See [Live Eval](../evals/LIVE_EVAL.md). \ No newline at end of file From 31e5339d4b21e9b26cb554887a336bf14febbcda Mon Sep 17 00:00:00 2001 From: avabbbb <89175608+avabbbb@users.noreply.github.com> Date: Wed, 23 Sep 2026 00:24:26 +0800 Subject: [PATCH 14/36] docs(ux): make OfferU guided desktop the primary workspace --- docs/architecture/workbench-interaction.md | 220 +++++---------------- 1 file changed, 44 insertions(+), 176 deletions(-) diff --git a/docs/architecture/workbench-interaction.md b/docs/architecture/workbench-interaction.md index de4edf52..720f81ed 100644 --- a/docs/architecture/workbench-interaction.md +++ b/docs/architecture/workbench-interaction.md @@ -1,205 +1,73 @@ -# OfferU 原生工作区交互 +# Workbench Interaction -> 状态:accepted target design;DSH 映射校准到 `dsh-v0.1.0-rc.8` -> 决策:[ADR-0030](../adr/README.md#adr-0030)、[ADR-0031](../adr/README.md#adr-0031)、[ADR-0053](../adr/README.md#adr-0053)、[ADR-0055](../adr/README.md#adr-0055)、[ADR-0056](../adr/README.md#adr-0056) -> DSH 接缝:[Harness 接入](./harness-integrations.md#deepseek-harness-rc8第一条-tracer) +Status: **CURRENT PRODUCT INTERACTION** +Updated: 2026-09-23 -## 交互结论 +OfferU Desktop is the primary Career OS workspace. -本地 Coding Agent 使用者已经把 Harness 当作日常主应用。OfferU 因而不是第二个聊天应用,也不是悬浮在旁边的完整独立工作台,而是嵌入 Harness 的职业操作工作区:Harness 保留提示输入、会话导航和唯一主控 Loop;OfferU 提供求职任务、事实、证据、Operations、候选工件、业务确认和审计。 +A local Agent may be the preferred reasoning environment, but users should not be forced to live inside a Harness UI to use OfferU. -在 DSH rc8 中,同一套 OfferU 领域投影与交互状态由 DSH 原生渲染器呈现为三个表面: +## Default beginner experience -```text -┌ DSH sidebar ─────────┬ DSH active session ─────────────────────┐ -│ DSH workspaces │ Chat | Trajectory | OfferU │ -│ DSH sessions │ ┌───────────────────┐ │ -│ │ │ OfferU 任务视图 │ │ -│ │ │ 当前 Task / Run │ │ -│ [OfferU 入口/状态] │ └───────────────────┘ │ -└──────────────────────┴──────────────────────────────────────────┘ - └─ OfferU 全局配对/确认浮层(按需出现) -``` +~~~ +Install +→ Agent auto-discovery +→ Know Me / Profile +→ Save first Job +→ Connect inbox +→ Today +~~~ -OfferU 不注册一个永久占据 DSH 中央区域的全局页面。入口和确认可以是 root/global,主视图则属于当前 DSH session。全局职业数据可在任务视图中浏览,但 Agent 动作、授权和事件必须绑定当前求职任务与 Run。 +The default interaction is Guided, not command-first. -## 视觉与共享边界 +## Today -DSH 中的 OfferU 页面直接使用 DSH 原生组件、布局、设计令牌、焦点行为和响应式规则,视觉上属于 DSH,不建立 OfferU 品牌岛。跨 Harness 共享的是类型化领域投影、交互状态机、Operation 合约、确认语义和标准事件,不共享同一套 React 页面或宿主无关视觉组件。 +Today answers: **What should I do next?** -DSH client 只实现薄的宿主原生渲染器;领域判断、生命周期规则、权限和业务动作仍由 OfferU 控制面与无头契约拥有。companion window 使用 OfferU 自有渲染器,但必须消费同一投影和状态机,不能因此维护第二份业务状态。跨 Harness 验收业务与交互语义一致,不要求像素一致。 +It should show at most a few primary actions derived from existing Career State. Priority inputs include pending progress review, upcoming interviews, deadlines, high-value job preparation, stale follow-up and failed/blocked work that requires attention. -## rc8 原生表面 +Each recommendation explains why now. Completing one action should recalculate the next actions. -| 表面 | rc8 slot | 交互职责 | -| --- | --- | --- | -| OfferU 固定入口 | `sidebar.footer.action` | 连接状态、配对、打开当前 session 的 OfferU tab | -| OfferU 任务视图 | `conversation.view` | 当前 session 内的求职任务、Run、证据、Operations、工件和结果 | -| OfferU 全局浮层 | `shell.overlay` | 配对、业务确认、断连、冲突和跨 session 提醒 | -| 可选 session 动作 | `conversation.session.header.actions` | 请求中断、打开专注窗口等小型快捷动作 | +## Progressive onboarding -这些都是 list/additive slots。实现不得占用 `root`、`sidebar`、`conversation`、`details`、`conversation.session`、`conversation.session.header`、`sidebar.workspaces` 或 `sidebar.settings`;它们是 DSH 核心单席位,注册会造成替换,不是“加一个 OfferU 区域”。 +Do not show a configuration wall. If the system is missing several prerequisites, request only the next useful one. -## 无活动 session 的入口 +Example: if Agent is ready but Resume, Email and Extension are not, the UI should first ask for the resume rather than presenting three setup panels. -`conversation.view` 是 session-scoped,因此首次启动或没有活动 session 时只使用固定入口与全局浮层: +## Progressive Profile questions -1. 入口显示 `未连接 OfferU`、`待配对`、`已连接` 或 `需要处理`; -2. 点击后在浮层中探测本机 OfferU Bridge,不跳到 iframe; -3. 只有完全空白且未绑定的 DSH session 才显示岗位选择器;使用者从 OfferU 已存在的真实岗位中选择一个,并在 DSH 内创建对应求职任务; -4. OfferU 将该任务一次性绑定当前 DSH session,并展示 profile、preset、cwd 与能力摘要; -5. 关联完成后进入该 session 的 `OfferU` tab; -6. 失败时保留 DSH 当前会话,给出明确原因,不自动切换 Harness 或 preset。 +Do not ask every preference on day one. Ask small contextual questions only when useful to a live decision, then persist the answer as a sourced preference/fact candidate. -“允许此 DSH 接入 OfferU”是配对决定,不是副作用批准。两者必须使用不同标题、对象、有效期和审计事件。 +## Agent interaction -## OfferU 任务视图 +Normal users should not have to choose Agent Skills manually. Natural-language goals and current Career State should route to the relevant Skill. -任务视图不复制 OfferU 全局的“今日、机会、材料、进展、面试”导航,也不复制 DSH 的 sidebar、聊天 composer 或 details panel。它只服务当前 session 已绑定的一个真实岗位,并采用任务驾驶舱布局: +Advanced users may open Agent/Skill/CLI controls in Power Mode. -```text -┌ 公司 / 岗位 / 任务与 Run 状态 ────────────────────────────────┐ -│ 生命周期:准备 → 已投递 → 可选环节 … → Offer / 拒绝 │ -├────────────────────────────────────────────────────────────────┤ -│ 当前状态 / 下一动作 / 待确认 / 最近结果 │ -├────────────────────────────────────────────────────────────────┤ -│ 事实、证据、候选工件与阶段详情 │ -├────────────────────────────────────────────────────────────────┤ -│ Run 事件 / Operation / outcome / 诊断(渐进披露) │ -└────────────────────────────────────────────────────────────────┘ -``` +## Skill ecosystem UX -生命周期轨道沿用九个现有业务状态,但不是线性完成度: +OfferU may tell the user that their local Agent already has compatible resume/interview/recruiting Skills, but the default integration relies on the host's native Skill discovery. -```text -准备 → 已投递 → [笔试?] → [测评?] → [一面?] → [二面?] → [HR 面?] - └──────────── 任一投递后阶段 ────────────→ Offer - └──────────── 任一投递后阶段 ────────────→ 拒绝 -``` +A future Skill Inventory should be opt-in and metadata-only by default. -方括号节点是可选里程碑。后续阶段已有事实而前置可选节点没有事件时,显示“未发生/已跳过”,不显示“已完成”;`offer` 和 `rejected` 互斥。投前选择“不投”是投前任务结果,不进入 `rejected`,也不创建投递尝试。首个 tracer 虽展示完整轨道,但只有投前决策闭环提供真实可执行动作;后续阶段只显示已有事实、进入条件与明确的“尚未接入”。 +## Browser capture -### 首屏主状态 +~~~ +open job page +→ click 保存到 OfferU +→ preview/dedupe +→ Job appears in OfferU +→ OfferU recommends the next preparation action +~~~ -任务视图不把待确认、错误、运行、下一动作和最近结果铺成同权卡片。首屏只突出一个主状态,按以下固定优先级派生: +## Email progress -1. `待确认`:显示提案对象、影响、证据、有效期和确认入口; -2. `失败/断连`:区分 Bridge 离线、adapter 断开、Run 失败、状态待对账,并给出对应恢复条件; -3. `正在执行`:显示当前 Skill/Operation、开始时间、最新可理解事件和请求中断; -4. `下一动作`:显示现在应做什么、为什么、所需前置事实以及动作归属; -5. `最近完成`:显示经过 outcome 校验的结果以及任务是否仍有下一动作。 +After inbox connection, OfferU may proactively detect likely career updates but presents ambiguous or important changes for review. The user should see a human-readable card, not IMAP/UID/cursor terminology. -较低优先级信息保留在阶段详情和 Run 时间线中,但不得与主状态争夺首要按钮。主状态是注意力投影,不写回或覆盖任务、Run、提案和投递阶段事实。 +## Focus work -不再设计一个侵入 DSH 核心布局的常驻“右侧 OfferU 控制栏”。窄幅状态与动作留在 OfferU tab 内;简历深编、摄像头面试等大画布任务打开同一状态边界的 OfferU 专注窗口。 +Resume deep editing, interview practice and complex evidence review may use focused workspaces, but they remain part of the same Job/Profile truth. -任务视图不能在当前 session 内切换浏览其他岗位。切换岗位必须从固定入口新建或恢复该岗位对应的 DSH session;不能在 A 岗位 session 中仅靠前端选中 B 岗位,就把 B 的上下文注入同一个隐藏模型会话。 +## Design rule -## Run 顶栏 - -每个关联 Run 明确显示: - -- Harness 名称、真实版本、adapter 与 Bridge 版本; -- DSH profile、agent preset、session ID、Run ID 和 Skill; -- 输入主权,例如 `DSH Chat` 或 `Codex 原生界面`; -- Operations、数据范围、网络和 Run 工件目录; -- 当前阶段:运行、等待确认、中断、对账、完成或失败; -- 主动作:返回 Chat、请求中断、取消 Run、打开专注窗口。 - -不使用“AI 在线”“自动运行中”等模糊状态。adapter 断开但 Run 仍可恢复时,应显示“连接中断,尚未确认失败”。 - -## rc8 tracer 路径 - -首个纵向切片只证明一条只读求职链路: - -1. 精确版本 `0.1.0-rc.8` 的 DSH 以 `offeru` profile 启动; -2. OfferU 固定入口显示 host plugin 与 Bridge 探测结果; -3. 使用者在全局浮层中选择求职任务与 Skill,确认配对; -4. DSH session 的 `OfferU` tab 出现相同 Task/Run identity; -5. 使用者回到 DSH Chat 输入目标,DSH 是唯一提示输入端; -6. host plugin 调用一个真实只读 Operation,任务视图显示同一事件与结果; -7. DSH 给出非空最终回复,OfferU 以领域 outcome 判断是否完成; -8. 刷新 client、重启 Bridge 或卸载 plugin 后,不留下幽灵入口、重复订阅或失控租约。 - -OfferU client half 不向 DSH 会话悄悄注入普通聊天文本。将来若支持工作区 follow-up,仍须经过单输入写入者协议,并显示来源、顺序与宿主接收确认。 - -## 全局确认浮层 - -副作用 proposal 使用 OfferU 自有 `shell.overlay` 表面;DSH 原生 tool approval 与 OfferU 业务确认永远是两件事。确认卡至少包含: - -```text -OfferU 业务确认 -动作:更新投递阶段 -对象:示例公司 / 后端工程师 / Attempt #2 -变化:Interview → Offer -依据:邮件候选 #123(发生于 2026-08-19) -来源:DSH session / Run / Operation update_application_status -有效期:还剩 9 分钟 - -[拒绝] [批准一次] -``` - -规则: - -- 参数、影响、来源、Task/Run 和证据同时可见; -- 敏感值脱敏,但不能脱敏到无法判断动作; -- 只有“批准一次”,没有“本会话全部允许”; -- 重复点击返回同一决定,不执行第二次; -- proposal 过期、Run 结束、数据版本变化或 host 断连时按钮禁用; -- 浮层关闭不等于批准或拒绝,Harness 继续等待或按超时失败关闭; -- DSH 对 shell/file 的原生批准只能进入诊断事件,不能授权 OfferU proposal。 - -浮层由 client half 渲染,但决定必须交给 OfferU 控制面持久化。client half、DSH 模型和 host plugin 都不能自行生成批准。 - -## host/client 数据边界 - -DSH browser client 只取得渲染所需的最小投影:连接状态、Task/Run identity、标准事件、脱敏 proposal、可见领域数据和用户决定结果。它不得: - -- 直接调用 OfferU FastAPI、SQLite、Operation Registry 或任意 CLI; -- 持有 Bridge bootstrap token、数据库密钥或云 Provider 凭据; -- 执行 shell,或把 DSH browser 当作业务 API 客户端; -- 使用 iframe 加载完整 OfferU SPA; -- 捆绑第二份 React,或依赖 DSH 内部 DOM 选择器覆盖核心界面。 - -所有业务请求经过 DSH host half 与 `offeru bridge --stdio`。host/client 类型化通道、断线恢复、背压和身份绑定是 rc8 tracer 的强制验证项;尚未证明时界面显示 `incompatible`,不降级成 HTTP/MCP 旁路。 - -## 事件与工件 - -默认时间线只展示用户可理解的标准事件:读取了哪些已确认事实、选择了哪个 Skill、调用了哪个 Operation、为何等待确认、生成了哪些候选工件、改变了哪些业务状态,以及失败发生在哪一层。模型 token delta、provider JSON、内部 reasoning 和命令噪音折叠到诊断视图;OfferU 不展示或持久化隐藏思维链。 - -Harness 生成的文件先进入候选区: - -| 状态 | 含义 | -| --- | --- | -| `candidate` | 已声明并完成安全扫描,尚未进入正式业务 | -| `needs-fact-review` | 含可能的职业事实,需逐项核对 | -| `accepted` | 已经相应 Operation 接受并关联领域对象 | -| `rejected` | 使用者拒绝,不进入正式状态 | -| `stale` | 上下文或来源变化,需重新生成/核对 | - -“生成成功”不等于“已应用”。任务视图必须说明哪个工件已接受、哪个仍待审核。 - -## 中断、恢复与专注窗口 - -“请求中断”先调用 Harness 原生 interrupt,并显示宿主是否确认、是否有 executing Operation、是否需要对账和能否恢复同一 session。不能恢复时,使用者可以结束 Run,或显式交接到另一 Harness;交接创建新 Run,不迁移隐藏推理或原生进程状态。 - -专注窗口只用于简历深编、面试摄像头/音频、复杂证据核对等大画布任务。它复用同一无头领域投影、交互状态机、Task/Run identity、proposal 与 Operation Registry,并由 OfferU 自有渲染器呈现;它不启动第二个主控 Agent,也不改变 DSH 的提示输入主权。 - -对于没有安全 UI extension point 的 Codex、Claude Code、OpenCode 或 Pi,OfferU 打开消费同一无头契约的 companion window。跨 Harness 一致性要求是 Run、Operations、确认、事件和审计一致,不强求相同组件、slot 名称或布局。 - -## 移动端 - -移动端只支持查看 Run、批准/拒绝、更新投递进展和请求中断。安装 DSH bundle/profile、工件深度审核、简历编辑和面试训练保留在桌面/平板。移动端与 DSH client 共享决定和事件,不建立第二套控制面。 - -## 交互验收 - -- rc8 中出现固定 OfferU 入口、session 级 OfferU tab 和全局确认浮层,卸载后全部清理; -- DSH 的 Workspace/Session 导航、Chat、Trajectory、details 和 settings 仍正常,未被 OfferU 替换; -- 没有 session 时可完成配对/创建流程,但不会显示伪造的全局 Agent 主视图; -- 切换求职任务会切换或创建对应 DSH session/Run,不共享隐藏上下文; -- DSH Chat 是 tracer 唯一提示输入端,OfferU UI 不暗中注入文本; -- 配对、DSH 原生 approval 与 OfferU proposal 确认可清楚区分; -- client 不直连业务 HTTP/数据库/CLI,不使用 MCP、iframe、第二份 React 或核心 slot replacement; -- proposal 参数和影响可核对,批准恰好生效一次; -- 中断、断连、对账、失败和业务 outcome 都有不同状态与下一步; -- 键盘、窄宽度和 reduced-motion 场景可以完成配对、确认与中断。 +OfferU should minimize both setup burden and decision burden. Do not add a new mode or page when a Next Best Action can safely guide the user instead. \ No newline at end of file From 585b15cc70bb88c34ff22bbb3e2c18ead493d2fc Mon Sep 17 00:00:00 2001 From: avabbbb <89175608+avabbbb@users.noreply.github.com> Date: Wed, 23 Sep 2026 00:24:29 +0800 Subject: [PATCH 15/36] docs(agent): replace DSH-first plan with host integration contract --- docs/architecture/harness-integrations.md | 238 ++++------------------ 1 file changed, 34 insertions(+), 204 deletions(-) diff --git a/docs/architecture/harness-integrations.md b/docs/architecture/harness-integrations.md index afc7747c..be8eae3d 100644 --- a/docs/architecture/harness-integrations.md +++ b/docs/architecture/harness-integrations.md @@ -1,232 +1,62 @@ -# Harness 接入设计 - -> 状态:accepted architecture;宿主 API 仍需实时 probe,当前验收状态见下文 -> 优先级:DeepSeek Harness 与 Codex 第一批,Claude Code、OpenCode、Pi 第二批 -> 共同协议:[Agent Bridge](./agent-bridge-protocol.md) - -## 当前验收状态(2026-08-28) - -- Main Agent UI 消费 provider-neutral `AgentRuntimeProvider`;Pi/Replay 是当前已覆盖的本地适配路径。 -- Operation Registry 的全局 Route mutation 审计为 `PASS_GLOBAL`;适配器、插件和自动化不能把领域写入当作自己的事实。 -- Codex App Server 适配器有结构化协议边界,但本机真实认证仍为 `BLOCKED_EXTERNAL_AUTH`,不得由 OfferU 修改凭据或静默切换 Provider。 -- DSH 仍是可替换的后续 Provider;现有协议/插件资料不等于独立 DSH AgentRun live 验收。 -- `job-search` 是首个真实公开源 Capability Plugin 的实现与契约验证;它的 live Role Intelligence 采集结果必须另行记录为 `PASS` 或 `INSUFFICIENT_SAMPLE`,不能用 fixture 结果代替。 - -## 接入原则 - -每种 Harness 保留自己的会话、模型、compaction、原生工具和事件语义;OfferU 只编写薄接入包,把这些差异映射为同一行为契约。适配层不得包含岗位、简历、投递或职业记忆逻辑。 - -```ts -interface HarnessAdapter { - probe(): Promise; - start(input: StartRunInput): Promise; - resume(ref: HarnessSessionRef): Promise; - steer(input: UserInput): Promise<"accepted" | "unsupported">; - interrupt(reason: string): Promise; - stream(cursor?: string): AsyncIterable; - close(): Promise; -} -``` +# Agent Host Integrations -对插件型宿主,adapter 可以运行在宿主进程内;对 app-server/RPC 型宿主,adapter 运行在 OfferU 管理的本地进程边界。两者都通过 stdio Bridge 调用业务能力。 +Status: **CURRENT ARCHITECTURE** +Updated: 2026-09-23 -## 统一支持门 +This document replaces the old DSH/Codex-first integration plan as the default architecture. -“已安装”不等于“已支持”。每个 adapter 必须通过: - -| 维度 | 必须证明 | -| --- | --- | -| Identity | 真实可执行文件、版本、协议和接入包版本可记录 | -| Session | 创建、恢复、完成与失败可区分 | -| Input | 初始提示、后续提示与运行中转向语义明确 | -| Control | 中断、取消、超时和退出码可归一 | -| Tools | 只暴露当前 Run Operations;参数通过 schema | -| Approval | OfferU 提案只由工作台决定,宿主不能自批 | -| Events | 文本、工具、工件、终态可映射到标准事件 | -| Workspace | 原生文件/shell 工具不能越出 Run 工件区 | -| Recovery | 断开后能恢复或显式标记不可恢复 | -| Failure | 不用假结果、普通文本或另一个 Harness 静默兜底 | +The previous detailed DSH-era design is preserved at [historical harness integration design](../archive/architecture/harness-integrations-dsh-era-2026-09.md). -能力矩阵由 `probe()` 生成并写入 Run,不由文档硬编码。某版本失败时状态为 `unavailable` 或 `incompatible`,不能显示绿色“支持”。 +## Goal -## DeepSeek Harness rc8:第一条 tracer +Connect OfferU to local Agents the user already has without forcing duplicate model/API setup. -### 精确审计基线 +Current product principle: **Connect → Auto Detect → Verify → Ready**. -本设计只以官方 tag [`dsh-v0.1.0-rc.8`](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.0-rc.8) 为实现基线,对应 commit `141eb6fef83422698aef7a981029e843e8161534`,不是滚动 `master`。DSH 仍明确标记为 Developer Preview;“rc8 源码存在”只表示可为该 tag 编写接入,不表示接口已成为稳定的第三方兼容层。 +## Canonical host declaration -审计时 npm 的 `next` 指向 `0.1.0-rc.8`,而 `latest` 仍可能指向较早 rc。因此安装器、lockfile、capability report 和验收记录都必须写出 `@deepseek-ai/dsh@0.1.0-rc.8`;裸 `npx @deepseek-ai/dsh ...`、`@latest` 或 GitHub `master` 不能证明运行的是本设计版本。运行时仍以 `dsh --version` 和 composed profile 为事实源。 +Use the repository's Agent Host Registry and runtime definitions as the live source of truth. Documentation must not hard-code a host as fully supported merely because an adapter exists. -rc8 已直接证实的宿主能力,与 OfferU 的使用方式如下: +A host record should distinguish executable detection, Skill capability, authentication/readiness, runtime/executor capability, tested behavior and known limitations. -| rc8 能力 | OfferU 用法 | 边界 | -| --- | --- | --- | -| `profile` 按顺序组合 bundles、profile patch、home patch 和 argv patch | 创建独立 `offeru` profile | 启动前检查最终组合,不能只检查包已安装 | -| bundle 用 `dsh.bundle.patch` 声明配置层 | 分发一份 OfferU bundle | bundle 与可运行 profile 不是同一概念 | -| plugin 可用 `ctx.tools.register()` 注册类型化工具 | 注册当前 Run 的最小 OfferU tools | 业务调用仍经 CLI-first Bridge,不用 MCP | -| package 可声明 `dsh.client` 并导出 `./client` | 加载原生浏览器 client half | 这是 rc8 源码支持的预览接缝,不宣称稳定 API | -| Cordis client slots 支持可加式贡献 | 嵌入入口、任务视图与确认浮层 | 只用 list/additive slots,不替换核心单席位 | -| Codex/Claude Code 可按需安装为 DSH Profile Bundles | 作为 DSH 内部 subagent | 不等于 OfferU 的 Codex/Claude 主控 adapter | +## Preferred integration order -rc8 新增的图片输入、`@` 文件/会话引用、Windows 持久 PowerShell、subagent bundle 和 `dsh web` 自动开浏览器可以保留为 DSH 原生体验;OfferU 不复制这些能力,也不把它们改造成业务入口。 +For a host that supports portable Agent Skills: -### 产品形态:一个安装入口,两面 plugin +1. project/install OfferU Skill; +2. preserve the host's native account/model; +3. let the host discover OfferU and other Career Skills; +4. access OfferU business context through the Agent Tool Surface / CLI bridge; +5. keep protected mutations behind OfferU Proposal/HITL. -OfferU for DSH 是非官方原生集成,不是 iframe,也不修改 DSH 核心。按 rc8 的 bundle/profile/client 结构拆分: +For a host with a richer native runtime protocol, an adapter may additionally support session lifecycle, streaming, cancellation and resume. -- `@offeru/dsh-plugin`:同一插件包的 host half 与 client half;根导出运行于 DSH host,`./client` 是预构建浏览器入口,并在 manifest 声明 `dsh.client`; -- `@offeru/dsh-bundle`:声明 `dsh.bundle.patch`,依赖并启用 plugin,提供专用 preset 的配置资产; -- `offeru` profile:按顺序组合 `@deepseek-ai/dsh-base`、`@deepseek-ai/dsh-web-app` 和 `@offeru/dsh-bundle`; -- 使用者通过精确版本的 `dsh --profile offeru` 进入 DSH 原生界面,DSH 持有提示输入和唯一主控 Loop。 +Those lifecycle capabilities are useful, but they do not redefine OfferU's UI as a host plugin. -建议目录: +## Auth ownership -```text -integrations/dsh/ - packages/ - bundle/ - package.json # dsh.bundle.patch;依赖 plugin - cordis.patch.yml # 启用 host/client row 与专用 preset 配置 - presets/offeru/** - plugin/ - package.json # host export、./client、dsh.client、rc8 peers - src/ - host/ - index.ts # apply(ctx) / cleanup - bridge-client.ts # 唯一能启动 offeru bridge --stdio 的一侧 - tools.ts - events.ts - capability-probe.ts - client/ - index.ts - OfferULauncher.tsx - OfferUTaskView.tsx - OfferUOverlay.tsx - shared/contracts.ts - pnpm-lock.yaml -``` +OfferU should not edit another Agent's auth files or silently redirect its provider. -发布包必须包含预构建 `lib/client.js`、类型与所有运行资产。rc8 的 browser half 使用宿主提供的 React 18 模块;OfferU 必须 externalize/复用宿主 React,不能捆绑第二份 React 或在 DSH 内挂载完整 OfferU SPA。 +Report concrete readiness states such as READY, BLOCKED_AUTH, BLOCKED_EXTERNAL_AUTH, INCOMPATIBLE, NOT_INSTALLED or ERROR. Provider failure is not Agent task failure. -### rc8 原生 UI 投影 +## Runtime adapters -rc8 没有安全的“全局中央 OfferU 页面”席位。正确投影是由 DSH 原生渲染器消费同一 OfferU 无头契约并呈现的三个表面: +Runtime adapters must be thin. They may map probe/version, start/resume/steer, stream, interrupt/cancel, terminal result and execution metadata. -| OfferU 表面 | rc8 slot | 类型/作用域 | 用途 | -| --- | --- | --- | --- | -| 固定入口 | `sidebar.footer.action` | list / root | 显示连接状态并打开/配对 OfferU | -| 任务主视图 | `conversation.view` | list / session | 作为当前 DSH session 的 `OfferU` tab | -| 全局浮层 | `shell.overlay` | list / root | 配对、业务确认、断连和全局状态 | -| 可选快捷动作 | `conversation.session.header.actions` | list / session | 中断、打开专注窗口等小动作 | +They may not contain career business logic or parallel truth. -任务主视图可以浏览全局职业数据,但 Agent 动作始终绑定当前 Task/Run/DSH session。没有活动 session 时,只显示固定入口或浮层中的“选择/创建求职任务并创建 DSH session”流程;不能假造一个脱离 session 的中央 Agent 工作区。 +## Host parity -严禁注册 `root`、`sidebar`、`conversation`、`details`、`conversation.session`、`conversation.session.header`、`sidebar.workspaces` 或 `sidebar.settings`。这些是单席位或 DSH 核心已占用表面,注册会替换而不是并排扩展核心 UI。 +Treat WorkBuddy, Codex, Claude Code, OpenCode, OMP, Pi, Gemini and future hosts as capability-discovered peers. -client half 必须用 `ctx.slots.inject(slot, () => ctx.slots.register(...))` 等待目标 slot 声明并随 plugin 卸载清理。`dsh.client.inject` 只是包关系信息,不保证 slot 激活顺序。rc8 自带的 trajectory client 是 `conversation.view` 的参考实现,但 OfferU 仍需用 tracer 证明目标 slots 在发布包与实际 profile 中存在。 +Do not encode permanent first-class vs second-class product truth in prose. Let current code/tests report what is actually ready. -### host/client 与 Bridge 边界 +## Historical DSH integration -浏览器 client half 只负责渲染和用户手势,不能直接启动 CLI、访问 FastAPI、持有数据库凭据或调用 Operation。host half: +DSH-specific bundle/profile/client-slot research remains useful as an integration experiment but is not the current product shell design. Consult the archived document only when working specifically on that integration. -1. probe DSH、Node、adapter 与 OfferU Bridge 的真实版本; -2. 校验 active profile、专用 preset、最终工具集和工作目录; -3. 启动 `offeru bridge --stdio` 并发起配对; -4. 取得 Run、Skill、grant 后注册最小 OfferU tools; -5. 把工具调用、事件和 pending proposal 映射到 Bridge; -6. 通过 DSH 的类型化 host/client 通道向 client half 投影最小 UI 状态; -7. unload 时关闭 Bridge,撤销工具、订阅和租约。 +## Verification -第 6 步的具体 rc8 remote seam 必须在 Slice 2 用编译与真实浏览器 tracer 证明;在证明前它是实施验证项,不在文档里臆造稳定方法名。若该 seam 或任一目标 slot 不存在,adapter 报告 `incompatible`,不能在 DSH 内静默退回 iframe、浏览器直连 HTTP 或 MCP。 +Before claiming a host works with OfferU, verify connection/readiness, OfferU Skill discovery, at least one grounded read task, at least one safe Proposal/HITL task where applicable, recovery/error classification, and relevant live Eval cases. -业务确认不能复用 DSH Web/CLI 的原生 approval。DSH 原生 approval 只管理其 shell、文件等宿主工具;OfferU Operation 只能由 OfferU client half 的浮层或同状态边界的专注窗口决定。 - -### 专用 preset 与 rc8 安全边界 - -rc8 的 `Minimal` 不是 OfferU 的最小权限预设:其 Windows 配置已默认启用持久 PowerShell,并包含本地文件能力。`Standard` 还会启用更多 shell、文件、网络、jobs、skills、subagents/workflows 能力。因此第一条 tracer 必须使用 OfferU 自有 preset: - -- 初始只暴露 Bridge 投影的一个只读 Operation; -- 不启用 DSH 原生 PowerShell/Bash、文件读写、文件搜索、网络或 subagent 工具; -- profile 启动后读取最终有效工具集,发现额外工具就拒绝配对; -- 不把 cwd、preset 名称、`tools.restrict` 或提示词当成 OS 隔离证明; -- 后续只有通过 Windows 路径逃逸、secret、进程和网络验收后,才逐项加入原生工具。 - -Bundle 如何让 rc8 发现并选择随包发布的 agent preset 必须由安装 tracer 证明。安装器只调用 DSH CLI/profile 机制,不直接改 DSH 核心;用户选用通用 `minimal`/`standard` 时明确失败,不自动改写其全局默认值。 - -### rc8 subagent 不扩大主控边界 - -rc8 可把 Codex 与 Claude Code 安装为 Profile Bundles,并支持 Codex 的非交互 permission mode 与 named instance。这些是 DSH 主会话内部的 subagent:它们的活动映射为同一个 OfferU Run 下的嵌套事件,不能被记录成第二个 OfferU 主控 Run,也不能借此获得额外 Operations。 - -OfferU 自己的 Codex 主控 adapter 仍是独立第一批接入;`ExecutorSupervisor` 仍只用于 OfferU 明确托管的隔离重任务。不得利用 rc8 subagent 再造一个跨 Harness 业务编排器。 - -### 升级、发布与品牌 - -- 只发布预构建、带 hash 和 lockfile 的 npm/tarball,不依赖 Git 安装时临时构建; -- rc8 release 声明 SQLite 格式不兼容,升级验证使用独立/已备份的 DSH home 与新建 `offeru` profile; -- 每次 DSH 升级重新验证 manifest、profile composition、client boot graph、slots、tool set、host/client relay、Bridge schema 与生命周期; -- 版本或能力不匹配在配对前失败,不在运行中静默降级; -- 产品描述使用“OfferU,兼容 DSH / based on DSH”,包名采用 `@offeru/dsh-*`,并注明非官方、未获 DeepSeek Harness 背书;不把“DeepSeek Harness”放入 OfferU 项目名,也不挪用官方品牌资产。 - -rc8 官方事实源:[tag 源码](https://github.com/deepseek-ai/deepseek-harness/tree/dsh-v0.1.0-rc.8)、[发布说明](https://github.com/deepseek-ai/deepseek-harness/releases/tag/dsh-v0.1.0-rc.8)、[Developer Preview](https://github.com/deepseek-ai/deepseek-harness/blob/dsh-v0.1.0-rc.8/README.zh.md)、[CLI/profile 组合](https://github.com/deepseek-ai/deepseek-harness/blob/dsh-v0.1.0-rc.8/apps/cli/README.zh.md)、[plugin 开发](https://github.com/deepseek-ai/deepseek-harness/blob/dsh-v0.1.0-rc.8/docs/user/develop/basic/index.zh.md)、[tool 注册](https://github.com/deepseek-ai/deepseek-harness/blob/dsh-v0.1.0-rc.8/docs/user/develop/basic/tool.zh.md)、[bundle/profile 发布](https://github.com/deepseek-ai/deepseek-harness/blob/dsh-v0.1.0-rc.8/docs/user/develop/basic/publish.zh.md)、[品牌规范](https://github.com/deepseek-ai/deepseek-harness/blob/dsh-v0.1.0-rc.8/BRAND_GUIDELINES.zh.md)。client half 与 slots 还应逐 tag 对照 [`ui-trajectory`](https://github.com/deepseek-ai/deepseek-harness/blob/dsh-v0.1.0-rc.8/packages/client/ui-trajectory/src/client/index.ts) 和 rc8 client package manifests;它们属于源码级预览证据,不提升为稳定兼容承诺。 - -## Codex:第一批完整接入 - -首选接入为 `codex app-server --listen stdio://`,不是屏幕抓取或固定 `codex exec` argv。App Server 提供 thread/turn 生命周期、JSONL 通知、中断和版本匹配的 schema 导出。 - -目标 adapter: - -```text -integrations/codex/ - adapter/ - app-server-client.* - schema-probe.* - event-map.* - tool-dispatch.* - skill/ - SKILL.md # 只含 OfferU 工作方式与实时发现入口 -``` - -启动流程: - -1. probe `codex --version`,导出当前 app-server JSON Schema; -2. 以 Run 工件目录作为 cwd,启动 stdio app-server; -3. initialize 后创建/恢复 thread; -4. 把当前 grant 投影为 dynamic tools; -5. 收到 `item/tool/call` 时调用 OfferU Bridge; -6. 把 pending proposal 保持为工具等待或结构化 pending 结果; -7. 映射 item/turn events,并用原生 `turn/interrupt` 中断。 - -Codex 官方当前把 `dynamicTools` 标记为 experimental,因此第一版必须精确 pin 版本并执行 capability probe。若 dynamic tools 不可用,生成 Skill + shell CLI 只能作为开发兼容模式,不能标记为完整支持。OfferU 不修改用户的 Codex Plus/OAuth 配置,不写 `auth.json`,不把会话切到第三方 API bridge。 - -Codex 自己的 command/file approval 与 OfferU 业务批准是两层独立权限。Codex 只能在 Run 工件目录使用原生工具;即使 Codex UI 批准了一条 shell 命令,也不能因此批准 OfferU proposal。 - -官方资料:[Codex App Server](https://developers.openai.com/codex/app-server)。 - -## Claude Code、OpenCode 与 Pi - -第二批仍需完整同构,不做“只能发一次提示”的缩水支持。 - -| Harness | 首选原生 seam | 进入实现前必须证明 | -| --- | --- | --- | -| Claude Code | stream-json / Agent SDK 能力 | session resume、结构化事件、interrupt、受控工具/权限 | -| OpenCode | JSON run/session 或稳定 server seam | session identity、续接输入、取消、事件与 cwd 限制 | -| Pi | 外部 RPC/CLI session | 不依赖 OfferU 内置 Worker;Run 独占 session、工具投影和终态 | - -如果某宿主当前版本缺失 steer、恢复或工具暂停能力,adapter 应报告具体缺口。只有补齐或明确改变产品一致性契约后才能标记为支持,不能用轮询普通文本冒充事件协议。 - -## 主控与深度执行 adapter 不共用 - -同一个 Codex 或 Claude 可同时出现在两类目录,但 adapter 职责不同: - -- 主控 adapter:服务一个 Agent Run,拥有用户目标和完整对话; -- executor adapter:服务一个受限重任务,只返回 candidate 和来源。 - -两者不得复用 session、工作目录、幂等命名空间或未清洗上下文。`coding_agent_runtime.py` 等现有 hosted executor 代码不直接升格为主控 adapter。 - -## 发布与升级 - -- 每个 adapter 独立版本,记录支持的 Harness 版本区间与 Bridge 版本; -- 所有安装/升级入口先显示将安装的本地包、来源、hash 与权限; -- 禁止在线下载并执行未固定版本的脚本; -- conformance 报告包含 Windows 环境,因为 OfferU 首要桌面环境是 Windows; -- 升级失败保留上一已验证 adapter,不改变当前 Run;已运行 Run 不在中途换版本。 +Installed is not equivalent to verified. \ No newline at end of file From 25064a345932e55eaff86959fcb5e40fc144ed18 Mon Sep 17 00:00:00 2001 From: avabbbb <89175608+avabbbb@users.noreply.github.com> Date: Wed, 23 Sep 2026 00:25:01 +0800 Subject: [PATCH 16/36] docs(archive): preserve previous status and handoff --- .../STATUS-2026-09-23-pre-doc-reset.md | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 docs/archive/STATUS-2026-09-23-pre-doc-reset.md diff --git a/docs/archive/STATUS-2026-09-23-pre-doc-reset.md b/docs/archive/STATUS-2026-09-23-pre-doc-reset.md new file mode 100644 index 00000000..c22a45e6 --- /dev/null +++ b/docs/archive/STATUS-2026-09-23-pre-doc-reset.md @@ -0,0 +1,107 @@ +> **HISTORICAL SNAPSHOT** — archived from STATUS.md before the 2026-09-23 documentation authority reset. + +# OfferU Status + +Updated: 2026-09-17 + +## Verdict + +```text +OFFERU_PUBLIC_RELEASE_NOT_READY +``` + +Internal Beta quality bar is largely met; Public Release still requires signed installer, live external Role Intelligence, real Gmail OAuth, clean-machine verification, and the remaining security/privacy residuals. + +## Current phase + +```text +AUTONOMOUS_PRODUCTION_READINESS +``` + +Ports: frontend `http://127.0.0.1:7410`, backend `http://127.0.0.1:8766`. The optional local llama.cpp endpoint `8080` is never a web entry point. + +## Gate dashboard + +| Gate | Status | Notes | +| --- | --- | --- | +| Core Product | PARTIAL | 10/10 composite, 50/50 first-run, interview learning smoke pass; lacks independent stranger acceptance | +| Data Safety | PASS | R43–R49, R76 covered | +| Security | PARTIAL | 3 legacy email bodies, artifact/PII scrub, retention policy, real OAuth, code signing remain | +| Reliability | PARTIAL | 100-cycle worker, RSS threshold, dual-process claim, retry/restart contracts pass; full matrix missing | +| Architecture / Control | PARTIAL | Static audit 0 findings; dynamic browser/legacy runtime audit and remote CI missing | +| Packaging | PARTIAL | Tauri bundle, sidecar, install lifecycle pass; installer unsigned, upgrade/clean-machine unverified | +| Live Runtime | PASS (staged) | Packaged Pi Agent verified in isolated config; live Role Intelligence still blocked on external provider | +| E2E | PARTIAL | Local managed-Chromium smoke passes; remote runner, clean-machine, migration matrix missing | + +## Next actions + +1. **Security/Privacy residual** — decide fate of 3 legacy email bodies; finish artifact/PII/retention audit. +2. **Release engineering** — signing certificate, previous-release upgrade/migration, CI runner, clean-machine UI, RC artifact. +3. **Reliability matrix** — cross-process provider/network/restart coverage. +4. **Live Role Intelligence** — configure a real provider and run the 10-role matrix; current `deepseek-v4-flash-free` returns model unavailable. + +## Trust-boundary pass (2026-09-19) + +`TRUST_BOUNDARY_P0_CLOSED`. Apple-Bar adversarial review found real trust defects; +this pass closed the verified P0s. Full report: `docs/review/apple-bar/00-SYNTHESIS.md`. + +| Item | Root cause | Fix | +| --- | --- | --- | +| Test DB isolation | Tests/scripts could resolve `DATABASE_URL` → real `djm.db`; conftest had no DB guard | `conftest.py` now sets `OFFERU_DATA_DIR` → isolated tmp before any app import + fail-closed path guard; 2 scripts repointed to isolated tmp. Verified: real `djm.db` md5 unchanged across full suite | +| Studio preview SSRF | `/api/studio/resumes/{id}/preview` served `html_content` on API origin; iframe unsandboxed → generated HTML could call privileged APIs | Restrictive CSP `sandbox` (empty = no scripts/forms/popups/same-origin) + `X-Content-Type-Options` on endpoint; `sandbox=""` on `