protocol

package
v0.1.13 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 17, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Index

Constants

View Source
const (
	NotifySuccess = "success" // run 正常結束(done / pending-review)
	NotifyError   = "error"   // 失敗或 guard 攔截
	NotifyWarning = "warning" // 中斷或 escalation
)

通知等級常量,供 server 端標注 Event.Notify 及前端判斷顯示樣式,避免散落字串。

View Source
const (
	BatchOutcomeCompleted   = "completed"   // 主迴圈自然跑完排程(含失敗達上限被跳過),非被停止/中斷/crash
	BatchOutcomeStopped     = "stopped"     // 使用者按 Stop / 衝突暫停等 graceful 提前結束
	BatchOutcomeInterrupted = "interrupted" // 收到 SIGTERM/SIGINT 中斷
	BatchOutcomeCrashed     = "crashed"     // 行程 panic
)

Batch run 的結束結果(BatchReport.Outcome)列舉值,描述「批次如何終止」而非「是否全數成功」。 即使 outcome=completed,仍可能有 feature 失敗被跳過(看 Failed/Remaining 計數判斷實際結果)。

View Source
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"
)
View Source
const DeepReviewAngleCount = 11

DeepReviewAngleCount 是 deep-reviewer 模板定義的 review angle 總數(angle 1..11)。 平行 deep review 依此把 angle 平均分配給各 sub-reviewer。

Variables

This section is empty.

Functions

func BoolPtr

func BoolPtr(b bool) *bool

BoolPtr 建立 *bool 指標,用於 RunnerConfig 布林欄位的初始化

func BoolVal

func BoolVal(p *bool) bool

BoolVal 安全取 *bool 的值,nil 視為 false

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

func EffectiveHubRepos(cfg Config) []string

EffectiveHubRepos 合併 Config.HubRepos 與 workspace config 中 Hub: true 的 repo。

func GroupReviewAngles

func GroupReviewAngles(parallelReviewers, anglesPerReviewer, totalAngles int) [][]int

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 HumanSize

func HumanSize(bytes int64) string

HumanSize 將位元組數轉為人類可讀格式(如 "3.9M"、"124K"、"512B")。

func Init

func Init(root string, cfg Config) error

Init 建立 .4x/ 目錄和初始 config

func IsSimilarFeature

func IsSimilarFeature(a, b string) bool

IsSimilarFeature 判斷兩段文字是否相似:將文字正規化(小寫、去標點、切 token)後 計算 Jaccard token overlap,>= similarityThreshold(0.6)視為相似。

func MergeHooks

func MergeHooks(global, featureHooks map[string][]feature.HookEntry) map[string][]feature.HookEntry

MergeHooks 合併全域和 feature 的 hooks,feature 同名 key 整組替換全域。 兩者皆為 nil 時回傳 nil;否則複製 global 所有 key,再由 featureHooks 的 key 整組覆蓋。

func NotificationsEnabled added in v0.1.10

func NotificationsEnabled(cfg Config) bool

NotificationsEnabled 回報合併後設定是否啟用 OS 通知。 Notifications 為 nil(使用者未設定)時預設啟用,回傳 true。

func PhaseToStatus

func PhaseToStatus(phase Phase) feature.Status

PhaseToStatus 將 state machine 的 Phase 映射為面向 dashboard 的 feature.Status

func ProcessAlive

func ProcessAlive(pid int) bool

ProcessAlive 檢查 PID 是否仍在執行中

func ResolveAnglesPerReviewer

func ResolveAnglesPerReviewer(cfg Config, role Role) int

ResolveAnglesPerReviewer 解析每個 sub-reviewer 負責的 review angle 數量。 讀取 cfg.Roles[role].AnglesPerReviewer(role 一般為 RoleDeepReviewer); 未設定或 <= 0 時回傳 0,由 GroupReviewAngles 改用 ceil(總 angle/N) 平均分配。

func ResolveDeepModel

func ResolveDeepModel(cfg Config, runnerName string, role Role) (string, error)

ResolveDeepModel 解析 role 的 deep_model tier,回傳 runner 認識的 model name。 若 role 未設 deep_model,回傳空字串與 nil error(表示不需要 deep model)。

func ResolveFeatureRepoPaths

func ResolveFeatureRepoPaths(f feature.Feature, cfg Config, root string) map[string]string

ResolveFeatureRepoPaths 解析 feature 涉及的 repo name → absolute path。 feature.Repos 為空時:multi-repo 回傳所有 workspace repos,monorepo 回傳 {".": root}。

func ResolveMaxDiscoveredFeatures

func ResolveMaxDiscoveredFeatures(cfg Config) int

ResolveMaxDiscoveredFeatures 回傳自動建立 feature 的數量上限: cfg.MaxDiscoveredFeatures > 0 時用該值,否則套預設值(3)。

func ResolveMaxFixRounds

func ResolveMaxFixRounds(cfg Config, role Role) int

ResolveMaxFixRounds 解析 deep-reviewing phase 自癒循環的最大修正輪數。 讀取 cfg.Roles[role].MaxFixRounds(role 一般為 RoleDeepReviewer); 未設定或 <= 0 時回傳預設 defaultMaxFixRounds(2)。

func ResolveModel

func ResolveModel(cfg Config, runnerName string, role Role) (string, error)

ResolveModel 根據抽象 tier 解析出指定 runner 認識的 model name。 優先序:runners[name].tiers[tier] > model_tiers[tier][runner] > error。 若 tier 在兩處都找不到對應,回傳 error 而非 pass through tier name。

func ResolveParallelReviewers

func ResolveParallelReviewers(cfg Config, role Role) int

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

func ResolveRepoPaths(cfg Config, root string) map[string]string

ResolveRepoPaths 從 workspace config 解析 repo name → absolute path。 monorepo 模式回傳 {"." : root}。

func ScreenshotDir

func ScreenshotDir(cfg Config) string

ScreenshotDir 從 config 取得 tester 的截圖目錄,fallback 到 feature.DefaultScreenshotDir。

func SupportedRunnerMap

func SupportedRunnerMap() map[string]RunnerConfig

SupportedRunnerMap 回傳 name → RunnerConfig 的 map

func UserConfigPath

func UserConfigPath() (string, error)

UserConfigPath 回傳 ~/.4x/settings.json 的路徑

func ValidateConfig added in v0.1.11

func ValidateConfig(c Config) error

ValidateConfig 驗證 Config 結構的合法性,回傳所有錯誤的彙整。

func ValidateState added in v0.1.11

func ValidateState(s State) error

ValidateState 驗證 State 結構的關鍵欄位。

func WriteConfig

func WriteConfig(dotDir string, cfg Config) error

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

type CleanCandidate struct {
	FeatureID string
	Size      int64
}

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 的值。

func ReadConfig

func ReadConfig(dotDir string) (Config, error)

ReadConfig 讀取 .4x/settings.json

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/。

解析優先序:

  1. Feature YAML 的 Spec/Plan 欄位(依 docType 選取)。
  2. extraDirs 中各目錄下的 {feature.ID}-{docType}.md 與 {slug}-{docType}.md。
  3. docs/design/{feature.ID}-{docType}.md。
  4. docs/design/{slug}-{docType}.md。
  5. 都找不到 → 回傳零值 DesignDoc{}。

type DiscoveredFeature

type DiscoveredFeature struct {
	Title       string
	Description string
}

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

func ResolveProfile(cfg Config, f feature.Feature, override string) (string, ProfileConfig, error)

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

type RepoConfig struct {
	Path string `json:"path"`
	Hub  bool   `json:"hub,omitempty"`
}

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 Severity

type Severity string

Severity 表示 review issue 的嚴重等級

const (
	SeverityCritical Severity = "critical"
	SeverityWarning  Severity = "warning"
	SeverityLow      Severity = "low"
)

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 Find

func Find(startDir string) (*Workspace, error)

Find 從目前目錄往上找 .4x/ 目錄

func (*Workspace) AppendEvent

func (w *Workspace) AppendEvent(featureID string, evt Event) error

AppendEvent 追加一行到 events.jsonl

func (*Workspace) CleanFeature

func (w *Workspace) CleanFeature(featureID string) (int64, error)

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

func (w *Workspace) ClearBatchConflict() error

ClearBatchConflict 刪除 .4x/batch-conflict.json;檔案不存在時不視為錯誤。

func (*Workspace) ClearBatchPID

func (w *Workspace) ClearBatchPID() error

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) DotDir

func (w *Workspace) DotDir() string

DotDir 回傳 .4x/ 的完整路徑

func (*Workspace) FeatureDir

func (w *Workspace) FeatureDir(featureID string) string

FeatureDir 回傳 .4x/{featureId}/ 的路徑

func (*Workspace) InitFeatureDir

func (w *Workspace) InitFeatureDir(featureID string) error

InitFeatureDir 建立 feature 的運行時目錄

func (*Workspace) ListFeatures

func (w *Workspace) ListFeatures() ([]feature.Feature, error)

ListFeatures 列出所有 feature。 使用寬鬆驗證:格式有問題的 YAML 仍會載入並附帶 Warnings,只有完全無法解析的才跳過。

func (*Workspace) LoadFeature

func (w *Workspace) LoadFeature(id string) (feature.Feature, error)

LoadFeature 讀取 .4x/features/{id}.yaml

func (*Workspace) LoadMergedConfig

func (w *Workspace) LoadMergedConfig() (Config, error)

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

func (w *Workspace) ReadBatchPID() (int, error)

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

func (w *Workspace) ReadConfig() (Config, error)

ReadConfig 讀取 .4x/settings.json

func (*Workspace) ReadState

func (w *Workspace) ReadState(featureID string) (State, error)

ReadState 讀取 feature 的 state.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

func (w *Workspace) ReconcileActive(featureID string, s *State) error

ReconcileActive 以 process 存在為權威來源校正 Active 欄位。 若 state 記錄 Active=true 但 PID 已不存在,自動將 Active 設為 false 並回寫。

func (*Workspace) ResolveFeatureID

func (w *Workspace) ResolveFeatureID(prefix string) (string, error)

ResolveFeatureID 用前綴比對找出唯一 feature ID(大小寫不敏感)

func (*Workspace) RoundDir

func (w *Workspace) RoundDir(featureID string, round int) string

RoundDir 回傳 .4x/{featureId}/rounds/round-{n}/ 的路徑

func (*Workspace) SaveFeature

func (w *Workspace) SaveFeature(f feature.Feature) error

SaveFeature 寫入 feature YAML,採用 write-to-temp + rename 確保原子性

func (*Workspace) SyncFeatureStatus

func (w *Workspace) SyncFeatureStatus(featureID string, phase Phase) error

SyncFeatureStatus 將 feature YAML 的 Status 欄位同步為對應 phase 的狀態。 內部依序執行 LoadFeature → PhaseToStatus → SaveFeature,供 cmd/4x 與 internal/server 共用,避免 status 同步邏輯分散兩處。 若 feature YAML 被 git 追蹤,會自動 commit 狀態變更。

func (*Workspace) WorktreePath

func (w *Workspace) WorktreePath(featureID string) string

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

func (w *Workspace) WriteBatchPID(pid int) error

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

func (w *Workspace) WriteState(featureID string, s State) error

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 層被誤用於寫入。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL