#Centipede Move `distilled-features-*` files to target/hash-specific features subdir

The features files are meaningful only in the context of the specific version of the specific target, for which they were generated.

This is a minimal change:

PiperOrigin-RevId: 568699274
diff --git a/centipede/README.md b/centipede/README.md
index 82fadd0..52f8951 100644
--- a/centipede/README.md
+++ b/centipede/README.md
@@ -329,7 +329,7 @@
 
 ```shell
 $BIN_DIR/centipede --binary=$FUZZ_TARGET --workdir=$WD \
-  --binary_hash=a5e87c9b6057e5ffd3b32a5b9a9ef3978527e9cd  --distill \
+  --binary_hash=a5e87c9b6057e5ffd3b32a5b9a9ef3978527e9cd --distill \
   --total_shards=5 --num_threads=3
 ```
 
@@ -337,7 +337,8 @@
 so we also pass `--binary_hash=<HASH>`.
 
 The result of this command is that `$WD` will now contain 3 distilled versions
-of the corpus:
+of the corpus, while the features subdirectory, `$WD/<fuzz target name>-<fuzz
+target hash>`, will contain 3 distilled versions of the features:
 
 ```shell
 tree $WD
@@ -345,9 +346,14 @@
 
 ```
 ...
-├── distilled-features-byte_cmp_4.000000
-├── distilled-features-byte_cmp_4.000001
-├── distilled-features-byte_cmp_4.000002
+├── <fuzz target name>-d9d90139ee2ccc687f7c9d5821bcc04b8a847df5
+│   ├── distilled-features-byte_cmp_4.000000
+│   ├── distilled-features-byte_cmp_4.000001
+│   ├── distilled-features-byte_cmp_4.000002
+│   ├── features.000000
+│   ...
+├── corpus.000000
+│   ...
 ├── distilled-byte_cmp_4.000000
 ├── distilled-byte_cmp_4.000001
 ├── distilled-byte_cmp_4.000002
diff --git a/centipede/environment.cc b/centipede/environment.cc
index ed780c6..7cbaf7e 100644
--- a/centipede/environment.cc
+++ b/centipede/environment.cc
@@ -570,9 +570,9 @@
 }
 
 std::string Environment::MakeDistilledFeaturesPath() const {
-  return std::filesystem::path(workdir).append(
-      absl::StrFormat("distilled-features-%s.%0*d", binary_name,
-                      kDigitsInShardIndex, my_shard_index));
+  return std::filesystem::path(MakeCoverageDirPath())
+      .append(absl::StrFormat("distilled-features-%s.%0*d", binary_name,
+                              kDigitsInShardIndex, my_shard_index));
 }
 
 std::string Environment::MakeCoverageReportPath(
diff --git a/centipede/environment.h b/centipede/environment.h
index 7698c18..52a4407 100644
--- a/centipede/environment.h
+++ b/centipede/environment.h
@@ -120,8 +120,8 @@
 
   std::string exec_name;          // copied from argv[0]
   std::vector<std::string> args;  // copied from argv[1:].
-  const std::string binary_name;  // Name of `coverage_binary`, w/o directories.
-  const std::string binary_hash;  // Hash of the `coverage_binary` file.
+  std::string binary_name;        // Name of `coverage_binary`, w/o directories.
+  std::string binary_hash;        // Hash of the `coverage_binary` file.
   bool has_input_wildcards = false;  // Set to true iff `binary` contains "@@".
 
   // Experiment-related settings -----------------------------------------------
diff --git a/centipede/environment_test.cc b/centipede/environment_test.cc
index d6f384f..af0417e 100644
--- a/centipede/environment_test.cc
+++ b/centipede/environment_test.cc
@@ -14,6 +14,9 @@
 
 #include "./centipede/environment.h"
 
+#include <cstddef>
+#include <string_view>
+
 #include "gtest/gtest.h"
 
 namespace centipede {
@@ -52,8 +55,11 @@
 TEST(Environment, MakeDistilledCorpusAndFeaturesPaths) {
   Environment env;
   env.my_shard_index = 3;
-  EXPECT_EQ(env.MakeDistilledCorpusPath(), "distilled-.000003");
-  EXPECT_EQ(env.MakeDistilledFeaturesPath(), "distilled-features-.000003");
+  env.binary_name = "foo";
+  env.binary_hash = "foo_hash";
+  EXPECT_EQ(env.MakeDistilledCorpusPath(), "distilled-foo.000003");
+  EXPECT_EQ(env.MakeDistilledFeaturesPath(),
+            "foo-foo_hash/distilled-features-foo.000003");
 }
 
 TEST(Environment, MakeCoverageReportPath) {