✨ feat(spx): issue marker 支持第三种类型 prototype
- --type 三选一 spec|plan|prototype,marker 行写 <!-- spx:prototype=路径 -->,
与 spec/plan 共用同一套增量更新逻辑;类型→state 字段的映射收成一张表
- 同步写 state JSON 的 prototypeFile(pattern 要求 dir/.../x.json)
- 顺手补上 b62e58d 漏掉的 prototypeSessionId / prototypeProfilePath:
schema 与 knownStateFields 都没有它们,带原型会话的工单一 merge
就会被 additionalProperties 拒掉
Claude-Session: https://claude.ai/code/session_01Kgmb1LvrPmFX3NoUDB4zZC
This commit is contained in:
1 parent
814e0e8f5a
commit
def5f4e88c
5 files changed
+89
-8
No files matched your search
@@ -111,6 +111,20 @@ func buildRootCmd() *cobra.Command {
|
||||
return root
|
||||
}
|
||||
|
||||
// markerTypeToStateField maps a `spx issue marker --type` value to the state
|
||||
// JSON field it mirrors. All three types share one incremental-update path;
|
||||
// this table is the single source of truth — adding a type only touches it
|
||||
// (plus markerTypesHint below, which is what the user sees).
|
||||
var markerTypeToStateField = map[string]string{
|
||||
"spec": "specFile",
|
||||
"plan": "planFile",
|
||||
"prototype": "prototypeFile",
|
||||
}
|
||||
|
||||
// markerTypesHint is the human-readable enumeration used in help text and the
|
||||
// "bad --type" error, kept next to the table so the two can't drift.
|
||||
const markerTypesHint = "spec、plan 或 prototype"
|
||||
|
||||
func buildIssueCmd() *cobra.Command {
|
||||
issue := &cobra.Command{
|
||||
Use: "issue",
|
||||
@@ -215,17 +229,17 @@ func buildIssueCmd() *cobra.Command {
|
||||
|
||||
markerCmd := &cobra.Command{
|
||||
Use: "marker",
|
||||
Short: "增量更新现有工单的 spec/plan marker,并同步合并 specFile/planFile 进 state JSON",
|
||||
Short: "增量更新现有工单的 spec/plan/prototype marker,并同步合并 specFile/planFile/prototypeFile 进 state JSON",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if imIssue <= 0 {
|
||||
return fmt.Errorf("--issue 必须是正整数")
|
||||
}
|
||||
if imType != "spec" && imType != "plan" {
|
||||
return fmt.Errorf("--type 必须是 spec 或 plan,得到 %q", imType)
|
||||
fieldName, ok := markerTypeToStateField[imType]
|
||||
if !ok {
|
||||
return fmt.Errorf("--type 必须是 %s,得到 %q", markerTypesHint, imType)
|
||||
}
|
||||
// Fail fast on a bad path before we touch the network — the
|
||||
// schema's specFile/planFile pattern doubles as input check.
|
||||
fieldName := map[string]string{"spec": "specFile", "plan": "planFile"}[imType]
|
||||
// schema's pattern for this field doubles as input check.
|
||||
patch := map[string]any{fieldName: imValue}
|
||||
if err := state.ValidateValue(patch); err != nil {
|
||||
return err
|
||||
@@ -263,8 +277,8 @@ func buildIssueCmd() *cobra.Command {
|
||||
},
|
||||
}
|
||||
markerCmd.Flags().IntVar(&imIssue, "issue", 0, "工单编号(必填)")
|
||||
markerCmd.Flags().StringVar(&imType, "type", "", "marker 类型:spec 或 plan(必填)")
|
||||
markerCmd.Flags().StringVar(&imValue, "value", "", "marker 值(路径,必填,同步写入 state JSON 的 specFile/planFile)")
|
||||
markerCmd.Flags().StringVar(&imType, "type", "", "marker 类型:"+markerTypesHint+"(必填)")
|
||||
markerCmd.Flags().StringVar(&imValue, "value", "", "marker 值(路径,必填,同步写入 state JSON 的 specFile/planFile/prototypeFile)")
|
||||
_ = markerCmd.MarkFlagRequired("issue")
|
||||
_ = markerCmd.MarkFlagRequired("type")
|
||||
_ = markerCmd.MarkFlagRequired("value")
|
||||
@@ -394,11 +408,14 @@ var knownStateFields = map[string]struct{}{
|
||||
"implementSessionId": {},
|
||||
"reviewSessionId": {},
|
||||
"testSessionId": {},
|
||||
"prototypeSessionId": {},
|
||||
"profilePath": {},
|
||||
"brainstormProfilePath": {},
|
||||
"testProfilePath": {},
|
||||
"prototypeProfilePath": {},
|
||||
"specFile": {},
|
||||
"planFile": {},
|
||||
"prototypeFile": {},
|
||||
"prDiffFile": {},
|
||||
"pr": {},
|
||||
"prMerged": {},
|
||||
|
||||
Reference in new issue
Block a user