Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 52 additions & 7 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

# AGENTS.md

本文档用于约束本项目中的 AI / 自动化开发行为。开发时优先遵循本文件,其次遵循用户当前消息。
本文档用于约束本项目中的 AI / 自动化开发行为。用户当前明确任务与更高优先级指令优先;在其范围内,本文件提供 OfferU 仓库级施工约束。遇到文档冲突时,不凭旧聊天或历史设计猜测,按下述“当前事实源”顺序裁决。

## 角色设定

Expand All @@ -11,14 +11,46 @@
Playwright MCP 或Browser 来访问/截图/识别/探索网站的视觉和代码Context7 MCP 来查询某些技术文档(如果你需要使用到它们的话)动效丰富的部分,可以使用/web-shader-extractor进行分析
关于分析:这是个重大且复杂的工程,并且你上下文有限,你可以先进行整体分析,按模块进行顺序执行,每个模块任务的结果落盘分析文档到本地,这样即便上下文被压缩,后续也能够通过本地文档得到保证。分析思维你可以参考/duck

## 当前事实源与产品模型

当产品/架构文档冲突时,按以下顺序:

```text
GOAL.md
↓
docs/product/current-product.md
↓
CONTEXT.md
↓
docs/adr/README.md
↓
ARCHITECTURE.md + current architecture topic docs
↓
live code / Registry / Host / generated Skill projections
↓
current Eval evidence
```

`docs/archive/**`、旧 dated report、旧 harness/DSH/Pi 方案只作历史证据,不得覆盖当前 authority。

当前必须保持的产品模型:

- **App-first 是普通用户默认入口**:安装 OfferU → 自动发现可用本地 Agent → 支持时自动投影/注册 OfferU Skill → 建立 Profile → 保存 Job → 打开 canonical Job Workspace → Today 引导下一步。
- **Skill-first 是高级用户入口**:用户可从 Codex / Claude Code / WorkBuddy / OpenCode / OMP / Pi 等支持宿主直接调用 OfferU Skill,但最终必须解析或创建同一个 canonical Job / Application 状态。
- **Skill 是 Agent entry,不是第二套产品状态**;不得创建 Agent-only Job、隐藏 workspace、重复 Profile 或平行 Application state。
- **Job / Opportunity 是持久 Job Workspace**:Job Snapshot、Role Intelligence、Evidence Map、Application Materials、Interview、Timeline / Next Action 都属于同一机会工作区。
- Agent 长任务结果必须逐步物化为 OfferU 可见状态(completed / needs review / blocked / failed / next action),不得只留在聊天文本里。
- **Career Runtime 是 Truth authority**,Operation Registry 是 execution/permission authority,当前 active Agent 是 reasoning authority;Today / Pipeline / UI 只投影同一份 Career Truth。
- 对外产品叙事优先使用“一个 Job → 岗位要求 × 可验证证据 → evidence-backed Job Workspace”,Career OS 与三权分立是第二层解释,不应成为普通用户的理解前置条件。

## 基本原则

- 先读现有代码,再动手修改,优先沿用项目已有结构和写法。
- 写代码保持最少行数,能简单实现就不要引入复杂抽象。
- 标准格式、协议、解析、压缩、加密、日期等通用能力优先使用成熟稳定的库,不要手写底层实现,除非用户明确要求或项目已有实现必须沿用。
- 不要为了“兼容更多场景”写大量分支,只实现当前明确需要的功能。
- 项目尚未上线,不需要兼容旧数据;表结构或字段调整时直接按新设计修改,不写旧字段兼容、数据迁移兜底或删除旧表的清理逻辑,除非用户明确要求。
- 每次写完代码,不需要检查语法,不需要执行构建,用户会自己做。
- OfferU 已进入 Public Release 准备路径,**不得再假设旧数据可以直接丢弃**。涉及 schema / persistence / version 的变更必须按 `GOAL.md` 的 migration、backup/restore、upgrade 规则处理;只有明确标记为开发 fixture/demo 的数据才能按任务要求 reset。
- 修改代码后必须做与改动范围匹配的验证,并如实报告:后端至少运行相关 pytest;前端改动至少 typecheck + 相关 test,影响构建/路由/依赖时再跑 production build;跨层、release/security/migration 变更按 `GOAL.md` / CI 对应 gate 扩大验证。文档-only 改动不要求无意义地跑全量构建。**未运行或失败的检查必须明确写出,绝不把“看起来没问题”当 PASS。**
- 不要改无关文件,不要顺手重构。
- 如果工作区已有用户改动,不要回滚,不要覆盖;只在必要范围内追加修改。
- **前端 dev 端口固定 7410,后端固定 8766**:两个端口均避开 AI/框架常用端口(3000/3300/5173/8000/8080/11434 等)与当前 winnat 动态排除段。winnat 排除段会漂移(曾见 2942-3041,后又出现 4229-4328,4321 因此 EACCES),改端口前必须先执行 `netsh interface ipv4 show excludedportrange protocol=tcp` 确认不在任何段内。改前端端口必须同步 `frontend/package.json` 的 `scripts.dev` / `scripts.start`、`frontend/vite.config.ts`(含 TAURI HMR 端口 7411)、`frontend/src-tauri/tauri.conf.json` 的 `devUrl`、`backend/app/config.py` 默认 CORS、`backend/app/routes/email.py`、`backend/app/routes/resume.py` 的 `FRONTEND_BASE_URL`、`.env.example` 与 `backend/.env`;`frontendDist` 必须继续指向静态目录 `../dist`,不能改成 localhost URL。
Expand Down Expand Up @@ -53,17 +85,17 @@ Issues 和 PRD 使用当前 Git remote 对应的 GitHub Issues;外部 Pull Req

## 实现 Agent 准则

- 实现阶段以 `CONTEXT.md`、相关 ADR 和已批准实施路线为事实源;评审意见、聊天总结和旧设计与 ADR 冲突时,以最新 accepted ADR 为准。
- 实现阶段先按“当前事实源”读取 `GOAL.md`、`docs/product/current-product.md`,再按任务读取 `CONTEXT.md`、相关 ADR / architecture docs 与 live code。评审意见、聊天总结、历史报告与当前 authority 冲突时,以当前 authority + live code/evidence 为准。
- 一次只实现一个边界明确、可独立验收的纵向切片。不要同时铺开多个模块,也不要把数据库、API、前端分别做成长期未闭环的横向工程。
- 实现 Agent 负责落地,不重新进行产品问卷或自行新增架构。只有遇到 ADR 冲突、必须扩大文件范围、会改变领域模型或需要新外部权限时,才停止并提出一个阻塞问题。
- 开工前先读取与任务直接相关的代码和文档,用不超过 10 行复述目标、修改范围和验收映射;没有真实阻塞时立即实施。
- 用户或主 Agent 必须在任务中给出允许修改的文件范围。未经确认不得越界,不得修改无关文件、顺手重构、清理历史代码或创建新 ADR/PRD/Issue。
- GUI、CLI、TUI、斜杠 Skill 和本地 Coding Agent 都必须通过同一 Operation Registry;不得复制业务逻辑、直接写数据库、执行隐藏 shell 或绕过 dry-run、确认、审计和数据授权。
- 修改范围由当前任务目标决定,不要求用户预先枚举每个文件。Agent 可修改完成该纵向切片**直接必要**的相邻文件与测试,但不得借机做无关重构、历史清理或创建无关 ADR/PRD/Issue;若必须扩大到新的领域边界或外部权限,再提出阻塞问题。
- GUI、CLI、TUI、斜杠 Skill 和本地 Coding Agent 都必须通过同一 Operation Registry;不得复制业务逻辑、直接写数据库、执行隐藏 shell 或绕过 dry-run、确认、审计和数据授权。**Skill-first 与 App-first 的结果必须落到同一 canonical Job Workspace / Profile / Pipeline。**
- 本地 Coding Agent 只承担可审计重任务。CLI 参数和能力必须通过 capability probe 判断,不能把某个 Codex、Claude 或其他 CLI 版本的 argv 永久写死。
- Agent 推断、面试反馈、简历建议和投递信号不能直接成为职业事实;必须遵循学习观察、事实门、候选进展和使用者确认规则。
- 当前产品仅为本地单人版;不要引入 SaaS、多租户、`workspace_id`、组织、计费、登录或为未来需求预埋兼容层。
- 保持最小实现,优先复用成熟库和现有结构。不得用固定假分、伪造 JSON、静默降级或“返回成功但实际未执行”掩盖失败。
- 完成后按“修改文件、验收映射、未执行命令、剩余风险”报告。遵循本文件既有规则,不运行构建、语法检查或测试,只列出建议由用户执行的命令。
- 完成后按“修改文件、验收映射、已执行检查及结果、未执行检查、剩余风险”报告。能在当前环境执行的相关自动检查应由 Agent 自己执行;只有环境/凭据/平台限制导致无法运行时,才把命令留给用户,并说明原因。

## 反复提醒沉淀

Expand All @@ -76,3 +108,16 @@ Issues 和 PRD 使用当前 Git remote 对应的 GitHub Issues;外部 Pull Req
- **配置文件路径统一走 `llm_config_store.config_file_path()`**:该函数每次调用 `runtime_config_file()` 运行期现取(跟随 `OFFERU_DATA_DIR`),`app/routes/config.py` 与 `app/llm_config_store.py` 不再有模块级 `_CONFIG_FILE` 副本。测试隔离用 `patch("app.llm_config_store.runtime_config_file", return_value=...)` 或 `OFFERU_DATA_DIR` 环境变量,一处生效两处覆盖;不要重新引入模块级路径常量。
- **清理钥匙串时只能删自己写过的 ref**:不要按 `legacy_ref(...)` / `config_ref(...)` 这类固定 ref 批量删除。用户真实 LLM 凭据就存放在 `llm/legacy/*` 与 `llm/config/*` 下,误删会直接让用户丢失 API Key。测试用 fake vault(`unittest.mock.patch` credential_store 的同步函数),不要碰真实钥匙串。
- **API Key 只进钥匙串**:`config.json` 只允许出现 `credential_ref` 和 `env:VAR_NAME` 引用。写入钥匙串失败必须 fail-closed(`VaultUnavailableError`),绝不回退为明文落盘;读取失败不阻断启动,但必须经 `/api/config` 的 `vault_status` 暴露给用户。新增任何会写 config.json 的入口,都要经过 `llm_secret_vault.dehydrate()`。


## 安全回归红线(2026-09-23 加固基线)

这部分来自最新 critical/high/medium/low 修复后的稳定约束。后续改动不得为了“方便”退回旧行为:

- 新增或修改远程 URL / model endpoint / fetch 路径时,必须复用当前 SSRF / scheme / host 校验与 SSL 验证边界;不得关闭证书验证,不得自行放宽到 loopback/private/metadata 等高风险目标。
- 上传文件、PDF/HTML 渲染、导出与本地文件访问必须保持 filename/path canonicalization 与边界校验,禁止重新引入路径穿越。
- 富文本/模板输出继续使用当前安全 sanitizer / sandbox 机制;不得用正则清 HTML 或把用户内容拼入可执行 JS/template。
- 发往外部模型的 cover letter、interview prep 等包含个人信息的内容必须保持 desensitize → model → restore 边界;不得把 PII 明文上送作为“临时简化”。
- API/Bridge/Operation 入口不得移除现有鉴权与权限边界;本地部署也不等于所有 endpoint 可以匿名写。
- config、Agent run、resume/application workspace 等并发写路径必须保留当前锁、事务、idempotency / version 检查;不要用“单用户所以不会并发”作为删除并发保护的理由。
- Secret 永远不进 repo、日志、前端持久状态或明文 config;继续遵循本文件的 keyring / credential_ref 规则。
19 changes: 15 additions & 4 deletions GOAL.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ Job / Opportunity
Profile
```

Agent 是全局能力;Memory 是 Profile 的演进机制;Resume、Role Intelligence、Research、Application Packet 和 Interview 均属于 Job Context。Today、Pipeline、Agent 不拥有独立业务事实,只投影 OfferU Domain Runtime 中同一份 Career Truth。
其中 **Job / Opportunity 是一个持久的 Job Workspace,而不是一次聊天或单纯详情页**。Job Snapshot、Role Intelligence、Evidence Map、Resume/Application Materials、Interview 与 Timeline 都属于同一机会工作区,并逐步物化 Agent 的准备结果。

Agent 是全局能力;Memory 是 Profile 的演进机制;Resume、Role Intelligence、Research、Application Packet 和 Interview 均属于 Job Workspace。Today、Pipeline、Agent 不拥有独立业务事实,只投影 OfferU Domain Runtime 中同一份 Career Truth。

## Stable Technical Boundary

Expand Down Expand Up @@ -110,15 +112,23 @@ Event → Rule → CareerTask → Agent / Runtime → Operation

### First Run

Install → Launch → auto-detect local AI → Resume + explicitly authorized memory → Profile → save first Job → optionally connect job-search inbox → Today / Next Best Actions。正常路径不得要求终端,也不得让用户理解 MCP、Operation Registry、Provider、Harness、FastAPI 或 SQLite。
普通用户主路径:

Install → Launch → auto-detect local AI → 在支持时自动投影/注册 OfferU Skill → Resume + explicitly authorized memory → Profile → save first Job → create/open canonical Job Workspace → optionally connect job-search inbox → Today / Next Best Actions。

高级用户允许从支持的外部 Agent 通过 OfferU Skill 直接开始一个 Job,但最终必须解析/创建同一个 canonical Job Workspace,不能形成 Agent-only 第二套项目状态。

正常路径不得要求终端,也不得让用户理解 Skill 安装、MCP、Operation Registry、Provider、Harness、FastAPI 或 SQLite。

Onboarding Golden Path 必须 100% 通过,并达到 0 uncaught exception、0 blank page、0 developer-only blocker。Today、Pipeline、Profile、Job、Resume 的空状态必须解释原因并给出下一步。

### Today / Pipeline / Job
### Today / Pipeline / Job Workspace

- Today 从 Application、Event、CareerTask、Candidate、Interview 和 Role Intelligence 派生,展示 completed、needs attention、next best action 和 failed/blocked tasks;
- Pipeline 是 Application State 的主要视图,至少展示 Job、Stage、Next action、Last event、Priority;
- Job Detail 收敛 Overview、Role Intelligence、Evidence Gap、Application Materials、Interview、Timeline;
- Job Workspace 收敛 Job Snapshot、Role Intelligence、Evidence Map、Application Materials、Interview、Timeline;
- 长任务结果应逐步物化到 Job Workspace,不得只存在 Agent 会话文本中;
- 关闭/切换 Agent 后,用户仍能从 Job Workspace 理解已完成、待审核、阻塞/失败与下一动作;
- 任何页面出现不同阶段都是 Release Blocker。

### Resume Workspace
Expand Down Expand Up @@ -211,6 +221,7 @@ Critical E2E 必须连续 10/10 通过,不依赖 retry 染绿;核心 Journey
## Product Claims and Support

- README、官网和 UI 只能宣传真实验证的能力;Live Role Intelligence 未通过时只能称岗位差异分析 Beta;
- 首屏优先表达具体用户结果:一个 Job 进入 → 角色要求 × 可验证证据 → reviewable Job Workspace;“Career OS”、Operation Registry、Reasoning Authority 等作为第二层解释,不应成为普通用户理解产品的前置条件;
- README 只有 Final Release Gate 通过后才从 POC/Internal Beta 改为正式 Release claim;
- Public QUICKSTART 只包含 Download、Install、Launch、Onboarding,开发者启动移至 DEVELOPMENT.md;
- 用户报告“Agent 不工作”时,支持人员通过 Doctor、Diagnostic Bundle、Error ID 定位 Provider auth、Backend、DB、Network 或 Task,不要求用户截图 Terminal;
Expand Down
74 changes: 66 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@
<h1 align="center">OfferU</h1>

<p align="center">
<strong>Your local-first AI Career OS.</strong><br/>
Understand every job. Tailor every application. Learn from every interview.
<strong>Give OfferU a job. Get an evidence-backed application workspace.</strong><br/>
See what the role really asks for, what you can prove, and what to prepare next.
</p>

<p align="center">
<em>A local-first AI Career OS that compounds what you learn across jobs and interviews.</em>
</p>

<p align="center">
Expand Down Expand Up @@ -55,10 +59,25 @@

Most job-search tools solve one step.

Your resume lives in one place. Job research lives in another. Application tracking becomes a spreadsheet.
Interview practice starts from zero every single time.
Your JD lives in the browser. Your resume lives in a file. Research lives in another tab. Application tracking becomes a spreadsheet. Interview learning disappears into another AI chat.

So every application starts from zero.

OfferU treats the whole search as one evolving system instead of four disconnected chores:
OfferU changes the unit of work from **a chat** to **a durable Job Workspace**:

```text
Target Job
↓
What does this role really care about?
×
What can I actually prove?
↓
What should I prepare next?
↓
Evidence-backed Job Workspace
```

That Workspace then compounds into the larger Career OS:

```text
Career Profile
Expand All @@ -82,6 +101,21 @@ Debrief & Learning
Instead of opening a fresh AI chat for every job, OfferU keeps one persistent, evidence-backed career
context and carries what it learns across the entire search.

### One Job, one durable Workspace

A Job is not just a detail page. It is the canonical workspace for one opportunity:

```text
Job Snapshot
Role Intelligence
Evidence Map
Application Materials
Interview
Timeline / Next Action
```

Agent work progressively materializes into these objects, so closing a chat does not make the work disappear.

### Persistent career context

OfferU maintains structured career evidence — experience, achievements, skills, preferences, goals and
Expand Down Expand Up @@ -164,7 +198,7 @@ The active agent reasons. OfferU controls capabilities, evidence, side effects a
| ------------ | -------------------------------------------------------------------------------------------------- |
| **Today** | What changed, what OfferU finished, what needs your attention, and what matters next |
| **Pipeline** | Every opportunity, application stage, timeline and next action |
| **Job** | Research, Role Intelligence, evidence gaps, resume, application packet and interview preparation |
| **Job** | Durable Job Workspace: snapshot, Role Intelligence, Evidence Map, materials, interview and timeline |
| **Profile** | Long-term career evidence, goals, preferences and reviewed learning |

Memory is a mechanism for evolving Profile — not a separate product silo.
Expand All @@ -176,9 +210,31 @@ same Operation Registry instead of scraping or auto-applying on its own.

## AI setup

The product direction is **Connect → Auto → Ready**.
The product has **two front doors and one Career Truth**.

**Normal users: App-first**

```text
Install OfferU
→ auto-detect local AI
→ project/register OfferU Skill where supported
→ save a Job
→ work appears in the canonical Job Workspace
```

**Power users: Skill-first**

```text
Open Codex / Claude Code / WorkBuddy / OpenCode / OMP / another supported host
→ enable OfferU Skill
→ "analyze this job for me"
→ Agent creates/resolves the canonical Job
→ open the same Job Workspace in OfferU
```

The product direction remains **Connect → Auto → Ready**.

> **Beginner: connect an agent. Advanced: configure the stack.**
> **Skill is the Agent entry; Job Workspace is the user product.**

Normal users should not have to understand runtimes, protocol versions, model IDs or custom endpoints.
OfferU detects a local agent you already have, checks it, and consumes its own model and account:
Expand Down Expand Up @@ -294,8 +350,10 @@ The intended public user path is:
Download
→ Install
→ Auto-detect your local AI
→ Project/register OfferU Skill where supported
→ Resume + optional authorized AI memory → Profile
→ Save your first Job from the browser
→ Open the canonical Job Workspace
→ Optionally connect a job-search inbox
→ Today tells you what matters next
```
Expand Down
Loading