index

package
v0.2.2 Latest Latest
Warning

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

Go to latest
Published: Aug 28, 2026 License: Apache-2.0 Imports: 11 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var IndexCmd = &cobra.Command{
	Use:   "index [flags]",
	Short: "Build or rebuild the CANARY token database",
	Long: `Scan the codebase for CANARY tokens and store metadata in SQLite database.

This enables advanced features like priority ordering, keyword search, and checkpoints.
The database is stored at .canary/canary.db by default.`,
	RunE: func(cmd *cobra.Command, args []string) error {
		prompt, _ := cmd.Flags().GetString("prompt")
		if prompt != "" {
			if _, err := utils.LoadPrompt(prompt); err != nil {
				return err
			}
		}
		dbPath, _ := cmd.Flags().GetString("db")
		rootPath, _ := cmd.Flags().GetString("root")

		fmt.Printf("Indexing CANARY tokens from: %s\n", rootPath)

		db, err := storage.Open(dbPath)
		if err != nil {
			return fmt.Errorf("open database: %w", err)
		}

		defer func() { _ = db.Close() }()

		// Get git info if in a repo
		var commitHash, branch string
		if gitCmd := exec.Command("git", "rev-parse", "HEAD"); gitCmd.Dir == "" {
			if output, err := gitCmd.Output(); err == nil {
				commitHash = strings.TrimSpace(string(output))
			}
		}
		if gitCmd := exec.Command("git", "rev-parse", "--abbrev-ref", "HEAD"); gitCmd.Dir == "" {
			if output, err := gitCmd.Output(); err == nil {
				branch = strings.TrimSpace(string(output))
			}
		}

		grepCmd := exec.Command("grep",
			"-rn",
			"--include=*.go", "--include=*.md", "--include=*.py",
			"--include=*.js", "--include=*.ts", "--include=*.java",
			"--include=*.rb", "--include=*.rs", "--include=*.c",
			"--include=*.cpp", "--include=*.h", "--include=*.sql",
			"CANARY:",
			rootPath,
		)

		output, err := grepCmd.CombinedOutput()
		if err != nil && len(output) == 0 {
			fmt.Println("No CANARY tokens found")
			return nil
		}

		indexed := 0
		lines := strings.Split(string(output), "\n")
		for _, line := range lines {
			if line == "" {
				continue
			}

			parts := strings.SplitN(line, ":", 3)
			if len(parts) < 3 {
				continue
			}

			file := parts[0]
			lineNum := 0

			fmt.Sscanf(parts[1], "%d", &lineNum)
			content := parts[2]

			reqID := utils.ExtractField(content, "REQ")
			feature := utils.ExtractField(content, "FEATURE")
			aspect := utils.ExtractField(content, "ASPECT")
			status := utils.ExtractField(content, "STATUS")

			if reqID == "" || feature == "" {
				continue
			}

			docPath := utils.ExtractField(content, "DOC")
			docType := utils.ExtractField(content, "DOC_TYPE")

			if docPath != "" && docType == "" {

				firstPath := strings.Split(docPath, ",")[0]
				if strings.Contains(firstPath, ":") {
					docType = strings.Split(firstPath, ":")[0]
				}
			}

			token := &storage.Token{
				ReqID:       reqID,
				Feature:     feature,
				Aspect:      aspect,
				Status:      status,
				FilePath:    file,
				LineNumber:  lineNum,
				Test:        utils.ExtractField(content, "TEST"),
				Bench:       utils.ExtractField(content, "BENCH"),
				Owner:       utils.ExtractField(content, "OWNER"),
				Phase:       utils.ExtractField(content, "PHASE"),
				Keywords:    utils.ExtractField(content, "KEYWORDS"),
				SpecStatus:  utils.ExtractField(content, "SPEC_STATUS"),
				UpdatedAt:   utils.ExtractField(content, "UPDATED"),
				CreatedAt:   utils.ExtractField(content, "CREATED"),
				StartedAt:   utils.ExtractField(content, "STARTED"),
				CompletedAt: utils.ExtractField(content, "COMPLETED"),
				CommitHash:  commitHash,
				Branch:      branch,
				DependsOn:   utils.ExtractField(content, "DEPENDS_ON"),
				Blocks:      utils.ExtractField(content, "BLOCKS"),
				RelatedTo:   utils.ExtractField(content, "RELATED_TO"),
				DocPath:     docPath,
				DocHash:     utils.ExtractField(content, "DOC_HASH"),
				DocType:     docType,
				RawToken:    content,
				IndexedAt:   time.Now().UTC().Format(time.RFC3339),
			}

			if priorityStr := utils.ExtractField(content, "PRIORITY"); priorityStr != "" {
				if p, err := strconv.Atoi(priorityStr); err == nil {
					token.Priority = p
				} else {
					token.Priority = 5
				}
			} else {
				token.Priority = 5
			}

			if token.UpdatedAt == "" {
				token.UpdatedAt = time.Now().UTC().Format("2006-01-02")
			}
			if token.SpecStatus == "" {
				token.SpecStatus = "draft"
			}

			if err := db.UpsertToken(token); err != nil {
				fmt.Fprintf(os.Stderr, "Warning: failed to store token %s/%s: %v\n", reqID, feature, err)
				continue
			}

			indexed++
		}

		reg := sources.LoadFromRoot(rootPath)
		ignorePatterns, ierr := canaryscan.LoadCanaryIgnore(rootPath)
		if ierr != nil {
			fmt.Fprintf(os.Stderr, "Warning: failed to load .canaryignore: %v\n", ierr)
		}
		diagRefs, derr := canaryscan.ScanDiagramRefs(rootPath, nil, reg, ignorePatterns)
		if derr != nil {
			fmt.Fprintf(os.Stderr, "Warning: diagram ref scan failed: %v\n", derr)
		}
		if derr == nil {
			refs := make([]storage.Ref, 0, len(diagRefs))
			for _, r := range diagRefs {
				refs = append(refs, storage.Ref{ReqID: r.ReqID, Kind: "diagram", FilePath: r.File, LineNumber: r.Line})
			}
			if err := db.ReplaceRefs("diagram", refs); err != nil {
				fmt.Fprintf(os.Stderr, "Warning: failed to index diagram refs: %v\n", err)
			} else if len(refs) > 0 {
				fmt.Printf("Indexed %d diagram reference(s)\n", len(refs))
			}
		}

		fmt.Printf("\n✅ Indexed %d CANARY tokens\n", indexed)
		fmt.Printf("Database: %s\n", dbPath)

		if commitHash != "" {
			fmt.Printf("Commit: %s\n", commitHash[:8])
		}
		if branch != "" {
			fmt.Printf("Branch: %s\n", branch)
		}

		return nil
	},
}

CANARY: REQ=CBIN-124; FEATURE="IndexCmd"; ASPECT=CLI; STATUS=IMPL; OWNER=canary; UPDATED=2025-10-16

Functions

This section is empty.

Types

This section is empty.

Jump to

Keyboard shortcuts

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