# Jyotisha Agent Constraints 本文件对所有协作代理生效(Claude Code、Codex、Cursor 以及派生工作流)。它把最容易被省略、或在多窗口工作时遗失的规则钉死。`CLAUDE.md` 只补充 Claude 会话的分工,不重复这里的规则;`frontend/AGENTS.md` 是 Next.js 版本提示。 全文分两部分:**Part A** 是所有代码与文档工作的约束;**Part B** 只在输出占星解读(解盘、推运、校正解释)时生效。 ## 0. 先读什么 | 任务类型 | 开工前必读 | | --- | --- | | 任何任务 | 本文件 §1–§4;`git status -sb` 的第一行(确认分支) | | 前端改动 | `frontend/AGENTS.md`、`frontend/DESIGN.md`、`frontend/docs/VOICE.md`、§7 | | Bug / 报错 / 回归 | §5,并检索 `docs/BUG_HISTORY.md` | | 部署、线上故障、域名、登录、环境变量 | `deploy/README.md`(不要重新猜架构) | | 引擎、外部 oracle、镜像边界、远端同步、发布 | §9 与 `docs/research/pre_work_error_ledger.md` | | 领域术语(会话、轮次、故障、评价) | `CONTEXT.md`;命名与术语表一致,见 `docs/agents/domain.md` | | 输出占星解读 | Part B | --- # Part A · 代码与文档工作 ## 1. 生产与环境真相 - Production domain: `https://jyotisha.chat`;staging: `https://staging.jyotisha.chat` - Primary source and the only CI/CD control plane: `https://git.copse.top/root/Jyotisha.git`(Gitea)。GitHub `https://github.com/jesse-ux/Jyotisha.git` 是只读镜像:无 workflow、Actions 已关闭,不得用它验证交付状态,也没有 GitHub Issues 流程。 - Production host: Ubuntu VPS `118.194.235.34`,专用 `deploy` 用户,SSH 端口是部署变量;2 vCPU / 4 GB RAM,只跑 digest 固定镜像,不在主机构建。 - Runtime: `/opt/jyotisha-production`,Compose project `jyotisha-production`,Compose 文件 `deploy/docker-compose.server.yml`。 - Secrets: `/opt/jyotisha-production/.env.production` 与 `.env.production.database`(`0600`);never print, copy into chat, or commit。 - Public edge: Caddy only;Next.js `3000` 与 Python API `5200` 仅 Docker 内网。 - Persistence: 同主机私有 PostgreSQL 17 + Better Auth。从 Supabase 的迁移已切换完成;旧 VPS 不再是部署目标,Supabase 项目按 `docs/operations/production-server-migration-2026-08.md` 作为回滚资产保留到最终对账。 - API 容器有命名卷 `api_scratch`(chart 缓存与异步任务态);重计算端点受 `JYOTISH_HEAVY_COMPUTE_CONCURRENCY`(默认 2)限流,饱和返回 429。 部署安全规则: 1. 打包前 `git status --short --branch`;不得覆盖无关的脏文件。 2. 部署后验证 `/login`、未登录 `/api/account` = `401`、内部 `/api/health` = `200` 且 `swisseph_available = true`;`deployment.gitCommit` 必须等于预期 SHA。 3. 不得暴露端口 `5200`、模型 key、数据库口令、用户 JWT、SSH 私钥。 4. 生产部署只走 Gitea 手动流程(先 `release-quality-gate`,再 dispatch `deploy-production`),复用 staging 已验收的镜像 digest;不改 DNS、不导入生产数据。 ## 2. 分支与交付 分支模型:`staging` 是测试环境,`main` 是生产控制分支。所有改动先经 `staging` 验收,再提升到 `main`;不存在直接改 `main` 的路径。 1. 动手前 `git fetch origin --prune`,以远端 **`origin/staging`** 为基线。本地 `staging` / `main` 经常落后远端上百个提交,不得作为基线。 2. 在独立 worktree 开发:路径 `.worktrees/<主题>-<日期>`,分支 `codex/<主题>-<日期>`(见 §3)。 3. 交付到 staging 用快进推送 `git push origin HEAD:staging`。这会触发 Gitea `backend-quality-gate`;它的 `paths:` 过滤与 `deploy/gated-paths.txt` 逐行一致。改动**全部**落在清单之外的纯文档推送(`docs/**`、根目录 `BLOCKED.md` / `CHANGELOG*.md` / `CONTEXT.md` / `AGENTS.md` / `CLAUDE.md` / `README.md` 等)不触发门禁、不发布镜像、不部署。鼓励把文档与同批代码合并一次推送,避免 staging head 与已部署 SHA 分离。 4. 门禁构建 digest 固定镜像并 dispatch `deploy-staging`;随后在 staging 完成与风险相称的验收。`GET /api/health` 的 `.deployment.gitCommit` 必须等于**最近一次含门禁路径改动的 staging 提交**;其后若只有纯文档提交,`deploy/is-docs-only-range.sh <该 SHA> ` 必须退出 0,否则视为未部署。 5. 提升到 `main` **必须快进,不得 merge**。`deploy-production.yml` 强制 `main` 与 `staging` 指向同一 SHA,merge commit 会让生产部署失败。 6. 推送后必须核对远端 SHA;远端验证失败时不得声称已交付。 7. 不得自行提升 `main`、不改 `.gitea/workflows/**`、不动 DNS——这三件事只由产品负责人触发。 ## 3. 工作树与多会话 同一台机器上经常有多个代理会话并行,主检出 `/workspace/Jyotisha` 可能被别的会话切到别的分支。 1. 任何 git 操作前先看 `git status -sb` 第一行确认分支;不要假设自己还在上次的分支上。 2. 代码工作只在自己的 worktree 里做:`git worktree add -b codex/<主题>-<日期> .worktrees/<主题>-<日期> origin/staging`。 3. 文档/任务书推 staging 时,用专门跟踪 `staging` 的 worktree(例如 `.worktrees/staging-docs`):`git pull --ff-only origin staging` → commit → push;不要在主检出上直接 commit 到 staging。 4. 不得在有未提交修改的工作树上切分支、stash、reset、覆盖或顺带提交别人的变更;不得 reset / rebase 别的会话的分支。误落到别人分支上的提交用 cherry-pick 搬走并告知。 5. 两个同时改 `frontend/src/app/page.tsx` 或同一组件的轮次必须串行,任务书里写明先后。 ## 4. 记录文件放哪 | 内容 | 位置 | 规则 | | --- | --- | --- | | 任务书、执行进度 | `docs/tasks/TASK-<主题>-<日期>.md`、`docs/tasks/PROGRESS-<主题>-<日期>.md` | 新文件只写这里,不再放仓库根目录;索引在 `docs/tasks/README.md` | | 被环境/依赖挡住的事项 | `BLOCKED.md`(根目录) | 写清缺什么、替代证据是什么;解除后划掉而不是删除 | | Bug 事实、根因、防复发 | `docs/BUG_HISTORY.md` | 见 §5;编号连续,开工时核对当前最大号 | | 用户可感知的行为与 Skill 变化 | `CHANGELOG.md` | 日期 + 一句话标题 + 变更要点;Skill 版本是否 bump 写明 | | 视觉、动效、等待态、间距 | `frontend/DESIGN.md` | 改 UI 的同一提交内更新;`CLAUDE_DESIGN.md` 是上游参照不改 | | 文案口径 | `frontend/docs/VOICE.md` | 新文案先对照 | | 真人验收清单 | `docs/testing/` | 自动化做不了的浏览器级验收写成可照做的条目 | | 领域术语 | `CONTEXT.md` | 新术语先加到 glossary 再用 | `progress.md`、`findings.md`、`task_plan.md` 是早期实现日志,不是运行或部署说明,不再追加。 ## 5. Bug History Workflow Hard Constraint 任何包含"Bug、报错、失败、异常、回归、无法保存、无法删除、状态码错误、线上故障"等现象的任务,开始诊断前必须用报错原文、接口路径、状态码、模块名和用户操作强制检索,并完整读完命中的记录。该文件体量已不允许通读全文,但检索不是可选步骤,命中记录的防复发措施是否仍然存在必须逐条确认: - `docs/BUG_HISTORY.md` 这份文件是产品与代码 Bug 的长期历史入口;`docs/research/pre_work_error_ledger.md` 负责基础设施、外部引擎、碎片目录与预检风险,两者不得互相替代。 1. 修复前必须用报错原文、接口路径、状态码、模块名和用户操作搜索历史记录,优先检查相同模块的根因与防复发措施。 2. 若历史问题复发,必须关联原 `BUG-NNN`,说明旧测试、约束或发布门禁为何未拦住;不得把复发伪装成无关的新问题。 3. Bug 修复必须在同一变更中更新 `docs/BUG_HISTORY.md`:补充现有记录或新增连续编号,并记录状态、现象、触发条件、根因、修复、验证、防复发、关联记录和修复版本。 4. 若当轮只能诊断或被阻塞,也要把已确认事实写成 `investigating` 或 `blocked`,不得编造根因或提前标记 `resolved`。 5. `resolved` 必须有与风险相称的证据:至少一个针对性回归测试;生产问题还必须有脱敏后的迁移、部署、健康检查或 smoke 证据。 6. Bug 历史严禁写入姓名、出生资料、邮箱、用户/案例 ID、Cookie、JWT、密码、密钥、完整请求体或模型原文。 ## 6. 代码增长冻结 - `scripts/jyotish_api_server.py` must not grow. New endpoints and features go in dedicated modules under `scripts/` and are thinly registered from the main file. Do not add new handler bodies, workflows, or feature branches to this file. The cap is enforced by `tests/test_api_server_growth_contract.py`(冻结时行数 + 300 行 bugfix 余量)。 - `frontend/src/app/page.tsx` 已从 4,766 行拆到 2,000 行以下,**不得再增长**:新逻辑进 `frontend/src/hooks/`、`frontend/src/lib/` 或组件;参数式 hook 内部保持 0 个 React hook 的既定模式。 - 不得再手写第二个聊天输入框(一律 `ChatComposer`,自有草稿走 `value`)、第二套滚动跟随(一律 `useConversationScrollAnchor` + `JumpToLatestButton`)、第二套加载动画(揭幕后不得出现 spinner / 骨架 / "正在加载",流式生成中除外)。 ## 7. 前端红线 1. `./node_modules/.bin/tsc --noEmit` 通过;`npm run lint` **0 error**(react-hooks 编译器规则会拦 effect 内同步 setState、render 写 ref 等)。 2. `next build` 后 `/` 保持 `○ Static`;首屏 gzip 变化在 ±2% 内,超出要在进度记录里给出原因。 3. 测试总数不得低于开工时 `origin/staging` 的实测;改任何既有断言必须写"原值 / 新值 / 原因"三栏说明,不得静默弱化。 4. 合同测试的 fixture 必须来自真实引擎响应(golden),不得手造形状。 5. 改 UI 的提交同时更新 `frontend/DESIGN.md`;新文案对照 `frontend/docs/VOICE.md`。 6. 不改数据库结构的轮次不得顺带动迁移;动表的轮次必须真跑 `npm run test:db`。 7. 不得顺手升级依赖、不得顺手修不在任务书里的 warning;发现了写进 `BLOCKED.md` 或进度记录。 ## 8. 隐私与安全 1. 真实用户出生资料、姓名、邮箱、会话内容、JWT、Cookie、密钥,不得进入 skill 文件、测试、CHANGELOG、Bug 历史、任务书、进度记录或任何提交。示例只用公开名人或明确虚构数据。 2. 不得读取、猜测或借用他人的凭据与账号做验收;没有受控账号就把该项写进 `BLOCKED.md`。 3. 供应商地址必须经服务端 SSRF 防护;不得把任何 key 放进前端。 4. 不得放宽置信度或验证边界,除非有外部 benchmark 证据。 ## 9. 开工预检(引擎 / 基础设施 / 发布类任务) 为避免多窗口、多镜像、碎片目录导致重复误判,涉及运行入口、镜像边界、外部 oracle、远端同步、适配器、发布或大规模资料治理的任务,开工前必须读取: - `docs/research/pre_work_error_ledger.md` 若还涉及碎片目录或镜像仓,再读: - `docs/research/whole_machine_fragment_sweep_2026_07_05.md` - `docs/research/whole_machine_fragment_sweep_round25_2026_06_25.md` 并运行: - `python3 scripts/pre_work_check.py --remote-timeout 8 --command-timeout 45`(包含 `scripts/diagnose_external_engine_adapters.py --json`) 要求:不得把 `.workbuddy` 镜像当作运行主仓;不得在 `git ls-remote` / fetch / push 失败时声称云端已同步;新发现的重复错误、阻塞、碎片目录、远端验证失败追加到错误台账。 纯前端文案或组件改动不要求跑这条预检,但 §2、§3 照常。 ## 10. 测试分层与环境缺口 | 层 | 命令 | 何时必跑 | | --- | --- | --- | | Python 快速门 | `.venv/bin/python scripts/run_quality_gate.py --profile quick` | 任何 Python 改动 | | Python 定向 | `.venv/bin/python -m pytest tests/.py` | 改了对应模块 | | 前端 | `tsc --noEmit`、`npm run lint`、`npm test`、`npm run build` | 任何前端改动 | | 数据库 | `npm run test:db --prefix frontend`(需 Docker) | 动表 | | 发布前 | `run_quality_gate.py --profile release` | 提升 `main` 前 | 已知环境缺口,遇到时如实写进 `BLOCKED.md` 而不是宣称通过:无 Docker(DB/部署套件阻塞,用与基线逐条一致的失败清单代替);无登录态与 Chrome(浏览器级验收留给 `docs/testing/` 清单);无模型凭据(真实模型输出留待部署后复核)。 --- # Part B · 解盘类任务硬约束(只在输出占星解读时生效) 以下规则不替代 `SKILL.md` 与 `references/strict-workflow-router.md`,而是把其中最容易被省略的高严谨要求单独钉死。纯计算、纯代码、纯项目维护任务不适用。 ## B1. High-Rigor Override 当用户明确要求以下任一项时,必须进入高严谨模式: - 不要凭经验泛谈 - 必须拉满三大开源参照引擎能力 - 必须提交底层原始数据 - 必须验证过去案例 - 必须避免偷工减料 进入该模式后,以下规则全部强制执行: 1. 必须尝试交叉参照 `PyJHora`、`VedAstro`、`jyotishganit`,并保持许可证边界。 2. 必须优先调用本仓原生实现,不得只用轻量包装脚本代替主链代码。 3. 涉及 timing / event / outcome,不得只看 `Vimshottari`,至少需要 `Vimshottari + Narayana Dasha` 双轨交叉。 4. 必须按问题域强制调取相关分盘:事业 `D10 + A10`;财富 `D2 / D11`;婚恋 `D9 + UL`。 5. 必须交付原始数据依据:度数、Dasha 边界、Shadbala / Ashtakavarga、Yoga 名称、Ayanamsa / Node mode、外部证据路径。 ## B2. Functional Benefic/Malefic Hard Constraint **强制调取 Functional Benefic / Malefic 判定(功能性吉凶星判定)。** 这条约束与 Dasha / 分盘 / 原始数据交付同级,不得省略。 1. 每次进入高严谨模式,必须显式判定当前 Lagna 下的 `functional benefics` 与 `functional malefics`。 2. 任何关于事业、财富、婚恋、健康、障碍、回报、应期的结论,都不得只依据自然吉凶星下判断,必须叠加功能性吉凶星层。 3. 若某颗星在自然属性与功能属性之间冲突,必须在输出中说明冲突来源,并降低置信度或标记 `blocked`。 4. 若未调用功能性吉凶星判定,不得声称该次解读完成了高严谨模式。 5. Technique Audit Table 中必须出现 `Functional Benefic/Malefic` 一行,说明 `Used / not used / blocked`、关键功能吉星、关键功能凶星、对结论置信度的影响。 ## B3. Existing MEVG Invocation Hard Constraint **强制执行既有 MEVG 规则,不得把它当成可选增强项。** 本节不是新增一套验证系统,而是把 `SKILL.md` 与 `references/mandatory-verification-gate-protocol.md` 中已经存在的 MEVG 外部验证门控提升为协作代理硬约束。 1. 对用户提出的 **所有星盘运势类问题**、**所有有关印度占星推运的问题**,包括命盘解读、事业、财富、婚恋、健康、流年、流月、应期、事件预测、出生时间校正辅助和技法可靠性判断,必须执行 MEVG。 2. MEVG 必须包含:全球 / 全网外部资料采集、真实案例参考、来源分级、冲突仲裁、未验证声明降级。 3. 输出的 Technique Audit Table 必须出现 `MEVG / Global Web Evidence` 与 `Real Case Calibration` 两行。 4. 若无法完成外部资料采集、无法找到真实案例、网络/工具不可用、或来源之间出现重大冲突,必须写成 `blocked` 或降级置信度,不得静默跳过。 5. 只有 **纯计算 / 纯代码 / 纯项目维护** 可以豁免 MEVG(运行测试、检查 Git 状态、修复代码、输出未解释的原始度数或 Dasha 边界)。一旦开始解释"这代表什么运势",豁免立即失效。 ## B4. Honesty Boundary 以下情况必须明确写成 `blocked` 或降级置信度:外部 oracle 尚未闭环;三大外部参照引擎中有一层无法合法或稳定调用;缺少分盘、Ayanamsa、Node mode 或出生精度;功能性吉凶星层未完成;双重大运或多系统结果发生实质冲突;MEVG / Global Web Evidence 或 Real Case Calibration 未完成。 禁止把内部一致性伪装成"已经全球顶级精度"。候选出生时间不得写成 confirmed;医疗、法律、投资、安全关键结论及确定性死亡/诊断/妊娠预测禁止。