@@ -48,6 +48,12 @@ func parseChipArg(arg string) (string, string) {
4848
4949// Add installs a chip from the registry (not tracked by git).
5050func (inst * Installer ) Add (arg string ) error {
51+ // Async Matrix Fetch (Gap 4.1)
52+ matrixChan := make (chan * registry.Matrix , 1 )
53+ go func () {
54+ m , _ := inst .cache .FetchLiveMatrix ()
55+ matrixChan <- m
56+ }()
5157 name , version := parseChipArg (arg )
5258 if inst .lock .HasChip (name ) {
5359 e := inst .lock .GetChip (name )
@@ -115,16 +121,26 @@ func (inst *Installer) Add(arg string) error {
115121 }
116122 fmt .Printf ("Added chip '%s' (v%s) to lockfile [arch=%s, vendor=%s].\n " , name , ci .Version , ci .Arch , ci .Vendor )
117123
118- if ! ci .Verified {
119- fmt .Println ("\n \033 [33mWarning: This hardware configuration is marked as UNVERIFIED by the CI Compatibility Matrix. Build stability is not guaranteed.\033 [0m" )
124+ // Wait up to 1 second for the matrix to avoid blocking
125+ var matrix * registry.Matrix
126+ select {
127+ case matrix = <- matrixChan :
128+ case <- time .After (1 * time .Second ):
120129 }
130+ printMatrixCompatibility (matrix , ci .Name , ci .Version , ci .Verified )
121131
122132 fmt .Println ("Registry link established. Run `toob build` to compile." )
123133 return nil
124134}
125135
126136// Spawn installs a chip as locally editable (tracked by git).
127137func (inst * Installer ) Spawn (arg string ) error {
138+ // Async Matrix Fetch (Gap 4.1)
139+ matrixChan := make (chan * registry.Matrix , 1 )
140+ go func () {
141+ m , _ := inst .cache .FetchLiveMatrix ()
142+ matrixChan <- m
143+ }()
128144 name , version := parseChipArg (arg )
129145 if inst .lock .HasChip (name ) {
130146 e := inst .lock .GetChip (name )
@@ -229,9 +245,13 @@ func (inst *Installer) Spawn(arg string) error {
229245 }
230246 fmt .Printf ("Spawned chip '%s' (v%s) [locally editable]\n " , name , ci .Version )
231247
232- if ! ci .Verified {
233- fmt .Println ("\n \033 [33mWarning: This hardware configuration is marked as UNVERIFIED by the CI Compatibility Matrix. Build stability is not guaranteed.\033 [0m" )
248+ // Wait up to 1 second for the matrix to avoid blocking
249+ var matrix * registry.Matrix
250+ select {
251+ case matrix = <- matrixChan :
252+ case <- time .After (1 * time .Second ):
234253 }
254+ printMatrixCompatibility (matrix , ci .Name , ci .Version , ci .Verified )
235255
236256 return nil
237257}
@@ -246,6 +266,36 @@ func moveToTrash(dir string) {
246266 os .Rename (dir , trashDir )
247267}
248268
269+ func printMatrixCompatibility (matrix * registry.Matrix , chipName , chipVersion string , verified bool ) {
270+ if ! verified {
271+ fmt .Println ("\n \033 [33mWarning: This hardware configuration is marked as UNVERIFIED by the CI Compatibility Matrix. Build stability is not guaranteed.\033 [0m" )
272+ return
273+ }
274+
275+ if matrix == nil {
276+ return
277+ }
278+
279+ if chipEntry , has := (* matrix )[chipName ]; has {
280+ // Normalize version string to handle mismatching prefixes (Gap 4.2)
281+ searchVer := strings .TrimPrefix (chipVersion , "v" )
282+ for vKey , verEntry := range chipEntry .Versions {
283+ if strings .TrimPrefix (vKey , "v" ) == searchVer {
284+ var verifiedClis []string
285+ for cliVer , info := range verEntry .VerifiedCliVersions {
286+ if info .Status == "SUCCESS" {
287+ verifiedClis = append (verifiedClis , cliVer )
288+ }
289+ }
290+ if len (verifiedClis ) > 0 {
291+ fmt .Printf ("\n \033 [32m[toob] Chip %s v%s — Verified with CLI: %s\033 [0m\n " , chipName , chipVersion , strings .Join (verifiedClis , ", " ))
292+ }
293+ break
294+ }
295+ }
296+ }
297+ }
298+
249299// Remove uninstalls a chip and cleans up unshared dependencies.
250300func (inst * Installer ) Remove (name string ) error {
251301 entry := inst .lock .GetChip (name )
@@ -349,6 +399,7 @@ func (inst *Installer) installDeps(ci *registry.ChipInfo) ([]string, error) {
349399}
350400
351401// copyTree recursively copies src to dst.
402+ // Uses hard-links where possible for instant, zero-disk-cost copies.
352403func copyTree (src , dst string ) error {
353404 info , err := os .Stat (src )
354405 if err != nil {
@@ -373,12 +424,25 @@ func copyTree(src, dst string) error {
373424 if d .IsDir () {
374425 return os .MkdirAll (target , 0o755 )
375426 }
376- data , err := os .ReadFile (path )
377- if err != nil {
378- return err
379- }
380- return os .WriteFile (target , data , 0o644 )
427+ return linkOrCopy (path , target )
381428 })
382429}
383430
431+ // linkOrCopy attempts a hard-link first, falling back to a full byte-copy.
432+ // Hard-links share the inode and are instant with zero additional disk cost.
433+ // Fallback handles cross-device mounts, FAT32, and Windows restrictions.
434+ func linkOrCopy (src , dst string ) error {
435+ if err := os .MkdirAll (filepath .Dir (dst ), 0o755 ); err != nil {
436+ return err
437+ }
438+ if err := os .Link (src , dst ); err == nil {
439+ return nil
440+ }
441+ data , err := os .ReadFile (src )
442+ if err != nil {
443+ return err
444+ }
445+ return os .WriteFile (dst , data , 0o644 )
446+ }
447+
384448
0 commit comments