headwater-cli 0.2.0

The headwater binary, and what CI runs. headwater --help is the verb list
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
// SPDX-License-Identifier: Apache-2.0
//! What `headwater init` writes, byte for byte.
//!
//! # The defect this target exists for
//!
//! `headwater init` writes two files, and until this target no test of this
//! workspace read one byte of either. One `match` arm of the verb emits two
//! messages under one condition: the comment it writes above `version: 0.0.0`,
//! and the line it prints in its report. #276 found those two drifted apart —
//! the printed one naming two routes and the written one naming a route an
//! adopter cannot take — because the printed one was held and the written one
//! was held by nothing. That arm is still one arm.
//!
//! `.claude/tutorial/drive.py` does hold part of it: three substrings of the
//! declaration, the literal `  version: 0.0.0` line, and the fact that the
//! overlay ends `add: {}`. That guard is real and it sits in the wrong place
//! twice over. It is six claims rather than the file, and its failure message
//! is about a sixteen-step tutorial rather than about `init`. Its own comment
//! named #174 as the missing test's home, and #174 is closed.
//!
//! This target is a characterization of the verb rather than a statement of
//! what the verb should write. It passed on the day it was written, against an
//! unmodified `init`. Its value is that the bytes now have a reader.
//!
//! # Why the two arms are asserted differently
//!
//! The blank-tree arm is asserted as bytes, because every byte of it is a
//! literal in the verb.
//!
//! The package-present arm embeds the version the package declares, so this
//! target reads that version out of the manifest it copied rather than writing
//! it here. A literal would be the defect #427 already caused once: a bump to
//! 4.0.0 moved six mentions in the tutorial, left one behind, and failed every
//! step from 5 to 16 of a tutorial that was right.
//!
//! # What the last line is for
//!
//! `add: {}` is the last line of the overlay, and `.claude/tutorial/drive.py`
//! splices the reader's edit in at exactly that offset. Holding it here makes
//! a break point at `init`, which is where it belongs.
//!
//! # One oddity this target pins rather than repairs
//!
//! The declaration carries one comment at column zero — `# A bundle is an
//! optional part of the package` — where every comment around it carries two
//! spaces. A `\` line continuation in the verb's format string eats the
//! leading whitespace of the line that follows it. YAML reads a comment
//! wherever it sits, so nothing downstream is wrong, and the adopter commits
//! the file all the same. It is pinned here rather than repaired, because this
//! target exists to record what the verb writes today.

use std::path::{Path, PathBuf};
use std::process::Command;

/// The repository this test tree sits in.
fn repository() -> PathBuf {
    Path::new(env!("CARGO_MANIFEST_DIR"))
        .join("../../..")
        .canonicalize()
        .expect("the repository root resolves")
}

/// Everything the declaration carries before the version block.
const DECLARATION_HEAD: &str = r"# The consumer declaration, written by `headwater init`. It says two things,
# and they are different questions: what schema this repository takes, and what
# tree it walks.
#
# `headwater taxonomy resolve` reads this and writes .headwater/taxonomy.lock. Everything after that
# reads the lock and never these sources.

taxonomy:
  package: headwater/standard
";

/// The version block of the arm that found no package, which is an interview
/// stub, nine lines of comment and one commented field.
///
/// This constant is a copy of a string in the verb, and a copy checked against
/// nothing but itself is what #641 cost. The last case in this file runs the
/// route these bytes name, so the bytes have a reader that is not another copy
/// of them.
const NO_PACKAGE_VERSION: &str = r"  # INTERVIEW: no package of this name is under `.headwater/packages/`. Two routes
  # reach a lock, and each one needs a different field below.
  # Copy a package directory into `.headwater/packages/`, and pin `version` at
  # the version that package declares. Or run
  # `headwater taxonomy vendor <dir-or-location>` on a published artifact,
  # unpacked or at the `https://` location of its zip: that verb reads `digest`
  # and refuses until it holds the digest the publisher printed, and
  # `headwater taxonomy resolve` reads `version` after it, so the vendor route
  # needs the digest first and the version as well.
  # digest: sha256:<the digest the publisher printed>
  version: 0.0.0
";

/// Everything the declaration carries after the version block.
///
/// Its first line is the comment at column zero that the module header names.
const DECLARATION_TAIL: &str = r"# A bundle is an optional part of the package, and a selection is add-only.
  # INTERVIEW: which traditions does this corpus already follow?
  bundles: []
  overlay: .headwater/overlay.yml

corpus:
  # Proposed from this tree: the directory holding the most Markdown.
  root: docs
  # An exclusion states a reason. A pattern with none is a silent pass with a
  # configuration file in front of it, so the reason is not optional.
  # exclude:
  #   - path: docs/vendor/**
  #     reason: vendored copies of documents another team owns
";

/// The whole overlay. It is one arm, because `init` writes the same overlay
/// whether a package is on the tree or not.
const OVERLAY: &str = r#"# The adopter overlay, written by `headwater init`. It is an overlay and never a
# resolved taxonomy, so nothing here can weaken the package it sits on: a
# bundle selection is add-only, and an add-only overlay carries no operation
# that removes a base rule.
#
# Every block below is a question this engine cannot answer from a tree. It is
# prose about what this corpus is for, and a corpus does not state it.
#
# INTERVIEW 1 --- what does each purpose answer?
#
# A task is matched against declared purposes before it is matched against any
# text, and it is matched on the `answers` phrases first. Two purposes whose
# phrases share every term separate nothing, and every task then matches both
# equally. Read `headwater/standard`'s purposes, and add the phrases a person here would
# actually type.
#
#   add:
#     purposes.rationale.answers: ["why is it this way", "what was rejected"]
#
# INTERVIEW 2 --- what identifies a document, and what does the prefix mean?
#
# A relation names its target by identifier. A corpus whose documents carry none
# has no edges, and no check about an edge can say anything about it.
#
# `add` states a value the package leaves unstated, and `override` replaces one
# the package already states, so the operation follows the package rather than
# the taste of the writer. `headwater/standard` declares `decision_id` with no namespace
# and gives `decision` that scheme, so the namespace below is an `add` on a leaf
# the package leaves empty, and the kind below is an `override` because `add`
# over a value the package already states is refused. Replace ACME with the
# prefix this corpus uses.
#
#   add:
#     identifier_schemes.doc_id: {pattern: "{namespace}-DOC-{slug}", namespace: ACME, allocation: minted-once}
#     identifier_schemes.decision_id.namespace: ACME
#   override:
#     kinds.decision.identifier: {scheme: doc_id}
#
# INTERVIEW 3 --- what does this corpus already write?
#
# Run `headwater infer` once this file resolves. It reports the files that
# classify as nothing, which is the half a payload cannot carry, and the
# documents that state no summary, which nothing will route to.

add: {}
"#;

/// A scratch repository, and what one run of `init` leaves in it.
struct Root {
    at: PathBuf,
}

impl Root {
    /// A tree holding one Markdown file under `docs/`, which is the least that
    /// reaches the write path: `busiest_directory` proposes a corpus root from
    /// the directory holding the most Markdown, and a tree with none is
    /// refused.
    ///
    /// `label` names the case rather than the process, for the reason
    /// `wiring.rs` records beside its own helper. Cargo runs the cases of one
    /// target as threads of one process, so a directory keyed on the process
    /// alone is a directory one case removes while another is reading it.
    fn over(label: &str) -> Root {
        let at =
            std::env::temp_dir().join(format!("headwater-cli-init-{}-{label}", std::process::id()));
        let _ = std::fs::remove_dir_all(&at);
        std::fs::create_dir_all(at.join("docs")).expect("the corpus directory is there");
        std::fs::write(at.join("docs/one.md"), "# a document\n").expect("the document writes");
        Root { at }
    }

    /// The same tree, plus the manifest of the package this repository
    /// maintains.
    ///
    /// The manifest alone is the whole of the package-present arm, because
    /// `find_version` reads `package.yml` and opens nothing else. Copying the
    /// real one rather than writing a stand-in is what couples this target to
    /// the version the repository actually ships.
    fn with_package(label: &str) -> Root {
        let root = Root::over(label);
        let directory = root.at.join(".headwater/packages/headwater-standard");
        std::fs::create_dir_all(&directory).expect("the package directory is there");
        std::fs::copy(
            repository().join(".headwater/packages/headwater-standard/package.yml"),
            directory.join("package.yml"),
        )
        .expect("the manifest copies");
        root
    }

    /// One run of the verb over this root.
    ///
    /// The exit status is asserted here rather than returned, because every
    /// case below reads a file the verb writes and a refusal writes neither.
    fn init(&self) {
        let output = Command::new(env!("CARGO_BIN_EXE_headwater"))
            .args(["init", "--root"])
            .arg(&self.at)
            .output()
            .expect("the binary runs");
        assert_eq!(
            output.status.code(),
            Some(0),
            "`headwater init` writes both files:\n{}",
            String::from_utf8_lossy(&output.stderr)
        );
    }

    fn read(&self, relative: &str) -> String {
        std::fs::read_to_string(self.at.join(relative)).expect("the written file reads")
    }

    /// The version the copied manifest declares, read rather than written.
    ///
    /// The assertion on the count is the point of the helper. A manifest that
    /// stops declaring a version at the top level, or that declares two, fails
    /// here and names what it found, rather than silently answering with the
    /// wrong line.
    fn declared_version(&self) -> String {
        declared_version_at(
            &self
                .at
                .join(".headwater/packages/headwater-standard/package.yml"),
        )
    }

    /// A scratch directory beside this root, for something that is not part of
    /// the tree `init` reads.
    ///
    /// A published artifact under the root would join the tree that
    /// `busiest_directory` walks, so it goes outside rather than inside.
    fn beside(&self, label: &str) -> PathBuf {
        let at = self.at.with_file_name(format!(
            "{}-{label}",
            self.at
                .file_name()
                .expect("the scratch root is named")
                .to_string_lossy()
        ));
        let _ = std::fs::remove_dir_all(&at);
        std::fs::create_dir_all(&at).expect("the scratch directory is made");
        at
    }

    fn write(&self, relative: &str, body: &str) {
        std::fs::write(self.at.join(relative), body).expect("the file writes");
    }

    /// One run of the built binary over this root, with an optional path
    /// argument, returning the status and standard error.
    ///
    /// The two streams are kept apart, because a verb of this engine writes its
    /// report to one and its account of a refusal to the other.
    fn run(&self, verb: &[&str], argument: Option<&Path>) -> (Option<i32>, String) {
        let mut command = Command::new(env!("CARGO_BIN_EXE_headwater"));
        command.args(verb);
        if let Some(path) = argument {
            command.arg(path);
        }
        let output = command
            .arg("--root")
            .arg(&self.at)
            .output()
            .expect("the binary runs");
        (
            output.status.code(),
            String::from_utf8_lossy(&output.stderr).into_owned(),
        )
    }
}

/// The version a package manifest declares at the top level, read rather than
/// written.
///
/// The assertion on the count is the point of the helper. A manifest that stops
/// declaring a version at the top level, or that declares two, fails here and
/// names what it found, rather than silently answering with the wrong line.
fn declared_version_at(manifest: &Path) -> String {
    let body = std::fs::read_to_string(manifest)
        .unwrap_or_else(|error| panic!("{} reads: {error}", manifest.display()));
    let lines: Vec<&str> = body
        .lines()
        .filter(|line| line.starts_with("version:"))
        .collect();
    assert_eq!(
        lines.len(),
        1,
        "{} declares one version at the top level, and it declares {}",
        manifest.display(),
        lines.len()
    );
    lines[0].trim_start_matches("version:").trim().to_string()
}

/// The version this repository's maintained source of `headwater/standard`
/// declares.
fn maintained_version() -> String {
    declared_version_at(&repository().join("taxonomy-source/headwater-standard/package.yml"))
}

/// `taxonomy publish --from` over this repository's maintained source, giving
/// back the digest the report printed.
///
/// The digest is read out of the report rather than written here, so a change to
/// the package moves this case with it. `publish.rs` holds what the verb writes
/// to disk; this reads the one line the report tells a consumer to pin, and it
/// names `taxonomy-source/headwater-standard/` for the reason that target
/// states: it is the maintained source, and `.headwater/packages/headwater-standard/` is a
/// vendored artifact that `publish` refuses.
fn publish_maintained_source_into(out: &Path) -> String {
    let output = Command::new(env!("CARGO_BIN_EXE_headwater"))
        .arg("taxonomy")
        .arg("publish")
        .arg("--from")
        .arg(repository().join("taxonomy-source/headwater-standard"))
        .arg("--out")
        .arg(out)
        .arg("--root")
        .arg(repository())
        .output()
        .expect("the binary runs");
    assert_eq!(
        output.status.code(),
        Some(0),
        "the artifact publishes:\n{}",
        String::from_utf8_lossy(&output.stderr)
    );
    let report = String::from_utf8_lossy(&output.stdout).into_owned();
    let stated: Vec<&str> = report
        .lines()
        .filter_map(|line| line.trim().strip_prefix("digest "))
        .collect();
    assert_eq!(
        stated.len(),
        1,
        "the publish report states one digest, and it states {}:\n{report}",
        stated.len()
    );
    stated[0].to_string()
}

/// The declaration of a tree with no package under `.headwater/packages/`.
///
/// This is the first-run state that spec 7 calls the surface `init` is for,
/// and it is the state the tutorial runs its step 2 in. Every byte of it is a
/// literal in the verb, so every byte of it is asserted.
#[test]
fn the_declaration_of_a_tree_with_no_package_is_written_byte_for_byte() {
    let root = Root::over("declaration-no-package");
    root.init();
    let expected = format!("{DECLARATION_HEAD}{NO_PACKAGE_VERSION}{DECLARATION_TAIL}");
    assert_eq!(
        root.read(".headwater/taxonomy.yml"),
        expected,
        "the declaration `headwater init` writes on a blank tree"
    );
}

/// The overlay, which is one arm and carries no package-dependent byte.
#[test]
fn the_overlay_is_written_byte_for_byte() {
    let root = Root::over("overlay");
    root.init();
    assert_eq!(
        root.read(".headwater/overlay.yml"),
        OVERLAY,
        "the overlay `headwater init` writes"
    );
}

/// The declaration of a tree that carries the package, which pins the version
/// the package declares.
///
/// The version is read out of the manifest this case copied. A literal here
/// would go stale on the next bump of the package, which is what #427 did to
/// the tutorial: six mentions moved, one stayed, and every step from 5 to 16
/// failed on a document that was right.
#[test]
fn the_declaration_of_a_tree_with_a_package_pins_the_version_that_package_declares() {
    let root = Root::with_package("declaration-with-package");
    let version = root.declared_version();
    root.init();
    let expected = format!("{DECLARATION_HEAD}  version: {version}\n{DECLARATION_TAIL}");
    assert_eq!(
        root.read(".headwater/taxonomy.yml"),
        expected,
        "the declaration `headwater init` writes over a package it found"
    );
    assert!(
        !expected.contains("0.0.0"),
        "a package on the tree replaces the interview stub rather than joining it"
    );
}

/// `add: {}` is the last line of the overlay.
///
/// `.claude/tutorial/drive.py` asserts the same thing and then splices the
/// reader's edit in at that offset, so anything appended after it breaks a
/// driver assertion rather than an output block, and re-recording the block
/// does not repair it. Held here as well, so that a break points at the verb.
#[test]
fn the_last_line_of_the_overlay_is_the_line_the_tutorial_replaces() {
    let root = Root::over("overlay-last-line");
    root.init();
    let overlay = root.read(".headwater/overlay.yml");
    assert!(
        overlay.trim_end_matches('\n').ends_with("add: {}"),
        "the last line of the overlay is `add: {{}}`, and the tutorial replaces it in place:\n{}",
        overlay
            .lines()
            .rev()
            .take(3)
            .collect::<Vec<&str>>()
            .join("\n")
    );
}

/// The route the declaration names, run rather than read.
///
/// # Why this case exists
///
/// Every other case in this target asserts that the declaration *says*
/// something. None of them runs a command it names, so the comment `init`
/// writes was a claim about this engine sitting in a string literal, checked
/// only against a copy of itself in this file. [#641] is what that costs: the
/// comment stated one requirement for two routes that need different fields,
/// an adopter who did exactly what it said met `nothing pins this artifact`,
/// and both copies agreed with each other the whole time.
///
/// `.claude/tutorial/fixtures.sh` does not cover it either. The tutorial takes
/// the copy route, so `taxonomy vendor` is outside the population that suite
/// runs.
///
/// So this case reads the instruction out of the file the verb just wrote,
/// performs it, and runs the command the file names. It publishes a real
/// artifact from this repository's own maintained source rather than a
/// synthetic one, for the reason `publish.rs` states beside the same source:
/// the manifest of a small stand-in does not reach the paths a real one does.
///
/// # What it asserts, and in the order an adopter meets it
///
/// The declaration names a `digest` field. `taxonomy vendor` accepts the
/// artifact once that field carries the digest the publisher printed.
/// `taxonomy resolve` then gets past the version, which is the second field
/// the vendor route needs and the one the comment used to name alone.
///
/// `resolve` still refuses after all of that, and that refusal is by design:
/// it is the interview asking this corpus for an identifier namespace, which
/// no engine can answer off a tree. This case asserts the refusal is no longer
/// the version one.
///
/// [#641]: https://github.com/headwater-ai/headwater/issues/641
#[test]
fn the_vendor_route_the_declaration_names_reaches_a_resolved_version() {
    let root = a_root_the_vendor_route_reached("vendor-route");

    let (_, stderr) = root.run(&["taxonomy", "resolve"], None);
    assert!(
        !stderr.contains("this takes headwater/standard"),
        "`headwater taxonomy resolve` is past the version the vendor route also needs:\n{stderr}"
    );
}

/// A root that `init` wrote and that the vendor route the declaration names has
/// carried as far as a package on disk at the pinned version.
///
/// This is the setup of the two cases below it, extracted rather than typed
/// twice. Every edit in it is read out of a file the verb wrote, so a verb that
/// stops writing one of those lines fails here.
fn a_root_the_vendor_route_reached(label: &str) -> Root {
    let root = Root::over(label);
    let artifact = root.beside("artifact");
    let digest = publish_maintained_source_into(&artifact);
    root.init();

    // The edit the comment instructs, taken from the file rather than written
    // here: the commented `digest` line the declaration carries is the only
    // hint an adopter has that the field exists, so a declaration that stops
    // carrying it fails here rather than one command later in their tree.
    let declaration = root.read(".headwater/taxonomy.yml");
    let commented = declaration
        .lines()
        .find(|line| line.trim_start().starts_with("# digest:"))
        .unwrap_or_else(|| {
            panic!(
                "the declaration names the field `taxonomy vendor` reads, and it names none of \
                 these:\n{declaration}"
            )
        });
    let version = maintained_version();
    let pinned = declaration
        .replace(commented, &format!("  digest: {digest}"))
        .replace("  version: 0.0.0\n", &format!("  version: {version}\n"));
    assert!(
        pinned.contains(&format!("  digest: {digest}\n")),
        "the commented line is replaced by the pin:\n{pinned}"
    );
    root.write(".headwater/taxonomy.yml", &pinned);

    let (code, stderr) = root.run(&["taxonomy", "vendor"], Some(&artifact));
    assert_eq!(
        code,
        Some(0),
        "`headwater taxonomy vendor` accepts the artifact the declaration pins:\n{stderr}"
    );
    assert_eq!(
        declared_version_at(
            &root
                .at
                .join(".headwater/packages/headwater-standard/package.yml")
        ),
        version,
        "the vendored package is the one the declaration pins"
    );
    root
}

/// The example the overlay prints under `INTERVIEW 2`, lifted out of the file
/// `init` wrote and given back with the comment prefix and the common indent
/// removed.
///
/// # Why it is read rather than typed
///
/// The case below runs these lines. A case that retyped them would pass forever
/// whatever the template said, which is the defect `OVERLAY` above has on its
/// own: a string literal held against a copy of itself. Reading them here makes
/// the template the thing under test.
///
/// The example lines are the ones this block indents past its prose: a comment
/// line of the block carries one space after the `#`, and an example line
/// carries three or more. The panic is the second half of the mechanism —
/// a template that stopped printing an example would otherwise hand back an
/// empty patch, and the case would then be asserting something else.
fn the_interview_2_example(overlay: &str) -> String {
    let block: Vec<&str> = overlay
        .lines()
        .skip_while(|line| !line.starts_with("# INTERVIEW 2"))
        .skip(1)
        .take_while(|line| !line.starts_with("# INTERVIEW"))
        .collect();
    let example: Vec<&str> = block
        .iter()
        .filter_map(|line| line.strip_prefix('#'))
        .filter(|rest| rest.starts_with("   "))
        .collect();
    assert!(
        !example.is_empty(),
        "the overlay prints an example under `INTERVIEW 2`, and it prints none of these:\n{overlay}"
    );
    let indent = example
        .iter()
        .map(|line| line.len() - line.trim_start().len())
        .min()
        .expect("the example is not empty");
    example
        .iter()
        .map(|line| format!("{}\n", &line[indent..]))
        .collect()
}

/// The example the overlay hands an adopter resolves.
///
/// # The defect this case exists for
///
/// [#659]. `INTERVIEW 2` asks the corpus what identifies a document, and the
/// example under it was the only answer an adopter reading that file ever saw.
/// It answered nothing twice over: it declared a scheme of its own and never
/// the namespace that `headwater/standard` leaves to the corpus, so `resolve`
/// refused with `carries no namespace after resolution`; and it stated
/// `kinds.<kind>.identifier` under `add` over a kind the package already gives
/// an identifier, which `resolve` refuses on its own terms. Neither refusal
/// moves the other, so the example had to be repaired in both places at once.
///
/// The case that precedes this one is [#641]'s, and it stops one refusal short:
/// it asserts `resolve` is past the version and lets the namespace refusal
/// stand, because that refusal is by design. This case is the continuation. It
/// performs the overlay's own instruction and asserts `resolve` writes a lock.
///
/// # Why it extracts rather than retypes
///
/// See `the_interview_2_example`. Reverting the template to the example this
/// case was written against fails here with the refusal above, which is the
/// discriminator a retyped copy would not have.
///
/// [#641]: https://github.com/headwater-ai/headwater/issues/641
/// [#659]: https://github.com/headwater-ai/headwater/issues/659
#[test]
fn the_overlay_example_the_interview_prints_reaches_a_lock() {
    let root = a_root_the_vendor_route_reached("interview-example");

    let overlay = root.read(".headwater/overlay.yml");
    assert!(
        overlay.trim_end_matches('\n').ends_with("add: {}"),
        "the overlay ends with the line the example replaces:\n{overlay}"
    );
    let patched = format!(
        "{}{}",
        overlay.trim_end_matches('\n').trim_end_matches("add: {}"),
        the_interview_2_example(&overlay)
    );
    root.write(".headwater/overlay.yml", &patched);

    let (code, stderr) = root.run(&["taxonomy", "resolve"], None);
    assert_eq!(
        code,
        Some(0),
        "the example `INTERVIEW 2` prints resolves:\n{stderr}\nthe overlay it was run \
         against:\n{patched}"
    );
}

/// The argument `taxonomy vendor` takes, as the interface contract states it.
///
/// `docs/interfaces/headwater-taxonomy.md` is the contract for the verb, so the
/// placeholder `init` prints is held to that row rather than to a copy of it in
/// this file. A contract that renames the argument moves this case with it.
fn the_vendor_argument_the_contract_states() -> String {
    let contract =
        std::fs::read_to_string(repository().join("docs/interfaces/headwater-taxonomy.md"))
            .expect("the interface contract reads");
    let rows: Vec<String> = contract
        .lines()
        .filter_map(|line| line.strip_prefix("| `vendor <"))
        .filter_map(|rest| {
            rest.split_once('>')
                .map(|(argument, _)| argument.to_string())
        })
        .collect();
    assert_eq!(
        rows.len(),
        1,
        "the contract states one `vendor` row, and it states {}",
        rows.len()
    );
    rows[0].clone()
}

/// Every argument placeholder that follows `headwater taxonomy vendor` in `text`.
fn vendor_placeholders(text: &str) -> Vec<String> {
    let squeezed = text
        .lines()
        .map(|line| line.trim_start().trim_start_matches('#').trim())
        .collect::<Vec<_>>()
        .join(" ");
    squeezed
        .match_indices("headwater taxonomy vendor <")
        .filter_map(|(at, marker)| {
            squeezed[at + marker.len()..]
                .split_once('>')
                .map(|(argument, _)| argument.to_string())
        })
        .collect()
}

/// Pack a published artifact directory into the zip `release-taxonomy.yml`
/// uploads: every member at the root of the archive, deflated.
///
/// A copy of the helper of the same name in `publish.rs`. Two targets of one
/// crate share no module unless one is written for them, and `tests/common`
/// carries nothing about a published artifact.
#[cfg(feature = "fetch")]
fn zipped(artifact: &Path) -> Vec<u8> {
    use std::io::Write;
    let mut members = Vec::new();
    let mut pending = vec![artifact.to_path_buf()];
    while let Some(dir) = pending.pop() {
        for entry in std::fs::read_dir(&dir).expect("the artifact directory reads") {
            let path = entry.expect("the entry reads").path();
            if path.is_dir() {
                pending.push(path);
            } else {
                members.push(path);
            }
        }
    }
    members.sort();
    let mut writer = zip::ZipWriter::new(std::io::Cursor::new(Vec::new()));
    let options = zip::write::SimpleFileOptions::default()
        .compression_method(zip::CompressionMethod::Deflated);
    for path in members {
        let name = path
            .strip_prefix(artifact)
            .expect("under the artifact")
            .to_str()
            .expect("the path is UTF-8")
            .replace('\\', "/");
        writer.start_file(name, options).expect("the member starts");
        writer
            .write_all(&std::fs::read(&path).expect("the member reads"))
            .expect("the member writes");
    }
    writer.finish().expect("the archive closes").into_inner()
}

/// Serve `body` at `/<name>` on 127.0.0.1 for as long as the test process
/// lives, and give back the location. `headwater-fetch` takes plain `http`
/// to a loopback host alone, so the suite reaches no other host.
#[cfg(feature = "fetch")]
fn serve(name: &str, body: Vec<u8>) -> String {
    use std::io::{Read, Write};
    let listener = std::net::TcpListener::bind("127.0.0.1:0").expect("a loopback port binds");
    let location = format!(
        "http://{}/{name}",
        listener.local_addr().expect("the port reads")
    );
    let wanted = format!("/{name}");
    std::thread::spawn(move || {
        for stream in listener.incoming() {
            let Ok(mut stream) = stream else { continue };
            let mut request = [0_u8; 4096];
            let read = stream.read(&mut request).unwrap_or(0);
            let line = String::from_utf8_lossy(&request[..read]).to_string();
            let found = line.split_whitespace().nth(1) == Some(wanted.as_str());
            let (head, payload): (String, &[u8]) = if found {
                (
                    format!(
                        "HTTP/1.1 200 OK\r\nContent-Length: {}\r\nConnection: close\r\n\r\n",
                        body.len()
                    ),
                    &body,
                )
            } else {
                (
                    "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\nConnection: close\r\n\r\n"
                        .to_string(),
                    &[],
                )
            };
            let _ = stream.write_all(head.as_bytes());
            let _ = stream.write_all(payload);
        }
    });
    location
}

/// The vendor route `init` names takes the location a release publishes.
///
/// # Why this case exists
///
/// `HW-OBL-0085` recorded that this engine fetched no package, and `init`
/// said so in both messages of its no-package arm. [#959] gave
/// `taxonomy vendor` a location, so that sentence became false and the remedy
/// named `<dir>` alone. An adopter with no copy of the artifact on disk read
/// that they had to fetch and unpack it by other means. This is the #271 and
/// [#641] failure again: the first verb an adopter runs states a remedy that
/// does not match the binary in front of them.
///
/// # What it asserts
///
/// Both messages name the argument the interface contract states for the
/// verb. The case then takes that route as a reader would. It pins the digest
/// in the field the declaration names, and it vendors from a zip served on
/// 127.0.0.1 in the place of the placeholder. `taxonomy resolve` then gets
/// past the version, as the case above asserts for the directory form.
///
/// [#641]: https://github.com/headwater-ai/headwater/issues/641
/// [#959]: https://github.com/headwater-ai/headwater/issues/959
#[cfg(feature = "fetch")]
#[test]
fn the_vendor_route_init_names_takes_the_location_a_release_publishes() {
    let root = Root::over("vendor-location");
    let artifact = root.beside("artifact");
    let digest = publish_maintained_source_into(&artifact);

    let output = Command::new(env!("CARGO_BIN_EXE_headwater"))
        .args(["init", "--root"])
        .arg(&root.at)
        .output()
        .expect("the binary runs");
    assert_eq!(
        output.status.code(),
        Some(0),
        "`headwater init` writes both files"
    );
    let report = String::from_utf8_lossy(&output.stdout).into_owned();
    let declaration = root.read(".headwater/taxonomy.yml");

    let argument = the_vendor_argument_the_contract_states();
    for (name, text) in [
        ("the printed report", &report),
        ("the declaration", &declaration),
    ] {
        assert_eq!(
            vendor_placeholders(text),
            vec![argument.clone()],
            "{name} names `headwater taxonomy vendor <{argument}>`, the argument the contract \
             states:\n{text}"
        );
        assert!(
            !text.contains("fetches one"),
            "{name} no longer says that nothing fetches a package:\n{text}"
        );
    }

    let version = maintained_version();
    let commented = declaration
        .lines()
        .find(|line| line.trim_start().starts_with("# digest:"))
        .expect("the declaration names the field `taxonomy vendor` reads");
    let pinned = declaration
        .replace(commented, &format!("  digest: {digest}"))
        .replace("  version: 0.0.0\n", &format!("  version: {version}\n"));
    root.write(".headwater/taxonomy.yml", &pinned);

    let location = serve(
        &format!("headwater-standard-{version}.zip"),
        zipped(&artifact),
    );
    let (code, stderr) = root.run(&["taxonomy", "vendor", location.as_str()], None);
    assert_eq!(
        code,
        Some(0),
        "`headwater taxonomy vendor <{argument}>` accepts the location a release \
         publishes:\n{stderr}"
    );
    assert_eq!(
        declared_version_at(
            &root
                .at
                .join(".headwater/packages/headwater-standard/package.yml")
        ),
        version,
        "the fetched package is the one the declaration pins"
    );

    let (_, stderr) = root.run(&["taxonomy", "resolve"], None);
    assert!(
        !stderr.contains("this takes headwater/standard"),
        "`headwater taxonomy resolve` is past the version after a fetch:\n{stderr}"
    );
}