forked from boos/BoosAPI
[codex] add harness engineering guardrails (#284)
* refactor: add harness engineering guardrails * fix: address harness review feedback --------- Co-authored-by: apple <apple@appledeMacBook-Pro.local>
This commit is contained in:
@@ -35,6 +35,7 @@ npm run docs:build
|
||||
| 运维排障与日常维护 | [运维手册](./operations.md) / [常见问题](./faq.md) | 新排障案例、备份恢复、健康检查、典型报错变化时 |
|
||||
| FAQ / 教程协作沉淀 | [FAQ/教程贡献规范](./community/faq-tutorial-guidelines.md) | 需要新增教程、FAQ 模板、内容提交流程时 |
|
||||
| 仓库目录与组织约定 | [目录规范](./project-structure.md) | 目录结构、归档策略或命名约定变化时 |
|
||||
| 工程守则与漂移治理 | [Harness Engineering](./engineering/harness-engineering.md) | 需要更新仓库级黄金原则、自动巡检范围或垃圾回收流程时 |
|
||||
|
||||
## 维护约定
|
||||
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
# Metapi Harness Engineering
|
||||
|
||||
This document captures the repo-level engineering taste that should remain true
|
||||
even when future work is performed by autonomous agents. The goal is not to
|
||||
replace feature tests. The goal is to keep the repository readable,
|
||||
review-friendly, and hard to drift.
|
||||
|
||||
## Why This Exists
|
||||
|
||||
`metapi` already has strong local discipline in several areas:
|
||||
|
||||
- architecture tests that pin important boundaries
|
||||
- schema parity and runtime bootstrap verification across databases
|
||||
- shared protocol helpers that deliberately replace parallel implementations
|
||||
|
||||
What was still missing was one place that states the mechanical rules behind
|
||||
those choices and a lightweight loop that continuously checks for drift. This
|
||||
document is that shared contract.
|
||||
|
||||
## Golden Principles
|
||||
|
||||
### 1. One Invariant, One Source Of Truth
|
||||
|
||||
If a helper, contract, or workflow already owns an invariant, new work should
|
||||
reuse that home instead of creating a second implementation.
|
||||
|
||||
Examples:
|
||||
|
||||
- protocol shaping and normalization belong in `src/server/transformers/**`
|
||||
- endpoint fallback belongs in `src/server/routes/proxy/endpointFlow.ts`
|
||||
- proxy success/failure bookkeeping belongs in
|
||||
`src/server/proxy-core/surfaces/sharedSurface.ts`
|
||||
- schema heuristics belong in `src/server/db/schemaMetadata.ts`
|
||||
|
||||
### 2. Routes Are Adapters, Not Owners
|
||||
|
||||
`src/server/routes/**` should remain thin. Route files may register endpoints,
|
||||
read Fastify request state, and delegate to shared orchestration. They should
|
||||
not become the place where retry loops, protocol conversion, stream lifecycle,
|
||||
or billing logic lives.
|
||||
|
||||
If a helper is imported outside a single route file, that helper should move to
|
||||
`proxy-core`, `services`, `transformers`, or another neutral home.
|
||||
|
||||
### 3. Transformers Must Stay Protocol-Pure
|
||||
|
||||
Transformers are the protocol boundary. They may depend on canonical/shared
|
||||
contracts, but they should not reach back into route files, Fastify handlers,
|
||||
OAuth services, token routing, or runtime dispatch details.
|
||||
|
||||
In practice this means:
|
||||
|
||||
- `canonical` is the request truth source
|
||||
- `shared/normalized` is the response truth source
|
||||
- compatibility layers may orchestrate retries or fallback bodies, but they do
|
||||
not redefine protocol semantics
|
||||
|
||||
### 4. Proxy-Core Follows The Golden Path
|
||||
|
||||
Proxy orchestration should prefer shared, tested paths instead of bespoke
|
||||
surface-local logic.
|
||||
|
||||
Current preferred path:
|
||||
|
||||
- endpoint ranking and request shaping via `upstreamEndpoint.ts`
|
||||
- endpoint-attempt loops via `executeEndpointFlow()`
|
||||
- whole-body response decoding via `readRuntimeResponseText()`
|
||||
- OAuth refresh, sticky/lease behavior, billing, and proxy logging via
|
||||
`sharedSurface.ts`
|
||||
- Codex header/session semantics via provider profiles and header utils
|
||||
- Codex websocket transport via the dedicated websocket runtime, not generic
|
||||
fetch executors
|
||||
|
||||
### 5. Platform Capability Must Be Explicit
|
||||
|
||||
Platform behavior is easy to let drift because it spans adapters, discovery,
|
||||
endpoint preference, and routing. Any platform-specific behavior that matters
|
||||
at runtime should be stated once and reused, not re-inferred in multiple
|
||||
subsystems.
|
||||
|
||||
Thin adapters should stay honest. Feature-complete adapters should be tested as
|
||||
feature-complete. Do not silently “upgrade” support through generic defaults.
|
||||
|
||||
### 6. Database Changes Must Stay Contract-Driven
|
||||
|
||||
Schema work already has one of the strongest harnesses in the repo. Keep it
|
||||
that way.
|
||||
|
||||
- update Drizzle schema and SQLite migration history together
|
||||
- regenerate checked-in contract/artifacts together
|
||||
- keep cross-dialect bootstrap/upgrade generation contract-driven
|
||||
- keep legacy startup compatibility narrow and spec-owned
|
||||
|
||||
### 7. Web Pages Are Orchestration Surfaces
|
||||
|
||||
Top-level pages should not be reused as shared component libraries.
|
||||
|
||||
- no page-to-page imports for reusable UI
|
||||
- mobile behavior should reuse shared primitives first
|
||||
- extract repeated modals, drawers, and panels into domain subfolders early
|
||||
|
||||
## First-Wave Drift Checks
|
||||
|
||||
The first repo-level drift loop is intentionally small and high-signal. It
|
||||
checks for:
|
||||
|
||||
- transformer imports from `routes/proxy`
|
||||
- new proxy-core surface body reads that bypass `readRuntimeResponseText()`
|
||||
- new imports from `routes/proxy` inside `proxy-core` beyond the current debt
|
||||
baseline
|
||||
- new top-level page-to-page imports in the admin UI beyond the current debt
|
||||
baseline
|
||||
|
||||
These checks live in `scripts/dev/repo-drift-check.ts` and are wired into CI.
|
||||
|
||||
## Tracked Debt Vs New Violations
|
||||
|
||||
The repository already contains some known architectural debt, especially where
|
||||
`proxy-core` still imports helpers from `routes/proxy` and where one admin page
|
||||
reuses another page's export.
|
||||
|
||||
The harness uses a ratchet:
|
||||
|
||||
- tracked debt is reported so it stays visible
|
||||
- new violations fail CI
|
||||
|
||||
This keeps the repo moving forward without forcing a risky “rewrite
|
||||
everything first” migration.
|
||||
|
||||
## Garbage Collection Loop
|
||||
|
||||
The harness loop is intentionally conservative:
|
||||
|
||||
1. rules are encoded in repo docs and executable checks
|
||||
2. CI blocks new drift
|
||||
3. a scheduled workflow generates a drift report artifact
|
||||
4. targeted cleanup PRs can remove tracked debt in small slices
|
||||
|
||||
The goal is steady principal payments on technical debt, not occasional heroic
|
||||
cleanup sprints.
|
||||
@@ -90,6 +90,7 @@ scripts/
|
||||
docs/
|
||||
├── .vitepress/ # 文档站导航与主题配置
|
||||
├── community/ # 社区贡献规范
|
||||
├── engineering/ # 仓库级工程规则、harness 与漂移治理说明
|
||||
├── public/ # 文档站公开静态资源
|
||||
├── logos/ # 可编辑 Logo 源文件与草稿
|
||||
├── screenshots/ # 文档截图
|
||||
|
||||
Reference in New Issue
Block a user