Documentation
¶
Index ¶
- Constants
- func BoolPtr(b bool) *bool
- func BoolVal(p *bool) bool
- func DefaultProfiles() map[string]ProfileConfig
- func EffectiveHubRepos(cfg Config) []string
- func GroupReviewAngles(parallelReviewers, anglesPerReviewer, totalAngles int) [][]int
- func HumanSize(bytes int64) string
- func Init(root string, cfg Config) error
- func IsSimilarFeature(a, b string) bool
- func MergeHooks(global, featureHooks map[string][]feature.HookEntry) map[string][]feature.HookEntry
- func NotificationsEnabled(cfg Config) bool
- func PhaseToStatus(phase Phase) feature.Status
- func ProcessAlive(pid int) bool
- func ResolveAnglesPerReviewer(cfg Config, role Role) int
- func ResolveDeepModel(cfg Config, runnerName string, role Role) (string, error)
- func ResolveFeatureRepoPaths(f feature.Feature, cfg Config, root string) map[string]string
- func ResolveMaxDiscoveredFeatures(cfg Config) int
- func ResolveMaxFixRounds(cfg Config, role Role) int
- func ResolveModel(cfg Config, runnerName string, role Role) (string, error)
- func ResolveParallelReviewers(cfg Config, role Role) int
- func ResolveProfileModel(cfg Config, runnerName string, role Role, pc ProfileConfig) (string, error)
- func ResolveRepoPaths(cfg Config, root string) map[string]string
- func ScreenshotDir(cfg Config) string
- func SupportedRunnerMap() map[string]RunnerConfig
- func UserConfigPath() (string, error)
- func ValidateConfig(c Config) error
- func ValidateState(s State) error
- func WriteConfig(dotDir string, cfg Config) error
- func WriteUserConfig(cfg UserConfig) error
- type Baseline
- type BaselineRepo
- type BatchConflict
- type BatchFeatureReport
- type BatchReport
- type CachedWorkspace
- type CleanCandidate
- type Config
- type DesignDoc
- type DiscoveredFeature
- type Escalation
- type Event
- type HealthCheck
- type Phase
- type ProfileConfig
- type ProjectConfig
- type RepoConfig
- type ReviewIssue
- type ReviewResult
- type Role
- type RoleConfig
- type RunnerConfig
- type RunnerPreset
- type Severity
- type State
- type TestProfileOverride
- type TestStrategy
- type UserConfig
- type VerifyCommand
- type VerifyEvidence
- type Workspace
- func (w *Workspace) AppendEvent(featureID string, evt Event) error
- func (w *Workspace) CleanFeature(featureID string) (int64, error)
- func (w *Workspace) CleanableFeatures() ([]CleanCandidate, error)
- func (w *Workspace) ClearBatchConflict() error
- func (w *Workspace) ClearBatchPID() error
- func (w *Workspace) CompareBacklogMirror() ([]feature.BacklogDrift, error)
- func (w *Workspace) DiscoverScreenshots(featureID, screenshotDir string) ([]feature.ScreenshotGroup, error)
- func (w *Workspace) DotDir() string
- func (w *Workspace) FeatureDir(featureID string) string
- func (w *Workspace) InitFeatureDir(featureID string) error
- func (w *Workspace) ListFeatures() ([]feature.Feature, error)
- func (w *Workspace) LoadFeature(id string) (feature.Feature, error)
- func (w *Workspace) LoadMergedConfig() (Config, error)
- func (w *Workspace) ReadBacklogMirror() (feature.BacklogMirror, bool, error)
- func (w *Workspace) ReadBatchConflict() (*BatchConflict, error)
- func (w *Workspace) ReadBatchPID() (int, error)
- func (w *Workspace) ReadBatchReport() (*BatchReport, error)
- func (w *Workspace) ReadConfig() (Config, error)
- func (w *Workspace) ReadState(featureID string) (State, error)
- func (w *Workspace) ReadTestStrategy(featureID string) (TestStrategy, error)
- func (w *Workspace) ReconcileActive(featureID string, s *State) error
- func (w *Workspace) ResolveFeatureID(prefix string) (string, error)
- func (w *Workspace) RoundDir(featureID string, round int) string
- func (w *Workspace) SaveFeature(f feature.Feature) error
- func (w *Workspace) SyncFeatureStatus(featureID string, phase Phase) error
- func (w *Workspace) WorktreePath(featureID string) string
- func (w *Workspace) WriteBatchConflict(c BatchConflict) error
- func (w *Workspace) WriteBatchPID(pid int) error
- func (w *Workspace) WriteBatchReport(r BatchReport) error
- func (w *Workspace) WriteState(featureID string, s State) error
- type WorkspaceConfig
- type WorkspaceReader
Constants ¶
const ( NotifySuccess = "success" // run 正常結束(done / pending-review) NotifyError = "error" // 失敗或 guard 攔截 NotifyWarning = "warning" // 中斷或 escalation )
通知等級常量,供 server 端標注 Event.Notify 及前端判斷顯示樣式,避免散落字串。
const ( BatchOutcomeCompleted = "completed" // 主迴圈自然跑完排程(含失敗達上限被跳過),非被停止/中斷/crash BatchOutcomeStopped = "stopped" // 使用者按 Stop / 衝突暫停等 graceful 提前結束 BatchOutcomeInterrupted = "interrupted" // 收到 SIGTERM/SIGINT 中斷 BatchOutcomeCrashed = "crashed" // 行程 panic )
Batch run 的結束結果(BatchReport.Outcome)列舉值,描述「批次如何終止」而非「是否全數成功」。 即使 outcome=completed,仍可能有 feature 失敗被跳過(看 Failed/Remaining 計數判斷實際結果)。
const ( DirName = ".4x" UserConfigDir = ".4x" UserConfigFile = "settings.json" BacklogFile = "feature_list.json" ConfigFile = "settings.json" FeaturesDir = "features" StateFile = "state.json" EventsFile = "events.jsonl" BaselineFile = "baseline.json" RoundsDir = "rounds" FinalReport = "final-report.md" CommitPlan = "commit-plan.md" TaskBrief = "task-brief.md" Criteria = "acceptance-criteria.md" TestStratFile = "test-strategy.yaml" ReviewReport = "review-report.md" DeepReviewReport = "deep-review-report.md" CoderReport = "coder-report.md" TestReport = "test-report.md" VerifyFile = "verify.json" EscalationFile = "escalation.json" BatchStopFile = "batch-stop" BatchConflictFile = "batch-conflict.json" BatchReportFile = "batch-report.json" BatchPIDFile = "batch-pid" )
const DeepReviewAngleCount = 11
DeepReviewAngleCount 是 deep-reviewer 模板定義的 review angle 總數(angle 1..11)。 平行 deep review 依此把 angle 平均分配給各 sub-reviewer。
Variables ¶
This section is empty.
Functions ¶
func DefaultProfiles ¶
func DefaultProfiles() map[string]ProfileConfig
DefaultProfiles 回傳內建三組 pipeline profile,作為 auto-select 與 fallback 用。 full 跑完整 6 role;normal 省略 designer 與 deep-reviewer;quick 只跑 coder 與 reviewer。
func EffectiveHubRepos ¶
EffectiveHubRepos 合併 Config.HubRepos 與 workspace config 中 Hub: true 的 repo。
func GroupReviewAngles ¶
GroupReviewAngles 把 1..totalAngles 的 review angle 切分給 parallelReviewers 個 sub-reviewer, 回傳每個 sub-reviewer 負責的 angle 編號清單(1-based、連續、不重複、完整覆蓋)。
切分規則:anglesPerReviewer > 0 時以它為每組固定大小依序切(最後一組可能較少); anglesPerReviewer <= 0 時用 ceil(totalAngles/parallelReviewers) 平均分配。 parallelReviewers <= 1 或 totalAngles <= 0 時回傳 nil(由 caller 走 fallback 單 agent)。 實際產生的非空組數可能少於 parallelReviewers(angle 不夠分時)。
func IsSimilarFeature ¶
IsSimilarFeature 判斷兩段文字是否相似:將文字正規化(小寫、去標點、切 token)後 計算 Jaccard token overlap,>= similarityThreshold(0.6)視為相似。
func MergeHooks ¶
MergeHooks 合併全域和 feature 的 hooks,feature 同名 key 整組替換全域。 兩者皆為 nil 時回傳 nil;否則複製 global 所有 key,再由 featureHooks 的 key 整組覆蓋。
func NotificationsEnabled ¶ added in v0.1.10
NotificationsEnabled 回報合併後設定是否啟用 OS 通知。 Notifications 為 nil(使用者未設定)時預設啟用,回傳 true。
func PhaseToStatus ¶
PhaseToStatus 將 state machine 的 Phase 映射為面向 dashboard 的 feature.Status
func ResolveAnglesPerReviewer ¶
ResolveAnglesPerReviewer 解析每個 sub-reviewer 負責的 review angle 數量。 讀取 cfg.Roles[role].AnglesPerReviewer(role 一般為 RoleDeepReviewer); 未設定或 <= 0 時回傳 0,由 GroupReviewAngles 改用 ceil(總 angle/N) 平均分配。
func ResolveDeepModel ¶
ResolveDeepModel 解析 role 的 deep_model tier,回傳 runner 認識的 model name。 若 role 未設 deep_model,回傳空字串與 nil error(表示不需要 deep model)。
func ResolveFeatureRepoPaths ¶
ResolveFeatureRepoPaths 解析 feature 涉及的 repo name → absolute path。 feature.Repos 為空時:multi-repo 回傳所有 workspace repos,monorepo 回傳 {".": root}。
func ResolveMaxDiscoveredFeatures ¶
ResolveMaxDiscoveredFeatures 回傳自動建立 feature 的數量上限: cfg.MaxDiscoveredFeatures > 0 時用該值,否則套預設值(3)。
func ResolveMaxFixRounds ¶
ResolveMaxFixRounds 解析 deep-reviewing phase 自癒循環的最大修正輪數。 讀取 cfg.Roles[role].MaxFixRounds(role 一般為 RoleDeepReviewer); 未設定或 <= 0 時回傳預設 defaultMaxFixRounds(2)。
func ResolveModel ¶
ResolveModel 根據抽象 tier 解析出指定 runner 認識的 model name。 優先序:runners[name].tiers[tier] > model_tiers[tier][runner] > error。 若 tier 在兩處都找不到對應,回傳 error 而非 pass through tier name。
func ResolveParallelReviewers ¶
ResolveParallelReviewers 解析平行 deep review 要 spawn 的 sub-reviewer 數量。 讀取 cfg.Roles[role].ParallelReviewers(role 一般為 RoleDeepReviewer); 未設定或 <= 0 時回傳 1,代表 fallback 單 agent 模式(不分檔、不跑 synthesizer)。
func ResolveProfileModel ¶
func ResolveProfileModel(cfg Config, runnerName string, role Role, pc ProfileConfig) (string, error)
ResolveProfileModel 在 ResolveModel 外加上 profile 的 coder_model 覆蓋。 當 role 為 coder 且 pc.CoderModel 非空時,以 pc.CoderModel 當 tier 解析; 其餘 role 直接呼叫 ResolveModel。
func ResolveRepoPaths ¶
ResolveRepoPaths 從 workspace config 解析 repo name → absolute path。 monorepo 模式回傳 {"." : root}。
func ScreenshotDir ¶
ScreenshotDir 從 config 取得 tester 的截圖目錄,fallback 到 feature.DefaultScreenshotDir。
func SupportedRunnerMap ¶
func SupportedRunnerMap() map[string]RunnerConfig
SupportedRunnerMap 回傳 name → RunnerConfig 的 map
func UserConfigPath ¶
UserConfigPath 回傳 ~/.4x/settings.json 的路徑
func ValidateConfig ¶ added in v0.1.11
ValidateConfig 驗證 Config 結構的合法性,回傳所有錯誤的彙整。
func ValidateState ¶ added in v0.1.11
ValidateState 驗證 State 結構的關鍵欄位。
func WriteConfig ¶
WriteConfig 寫入 .4x/settings.json
func WriteUserConfig ¶
func WriteUserConfig(cfg UserConfig) error
WriteUserConfig 寫入 ~/.4x/settings.json
Types ¶
type Baseline ¶
type Baseline struct {
CreatedAt time.Time `json:"createdAt"`
Repos []BaselineRepo `json:"repos"`
}
Baseline 是 baseline.json 的結構
type BaselineRepo ¶
type BaselineRepo struct {
Name string `json:"name"`
Path string `json:"path"`
Branch string `json:"branch"`
Head string `json:"head"`
DirtyFiles []string `json:"dirtyFiles"`
}
BaselineRepo 是 baseline 中每個 repo 的快照
type BatchConflict ¶
type BatchConflict struct {
FeatureID string `json:"featureId"`
FeatureName string `json:"featureName"`
ConflictRepo string `json:"conflictRepo"`
Files []string `json:"files"`
DetectedAt time.Time `json:"detectedAt"`
}
BatchConflict 是 batch auto-merge 遇衝突暫停時寫入的信號(.4x/batch-conflict.json)。 dashboard 讀此檔得知是哪個 feature、哪個 repo、哪些檔案發生衝突,供使用者解完後 Continue Batch。
type BatchFeatureReport ¶
type BatchFeatureReport struct {
ID string `json:"id"`
Name string `json:"name"`
FinalStatus feature.Status `json:"finalStatus"`
DurationMs int64 `json:"durationMs"`
Rounds int `json:"rounds"`
StopReason string `json:"stopReason,omitempty"`
}
BatchFeatureReport 是 BatchReport 內單一 feature 的最終狀態快照。
type BatchReport ¶
type BatchReport struct {
StartedAt time.Time `json:"startedAt"`
FinishedAt time.Time `json:"finishedAt"`
DurationMs int64 `json:"durationMs"`
Outcome string `json:"outcome"`
Total int `json:"total"`
Completed int `json:"completed"`
Failed int `json:"failed"`
Remaining int `json:"remaining"`
Runner string `json:"runner"`
Features []BatchFeatureReport `json:"features"`
PanicMessage string `json:"panicMessage,omitempty"` // 僅 crashed
RunningFeature string `json:"runningFeature,omitempty"` // interrupted/crashed 時正在跑的 feature id
}
BatchReport 是一次 batch run 結束後(正常 / stop / interrupt / crash)寫入 .4x/batch-report.json 的整體報告。dashboard 在 batch 沒在跑時讀此檔顯示「上次 batch 報告」摘要與每個 feature 的最終狀態。
type CachedWorkspace ¶
type CachedWorkspace struct {
*Workspace
// contains filtered or unexported fields
}
CachedWorkspace 在 *Workspace 上加一層 mtime-based in-memory cache,供 long-running dashboard server 使用,減少每次 API 請求重複 parse 大量 YAML/JSON。
失效策略完全靠檔案 mtime 比對:每次讀取先用 os.Stat / os.ReadDir 取 metadata, 與 cache 記錄的 mtime 相同才回傳 cache,否則重新 parse。因此寫入端(SaveFeature / WriteState 等)無需主動通知 cache,下次讀取自動偵測變動。
為避免 stat→parse 之間檔案被改動造成「cache 記錄的 mtime 與資料版本不一致」 (存舊 mtime → 永久 miss;存新 mtime 配舊資料 → 回傳 stale),所有 override 方法採 stat→parse→stat:唯有 parse 前後兩次 mtime 一致才寫入 cache,不一致則 略過 cache(仍回傳這次讀到的正確資料),由下次讀取重試。
透過 Go embedding 滿足 WorkspaceReader 並沿用 *Workspace 的所有其他方法; 僅 ListFeatures / LoadFeature / ReadConfig 被 override 加上 cache。ReadState 刻意不 cache(頻繁變化、檔案小、parse 快)。
注意:Go embedding 無虛擬分派,*Workspace 內部方法呼叫的 w.ListFeatures() 等 仍走原版、不命中 cache,這是已知且可接受的限制(那些路徑非 server hot-path)。
func NewCachedWorkspace ¶
func NewCachedWorkspace(ws *Workspace) *CachedWorkspace
NewCachedWorkspace 建立一個包裝 ws 的 CachedWorkspace,初始 cache 為空。
func (*CachedWorkspace) ListFeatures ¶
func (c *CachedWorkspace) ListFeatures() ([]feature.Feature, error)
ListFeatures 列出所有 feature;features 目錄內容或任一 .yaml 的 mtime 改變時重新 parse。 回傳的是 cache 的 shallow copy:slice 結構與 value 欄位已隔離(增刪元素、改 Name 等 不影響 cache),但 Feature 的 reference 欄位(Repos / Subtasks / Rules / Depends / Hooks / Priority)仍與 cache 共用底層;呼叫端切勿就地修改這些欄位內容,否則會污染 cache 且不受 c.mu 保護。
func (*CachedWorkspace) LoadFeature ¶
func (c *CachedWorkspace) LoadFeature(id string) (feature.Feature, error)
LoadFeature 讀取單一 feature;對應 YAML 的 mtime 未變時回傳 cache。
func (*CachedWorkspace) LoadMergedConfig ¶
func (c *CachedWorkspace) LoadMergedConfig() (Config, error)
LoadMergedConfig 讀取 project config(走 cache 版 ReadConfig)並合併 user config。 必須 override 而非沿用 embedded *Workspace 版本——Go embedding 無虛擬分派, *Workspace.LoadMergedConfig 內部呼叫的是非 cache 的 w.ReadConfig,會 bypass cache。 語意與 *Workspace.LoadMergedConfig 一致:project config 失敗回 error 不做 user merge, user config 失敗印 slog.Warn 但不中斷。
func (*CachedWorkspace) ReadConfig ¶
func (c *CachedWorkspace) ReadConfig() (Config, error)
ReadConfig 讀取 .4x/settings.json;settings.json 的 mtime 未變時回傳 cache 副本。
type CleanCandidate ¶
CleanCandidate 描述一個可清理的 feature workspace。
type Config ¶
type Config struct {
Project ProjectConfig `json:"project"`
Runners map[string]RunnerConfig `json:"runners"`
Default string `json:"default_runner"`
Roles map[string]RoleConfig `json:"roles,omitempty"`
Rules []string `json:"rules,omitempty"`
HubRepos []string `json:"hub_repos,omitempty"`
Isolation string `json:"isolation,omitempty"`
MaxConcurrentRuns int `json:"max_concurrent_runs,omitempty"`
Commit string `json:"commit,omitempty"`
ModelTiers map[string]map[string]string `json:"model_tiers,omitempty"`
Workspace WorkspaceConfig `json:"workspace,omitempty"`
Hooks map[string][]feature.HookEntry `json:"hooks,omitempty"`
// Profiles 定義 pipeline profile(名稱 → 啟用的 role 子集),供依 feature priority
// 自動選擇或 --profile 手動覆蓋;為空時所有 feature 一律走 full(6 role 全跑)。
Profiles map[string]ProfileConfig `json:"profiles,omitempty"`
// ParallelReviewTest 啟用後,reviewer 與 tester 在 reviewing phase 並行執行(共用 worktree)。
ParallelReviewTest bool `json:"parallel_review_test,omitempty"`
// HealthCheck 是全域(settings.json)的 testing phase 前環境檢查設定,
// 未設為 nil(跳過);可被 per-feature test-strategy.yaml 整組覆蓋。
HealthCheck *HealthCheck `json:"health_check,omitempty"`
// TestProfiles 讓專案覆寫或擴充內建 test profile(key 為 profile 名稱)。
// 與 Profiles(pipeline profile)語意不同,不可混用。
TestProfiles map[string]TestProfileOverride `json:"test_profiles,omitempty"`
// AutoDiscoverFeatures 啟用後,run loop 在 final deep review PASS 後會 parse
// deep-review-report.md 的 [NEW-FEATURE] 標記並自動建立 feature。預設 false。
AutoDiscoverFeatures bool `json:"auto_discover_features,omitempty"`
// MaxDiscoveredFeatures 限制單次 run 最多自動建立幾張 feature;未設定或 <= 0 時套預設值(3)。
MaxDiscoveredFeatures int `json:"max_discovered_features,omitempty"`
// DesignDocDirs 指定設計文件(spec/plan)的額外搜尋目錄,優先於預設 docs/design/。
// 例如 ["docs/feature"] 會讓 ResolveDesignDoc 先找 docs/feature/{id}-spec.md。
DesignDocDirs []string `json:"design_doc_dirs,omitempty"`
// Notifications 控制 run 結束時是否推送 OS 原生通知;用 pointer 區分「未設定」與「明確 false」,
// nil(未設定)時 NotificationsEnabled 視為啟用。project 端非 nil 會覆蓋 user 端設定。
Notifications *bool `json:"notifications,omitempty"`
}
Config 是 .4x/settings.json 的專案設定
func MergeConfig ¶
func MergeConfig(user UserConfig, project Config) Config
MergeConfig 合併 user-level 和 project-level 設定。 project 非零值欄位覆蓋 user;project-only 欄位(Project、Isolation 等)直接使用 project 的值。
type DesignDoc ¶
type DesignDoc struct {
// Content 是檔案內容,找不到時為空字串。
Content string
// Source 是相對於 root 的來源路徑(YAML 欄位命中時為原始 YAML 路徑字串),空表示找不到。
Source string
}
DesignDoc 是設計文件(spec/plan)的解析結果。 找不到對應文件時,Content 與 Source 皆為空字串。
func ResolveDesignDoc ¶
func ResolveDesignDoc(root string, feature feature.Feature, docType string, extraDirs ...string) DesignDoc
ResolveDesignDoc 依優先序解析 feature 的設計文件,docType 為 "spec" 或 "plan"。 此函式統一 server 與 prompt 兩處原本各自不一致的解析邏輯,新增來源時只需改這裡。
extraDirs 為額外搜尋目錄(相對於 root),優先於預設 docs/design/。
解析優先序:
- Feature YAML 的 Spec/Plan 欄位(依 docType 選取)。
- extraDirs 中各目錄下的 {feature.ID}-{docType}.md 與 {slug}-{docType}.md。
- docs/design/{feature.ID}-{docType}.md。
- docs/design/{slug}-{docType}.md。
- 都找不到 → 回傳零值 DesignDoc{}。
type DiscoveredFeature ¶
DiscoveredFeature 代表從 deep-review-report.md 解析出的一筆候選 feature。
func DedupeDiscovered ¶
func DedupeDiscovered(candidates []DiscoveredFeature, existing []feature.Feature) []DiscoveredFeature
DedupeDiscovered 過濾候選 feature:保留的 candidate 必須與每個 existing feature (Name+" "+Description)都不相似,且與已保留的 candidate 也不相似(batch 內去重)。 比對對象是 candidate 的 Title+" "+Description。回傳順序維持輸入順序。
func ParseDiscoveredFeatures ¶
func ParseDiscoveredFeatures(report string) []DiscoveredFeature
ParseDiscoveredFeatures 掃描 deep-review-report.md 文字,抽出所有 [NEW-FEATURE] block。 每個 block 的標題取 [NEW-FEATURE] 之後的文字(trim);描述為其後續行,直到遇到空行、 下一個 [NEW-FEATURE] 或下一個 "##" heading 為止。標題為空的 block 整個丟棄。 回傳順序與在 report 中出現的順序一致。
type Escalation ¶
type Escalation struct {
Needed bool `json:"needed"`
Reason string `json:"reason"`
Detail string `json:"detail"`
}
Escalation 是 Coder/Tester 觸發 Designer 重新介入
type Event ¶
type Event struct {
Timestamp string `json:"ts"`
Phase Phase `json:"phase"`
Type string `json:"type"`
Role Role `json:"role,omitempty"`
Round int `json:"round,omitempty"`
Action string `json:"action,omitempty"`
Command string `json:"cmd,omitempty"`
Status string `json:"status,omitempty"`
Detail string `json:"detail,omitempty"`
Runner string `json:"runner,omitempty"`
Model string `json:"model,omitempty"`
// Notify 為前端統一判斷通知等級的提示,值域 NotifySuccess / NotifyError / NotifyWarning,
// 空字串代表不通知。新增欄位向下相容(omitempty),不改既有 event 的 Status 語意。
Notify string `json:"notify,omitempty"`
}
Event 是 events.jsonl 的一行
type HealthCheck ¶
type HealthCheck struct {
Commands []string `yaml:"commands" json:"commands"`
Recovery []string `yaml:"recovery,omitempty" json:"recovery,omitempty"`
Timeout int `yaml:"timeout,omitempty" json:"timeout,omitempty"`
}
HealthCheck 是 testing phase 啟動前的環境檢查設定。 Commands 逐一執行任一失敗即停;失敗時若有 Recovery 則逐一執行後重跑一次 Commands。 Timeout 為每個 command 的逾時秒數,未設定(0)時由呼叫端套用預設 30 秒。
type Phase ¶
type Phase string
Phase 表示 4x 狀態機的各階段
const ( PhaseInit Phase = "init" PhaseDesigning Phase = "designing" PhaseCoding Phase = "coding" PhaseReviewing Phase = "reviewing" PhaseDeepReviewing Phase = "deep-reviewing" PhaseTesting Phase = "testing" PhaseAmending Phase = "amending" PhaseAccepting Phase = "accepting" PhasePendingReview Phase = "pending-review" PhaseDone Phase = "done" PhaseAbandoned Phase = "abandoned" PhaseBlocked Phase = "blocked" PhaseNeedsAttention Phase = "needs-attention" )
type ProfileConfig ¶
type ProfileConfig struct {
// Roles 是啟用的 role 名稱列表;順序不影響行為(執行順序由 canonical pipeline 決定)。
// 必須包含 "coder"(唯一必要 role)。
Roles []string `json:"roles"`
// CoderModel 覆蓋 roles.coder.model 的 tier;為空時沿用既有 coder model 設定。
CoderModel string `json:"coder_model,omitempty"`
}
ProfileConfig 描述一個 pipeline profile:啟用哪些 role、以及 coder 的 model tier 覆蓋。 被停用的 role 在 run loop 中以 pass-through 方式沿合法 state 邊跳過、不呼叫 runner。
func ResolveProfile ¶
ResolveProfile 決定本次 run 使用的 profile 名稱與設定。
解析優先序:
- override 非空(--profile):先查 cfg.Profiles,再退 DefaultProfiles;都找不到回 error。
- override 為空且 cfg.Profiles 為空:回 full(向後相容,priority 不參與)。
- override 為空且 cfg.Profiles 非空:依 feature.Priority auto-select (nil/0/1→full、2→normal、>=3→quick),選到的名稱優先取 cfg.Profiles, 缺則退 DefaultProfiles,再缺則退 full 並印 warning。
解析出的 profile 若 Roles 不含 "coder" 視為設定錯誤,回 error(coder 為唯一必要 role)。
func (ProfileConfig) EnablesRole ¶
func (pc ProfileConfig) EnablesRole(role Role) bool
EnablesRole 判斷某 role 是否在 profile 的 Roles 列表中。
type ProjectConfig ¶
type ProjectConfig struct {
Name string `json:"name"`
Description string `json:"description,omitempty"`
Language string `json:"language,omitempty"`
Setup []string `json:"setup,omitempty"`
Build []string `json:"build,omitempty"`
Test []string `json:"test,omitempty"`
Lint []string `json:"lint,omitempty"`
Docs []string `json:"docs,omitempty"`
Rules []string `json:"rules,omitempty"`
Includes []string `json:"includes,omitempty"`
}
ProjectConfig 是專案基本設定,包含既有工具鏈的描述
type RepoConfig ¶
RepoConfig 描述 workspace 中單一 repo 的設定。
type ReviewIssue ¶
type ReviewIssue struct {
Severity Severity `json:"severity"`
Rule string `json:"rule"`
File string `json:"file"`
Detail string `json:"detail"`
}
ReviewIssue 是 reviewer 發現的問題
type ReviewResult ¶
type ReviewResult struct {
Passed bool `json:"passed"`
CriticalCount int `json:"criticalCount"`
WarningCount int `json:"warningCount"`
}
ReviewResult 是 review verdict 的結構化結果,包含通過與否及 critical/warning issue 計數
type Role ¶
type Role string
Role 表示 4x 的四個角色
const ( RoleDesigner Role = "designer" RoleCoder Role = "coder" RoleReviewer Role = "reviewer" RoleDeepReviewer Role = "deep-reviewer" RoleTester Role = "tester" RoleAcceptor Role = "acceptor" // RoleMiniCoder 與 RoleReVerifier 是 deep-reviewing phase 內自癒循環的子 role, // 不對應任何 state machine phase(全程維持 deep-reviewing),僅用於 prompt template // 與 event/log 辨識。 RoleMiniCoder Role = "mini-coder" RoleReVerifier Role = "re-verifier" // RoleSynthesizer 是平行 deep review 模式下合併多份 partial report 的子 role, // 同樣全程維持 deep-reviewing phase,僅用於 prompt template 與 event/log 辨識。 RoleSynthesizer Role = "synthesizer" )
type RoleConfig ¶
type RoleConfig struct {
Model string `json:"model,omitempty"`
DeepModel string `json:"deep_model,omitempty"`
ScreenshotDir string `json:"screenshot_dir,omitempty"`
Instructions []string `json:"instructions,omitempty"`
Includes []string `json:"includes,omitempty"`
// MaxFixRounds 限制 deep-reviewing phase 內自癒循環(mini-coder + re-verifier)
// 的最大迭代次數,僅對 deep-reviewer role 有意義;未設定時由 ResolveMaxFixRounds 套預設值。
MaxFixRounds int `json:"max_fix_rounds,omitempty"`
// ParallelReviewers 設定平行 deep review 要 spawn 幾個 sub-reviewer,僅對 deep-reviewer
// role 有意義;未設定或 <=1 時走 fallback 單 agent 模式(不分檔、不跑 synthesizer)。
ParallelReviewers int `json:"parallel_reviewers,omitempty"`
// AnglesPerReviewer 設定每個 sub-reviewer 負責的 review angle 數量,僅對 deep-reviewer
// role 有意義;未設定時由 ResolveAnglesPerReviewer 回 0,改用 ceil(總 angle/N) 平均分配。
AnglesPerReviewer int `json:"angles_per_reviewer,omitempty"`
}
RoleConfig 是各角色的模型與行為設定
type RunnerConfig ¶
type RunnerConfig struct {
Command string `json:"command"`
Args []string `json:"args"`
Model string `json:"model,omitempty"`
Tiers map[string]string `json:"tiers,omitempty"`
Stdin *bool `json:"stdin,omitempty"`
Tty *bool `json:"tty,omitempty"`
Quiet *bool `json:"quiet,omitempty"`
OutputFormat string `json:"output_format,omitempty"`
}
RunnerConfig 是 LLM runner 的設定
type RunnerPreset ¶
type RunnerPreset struct {
Name string `json:"name"`
Config RunnerConfig `json:"config"`
}
RunnerPreset 描述一個受支援 runner 的預設設定
func SupportedRunners ¶
func SupportedRunners() []RunnerPreset
SupportedRunners 回傳所有受支援 runner 的預設設定,作為 init 和 dashboard 的單一真相源
type State ¶
type State struct {
FeatureID string `json:"featureId"`
Phase Phase `json:"phase"`
Role Role `json:"role"`
Round int `json:"round"`
MaxRounds int `json:"maxRounds"`
Active bool `json:"active"`
Pid int `json:"pid,omitempty"`
Runner string `json:"runner"`
Label string `json:"label,omitempty"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
Since time.Time `json:"since,omitempty"`
ConsecutiveNoProgress int `json:"consecutiveNoProgress"`
LastFailCount int `json:"lastFailCount"`
StopReason string `json:"stopReason,omitempty"`
StopMessage string `json:"stopMessage,omitempty"`
Runners []string `json:"runners,omitempty"`
// Profile 記錄本次 run 使用的 pipeline profile 名稱,供 dashboard 顯示與 resume 沿用。
Profile string `json:"profile,omitempty"`
}
State 是 .4x/{feature-id}/state.json 的權威狀態
type TestProfileOverride ¶
type TestProfileOverride struct {
Content string `json:"content,omitempty"`
Include string `json:"include,omitempty"`
}
TestProfileOverride 允許專案在 settings.json 覆寫或新增 test profile。 Content 直接指定內容;Include 指定相對於 workspace root 的檔案路徑。兩者擇一,整組取代內建。
type TestStrategy ¶
type TestStrategy struct {
Web bool `yaml:"web" json:"web"`
API bool `yaml:"api" json:"api"`
Gate bool `yaml:"gate" json:"gate"`
CoderOnly bool `yaml:"coder_only" json:"coder_only"`
Verify []string `yaml:"verify_commands" json:"verify_commands"`
HealthCheck *HealthCheck `yaml:"health_check,omitempty" json:"health_check,omitempty"`
VerifyGroups map[string][]string `yaml:"verify_groups,omitempty" json:"verify_groups,omitempty"`
// Profiles 標記本 feature 適用的測試 profile(如 unit/web/api/e2e),
// Tester prompt 會依此自動注入對應的測試方法論;為空時行為與舊版一致。
Profiles []string `yaml:"profiles,omitempty" json:"profiles,omitempty"`
}
TestStrategy 是 test-strategy.yaml 的結構
type UserConfig ¶
type UserConfig struct {
Locale string `json:"locale,omitempty"`
Theme string `json:"theme,omitempty"`
DefaultRunner string `json:"default_runner,omitempty"`
Runners map[string]RunnerConfig `json:"runners,omitempty"`
Roles map[string]RoleConfig `json:"roles,omitempty"`
// LogLevel 設定 structured logging 的最低輸出等級(debug/info/warn/error),
// 為空時預設 "info";可被環境變數 FOURX_LOG_LEVEL 覆蓋。
LogLevel string `json:"logLevel,omitempty"`
// LogRetainDays 設定 ~/.4x/logs/ 下 log 檔的保留天數,
// 超過此天數的 log 檔會在 Init() 時自動清除;為零時預設 7 天。
LogRetainDays int `json:"logRetainDays,omitempty"`
// Notifications 為使用者層級的 OS 通知開關;用 pointer 區分「未設定」與「明確 false」,
// 會被 project 端非 nil 的設定覆蓋(見 MergeConfig)。
Notifications *bool `json:"notifications,omitempty"`
}
UserConfig 是 ~/.4x/settings.json 的使用者層級設定
func ReadUserConfig ¶
func ReadUserConfig() (UserConfig, error)
ReadUserConfig 讀取 ~/.4x/settings.json,不存在時回傳零值
type VerifyCommand ¶
type VerifyCommand struct {
Command string `json:"command"`
ExitCode int `json:"exitCode"`
ExpectedExitCode *int `json:"expectedExitCode,omitempty"`
DurationMs int64 `json:"durationMs"`
Summary string `json:"summary"`
StartedAt time.Time `json:"startedAt"`
FinishedAt time.Time `json:"finishedAt"`
Group string `json:"group,omitempty"`
Skipped bool `json:"skipped,omitempty"`
}
VerifyCommand 是單一 verify command 的結果
type VerifyEvidence ¶
type VerifyEvidence struct {
Passed bool `json:"passed"`
Round int `json:"round"`
Role Role `json:"role"`
Commands []VerifyCommand `json:"commands"`
Screenshots []feature.Screenshot `json:"screenshots,omitempty"`
}
VerifyEvidence 是 rounds/round-N/verify.json 的結構
type Workspace ¶
type Workspace struct {
Root string
}
Workspace 管理 .4x/ 目錄的讀寫
func (*Workspace) AppendEvent ¶
AppendEvent 追加一行到 events.jsonl
func (*Workspace) CleanFeature ¶
CleanFeature 刪除指定 feature 的 workspace 目錄,回傳釋放的位元組數。 僅允許 done 或 abandoned 且非 active 的 feature;非 terminal 或仍在執行中皆回 error。 feature 定義(.4x/features/{id}.yaml)不受影響。
func (*Workspace) CleanableFeatures ¶
func (w *Workspace) CleanableFeatures() ([]CleanCandidate, error)
CleanableFeatures 列出所有可清理的 feature workspace。 僅納入 done 或 abandoned、有 workspace 目錄、且目前非 active 的 feature, 供 4x clean 與 POST /api/clean 在實際刪除前向使用者預覽清理對象與預估空間。
func (*Workspace) ClearBatchConflict ¶
ClearBatchConflict 刪除 .4x/batch-conflict.json;檔案不存在時不視為錯誤。
func (*Workspace) ClearBatchPID ¶
ClearBatchPID 刪除 .4x/batch-pid;檔案不存在時不視為錯誤。
func (*Workspace) CompareBacklogMirror ¶
func (w *Workspace) CompareBacklogMirror() ([]feature.BacklogDrift, error)
CompareBacklogMirror 比對 canonical feature YAML 與 legacy feature_list.json mirror。
func (*Workspace) DiscoverScreenshots ¶
func (w *Workspace) DiscoverScreenshots(featureID, screenshotDir string) ([]feature.ScreenshotGroup, error)
DiscoverScreenshots 會合併 verify.json 與截圖目錄掃描結果,並按 round 分組回傳。
func (*Workspace) FeatureDir ¶
FeatureDir 回傳 .4x/{featureId}/ 的路徑
func (*Workspace) InitFeatureDir ¶
InitFeatureDir 建立 feature 的運行時目錄
func (*Workspace) ListFeatures ¶
ListFeatures 列出所有 feature。 使用寬鬆驗證:格式有問題的 YAML 仍會載入並附帶 Warnings,只有完全無法解析的才跳過。
func (*Workspace) LoadFeature ¶
LoadFeature 讀取 .4x/features/{id}.yaml
func (*Workspace) LoadMergedConfig ¶
LoadMergedConfig 讀取 project config 並合併 user config,封裝散落各處的三行 boilerplate。 project config 讀取失敗時回傳 error 由呼叫端決定如何處理; user config 讀取失敗時印 slog.Warn 但不中斷(沿用既有各站點的處理慣例)。
func (*Workspace) ReadBacklogMirror ¶
func (w *Workspace) ReadBacklogMirror() (feature.BacklogMirror, bool, error)
ReadBacklogMirror 讀取根目錄 feature_list.json;不存在時回傳 present=false。
func (*Workspace) ReadBatchConflict ¶
func (w *Workspace) ReadBatchConflict() (*BatchConflict, error)
ReadBatchConflict 讀取 .4x/batch-conflict.json;檔案不存在時回 (nil, nil) 代表目前無衝突。
func (*Workspace) ReadBatchPID ¶
ReadBatchPID 讀取 .4x/batch-pid 並解析為 PID;檔案不存在時回 (0, nil) 代表目前無 batch run 紀錄, 內容無法解析時回 (0, error)。
func (*Workspace) ReadBatchReport ¶
func (w *Workspace) ReadBatchReport() (*BatchReport, error)
ReadBatchReport 讀取 .4x/batch-report.json;檔案不存在時回 (nil, nil) 代表尚無 batch 報告。
func (*Workspace) ReadConfig ¶
ReadConfig 讀取 .4x/settings.json
func (*Workspace) ReadTestStrategy ¶
func (w *Workspace) ReadTestStrategy(featureID string) (TestStrategy, error)
ReadTestStrategy 讀取 .4x/{featureId}/test-strategy.yaml 並解析為 TestStrategy。 檔案不存在時回傳零值 TestStrategy 與 nil error,方便呼叫端把「沒設定」與「解析失敗」分開處理。
func (*Workspace) ReconcileActive ¶
ReconcileActive 以 process 存在為權威來源校正 Active 欄位。 若 state 記錄 Active=true 但 PID 已不存在,自動將 Active 設為 false 並回寫。
func (*Workspace) ResolveFeatureID ¶
ResolveFeatureID 用前綴比對找出唯一 feature ID(大小寫不敏感)
func (*Workspace) SaveFeature ¶
SaveFeature 寫入 feature YAML,採用 write-to-temp + rename 確保原子性
func (*Workspace) SyncFeatureStatus ¶
SyncFeatureStatus 將 feature YAML 的 Status 欄位同步為對應 phase 的狀態。 內部依序執行 LoadFeature → PhaseToStatus → SaveFeature,供 cmd/4x 與 internal/server 共用,避免 status 同步邏輯分散兩處。 若 feature YAML 被 git 追蹤,會自動 commit 狀態變更。
func (*Workspace) WorktreePath ¶
WorktreePath 從 events.jsonl 解析 feature 的 worktree 路徑。 若 feature 未使用 worktree 或 events.jsonl 不存在,回傳空字串。
func (*Workspace) WriteBatchConflict ¶
func (w *Workspace) WriteBatchConflict(c BatchConflict) error
WriteBatchConflict 將 batch auto-merge 衝突信號寫入 .4x/batch-conflict.json, 供 dashboard 顯示衝突細節並提供 Continue Batch 操作。
func (*Workspace) WriteBatchPID ¶
WriteBatchPID 將 batch run 子程序的 PID 以十進位字串寫入 .4x/batch-pid, 供 server 重啟後辨識並 adopt 仍存活的孤兒子程序。
func (*Workspace) WriteBatchReport ¶
func (w *Workspace) WriteBatchReport(r BatchReport) error
WriteBatchReport 原子寫入 .4x/batch-report.json(同目錄 temp file + os.Rename,仿 WriteState), 確保 dashboard 在 batch run 收尾/中斷的同時讀到的永遠是完整 JSON,不會撞上半寫狀態。
func (*Workspace) WriteState ¶
WriteState 寫入 feature 的 state.json。
採用 write-to-temp + rename 而非直接 os.WriteFile:後者會先 truncate 再寫, 在這段時間內 concurrent 的 ReadState 可能讀到截斷或半寫的 JSON 而 Unmarshal 失敗。 改用同目錄 temp file 寫完再 atomic rename 覆蓋,讓讀者永遠看到完整的舊檔或完整的新檔。
type WorkspaceConfig ¶
type WorkspaceConfig struct {
Repos map[string]RepoConfig `json:"repos,omitempty"`
}
WorkspaceConfig 描述 multi-repo workspace 的 repo 映射。 沒有設定時代表 monorepo 模式。
type WorkspaceReader ¶
type WorkspaceReader interface {
// ListFeatures 列出所有 feature。
ListFeatures() ([]feature.Feature, error)
// LoadFeature 讀取單一 feature YAML。
LoadFeature(id string) (feature.Feature, error)
// ReadState 讀取 feature 的 state.json。
ReadState(featureID string) (State, error)
// ReadConfig 讀取 .4x/settings.json。
ReadConfig() (Config, error)
}
WorkspaceReader 定義 Workspace 的唯讀操作集合,用於抽象出可被 cache 層包裝的讀取介面。 long-running server 透過此介面操作,便於以 CachedWorkspace 替換而不影響呼叫端; CLI 短命程序則直接用 *Workspace。寫入方法刻意不納入介面,避免 cache 層被誤用於寫入。