feat(index-builder): generate data/meta/index.json
Adds MetaIndex struct and generateMetaIndex function to create data/meta/index.json listing all available meta data files (archetypes.json, rivalries.json) with descriptions. Also adds the new file to the R2 warm cache upload list. Closes: bf-66rk Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
c9503d2588
commit
c37f68e08b
3 changed files with 87 additions and 0 deletions
|
|
@ -175,6 +175,11 @@ func generateAllIndexes(data *IndexData, outputDir string, db *sql.DB, cfg *Conf
|
|||
return fmt.Errorf("archetypes: %w", err)
|
||||
}
|
||||
|
||||
// Generate meta directory index (data/meta/index.json)
|
||||
if err := generateMetaIndex(outputDir); err != nil {
|
||||
return fmt.Errorf("meta index: %w", err)
|
||||
}
|
||||
|
||||
// Generate community hints (data/evolution/community_hints.json)
|
||||
if err := generateCommunityHints(data, outputDir); err != nil {
|
||||
return fmt.Errorf("community hints: %w", err)
|
||||
|
|
@ -1898,6 +1903,18 @@ type ArchetypesIndex struct {
|
|||
Archetypes []ArchetypeEntry `json:"archetypes"`
|
||||
}
|
||||
|
||||
// MetaFileEntry represents a single meta data file in the meta directory index.
|
||||
type MetaFileEntry struct {
|
||||
Name string `json:"name"` // e.g., "archetypes.json"
|
||||
Description string `json:"description"` // e.g., "Bot archetype classifications"
|
||||
}
|
||||
|
||||
// MetaIndex is the top-level structure for data/meta/index.json.
|
||||
type MetaIndex struct {
|
||||
UpdatedAt string `json:"updated_at"`
|
||||
Files []MetaFileEntry `json:"files"`
|
||||
}
|
||||
|
||||
// classifyArchetype infers a behavioral archetype from bot name when the
|
||||
// archetype field is empty.
|
||||
func classifyArchetype(bot BotData) string {
|
||||
|
|
@ -1983,6 +2000,26 @@ func generateArchetypes(data *IndexData, outputDir string) error {
|
|||
return writeJSON(filepath.Join(metaDir, "archetypes.json"), index)
|
||||
}
|
||||
|
||||
// generateMetaIndex builds data/meta/index.json listing all available meta data files.
|
||||
func generateMetaIndex(outputDir string) error {
|
||||
metaDir := filepath.Join(outputDir, "data", "meta")
|
||||
if err := os.MkdirAll(metaDir, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// List all available meta data files with descriptions
|
||||
files := []MetaFileEntry{
|
||||
{Name: "archetypes.json", Description: "Bot archetype classifications and statistics"},
|
||||
{Name: "rivalries.json", Description: "Top rivalries between bots"},
|
||||
}
|
||||
|
||||
index := MetaIndex{
|
||||
UpdatedAt: time.Now().Format(time.RFC3339),
|
||||
Files: files,
|
||||
}
|
||||
return writeJSON(filepath.Join(metaDir, "index.json"), index)
|
||||
}
|
||||
|
||||
// ─── Community Hints (§15.2 / §13.6) ──────────────────────────────────────────
|
||||
|
||||
// CommunityHint is a single high-upvote tactical insight from §13.6 feedback.
|
||||
|
|
|
|||
|
|
@ -124,6 +124,7 @@ func uploadMetaJSONToR2(ctx context.Context, cfg *Config, outputDir string, data
|
|||
}
|
||||
|
||||
static := []string{
|
||||
"data/meta/index.json",
|
||||
"data/meta/archetypes.json",
|
||||
"data/meta/rivalries.json",
|
||||
"data/evolution/community_hints.json",
|
||||
|
|
|
|||
|
|
@ -1546,3 +1546,52 @@ func TestGenerateMapsIndex(t *testing.T) {
|
|||
t.Errorf("Expected 0 cores for map_def456, got %d", len(detail2.Cores))
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateMetaIndex(t *testing.T) {
|
||||
tmpDir := t.TempDir()
|
||||
|
||||
if err := generateMetaIndex(tmpDir); err != nil {
|
||||
t.Fatalf("generateMetaIndex failed: %v", err)
|
||||
}
|
||||
|
||||
content, err := os.ReadFile(filepath.Join(tmpDir, "data", "meta", "index.json"))
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to read meta/index.json: %v", err)
|
||||
}
|
||||
|
||||
var index MetaIndex
|
||||
if err := json.Unmarshal(content, &index); err != nil {
|
||||
t.Fatalf("Failed to parse meta/index.json: %v", err)
|
||||
}
|
||||
|
||||
if len(index.Files) != 2 {
|
||||
t.Errorf("Expected 2 files in meta index, got %d", len(index.Files))
|
||||
}
|
||||
if index.UpdatedAt == "" {
|
||||
t.Error("UpdatedAt should not be empty")
|
||||
}
|
||||
|
||||
// Verify archetypes.json entry
|
||||
foundArchetypes := false
|
||||
foundRivalries := false
|
||||
for _, f := range index.Files {
|
||||
if f.Name == "archetypes.json" {
|
||||
foundArchetypes = true
|
||||
if f.Description == "" {
|
||||
t.Error("archetypes.json should have a description")
|
||||
}
|
||||
}
|
||||
if f.Name == "rivalries.json" {
|
||||
foundRivalries = true
|
||||
if f.Description == "" {
|
||||
t.Error("rivalries.json should have a description")
|
||||
}
|
||||
}
|
||||
}
|
||||
if !foundArchetypes {
|
||||
t.Error("Expected archetypes.json entry in meta index")
|
||||
}
|
||||
if !foundRivalries {
|
||||
t.Error("Expected rivalries.json entry in meta index")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue