Documentation
¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
View Source
var PlanCmd = &cobra.Command{ Use: "plan <CBIN-XXX> [tech-stack]", Short: "Generate technical implementation plan for a requirement", Long: `Generate a technical implementation plan from a requirement specification. Creates a plan.md file in the spec directory with implementation details, tech stack decisions, and CANARY token placement instructions.`, Args: cobra.MinimumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { prompt, _ := cmd.Flags().GetString("prompt") if prompt != "" { if _, err := utils.LoadPrompt(prompt); err != nil { return err } } reqID := args[0] techStack := "" if len(args) > 1 { techStack = strings.Join(args[1:], " ") } aspect, _ := cmd.Flags().GetString("aspect") specsDir := ".canary/specs" entries, err := os.ReadDir(specsDir) if err != nil { return fmt.Errorf("read specs directory: %w", err) } var specDir string for _, entry := range entries { if strings.HasPrefix(entry.Name(), reqID) && entry.IsDir() { specDir = filepath.Join(specsDir, entry.Name()) break } } if specDir == "" { return fmt.Errorf("specification not found for %s", reqID) } planFile := filepath.Join(specDir, "plan.md") if _, err := os.Stat(planFile); err == nil { return fmt.Errorf("plan already exists: %s", planFile) } templateContent, err := utils.ReadEmbeddedFile("base/templates/plan-template.md") if err != nil { return fmt.Errorf("read plan template: %w", err) } specFile := filepath.Join(specDir, "spec.md") specContent, err := os.ReadFile(specFile) if err != nil { return fmt.Errorf("read spec file: %w", err) } featureName := "Feature" specAspect := "" for _, line := range strings.Split(string(specContent), "\n") { if strings.HasPrefix(line, "# Feature Specification:") { featureName = strings.TrimPrefix(line, "# Feature Specification: ") featureName = strings.TrimSpace(featureName) } if strings.HasPrefix(line, "**Aspect:**") { parts := strings.SplitN(line, ":", 2) if len(parts) == 2 { aspectVal := strings.TrimSpace(parts[1]) aspectVal = strings.TrimPrefix(aspectVal, "[") aspectVal = strings.Split(aspectVal, "|")[0] aspectVal = strings.TrimSpace(aspectVal) if aspectVal != "" { specAspect = aspectVal } } } } if aspect == "" { if specAspect != "" { aspect = specAspect } else { aspect = "Engine" } } if err := reqid.ValidateAspect(aspect); err != nil { return fmt.Errorf("invalid aspect: %w", err) } aspect = reqid.NormalizeAspect(aspect) content := string(templateContent) content = strings.ReplaceAll(content, "REQID-XXX", reqID) content = strings.ReplaceAll(content, "[FEATURE NAME]", featureName) content = strings.ReplaceAll(content, "YYYY-MM-DD", time.Now().UTC().Format("2006-01-02")) content = strings.ReplaceAll(content, "SECURITY_REVIEW", aspect) if techStack != "" { content = strings.ReplaceAll(content, "[Go/Python/JavaScript/etc.]", techStack) } dbPath := ".canary/canary.db" if _, err := os.Stat(dbPath); err == nil { db, err := storage.Open(dbPath) if err == nil { defer db.Close() repo := storage.NewGapRepository(db) service := gap.NewService(repo) gapContent, err := service.FormatGapsForInjection(reqID) if err == nil && gapContent != "" { content += "\n" + gapContent } } } if err := os.WriteFile(planFile, []byte(content), 0640); err != nil { return fmt.Errorf("write plan file: %w", err) } fmt.Printf("✅ Created implementation plan: %s\n", planFile) fmt.Printf("\nRequirement: %s\n", reqID) fmt.Println("\nNext steps:") fmt.Printf(" 1. Edit %s to complete the plan\n", planFile) fmt.Println(" 2. Implement following TDD (test-first)") fmt.Println(" 3. Add CANARY tokens to source code") fmt.Println(" 4. Run: canary scan") return nil }, }
CANARY: REQ=ENG-4305; FEATURE="PlanCmd"; ASPECT=CLI; STATUS=IMPL; OWNER=canary; UPDATED=2025-10-16 CANARY: REQ=CP-259; FEATURE="PlanTemplatePlaceholderContract"; ASPECT=CLI; STATUS=TESTED; TEST=TestCANARY_CBIN_142_CLI_PlanRendersRealID; UPDATED=2026-08-29
Functions ¶
This section is empty.
Types ¶
This section is empty.
Click to show internal directories.
Click to hide internal directories.