-
Notifications
You must be signed in to change notification settings - Fork 0
docs\zh_tw\manifest.md
HypGo Framework — Project Manifest 原理與運作機制 版本:0.8.1-alpha | 2026-04
Manifest 是你整個專案的結構化快照。它把散落在數十個檔案中的路由、型別、設定,壓縮成一個 AI 可以在幾百 token 內讀完的 YAML/JSON 檔案。
你的專案(20 個 handler、10 個 model、5 個 service)
│
│ 傳統做法:AI 讀全部原始碼 → ~15,000 tokens
│
▼
.hyp/context.yaml(200 行)
│
│ HypGo 做法:AI 讀一個檔案 → ~500 tokens
│
▼
AI 理解你的專案(壓縮比 30:1)
Manifest 不是文檔。它是框架在運行時從 Router、Config、Schema Registry 自動收集的即時資訊。它不會與程式碼脫節,因為它就是從程式碼產出的。
version: "1.0" framework: HypGo generated_at: "2026年04月03日T14:30:00+08:00" server: addr: ":8080" protocol: http2 tls: true routes: - method: GET path: /api/users handler_names: - controllers.(*UserController).List summary: "List all users" tags: - users output_type: UserListResp - method: POST path: /api/users handler_names: - controllers.(*UserController).Create summary: "Create user" tags: - users input_type: CreateUserReq output_type: UserResp responses: 201: "User created" 400: "Invalid input" - method: GET path: /api/users/:id handler_names: - controllers.(*UserController).Get summary: "Get user by ID" tags: - users output_type: UserResp responses: 200: "User found" 404: "User not found" - method: GET path: /health handler_names: - main.healthHandler database: driver: postgres has_replicas: true
type Manifest struct { Version string // 固定 "1.0" Framework string // 固定 "HypGo" GeneratedAt time.Time // 生成時間 Server ServerInfo // 伺服器設定 Routes []RouteManifest // 所有路由(含 schema metadata) Middleware []string // 已註冊的中間件(可選) Database *DatabaseInfo // 資料庫設定(可選,無 DB 則 nil) }
| 欄位 | 來源 | 說明 |
|---|---|---|
method |
Router | HTTP 方法(GET/POST/PUT/DELETE) |
path |
Router | 路由路徑(含 :id、*filepath) |
handler_names |
Router(reflect) | Handler 函式名稱,用 runtime.FuncForPC 提取 |
summary |
Schema Registry | 一句話描述(只有 Schema 路由才有) |
description |
Schema Registry | 詳細描述(可選) |
tags |
Schema Registry | 分類標籤(可選) |
input_type |
Schema Registry | Input struct 名稱,如 "CreateUserReq"
|
output_type |
Schema Registry | Output struct 名稱,如 "UserResp"
|
responses |
Schema Registry | 狀態碼 → 描述,如 {201: "Created"}
|
關鍵差異:傳統路由(r.GET("/health", handler))只有 method、path、handler_names。Schema 路由額外有 summary、tags、input_type、output_type、responses。
Collector.Collect()
│
├─ 1. collectRoutes()
│ │
│ ├─ router.Routes()
│ │ → 遍歷所有 Radix Tree
│ │ → 每個 leaf node 提取:method, path, handlers
│ │ → 用 runtime.FuncForPC 取得 handler 函式名
│ │ → 回傳 []RouteInfo
│ │
│ └─ 對每個 RouteInfo:
│ schema.Global().Get(method, path)
│ → 有 schema?加入 summary, tags, input_type, output_type, responses
│ → 無 schema?只保留 method, path, handler_names
│
├─ 2. collectServer()
│ → config.Server.Addr
│ → config.Server.Protocol
│ → config.Server.TLS.Enabled
│
└─ 3. collectDatabase()
→ config.Database.Driver(空字串則回傳 nil)
→ config.Database.Replicas 數量 > 0?
排序:Routes 按 Path 字母序 + Method 字母序
// 從 handler 函式指標取得名稱 func nameOfFunction(f interface{}) string { full := runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name() // "github.com/myapp/app/controllers.(*UserController).Create-fm" // ↓ // 取最後一段 + 移除 -fm 後綴 // → "controllers.(*UserController).Create" }
| 方式 | 何時 | 命令/程式碼 |
|---|---|---|
| CLI | 手動執行 | hyp context -o .hyp/context.yaml |
| AutoSync | Server.Start() 自動 | autosync.SyncSafe() |
| 程式碼 | 任何時候 | manifest.NewCollector(r, cfg).Collect() |
Server.Start()
│
├─ autosync.New(config, router, appConfig, logger)
│
└─ autosync.SyncSafe()
│
├─ config.Enabled == false?→ 跳過
│
├─ os.MkdirAll(".hyp/", 0755)
│
├─ manifest.NewCollector(router, appConfig).Collect()
│ → 收集所有路由、設定、schema metadata
│
├─ manifest.SaveToFile(".hyp/context.yaml.tmp", m, "yaml")
│ → 寫入暫存檔(不直接覆蓋目標檔案)
│
├─ os.Rename(".hyp/context.yaml.tmp", ".hyp/context.yaml")
│ → 原子替換(防止寫入中途損壞)
│
└─ logger.Info("AutoSync: manifest saved to .hyp/context.yaml")
❌ 直接寫入(危險):
os.Create(".hyp/context.yaml") ← 此刻檔案被清空
writer.Write(data) ← 寫入中途斷電 → 檔案損壞
file.Close()
✅ 原子寫入(安全):
os.Create(".hyp/context.yaml.tmp") ← 暫存檔
writer.Write(data) ← 寫入暫存檔
file.Close()
os.Rename(".tmp", ".yaml") ← 原子替換,全有或全無
如果 Rename 之前程式崩潰,.yaml 保持上一次的完整版本,.tmp 是不完整的 — 下次啟動會重新生成。
autosync.Config{ Enabled: true, // 預設 true Path: ".hyp/context.yaml", // 預設路徑 Format: "yaml", // "yaml" 或 "json" }
✅ Manifest 包含(結構資訊) ❌ Manifest 不包含(敏感資料)
───────────────────────────── ────────────────────────────
路由路徑 /api/users 資料庫密碼
HTTP 方法 POST DSN 連線字串
型別名稱 CreateUserReq API key / token
欄位名稱 name, email 使用者資料
Handler 名稱 controllers.Create 環境變數值
Server addr :8080 TLS 證書內容
Protocol http2 Redis 密碼
Database driver postgres Session 資料
HasReplicas true Request/Response 實際值
設計原則:AI 看得到「結構」(路由長什麼樣、型別叫什麼名字),看不到「資料」(密碼是什麼、使用者存了什麼)。
func (c *Collector) collectDatabase() *DatabaseInfo { if c.config.Database.Driver == "" { return nil // 沒設定 DB → 不出現在 manifest 中 } return &DatabaseInfo{ Driver: c.config.Database.Driver, // "postgres"(只有 driver 名) HasReplicas: len(c.config.Database.Replicas) > 0, // true/false // ❌ 不包含 DSN // ❌ 不包含 Password // ❌ 不包含 Replica DSN } }
# AI 的第一個動作
cat .hyp/context.yamlAI 從 manifest 中取得:
- 所有 API 端點清單(method + path)
- 每個端點的 Input/Output 型別名稱
- Handler 函式名稱(知道要修改哪個檔案)
- Server 設定(知道用什麼協議)
- Database driver(知道用哪種 SQL)
hyp ai-rules 會嘗試讀取 .hyp/context.yaml,如果存在,就把路由表注入到 AGENTS.md 等配置檔中:
func loadManifestIfExists(dir string) *manifest.Manifest { path := filepath.Join(dir, ".hyp", "context.yaml") data, err := os.ReadFile(path) if err != nil { return nil // 不存在 → AI 配置檔只有靜態慣例,沒有動態路由 } var m manifest.Manifest yaml.Unmarshal(data, &m) return &m }
如果 manifest 存在,AGENTS.md 會包含:
## Current Routes | Method | Path | Summary | |--------|------|---------| | GET | /api/users | List all users | | POST | /api/users | Create user | | GET | /health | - |
# YAML 到 stdout hyp context # JSON 格式 hyp context -f json # 儲存到檔案 hyp context -o .hyp/context.yaml hyp context -o manifest.json -f json
srv := server.New(cfg, log) // 註冊路由後... m := srv.Manifest() // 輸出 manifest.WriteYAML(os.Stdout, m) // 或直接存取欄位 for _, route := range m.Routes { fmt.Printf("%s %s → %s\n", route.Method, route.Path, route.InputType) }
傳統路由:
r.POST("/api/users", createUserHandler)
Manifest 輸出:
- method: POST path: /api/users handler_names: - main.createUserHandler # ← 沒有 summary、沒有 input_type、沒有 output_type
AI 看到這個:「有一個 POST /api/users,handler 叫 createUserHandler... 但我不知道它接受什麼、回傳什麼。讓我去讀原始碼...」→ 消耗 ~2,000 tokens。
Schema 路由:
r.Schema(schema.Route{ Method: "POST", Path: "/api/users", Summary: "Create user", Tags: []string{"users"}, Input: CreateUserReq{}, Output: UserResp{}, Responses: map[int]schema.ResponseSchema{ 201: {Description: "User created"}, 400: {Description: "Invalid input"}, }, }).Handle(createUserHandler)
Manifest 輸出:
- method: POST path: /api/users handler_names: - main.createUserHandler summary: "Create user" tags: - users input_type: CreateUserReq output_type: UserResp responses: 201: "User created" 400: "Invalid input"
AI 看到這個:「POST /api/users,接受 CreateUserReq,回傳 UserResp,可能回 201 或 400。」→ 消耗 ~200 tokens。
| 資訊 | 傳統路由 | Schema 路由 |
|---|---|---|
| 路由路徑 | ✅ | ✅ |
| Handler 名稱 | ✅ | ✅ |
| 一句話描述 | ❌ 不知道 | ✅ "Create user" |
| Input 型別 | ❌ 要讀 handler 推斷 | ✅ "CreateUserReq" |
| Output 型別 | ❌ 要讀 handler 推斷 | ✅ "UserResp" |
| 可能的錯誤 | ❌ 不知道 | ✅ 201/400 |
| AI 理解成本 | ~2,000 tokens | ~200 tokens |
一個 handler 的原始碼可能是 50 行:
func (ctrl *UserController) Create(c *hypcontext.Context) { var req models.CreateUserReq if err := c.ShouldBindJSON(&req); err != nil { errors.AbortWithAppError(c, ErrUserInvalid.With("reason", err.Error())) return } user := &models.User{ Name: req.Name, Email: req.Email, } if _, err := db.WriteHypDB().NewInsert().Model(user).Exec(ctx); err != nil { errors.AbortWithAppError(c, ErrUserInvalid.With("reason", "db error")) return } c.JSON(201, models.UserResp{ ID: user.ID, Name: user.Name, Email: user.Email, }) }
Manifest 把它壓縮成 6 行:
- method: POST path: /api/users summary: "Create user" input_type: CreateUserReq output_type: UserResp handler_names: [controllers.(*UserController).Create]
省略了什麼:
- 怎麼解析 Input(
ShouldBindJSON)→ 這是慣例,不需要每次告訴 AI - 怎麼存 DB(
NewInsert().Model())→ 這是實作細節 - 怎麼處理錯誤(
AbortWithAppError)→ 這是慣例
保留了什麼:
- API 端點是什麼(POST /api/users)→ AI 需要知道
- 接受什麼(CreateUserReq)→ AI 需要知道
- 回傳什麼(UserResp)→ AI 需要知道
- 誰處理(controllers.Create)→ AI 需要知道
這就是為什麼不是有損壓縮:AI 做出正確決策所需的全部結構資訊都在 manifest 中。省略的只是可推斷的慣例和實作細節。
| 時機 | 方式 | 原因 |
|---|---|---|
| Server 啟動 | AutoSync(自動) | 每次啟動都更新,保持同步 |
| 新增/修改路由後 | hyp context -o .hyp/context.yaml |
讓 AI 看到最新路由 |
| 新增路由後 | hyp ai-rules |
把路由表注入 AGENTS.md |
| CI/CD 中 | hyp context -o manifest.yaml |
歸檔 API 結構 |
| 策略 | 做法 | 適合 |
|---|---|---|
| 加入 git | commit .hyp/context.yaml
|
團隊協作,新成員 clone 後立刻有 manifest |
| 加入 .gitignore | 每次 hyp run 自動生成 |
單人開發,避免不必要的 diff |
# 1. 寫好 Schema 路由 # 2. 生成 manifest hyp context -o .hyp/context.yaml # 3. 生成 AI 配置檔(會讀取 manifest 注入路由表) hyp ai-rules # 4. 開啟 AI 工具 → AI 自動讀取 AGENTS.md → 知道所有路由
如果跳過步驟 2 直接跑步驟 3,AGENTS.md 只會有框架慣例,不會有路由表。先 manifest,再 ai-rules。
# YAML 到 stdout hyp context # JSON 格式 hyp context -f json # 只看路由 hyp context | grep "path:"
import "gopkg.in/yaml.v3" data, _ := os.ReadFile(".hyp/context.yaml") var m manifest.Manifest yaml.Unmarshal(data, &m) fmt.Printf("Routes: %d\n", len(m.Routes)) for _, r := range m.Routes { fmt.Printf(" %s %s → %s\n", r.Method, r.Path, r.InputType) }
# 在修改前後各生成一份,用 diff 比較 hyp context -o before.yaml # ... 修改路由 ... hyp context -o after.yaml diff before.yaml after.yaml
m := srv.Manifest() for _, r := range m.Routes { if r.InputType == "" && (r.Method == "POST" || r.Method == "PUT") { fmt.Printf("⚠️ %s %s: missing Input type\n", r.Method, r.Path) } if r.Summary == "" { fmt.Printf("⚠️ %s %s: missing Summary\n", r.Method, r.Path) } }
HypGo · Manifest 機制詳解 · 2026-04
設計文件
套件
- config — 設定
- context — 請求上下文
- router — 路由器
- server — 伺服器
- middleware — 中介層
- websocket — WebSocket
- hidb — 資料庫 ORM
- hidb/cassandra — Cassandra
- logger — 日誌
- json — JSON 處理
- grpc — gRPC
AI 協作工具鏈
- schema — Schema-first 路由
- manifest — 專案 Manifest
- contract — Contract Testing
- errors — Typed Error Catalog
- migrate — Migration Diff
- scaffold — 智慧 Scaffold
- airules — AI Rules
CLI 命令
- hyp 總覽
- hyp new
- hyp api
- hyp run
- hyp restart
- hyp generate
- hyp migrate
- hyp context
- hyp ai-rules
- hyp chkcomment
- hyp impact
- hyp docker
- hyp health
- hyp version
- hyp difflog
Design Docs
Packages
- config — Configuration
- context — Request Context
- router — Router
- server — Server
- middleware — Middleware
- websocket — WebSocket
- hidb — Database ORM
- hidb/cassandra - Cassandra 5.0
- logger — Logger
- json — JSON
- grpc — gRPC
AI Collaboration Toolchain
- schema — Schema-first Routing
- manifest — Project Manifest
- contract — Contract Testing
- errors — Typed Error Catalog
- migrate — Migration Diff
- scaffold — Smart Scaffold
- airules — AI Rules
CLI Commands