Files
mathiasandClaude Sonnet 5.5 006a891423
CI / Lint / Test / Vet (pull_request) Failing after 1m2s
CI / Mirror to GitHub (pull_request) Skipped
fix(watcher): never overwrite a parked note; a proposal cannot be forged or pre-empted; CRLF notes; wing dirs must be plain (#205)
From the independent review of #207:
- parked notes are created O_EXCL with -2,-3 suffixes (same-named notes from
  different subfolders were overwritten and their originals deleted)
- proposed_wing is emitted only if a plain wing name; a note's own proposal_*
  keys are dropped so they cannot outrank the resolver's (first-wins reads)
- CRLF notes: wing: key honoured, one valid frontmatter block on parking
- KnownWings skips wiki dirs that are not canonical lower-case names
- adds the wingmigrate dry-run/apply command
Each fix has a test that failed first and a mutant that fails it.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-20 06:16:48 +02:00

47 lines
1.3 KiB
Go

package wing
import (
"fmt"
"os"
"path/filepath"
"sort"
"github.com/mathiasbq/hyperguild/ingestion/internal/brain"
)
// legacyDirs are the retired wiki/{concepts,entities,sources}/ layout, not wings.
var legacyDirs = map[string]bool{"concepts": true, "entities": true, "sources": true}
// KnownWings lists wiki/<wing>/ directories that contain at least one hall
// subdirectory, sorted. The retired layout is not a wing. A missing wiki/ is
// an error: an unreadable brain must not look like "no wings".
func KnownWings(brainDir string) ([]string, error) {
entries, err := os.ReadDir(filepath.Join(brainDir, "wiki"))
if err != nil {
return nil, fmt.Errorf("list wings: %w", err)
}
var out []string
for _, e := range entries {
if !e.IsDir() || legacyDirs[e.Name()] || !plainWingName(e.Name()) {
continue
}
subs, err := os.ReadDir(filepath.Join(brainDir, "wiki", e.Name()))
if err != nil {
continue
}
for _, s := range subs {
if s.IsDir() {
out = append(out, e.Name())
break
}
}
}
sort.Strings(out)
return out, nil
}
// plainWingName reports whether name is already in the canonical lower-case form
// the pipeline writes. Anything else would make the pipeline create a different
// wing than the one matched.
func plainWingName(name string) bool { return brain.Sanitise(name) == name }