[INFO] fetching crate tacks 0.2.4...
[INFO] testing tacks-0.2.4 against master#ec6f9a5b4413f74386267ef8efc93712c2ce6db6 for pr-155739-1
[INFO] extracting crate tacks 0.2.4 into /workspace/builds/worker-4-tc1/source
[INFO] started tweaking crates.io crate tacks 0.2.4
[INFO] removed 0 missing tests
[INFO] finished tweaking crates.io crate tacks 0.2.4
[INFO] tweaked toml for crates.io crate tacks 0.2.4 written to /workspace/builds/worker-4-tc1/source/Cargo.toml
[INFO] validating manifest of crates.io crate tacks 0.2.4 on toolchain ec6f9a5b4413f74386267ef8efc93712c2ce6db6
[INFO] running `Command { std: CARGO_HOME="/workspace/cargo-home" RUSTUP_HOME="/workspace/rustup-home" "/workspace/cargo-home/bin/cargo" "+ec6f9a5b4413f74386267ef8efc93712c2ce6db6" "metadata" "--manifest-path" "Cargo.toml" "--no-deps", kill_on_drop: false }`
[INFO] crate crates.io crate tacks 0.2.4 already has a lockfile, it will not be regenerated
[INFO] running `Command { std: CARGO_HOME="/workspace/cargo-home" RUSTUP_HOME="/workspace/rustup-home" "/workspace/cargo-home/bin/cargo" "+ec6f9a5b4413f74386267ef8efc93712c2ce6db6" "fetch" "--manifest-path" "Cargo.toml", kill_on_drop: false }`
[INFO] [stderr]     Updating crates.io index
[INFO] [stderr]  Downloading crates ...
[INFO] [stderr]   Downloaded wasm-bindgen-shared v0.2.113
[INFO] [stderr]   Downloaded wasm-bindgen v0.2.113
[INFO] [stderr]   Downloaded wasm-bindgen-macro-support v0.2.113
[INFO] [stderr]   Downloaded wasm-bindgen-macro v0.2.113
[INFO] [stderr]   Downloaded tabled_derive v0.9.0
[INFO] [stderr]   Downloaded wasm-bindgen-futures v0.4.63
[INFO] [stderr]   Downloaded js-sys v0.3.90
[INFO] [stderr]   Downloaded papergrid v0.13.0
[INFO] [stderr]   Downloaded pulldown-cmark-escape v0.11.0
[INFO] [stderr]   Downloaded smart-default v0.7.1
[INFO] [stderr]   Downloaded lazy-regex v3.6.0
[INFO] [stderr]   Downloaded sealed v0.5.0
[INFO] [stderr]   Downloaded lazy-regex-proc_macros v3.6.0
[INFO] [stderr]   Downloaded typed-builder-macro v0.15.2
[INFO] [stderr]   Downloaded smawk v0.3.2
[INFO] [stderr]   Downloaded drain_filter_polyfill v0.1.3
[INFO] [stderr]   Downloaded peg-runtime v0.6.3
[INFO] [stderr]   Downloaded synthez v0.3.1
[INFO] [stderr]   Downloaded synthez-codegen v0.3.1
[INFO] [stderr]   Downloaded gherkin v0.14.0
[INFO] [stderr]   Downloaded typed-builder v0.15.2
[INFO] [stderr]   Downloaded peg v0.6.3
[INFO] [stderr]   Downloaded peg-macros v0.6.3
[INFO] [stderr]   Downloaded cucumber-codegen v0.21.1
[INFO] [stderr]   Downloaded synthez-core v0.3.1
[INFO] [stderr]   Downloaded cucumber-expressions v0.3.0
[INFO] [stderr]   Downloaded axum-htmx v0.6.0
[INFO] [stderr]   Downloaded axum-core v0.4.5
[INFO] [stderr]   Downloaded rusqlite v0.33.0
[INFO] [stderr]   Downloaded askama v0.13.1
[INFO] [stderr]   Downloaded askama_parser v0.13.0
[INFO] [stderr]   Downloaded askama_derive v0.13.1
[INFO] [stderr]   Downloaded pulldown-cmark v0.13.1
[INFO] [stderr]   Downloaded tabled v0.17.0
[INFO] [stderr]   Downloaded cucumber v0.21.1
[INFO] [stderr]   Downloaded web-sys v0.3.90
[INFO] [stderr]   Downloaded libsqlite3-sys v0.31.0
[INFO] running `Command { std: "docker" "create" "-v" "/var/lib/crater-agent-workspace/builds/worker-4-tc1/target:/opt/rustwide/target:rw,Z" "-v" "/var/lib/crater-agent-workspace/builds/worker-4-tc1/source:/opt/rustwide/workdir:ro,Z" "-v" "/var/lib/crater-agent-workspace/cargo-home:/opt/rustwide/cargo-home:ro,Z" "-v" "/var/lib/crater-agent-workspace/rustup-home:/opt/rustwide/rustup-home:ro,Z" "-e" "SOURCE_DIR=/opt/rustwide/workdir" "-e" "CARGO_TARGET_DIR=/opt/rustwide/target" "-e" "CARGO_HOME=/opt/rustwide/cargo-home" "-e" "RUSTUP_HOME=/opt/rustwide/rustup-home" "-w" "/opt/rustwide/workdir" "-m" "1610612736" "--user" "0:0" "--network" "none" "ghcr.io/rust-lang/crates-build-env/linux@sha256:d429b63d4308055ea97f60fb1d3dfca48854a00942f1bd2ad806beaf015945ec" "/opt/rustwide/cargo-home/bin/cargo" "+ec6f9a5b4413f74386267ef8efc93712c2ce6db6" "metadata" "--no-deps" "--format-version=1", kill_on_drop: false }`
[INFO] [stdout] 612b02c22fbf7d01074b2955f71343d328f5182278ec73a58fd8b56a5db5ede9
[INFO] running `Command { std: "docker" "start" "-a" "612b02c22fbf7d01074b2955f71343d328f5182278ec73a58fd8b56a5db5ede9", kill_on_drop: false }`
[INFO] running `Command { std: "docker" "inspect" "612b02c22fbf7d01074b2955f71343d328f5182278ec73a58fd8b56a5db5ede9", kill_on_drop: false }`
[INFO] running `Command { std: "docker" "rm" "-f" "612b02c22fbf7d01074b2955f71343d328f5182278ec73a58fd8b56a5db5ede9", kill_on_drop: false }`
[INFO] [stdout] 612b02c22fbf7d01074b2955f71343d328f5182278ec73a58fd8b56a5db5ede9
[INFO] running `Command { std: "docker" "create" "-v" "/var/lib/crater-agent-workspace/builds/worker-4-tc1/target:/opt/rustwide/target:rw,Z" "-v" "/var/lib/crater-agent-workspace/builds/worker-4-tc1/source:/opt/rustwide/workdir:ro,Z" "-v" "/var/lib/crater-agent-workspace/cargo-home:/opt/rustwide/cargo-home:ro,Z" "-v" "/var/lib/crater-agent-workspace/rustup-home:/opt/rustwide/rustup-home:ro,Z" "-e" "SOURCE_DIR=/opt/rustwide/workdir" "-e" "CARGO_TARGET_DIR=/opt/rustwide/target" "-e" "CARGO_INCREMENTAL=0" "-e" "RUST_BACKTRACE=full" "-e" "RUSTFLAGS=--cap-lints=forbid" "-e" "RUSTDOCFLAGS=--cap-lints=forbid" "-e" "CARGO_HOME=/opt/rustwide/cargo-home" "-e" "RUSTUP_HOME=/opt/rustwide/rustup-home" "-w" "/opt/rustwide/workdir" "-m" "1610612736" "--user" "0:0" "--network" "none" "ghcr.io/rust-lang/crates-build-env/linux@sha256:d429b63d4308055ea97f60fb1d3dfca48854a00942f1bd2ad806beaf015945ec" "/opt/rustwide/cargo-home/bin/cargo" "+ec6f9a5b4413f74386267ef8efc93712c2ce6db6" "build" "--frozen" "--message-format=json", kill_on_drop: false }`
[INFO] [stdout] d4703e362fe48cdb8dfc3a21d19bdeb539fc62de6fc153c13472db79e0a2d6bd
[INFO] running `Command { std: "docker" "start" "-a" "d4703e362fe48cdb8dfc3a21d19bdeb539fc62de6fc153c13472db79e0a2d6bd", kill_on_drop: false }`
[INFO] [stderr]    Compiling quote v1.0.44
[INFO] [stderr]    Compiling itoa v1.0.17
[INFO] [stderr]    Compiling libc v0.2.182
[INFO] [stderr]    Compiling serde_core v1.0.228
[INFO] [stderr]    Compiling tower-layer v0.3.3
[INFO] [stderr]    Compiling futures-task v0.3.32
[INFO] [stderr]    Compiling serde v1.0.228
[INFO] [stderr]    Compiling slab v0.4.12
[INFO] [stderr]    Compiling sync_wrapper v1.0.2
[INFO] [stderr]    Compiling cc v1.2.56
[INFO] [stderr]    Compiling tracing-core v0.1.36
[INFO] [stderr]    Compiling syn v1.0.109
[INFO] [stderr]    Compiling sha2 v0.10.9
[INFO] [stderr]    Compiling futures-channel v0.3.32
[INFO] [stderr]    Compiling winnow v0.7.14
[INFO] [stderr]    Compiling serde_json v1.0.149
[INFO] [stderr]    Compiling http v1.4.0
[INFO] [stderr]    Compiling getrandom v0.4.1
[INFO] [stderr]    Compiling pulldown-cmark v0.13.1
[INFO] [stderr]    Compiling rustc-hash v2.1.1
[INFO] [stderr]    Compiling bytecount v0.6.9
[INFO] [stderr]    Compiling clap_lex v1.0.0
[INFO] [stderr]    Compiling futures-util v0.3.32
[INFO] [stderr]    Compiling papergrid v0.13.0
[INFO] [stderr]    Compiling getopts v0.2.24
[INFO] [stderr]    Compiling matchit v0.8.4
[INFO] [stderr]    Compiling rust-embed-utils v8.11.0
[INFO] [stderr]    Compiling clap_builder v4.5.60
[INFO] [stderr]    Compiling syn v2.0.117
[INFO] [stderr]    Compiling proc-macro-error-attr2 v2.0.0
[INFO] [stderr]    Compiling unicase v2.9.0
[INFO] [stderr]    Compiling tracing v0.1.44
[INFO] [stderr]    Compiling basic-toml v0.1.10
[INFO] [stderr]    Compiling pulldown-cmark-escape v0.11.0
[INFO] [stderr]    Compiling colored v3.1.1
[INFO] [stderr]    Compiling errno v0.3.14
[INFO] [stderr]    Compiling socket2 v0.6.2
[INFO] [stderr]    Compiling mio v1.1.1
[INFO] [stderr]    Compiling uuid v1.21.0
[INFO] [stderr]    Compiling libsqlite3-sys v0.31.0
[INFO] [stderr]    Compiling http-body v1.0.1
[INFO] [stderr]    Compiling tower-http v0.6.8
[INFO] [stderr]    Compiling http-body-util v0.1.3
[INFO] [stderr]    Compiling signal-hook-registry v1.4.8
[INFO] [stderr]    Compiling axum-core v0.5.6
[INFO] [stderr]    Compiling serde_path_to_error v0.1.20
[INFO] [stderr]    Compiling proc-macro-error2 v2.0.1
[INFO] [stderr]    Compiling serde_derive v1.0.228
[INFO] [stderr]    Compiling tokio-macros v2.6.0
[INFO] [stderr]    Compiling async-trait v0.1.89
[INFO] [stderr]    Compiling clap_derive v4.5.55
[INFO] [stderr]    Compiling rust-embed-impl v8.11.0
[INFO] [stderr]    Compiling tabled_derive v0.9.0
[INFO] [stderr]    Compiling tokio v1.49.0
[INFO] [stderr]    Compiling axum-core v0.4.5
[INFO] [stderr]    Compiling tabled v0.17.0
[INFO] [stderr]    Compiling rust-embed v8.11.0
[INFO] [stderr]    Compiling clap v4.5.60
[INFO] [stderr]    Compiling askama_parser v0.13.0
[INFO] [stderr]    Compiling serde_urlencoded v0.7.1
[INFO] [stderr]    Compiling chrono v0.4.44
[INFO] [stderr]    Compiling axum-htmx v0.6.0
[INFO] [stderr]    Compiling hyper v1.8.1
[INFO] [stderr]    Compiling tower v0.5.3
[INFO] [stderr]    Compiling hyper-util v0.1.20
[INFO] [stderr]    Compiling axum v0.8.8
[INFO] [stderr]    Compiling askama_derive v0.13.1
[INFO] [stderr]    Compiling askama v0.13.1
[INFO] [stderr]    Compiling rusqlite v0.33.0
[INFO] [stderr]    Compiling tacks v0.2.4 (/opt/rustwide/workdir)
[INFO] [stderr]     Finished `dev` profile [unoptimized + debuginfo] target(s) in 47.81s
[INFO] running `Command { std: "docker" "inspect" "d4703e362fe48cdb8dfc3a21d19bdeb539fc62de6fc153c13472db79e0a2d6bd", kill_on_drop: false }`
[INFO] running `Command { std: "docker" "rm" "-f" "d4703e362fe48cdb8dfc3a21d19bdeb539fc62de6fc153c13472db79e0a2d6bd", kill_on_drop: false }`
[INFO] [stdout] d4703e362fe48cdb8dfc3a21d19bdeb539fc62de6fc153c13472db79e0a2d6bd
[INFO] running `Command { std: "docker" "create" "-v" "/var/lib/crater-agent-workspace/builds/worker-4-tc1/target:/opt/rustwide/target:rw,Z" "-v" "/var/lib/crater-agent-workspace/builds/worker-4-tc1/source:/opt/rustwide/workdir:ro,Z" "-v" "/var/lib/crater-agent-workspace/cargo-home:/opt/rustwide/cargo-home:ro,Z" "-v" "/var/lib/crater-agent-workspace/rustup-home:/opt/rustwide/rustup-home:ro,Z" "-e" "SOURCE_DIR=/opt/rustwide/workdir" "-e" "CARGO_TARGET_DIR=/opt/rustwide/target" "-e" "CARGO_INCREMENTAL=0" "-e" "RUST_BACKTRACE=full" "-e" "RUSTFLAGS=--cap-lints=forbid" "-e" "RUSTDOCFLAGS=--cap-lints=forbid" "-e" "CARGO_HOME=/opt/rustwide/cargo-home" "-e" "RUSTUP_HOME=/opt/rustwide/rustup-home" "-w" "/opt/rustwide/workdir" "-m" "1610612736" "--user" "0:0" "--network" "none" "ghcr.io/rust-lang/crates-build-env/linux@sha256:d429b63d4308055ea97f60fb1d3dfca48854a00942f1bd2ad806beaf015945ec" "/opt/rustwide/cargo-home/bin/cargo" "+ec6f9a5b4413f74386267ef8efc93712c2ce6db6" "test" "--frozen" "--no-run" "--message-format=json", kill_on_drop: false }`
[INFO] [stdout] 71c2de6e87f759035b9e993771f4687b961e10d51c38b6f3b38cf2771b18a37a
[INFO] running `Command { std: "docker" "start" "-a" "71c2de6e87f759035b9e993771f4687b961e10d51c38b6f3b38cf2771b18a37a", kill_on_drop: false }`
[INFO] [stderr]    Compiling syn v2.0.117
[INFO] [stderr]    Compiling memchr v2.8.0
[INFO] [stderr]    Compiling bitflags v2.11.0
[INFO] [stderr]    Compiling regex-syntax v0.8.10
[INFO] [stderr]    Compiling openssl-sys v0.9.111
[INFO] [stderr]    Compiling sync_wrapper v1.0.2
[INFO] [stderr]    Compiling rustix v1.1.4
[INFO] [stderr]    Compiling indexmap v2.13.0
[INFO] [stderr]    Compiling crossbeam-utils v0.8.21
[INFO] [stderr]    Compiling foreign-types-shared v0.1.1
[INFO] [stderr]    Compiling minimal-lexical v0.2.1
[INFO] [stderr]    Compiling openssl v0.10.75
[INFO] [stderr]    Compiling ipnet v2.11.0
[INFO] [stderr]    Compiling icu_normalizer_data v2.1.1
[INFO] [stderr]    Compiling icu_properties_data v2.1.2
[INFO] [stderr]    Compiling native-tls v0.2.18
[INFO] [stderr]    Compiling foreign-types v0.3.2
[INFO] [stderr]    Compiling either v1.15.0
[INFO] [stderr]    Compiling regex-syntax v0.7.5
[INFO] [stderr]    Compiling iri-string v0.7.10
[INFO] [stderr]    Compiling openssl-probe v0.2.1
[INFO] [stderr]    Compiling peg-runtime v0.6.3
[INFO] [stderr]    Compiling axum-core v0.5.6
[INFO] [stderr]    Compiling predicates-core v1.0.10
[INFO] [stderr]    Compiling unicode-linebreak v0.1.5
[INFO] [stderr]    Compiling aho-corasick v1.1.4
[INFO] [stderr]    Compiling nom v7.1.3
[INFO] [stderr]    Compiling serde_json v1.0.149
[INFO] [stderr]    Compiling peg-macros v0.6.3
[INFO] [stderr]    Compiling crossbeam-epoch v0.9.18
[INFO] [stderr]    Compiling smawk v0.3.2
[INFO] [stderr]    Compiling rusqlite v0.33.0
[INFO] [stderr]    Compiling textwrap v0.16.2
[INFO] [stderr]    Compiling crossbeam-deque v0.8.6
[INFO] [stderr]    Compiling pulldown-cmark v0.13.1
[INFO] [stderr]    Compiling itertools v0.13.0
[INFO] [stderr]    Compiling float-cmp v0.10.0
[INFO] [stderr]    Compiling nom_locate v4.2.0
[INFO] [stderr]    Compiling normalize-line-endings v0.3.0
[INFO] [stderr]    Compiling termtree v0.5.1
[INFO] [stderr]    Compiling assert_cmd v2.1.2
[INFO] [stderr]    Compiling difflib v0.4.0
[INFO] [stderr]    Compiling inflections v1.1.1
[INFO] [stderr]    Compiling predicates-tree v1.0.13
[INFO] [stderr]    Compiling console v0.15.11
[INFO] [stderr]    Compiling peg v0.6.3
[INFO] [stderr]    Compiling wait-timeout v0.2.1
[INFO] [stderr]    Compiling linked-hash-map v0.5.6
[INFO] [stderr]    Compiling drain_filter_polyfill v0.1.3
[INFO] [stderr]    Compiling humantime v2.3.0
[INFO] [stderr]    Compiling inventory v0.3.22
[INFO] [stderr]    Compiling regex-automata v0.4.14
[INFO] [stderr]    Compiling terminal_size v0.4.3
[INFO] [stderr]    Compiling tempfile v3.26.0
[INFO] [stderr]    Compiling clap_builder v4.5.60
[INFO] [stderr]    Compiling regex v1.12.3
[INFO] [stderr]    Compiling synstructure v0.13.2
[INFO] [stderr]    Compiling proc-macro-error2 v2.0.1
[INFO] [stderr]    Compiling bstr v1.12.1
[INFO] [stderr]    Compiling predicates v3.1.4
[INFO] [stderr]    Compiling serde_derive v1.0.228
[INFO] [stderr]    Compiling zerofrom-derive v0.1.6
[INFO] [stderr]    Compiling yoke-derive v0.8.1
[INFO] [stderr]    Compiling futures-macro v0.3.32
[INFO] [stderr]    Compiling tokio-macros v2.6.0
[INFO] [stderr]    Compiling zerovec-derive v0.11.2
[INFO] [stderr]    Compiling displaydoc v0.2.5
[INFO] [stderr]    Compiling openssl-macros v0.1.1
[INFO] [stderr]    Compiling sealed v0.5.0
[INFO] [stderr]    Compiling async-trait v0.1.89
[INFO] [stderr]    Compiling clap_derive v4.5.55
[INFO] [stderr]    Compiling derive_more v0.99.20
[INFO] [stderr]    Compiling thiserror-impl v1.0.69
[INFO] [stderr]    Compiling synthez-core v0.3.1
[INFO] [stderr]    Compiling globset v0.4.18
[INFO] [stderr]    Compiling rust-embed-impl v8.11.0
[INFO] [stderr]    Compiling typed-builder-macro v0.15.2
[INFO] [stderr]    Compiling synthez-codegen v0.3.1
[INFO] [stderr]    Compiling tokio v1.49.0
[INFO] [stderr]    Compiling futures-util v0.3.32
[INFO] [stderr]    Compiling tabled_derive v0.9.0
[INFO] [stderr]    Compiling lazy-regex-proc_macros v3.6.0
[INFO] [stderr]    Compiling thiserror v1.0.69
[INFO] [stderr]    Compiling synthez v0.3.1
[INFO] [stderr]    Compiling ignore v0.4.25
[INFO] [stderr]    Compiling pin-project-internal v1.1.10
[INFO] [stderr]    Compiling smart-default v0.7.1
[INFO] [stderr]    Compiling zerofrom v0.1.6
[INFO] [stderr]    Compiling rust-embed v8.11.0
[INFO] [stderr]    Compiling yoke v0.8.1
[INFO] [stderr]    Compiling lazy-regex v3.6.0
[INFO] [stderr]    Compiling zerovec v0.11.5
[INFO] [stderr]    Compiling zerotrie v0.2.3
[INFO] [stderr]    Compiling clap v4.5.60
[INFO] [stderr]    Compiling cucumber-expressions v0.3.0
[INFO] [stderr]    Compiling typed-builder v0.15.2
[INFO] [stderr]    Compiling globwalk v0.9.1
[INFO] [stderr]    Compiling pin-project v1.1.10
[INFO] [stderr]    Compiling tinystr v0.8.2
[INFO] [stderr]    Compiling potential_utf v0.1.4
[INFO] [stderr]    Compiling tabled v0.17.0
[INFO] [stderr]    Compiling icu_collections v2.1.1
[INFO] [stderr]    Compiling icu_locale_core v2.1.1
[INFO] [stderr]    Compiling cucumber-codegen v0.21.1
[INFO] [stderr]    Compiling serde v1.0.228
[INFO] [stderr]    Compiling serde_urlencoded v0.7.1
[INFO] [stderr]    Compiling basic-toml v0.1.10
[INFO] [stderr]    Compiling askama_parser v0.13.0
[INFO] [stderr]    Compiling chrono v0.4.44
[INFO] [stderr]    Compiling gherkin v0.14.0
[INFO] [stderr]    Compiling icu_provider v2.1.1
[INFO] [stderr]    Compiling icu_normalizer v2.1.1
[INFO] [stderr]    Compiling icu_properties v2.1.2
[INFO] [stderr]    Compiling axum-core v0.4.5
[INFO] [stderr]    Compiling futures-executor v0.3.32
[INFO] [stderr]    Compiling futures v0.3.32
[INFO] [stderr]    Compiling cucumber v0.21.1
[INFO] [stderr]    Compiling idna_adapter v1.2.1
[INFO] [stderr]    Compiling idna v1.1.0
[INFO] [stderr]    Compiling url v2.5.8
[INFO] [stderr]    Compiling askama_derive v0.13.1
[INFO] [stderr]    Compiling tokio-util v0.7.18
[INFO] [stderr]    Compiling tower v0.5.3
[INFO] [stderr]    Compiling tokio-native-tls v0.3.1
[INFO] [stderr]    Compiling h2 v0.4.13
[INFO] [stderr]    Compiling tower-http v0.6.8
[INFO] [stderr]    Compiling axum-htmx v0.6.0
[INFO] [stderr]    Compiling askama v0.13.1
[INFO] [stderr]    Compiling hyper v1.8.1
[INFO] [stderr]    Compiling hyper-util v0.1.20
[INFO] [stderr]    Compiling axum v0.8.8
[INFO] [stderr]    Compiling hyper-tls v0.6.0
[INFO] [stderr]    Compiling reqwest v0.12.28
[INFO] [stderr]    Compiling tacks v0.2.4 (/opt/rustwide/workdir)
[INFO] [stdout] warning: use of deprecated associated function `assert_cmd::Command::cargo_bin`: incompatible with a custom cargo build-dir, see instead `cargo::cargo_bin_cmd!`
[INFO] [stdout]    --> src/commands/prime.rs:140:32
[INFO] [stdout]     |
[INFO] [stdout] 140 |         let mut cmd = Command::cargo_bin("tk").expect("tk binary not found");
[INFO] [stdout]     |                                ^^^^^^^^^
[INFO] [stdout]     |
[INFO] [stdout]     = note: `#[warn(deprecated)]` on by default
[INFO] [stdout] 
[INFO] [stdout] 
[INFO] [stdout] warning: use of deprecated associated function `assert_cmd::Command::cargo_bin`: incompatible with a custom cargo build-dir, see instead `cargo::cargo_bin_cmd!`
[INFO] [stdout]    --> src/commands/prime.rs:154:18
[INFO] [stdout]     |
[INFO] [stdout] 154 |         Command::cargo_bin("tk")
[INFO] [stdout]     |                  ^^^^^^^^^
[INFO] [stdout] 
[INFO] [stdout] 
[INFO] [stderr]     Finished `test` profile [unoptimized + debuginfo] target(s) in 1m 49s
[INFO] running `Command { std: "docker" "inspect" "71c2de6e87f759035b9e993771f4687b961e10d51c38b6f3b38cf2771b18a37a", kill_on_drop: false }`
[INFO] running `Command { std: "docker" "rm" "-f" "71c2de6e87f759035b9e993771f4687b961e10d51c38b6f3b38cf2771b18a37a", kill_on_drop: false }`
[INFO] [stdout] 71c2de6e87f759035b9e993771f4687b961e10d51c38b6f3b38cf2771b18a37a
[INFO] running `Command { std: "docker" "create" "-v" "/var/lib/crater-agent-workspace/builds/worker-4-tc1/target:/opt/rustwide/target:rw,Z" "-v" "/var/lib/crater-agent-workspace/builds/worker-4-tc1/source:/opt/rustwide/workdir:ro,Z" "-v" "/var/lib/crater-agent-workspace/cargo-home:/opt/rustwide/cargo-home:ro,Z" "-v" "/var/lib/crater-agent-workspace/rustup-home:/opt/rustwide/rustup-home:ro,Z" "-e" "SOURCE_DIR=/opt/rustwide/workdir" "-e" "CARGO_TARGET_DIR=/opt/rustwide/target" "-e" "CARGO_INCREMENTAL=0" "-e" "RUST_BACKTRACE=full" "-e" "RUSTFLAGS=--cap-lints=forbid" "-e" "RUSTDOCFLAGS=--cap-lints=forbid" "-e" "CARGO_HOME=/opt/rustwide/cargo-home" "-e" "RUSTUP_HOME=/opt/rustwide/rustup-home" "-w" "/opt/rustwide/workdir" "-m" "1610612736" "--user" "0:0" "--network" "none" "ghcr.io/rust-lang/crates-build-env/linux@sha256:d429b63d4308055ea97f60fb1d3dfca48854a00942f1bd2ad806beaf015945ec" "/opt/rustwide/cargo-home/bin/cargo" "+ec6f9a5b4413f74386267ef8efc93712c2ce6db6" "test" "--frozen", kill_on_drop: false }`
[INFO] [stdout] 78970a144f9e563cb118851caec0379738db551dfcc39dbad28a902dd8c96592
[INFO] running `Command { std: "docker" "start" "-a" "78970a144f9e563cb118851caec0379738db551dfcc39dbad28a902dd8c96592", kill_on_drop: false }`
[INFO] [stderr] warning: use of deprecated associated function `assert_cmd::Command::cargo_bin`: incompatible with a custom cargo build-dir, see instead `cargo::cargo_bin_cmd!`
[INFO] [stderr]    --> src/commands/prime.rs:140:32
[INFO] [stderr]     |
[INFO] [stderr] 140 |         let mut cmd = Command::cargo_bin("tk").expect("tk binary not found");
[INFO] [stderr]     |                                ^^^^^^^^^
[INFO] [stderr]     |
[INFO] [stderr]     = note: `#[warn(deprecated)]` on by default
[INFO] [stderr] 
[INFO] [stderr] warning: use of deprecated associated function `assert_cmd::Command::cargo_bin`: incompatible with a custom cargo build-dir, see instead `cargo::cargo_bin_cmd!`
[INFO] [stderr]    --> src/commands/prime.rs:154:18
[INFO] [stderr]     |
[INFO] [stderr] 154 |         Command::cargo_bin("tk")
[INFO] [stderr]     |                  ^^^^^^^^^
[INFO] [stderr] 
[INFO] [stderr] warning: `tacks` (bin "tk" test) generated 2 warnings
[INFO] [stderr]     Finished `test` profile [unoptimized + debuginfo] target(s) in 0.45s
[INFO] [stderr]      Running unittests src/lib.rs (/opt/rustwide/target/debug/deps/tacks-4abb15150e056fd8)
[INFO] [stdout] 
[INFO] [stdout] running 9 tests
[INFO] [stdout] test web::tests::test_render_markdown_basics ... ok
[INFO] [stdout] test db::tests::test_dependency_chain_invalid_direction ... ok
[INFO] [stdout] test db::tests::test_dependency_chain_single_dep ... ok
[INFO] [stdout] test db::tests::test_dependency_chain_empty_no_deps ... ok
[INFO] [stdout] test db::tests::test_list_tasks_completed_after_none_returns_all ... ok
[INFO] [stdout] test db::tests::test_list_tasks_completed_after_filters_by_updated_at ... ok
[INFO] [stdout] test db::tests::test_dependency_chain_both_direction ... ok
[INFO] [stdout] test db::tests::test_dependency_chain_linear_chain ... ok
[INFO] [stdout] test db::tests::test_dependency_chain_diamond ... ok
[INFO] [stdout] 
[INFO] [stdout] test result: ok. 9 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.09s
[INFO] [stdout] 
[INFO] [stderr]      Running unittests src/main.rs (/opt/rustwide/target/debug/deps/tk-378394bce9de57fe)
[INFO] [stdout] 
[INFO] [stdout] running 16 tests
[INFO] [stdout] test commands::tests::test_print_tasks_with_multibyte_chars ... ok
[INFO] [stdout] test web::tests::test_render_markdown_basics ... ok
[INFO] [stdout] test commands::prime::tests::test_prime_silent_exit_when_no_db ... ok
[INFO] [stdout] test db::tests::test_list_tasks_completed_after_filters_by_updated_at ... ok
[INFO] [stdout] test db::tests::test_dependency_chain_empty_no_deps ... ok
[INFO] [stdout] test db::tests::test_dependency_chain_both_direction ... ok
[INFO] [stdout] test db::tests::test_dependency_chain_invalid_direction ... ok
[INFO] [stdout] test db::tests::test_list_tasks_completed_after_none_returns_all ... ok
[INFO] [stdout] test db::tests::test_dependency_chain_single_dep ... ok
[INFO] [stdout] test db::tests::test_dependency_chain_linear_chain ... ok
[INFO] [stdout] test db::tests::test_dependency_chain_diamond ... ok
[INFO] [stdout] test commands::prime::tests::test_prime_markdown_empty_db ... ok
[INFO] [stdout] test commands::prime::tests::test_prime_json_empty_db ... ok
[INFO] [stdout] test commands::prime::tests::test_prime_shows_ready_tasks ... ok
[INFO] [stdout] test commands::prime::tests::test_prime_shows_in_progress_tasks ... ok
[INFO] [stdout] test commands::prime::tests::test_prime_json_in_progress_and_ready ... ok
[INFO] [stdout] 
[INFO] [stdout] test result: ok. 16 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.24s
[INFO] [stdout] 
[INFO] [stderr]      Running tests/bdd/main.rs (/opt/rustwide/target/debug/deps/bdd-fc03f335ae1279a0)
[INFO] [stdout] Feature: Agent workflow commands
[INFO] [stdout]   Scenario: tk update --claim sets status to in_progress and assignee
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "work" with title "Feature to implement"
[INFO] [stdout]    ✔  When I claim the task "work"
[INFO] [stdout]    ✔  Then the task "work" has status "in_progress"
[INFO] [stdout]    ✔  And the task "work" has assignee "agent"
[INFO] [stdout]   Scenario: tk comment adds a comment visible in tk show
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "commented" with title "Task to comment on"
[INFO] [stdout]    ✔  When I add a comment "Making progress" to the task "commented"
[INFO] [stdout]    ✔  And I show the task "commented"
[INFO] [stdout]    ✔  Then the task details show a comment with body "Making progress"
[INFO] [stdout]   Scenario: tk stats shows correct counts by status
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "t1" with title "Open task one"
[INFO] [stdout]    ✔  And I have a task called "t2" with title "Open task two"
[INFO] [stdout]    ✔  And I close the task "t2"
[INFO] [stdout]    ✔  When I run tk stats with json output
[INFO] [stdout]    ✔  Then the stats JSON shows "open" count of 1
[INFO] [stdout]    ✔  And the stats JSON shows "done" count of 1
[INFO] [stdout]   Scenario: tk stats --oneline outputs compact format
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "t1" with title "One open task"
[INFO] [stdout]    ✔  When I run tk stats with oneline output
[INFO] [stdout]    ✔  Then the oneline output contains "open"
[INFO] [stdout]   Scenario: tk stats --json outputs structured JSON
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "t1" with title "Tagged stats task" and tag "backend"
[INFO] [stdout]    ✔  When I run tk stats with json output
[INFO] [stdout]    ✔  Then the stats JSON has a "by_status" field
[INFO] [stdout]    ✔  And the stats JSON has a "by_priority" field
[INFO] [stdout]    ✔  And the stats JSON has a "by_tag" field
[INFO] [stdout]   Scenario: tk ready --limit 1 returns only one task
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "a" with title "Ready task A"
[INFO] [stdout]    ✔  And I have a task called "b" with title "Ready task B"
[INFO] [stdout]    ✔  And I have a task called "c" with title "Ready task C"
[INFO] [stdout]    ✔  When I run tk ready with limit 1
[INFO] [stdout]    ✔  Then the ready list contains exactly 1 task
[INFO] [stdout]   Scenario: tk ready with no ready tasks returns empty list
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "blocker" with title "The blocker"
[INFO] [stdout]    ✔  And I have a task called "blocked" with title "The blocked"
[INFO] [stdout]    ✔  When I add a dependency so "blocked" is blocked by "blocker"
[INFO] [stdout]    ✔  And I close the task "blocker"
[INFO] [stdout]    ✔  And I close the task "blocked"
[INFO] [stdout]    ✔  When I run tk ready with json output
[INFO] [stdout]    ✔  Then the ready list is empty
[INFO] [stdout] Feature: Blocked task listing
[INFO] [stdout]   Scenario: Blocked tasks are shown when dependencies exist
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "blocker" with title "Must finish first"
[INFO] [stdout]    ✔  And I have a task called "blocked" with title "Waiting on blocker"
[INFO] [stdout]    ✔  When I add a dependency so "blocked" is blocked by "blocker"
[INFO] [stdout]    ✔  And I run tk blocked with JSON
[INFO] [stdout]    ✔  Then the blocked output contains "Waiting on blocker"
[INFO] [stdout]    ✔  And the blocked output does not contain "Must finish first"
[INFO] [stdout]   Scenario: No blocked tasks shows empty list
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "free" with title "Free task"
[INFO] [stdout]    ✔  When I run tk blocked with JSON
[INFO] [stdout]    ✔  Then the JSON output is an empty array
[INFO] [stdout]   Scenario: Resolved blocker removes task from blocked list
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "blocker" with title "Resolve me"
[INFO] [stdout]    ✔  And I have a task called "blocked" with title "Waiting task"
[INFO] [stdout]    ✔  When I add a dependency so "blocked" is blocked by "blocker"
[INFO] [stdout]    ✔  And I close task "blocker" with reason "done"
[INFO] [stdout]    ✔  And I run tk blocked with JSON
[INFO] [stdout]    ✔  Then the JSON output is an empty array
[INFO] [stdout] Feature: Board done column filtering by done_since
[INFO] [stdout]   Scenario: Default filter hides done tasks older than 3 days
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Recent task" as "recent"
[INFO] [stdout]    ✔  And I created a task via API with title "Old task" as "old"
[INFO] [stdout]    ✔  And I closed the API task "recent"
[INFO] [stdout]    ✔  And I closed the API task "old" 4 days ago
[INFO] [stdout]    ✔  When I GET "/board"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "Recent task"
[INFO] [stdout]    ✔  And the response body does not contain "Old task"
[INFO] [stdout]   Scenario: done_since=7d shows recently closed task
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Week-old task" as "week-task"
[INFO] [stdout]    ✔  And I closed the API task "week-task"
[INFO] [stdout]    ✔  When I GET "/board?done_since=7d"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "Week-old task"
[INFO] [stdout]   Scenario: done_since=7d hides task closed 8 days ago
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Stale task" as "stale"
[INFO] [stdout]    ✔  And I closed the API task "stale" 8 days ago
[INFO] [stdout]    ✔  When I GET "/board?done_since=7d"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body does not contain "Stale task"
[INFO] [stdout]   Scenario: done_since=all shows all done tasks regardless of age
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Very old task" as "very-old"
[INFO] [stdout]    ✔  And I closed the API task "very-old" 60 days ago
[INFO] [stdout]    ✔  When I GET "/board?done_since=all"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "Very old task"
[INFO] [stdout]   Scenario: done_since=3d shows task closed 2 days ago
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Three-day-window task" as "threeday"
[INFO] [stdout]    ✔  And I closed the API task "threeday" 2 days ago
[INFO] [stdout]    ✔  When I GET "/board?done_since=3d"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "Three-day-window task"
[INFO] [stdout]   Scenario: done_since=3d hides task closed 8 days ago
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Older than 3 days" as "old-3"
[INFO] [stdout]    ✔  And I closed the API task "old-3" 8 days ago
[INFO] [stdout]    ✔  When I GET "/board?done_since=3d"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body does not contain "Older than 3 days"
[INFO] [stdout]   Scenario: done_since=30d shows task closed 20 days ago
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Month window task" as "monthly"
[INFO] [stdout]    ✔  And I closed the API task "monthly" 20 days ago
[INFO] [stdout]    ✔  When I GET "/board?done_since=30d"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "Month window task"
[INFO] [stdout]   Scenario: Board with no done tasks renders without error
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Undone task" as "undone"
[INFO] [stdout]    ✔  When I GET "/board"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "Undone task"
[INFO] [stdout]   Scenario: Default filter on epic board shows all done subtasks regardless of age
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "My epic" as "epic"
[INFO] [stdout]    ✔  And I created a subtask via API with title "Old subtask" under "epic" as "old-sub"
[INFO] [stdout]    ✔  And I closed the API task "old-sub" 8 days ago
[INFO] [stdout]    ✔  When I GET the epic board for "epic"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "Old subtask"
[INFO] [stdout]   Scenario: done_since=all on epic board shows old done subtask
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Full epic" as "full-epic"
[INFO] [stdout]    ✔  And I created a subtask via API with title "Ancient subtask" under "full-epic" as "ancient-sub"
[INFO] [stdout]    ✔  And I closed the API task "ancient-sub" 60 days ago
[INFO] [stdout]    ✔  When I GET the epic board for "full-epic" with done_since "all"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "Ancient subtask"
[INFO] [stdout]   Scenario: Epic completion stats are unaffected by done_since filter
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Stats epic" as "stats-epic"
[INFO] [stdout]    ✔  And I created a subtask via API with title "New done subtask" under "stats-epic" as "new-sub"
[INFO] [stdout]    ✔  And I created a subtask via API with title "Old done subtask" under "stats-epic" as "old-sub2"
[INFO] [stdout]    ✔  And I closed the API task "new-sub"
[INFO] [stdout]    ✔  And I closed the API task "old-sub2" 30 days ago
[INFO] [stdout]    ✔  When I GET the API task "stats-epic"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response JSON field "status" equals "done"
[INFO] [stdout] Feature: Board drag-and-drop status transitions
[INFO] [stdout]   Scenario: Drag task from Open to In Progress
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "New feature" as "feature"
[INFO] [stdout]    ✔  When I PATCH the API task "feature" with body '{"status":"in_progress"}'
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response JSON field "status" equals "in_progress"
[INFO] [stdout]    ✔  When I GET the API task "feature"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response JSON field "status" equals "in_progress"
[INFO] [stdout]   Scenario: Drag task from In Progress to Done
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Work in progress" as "wip"
[INFO] [stdout]    ✔  When I PATCH the API task "wip" with body '{"status":"in_progress"}'
[INFO] [stdout]    ✔  And I PATCH the API task "wip" with body '{"status":"done"}'
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response JSON field "status" equals "done"
[INFO] [stdout]    ✔  When I GET the API task "wip"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response JSON field "status" equals "done"
[INFO] [stdout]   Scenario: Drag task to Blocked column
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Waiting on dependency" as "waiting"
[INFO] [stdout]    ✔  When I PATCH the API task "waiting" with body '{"status":"blocked"}'
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response JSON field "status" equals "blocked"
[INFO] [stdout]    ✔  When I GET the API task "waiting"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response JSON field "status" equals "blocked"
[INFO] [stdout]   Scenario: Drag task back from Done to Open
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Reopened task" as "reopened"
[INFO] [stdout]    ✔  When I PATCH the API task "reopened" with body '{"status":"done"}'
[INFO] [stdout]    ✔  And I PATCH the API task "reopened" with body '{"status":"open"}'
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response JSON field "status" equals "open"
[INFO] [stdout]    ✔  When I GET the API task "reopened"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response JSON field "status" equals "open"
[INFO] [stdout]   Scenario: Drop on same column is a no-op
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Stable task" as "stable"
[INFO] [stdout]    ✔  When I PATCH the API task "stable" with body '{"status":"open"}'
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response JSON field "status" equals "open"
[INFO] [stdout]    ✔  When I GET the API task "stable"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response JSON field "status" equals "open"
[INFO] [stdout]   Scenario: Drag-and-drop on epic detail board updates subtask and syncs epic
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "My epic" as "epic"
[INFO] [stdout]    ✔  And I created a subtask via API with title "Subtask one" under "epic" as "subtask"
[INFO] [stdout]    ✔  When I PATCH the API task "subtask" with body '{"status":"in_progress"}'
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response JSON field "status" equals "in_progress"
[INFO] [stdout]    ✔  When I GET the API task "epic"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response JSON field "status" equals "in_progress"
[INFO] [stdout]    ✔  When I GET the API task "subtask"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response JSON field "status" equals "in_progress"
[INFO] [stdout] Feature: List child tasks
[INFO] [stdout]   Scenario: Listing children of a parent task
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "parent" with title "Epic task"
[INFO] [stdout]    ✔  When I create a subtask of "parent" with title "Child one"
[INFO] [stdout]    ✔  And I create a subtask of "parent" with title "Child two"
[INFO] [stdout]    ✔  And I run tk children for "parent"
[INFO] [stdout]    ✔  Then the output contains "Child one"
[INFO] [stdout]    ✔  And the output contains "Child two"
[INFO] [stdout]   Scenario: Children of a task with no children shows empty
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "leaf" with title "Leaf task"
[INFO] [stdout]    ✔  When I run tk children for "leaf" with JSON
[INFO] [stdout]    ✔  Then the JSON output is an empty array
[INFO] [stdout]   Scenario: Children command with invalid ID fails
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  When I run tk children for "tk-0000"
[INFO] [stdout]    ✔  Then the command should fail
[INFO] [stdout]    ✔  And the error output contains "not found"
[INFO] [stdout] Feature: Close guard for tasks with open subtasks
[INFO] [stdout]   Scenario: Closing a task with open subtasks is rejected
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "parent" with title "Core module"
[INFO] [stdout]    ✔  When I create a subtask of "parent" with title "Open subtask"
[INFO] [stdout]    ✔  And I try to close task "parent"
[INFO] [stdout]    ✔  Then the command should fail
[INFO] [stdout]    ✔  And the error output contains "open dependent"
[INFO] [stdout]   Scenario: Closing a task with --force bypasses the guard
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "parent" with title "Forceable task"
[INFO] [stdout]    ✔  When I create a subtask of "parent" with title "Dependent subtask"
[INFO] [stdout]    ✔  And I force close task "parent"
[INFO] [stdout]    ✔  And I show task "parent" in JSON
[INFO] [stdout]    ✔  Then the task details show status "done"
[INFO] [stdout]   Scenario: Closing a task with no subtasks works normally
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "solo" with title "No subtasks"
[INFO] [stdout]    ✔  When I close task "solo" with reason "done"
[INFO] [stdout]    ✔  And I show task "solo" in JSON
[INFO] [stdout]    ✔  Then the task details show status "done"
[INFO] [stdout]   Scenario: Closing a task whose subtasks are already done works
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "parent" with title "Already clear"
[INFO] [stdout]    ✔  When I create a subtask of "parent" with title "Already done child"
[INFO] [stdout]    ✔  And I force close subtask "Already done child"
[INFO] [stdout]    ✔  And I close task "parent" with reason "done"
[INFO] [stdout]    ✔  And I show task "parent" in JSON
[INFO] [stdout]    ✔  Then the task details show status "done"
[INFO] [stdout] Feature: Close reason tracking
[INFO] [stdout]   Scenario: Closing a task with default reason
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  When I create a task with title "Default close"
[INFO] [stdout]    ✔  And I close the task
[INFO] [stdout]    ✔  And I show the task
[INFO] [stdout]    ✔  Then the task details show close_reason "done"
[INFO] [stdout]   Scenario: Closing a task with explicit reason
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "dup" with title "Duplicate work"
[INFO] [stdout]    ✔  When I close task "dup" with reason "duplicate"
[INFO] [stdout]    ✔  And I show task "dup" in JSON
[INFO] [stdout]    ✔  Then the task details show close_reason "duplicate"
[INFO] [stdout]   Scenario: Closing a task with stale reason
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "old" with title "Stale task"
[INFO] [stdout]    ✔  When I close task "old" with reason "stale"
[INFO] [stdout]    ✔  And I show task "old" in JSON
[INFO] [stdout]    ✔  Then the task details show close_reason "stale"
[INFO] [stdout]   Scenario: Invalid close reason is rejected
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "bad" with title "Bad reason"
[INFO] [stdout]    ✔  When I try to close task "bad" with reason "invalid_reason"
[INFO] [stdout]    ✔  Then the command should fail
[INFO] [stdout]    ✔  And the error output contains "invalid close reason"
[INFO] [stdout] Feature: Task creation modal
[INFO] [stdout]   Scenario: Modal endpoint returns HTML fragment
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I GET "/tasks/new/modal"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response content type is "text/html"
[INFO] [stdout]   Scenario: Modal form contains a form element
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I GET "/tasks/new/modal"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "<form"
[INFO] [stdout]   Scenario: Modal form has a title input field
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I GET "/tasks/new/modal"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "title"
[INFO] [stdout]   Scenario: Modal form has a description input field
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I GET "/tasks/new/modal"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "description"
[INFO] [stdout]   Scenario: Modal form has a priority input field
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I GET "/tasks/new/modal"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "priority"
[INFO] [stdout]   Scenario: Modal form has a status input field
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I GET "/tasks/new/modal"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "status"
[INFO] [stdout]   Scenario: Modal form has a tags input field
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I GET "/tasks/new/modal"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "tags"
[INFO] [stdout]   Scenario: Modal form has an assignee input field
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I GET "/tasks/new/modal"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "assignee"
[INFO] [stdout]   Scenario: Modal form has a parent field
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I GET "/tasks/new/modal"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "parent"
[INFO] [stdout]   Scenario: Modal fragment does not include full HTML page wrapper
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I GET "/tasks/new/modal"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body does not contain "<!DOCTYPE"
[INFO] [stdout]    ✔  And the response body does not contain "<html"
[INFO] [stdout]   Scenario: Modal form shows available epics in parent dropdown
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Epic task" as "epic-task"
[INFO] [stdout]    ✔  And I created a subtask via API with title "Child of epic" under "epic-task" as "epic-child"
[INFO] [stdout]    ✔  When I GET "/tasks/new/modal"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "Epic task"
[INFO] [stdout]   Scenario: POST to modal create endpoint with all fields creates a task
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I POST the modal create form with title "Modal task" and priority 1
[INFO] [stdout]    ✔  Then the response status is 201
[INFO] [stdout]    ✔  And the response body contains "Modal task"
[INFO] [stdout]   Scenario: POST to modal create endpoint with missing title returns validation error
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I POST the modal create form with an empty title
[INFO] [stdout]    ✔  Then the response status is 422
[INFO] [stdout]   Scenario: POST to modal create endpoint with parent_id sets parent
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Parent epic" as "modal-parent"
[INFO] [stdout]    ✔  When I POST the modal create form with title "Child task" under "modal-parent"
[INFO] [stdout]    ✔  Then the response status is 201
[INFO] [stdout]    ✔  And the response body contains "Child task"
[INFO] [stdout]   Scenario: POST with parent_id auto-tags parent as epic
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Future epic" as "future-epic"
[INFO] [stdout]    ✔  When I POST the modal create form with title "Subtask" under "future-epic"
[INFO] [stdout]    ✔  Then the response status is 201
[INFO] [stdout]    ✔  And the parent task "future-epic" has tag "epic"
[INFO] [stdout]   Scenario: Task list page nav bar contains a New Issue button
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I GET "/tasks"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "New Issue"
[INFO] [stdout]   Scenario: Board page nav bar contains a New Issue button
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I GET "/board"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "New Issue"
[INFO] [stdout]   Scenario: Epics page nav bar contains a New Issue button
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I GET "/epics"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "New Issue"
[INFO] [stdout]   Scenario: New Issue button links to the modal endpoint
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I GET "/tasks"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "/tasks/new/modal"
[INFO] [stdout] Feature: Dependency visualization
[INFO] [stdout]   Scenario: Task with no dependencies shows empty blockers and dependents
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "solo" with title "Standalone task"
[INFO] [stdout]    ✔  When I show task "solo" in JSON
[INFO] [stdout]    ✔  Then the task details have no blockers
[INFO] [stdout]    ✔  And the task details have no dependents
[INFO] [stdout]   Scenario: Task with a blocker shows the blocker in show output
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "A" with title "Foundation work"
[INFO] [stdout]    ✔  And I have a task called "B" with title "Depends on foundation"
[INFO] [stdout]    ✔  When I add a dependency so "B" is blocked by "A"
[INFO] [stdout]    ✔  And I show task "B" in JSON
[INFO] [stdout]    ✔  Then the task details include blocker "Foundation work"
[INFO] [stdout]   Scenario: Task with a dependent shows the dependent in show output
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "A" with title "Library task"
[INFO] [stdout]    ✔  And I have a task called "B" with title "Consumer task"
[INFO] [stdout]    ✔  When I add a dependency so "B" is blocked by "A"
[INFO] [stdout]    ✔  And I show task "A" in JSON
[INFO] [stdout]    ✔  Then the task details include dependent "Consumer task"
[INFO] [stdout]   Scenario: Blocked task appears in tk list output
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "blocker" with title "Must do first"
[INFO] [stdout]    ✔  And I have a task called "blocked" with title "Waiting for blocker"
[INFO] [stdout]    ✔  When I add a dependency so "blocked" is blocked by "blocker"
[INFO] [stdout]    ✔  Then the task list contains "Waiting for blocker"
[INFO] [stdout]   Scenario: Linear chain shows all intermediate tasks in blocked list
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "A" with title "Step one"
[INFO] [stdout]    ✔  And I have a task called "B" with title "Step two"
[INFO] [stdout]    ✔  And I have a task called "C" with title "Step three"
[INFO] [stdout]    ✔  When I add a dependency so "B" is blocked by "A"
[INFO] [stdout]    ✔  And I add a dependency so "C" is blocked by "B"
[INFO] [stdout]    ✔  And I run tk blocked with JSON
[INFO] [stdout]    ✔  Then the blocked output contains "Step two"
[INFO] [stdout]    ✔  And the blocked output contains "Step three"
[INFO] [stdout]    ✔  And the blocked output does not contain "Step one"
[INFO] [stdout]   Scenario: Closing middle blocker in chain unblocks downstream task
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "A" with title "First step"
[INFO] [stdout]    ✔  And I have a task called "B" with title "Middle step"
[INFO] [stdout]    ✔  And I have a task called "C" with title "Last step"
[INFO] [stdout]    ✔  When I add a dependency so "B" is blocked by "A"
[INFO] [stdout]    ✔  And I add a dependency so "C" is blocked by "B"
[INFO] [stdout]    ✔  And I close task "A" with reason "done"
[INFO] [stdout]    ✔  And I run tk blocked with JSON
[INFO] [stdout]    ✔  Then the blocked output does not contain "Middle step"
[INFO] [stdout]    ✔  And the blocked output contains "Last step"
[INFO] [stdout]   Scenario: Task is unblocked once all its blockers are closed
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "dep1" with title "Prerequisite one"
[INFO] [stdout]    ✔  And I have a task called "dep2" with title "Prerequisite two"
[INFO] [stdout]    ✔  And I have a task called "main" with title "Main work"
[INFO] [stdout]    ✔  When I add a dependency so "main" is blocked by "dep1"
[INFO] [stdout]    ✔  And I add a dependency so "main" is blocked by "dep2"
[INFO] [stdout]    ✔  And I close task "dep1" with reason "done"
[INFO] [stdout]    ✔  And I run tk blocked with JSON
[INFO] [stdout]    ✔  Then the blocked output contains "Main work"
[INFO] [stdout]    ✔  When I close task "dep2" with reason "done"
[INFO] [stdout]    ✔  And I run tk blocked with JSON
[INFO] [stdout]    ✔  Then the JSON output is an empty array
[INFO] [stdout] Feature: Dependency management
[INFO] [stdout]   Scenario: Adding a dependency blocks a task from the ready list
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "blocker" with title "Prerequisite work"
[INFO] [stdout]    ✔  And I have a task called "blocked" with title "Depends on prerequisite"
[INFO] [stdout]    ✔  When I add a dependency so "blocked" is blocked by "blocker"
[INFO] [stdout]    ✔  Then the ready list does not contain "Depends on prerequisite"
[INFO] [stdout]    ✔  And the ready list contains "Prerequisite work"
[INFO] [stdout]   Scenario: Removing a dependency unblocks a task
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "blocker" with title "Step one"
[INFO] [stdout]    ✔  And I have a task called "blocked" with title "Step two"
[INFO] [stdout]    ✔  When I add a dependency so "blocked" is blocked by "blocker"
[INFO] [stdout]    ✔  And I remove the dependency so "blocked" is no longer blocked by "blocker"
[INFO] [stdout]    ✔  Then the ready list contains "Step two"
[INFO] [stdout]   Scenario: A task with no dependencies appears in the ready list
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "solo" with title "Independent task"
[INFO] [stdout]    ✔  Then the ready list contains "Independent task"
[INFO] [stdout]   Scenario: Adding a dependency with an invalid task ID fails gracefully
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "real" with title "A real task"
[INFO] [stdout]    ✔  When I try to add a dependency so "real" is blocked by "tk-0000"
[INFO] [stdout]    ✔  Then the command should fail
[INFO] [stdout]    ✔  And the error output contains "not found"
[INFO] [stdout]   Scenario: Self-dependency is rejected
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "self" with title "Self referencing task"
[INFO] [stdout]    ✔  When I try to add a self-dependency for "self"
[INFO] [stdout]    ✔  Then the command should fail
[INFO] [stdout]   Scenario: Show command displays dependents
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "parent" with title "Core library"
[INFO] [stdout]    ✔  And I have a task called "child" with title "Uses core library"
[INFO] [stdout]    ✔  When I add a dependency so "child" is blocked by "parent"
[INFO] [stdout]    ✔  And I show task "parent" in JSON
[INFO] [stdout]    ✔  Then the task details include dependent "Uses core library"
[INFO] [stdout]   Scenario: Show command displays both blockers and dependents
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "A" with title "Task A"
[INFO] [stdout]    ✔  And I have a task called "B" with title "Task B"
[INFO] [stdout]    ✔  And I have a task called "C" with title "Task C"
[INFO] [stdout]    ✔  When I add a dependency so "B" is blocked by "A"
[INFO] [stdout]    ✔  And I add a dependency so "C" is blocked by "B"
[INFO] [stdout]    ✔  And I show task "B" in JSON
[INFO] [stdout]    ✔  Then the task details include blocker "Task A"
[INFO] [stdout]    ✔  And the task details include dependent "Task C"
[INFO] [stdout]   Scenario: Removing a dependency with invalid task ID fails
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "real" with title "Valid task"
[INFO] [stdout]    ✔  When I try to remove a dependency so "real" is no longer blocked by "tk-0000"
[INFO] [stdout]    ✔  Then the command should fail
[INFO] [stdout]    ✔  And the error output contains "not found"
[INFO] [stdout] Feature: Three-part epic progress
[INFO] [stdout]   Scenario: Epic with mixed status children shows three-part counts in JSON
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "epic" with title "Mixed epic" and tag "epic"
[INFO] [stdout]    ✔  When I create a subtask of "epic" with title "Done step"
[INFO] [stdout]    ✔  And I create a subtask of "epic" with title "WIP step"
[INFO] [stdout]    ✔  And I create a subtask of "epic" with title "Open step"
[INFO] [stdout]    ✔  And I force close subtask "Done step"
[INFO] [stdout]    ✔  And I claim subtask "WIP step"
[INFO] [stdout]    ✔  And I run tk epic with JSON
[INFO] [stdout]    ✔  Then the epic JSON shows "Mixed epic" with 1 done, 1 in_progress, 1 open
[INFO] [stdout]   Scenario: All-done epic shows N/0/0 in JSON
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "epic" with title "Finished epic" and tag "epic"
[INFO] [stdout]    ✔  When I create a subtask of "epic" with title "Step one"
[INFO] [stdout]    ✔  And I create a subtask of "epic" with title "Step two"
[INFO] [stdout]    ✔  And I force close subtask "Step one"
[INFO] [stdout]    ✔  And I force close subtask "Step two"
[INFO] [stdout]    ✔  And I run tk epic with JSON
[INFO] [stdout]    ✔  Then the epic JSON shows "Finished epic" with 2 done, 0 in_progress, 0 open
[INFO] [stdout]   Scenario: All-open epic shows 0/0/N in JSON
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "epic" with title "Fresh epic" and tag "epic"
[INFO] [stdout]    ✔  When I create a subtask of "epic" with title "Step A"
[INFO] [stdout]    ✔  And I create a subtask of "epic" with title "Step B"
[INFO] [stdout]    ✔  And I create a subtask of "epic" with title "Step C"
[INFO] [stdout]    ✔  And I run tk epic with JSON
[INFO] [stdout]    ✔  Then the epic JSON shows "Fresh epic" with 0 done, 0 in_progress, 3 open
[INFO] [stdout]   Scenario: Human-readable epic output shows done/wip/open format
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "epic" with title "Progress epic" and tag "epic"
[INFO] [stdout]    ✔  When I create a subtask of "epic" with title "Done step"
[INFO] [stdout]    ✔  And I create a subtask of "epic" with title "WIP step"
[INFO] [stdout]    ✔  And I create a subtask of "epic" with title "Open step"
[INFO] [stdout]    ✔  And I force close subtask "Done step"
[INFO] [stdout]    ✔  And I claim subtask "WIP step"
[INFO] [stdout]    ✔  And I run tk epic
[INFO] [stdout]    ✔  Then the epic output contains "1/1/1"
[INFO] [stdout] Feature: Epic progress tracking
[INFO] [stdout]   Scenario: Epic shows child completion progress
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "epic" with title "Big feature" and tag "epic"
[INFO] [stdout]    ✔  When I create a subtask of "epic" with title "Step one"
[INFO] [stdout]    ✔  And I create a subtask of "epic" with title "Step two"
[INFO] [stdout]    ✔  And I run tk epic with JSON
[INFO] [stdout]    ✔  Then the epic output shows "Big feature" with 0 of 2 done
[INFO] [stdout]   Scenario: Epic progress updates when children close
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "epic" with title "Progressing feature" and tag "epic"
[INFO] [stdout]    ✔  When I create a subtask of "epic" with title "Done step"
[INFO] [stdout]    ✔  And I create a subtask of "epic" with title "Open step"
[INFO] [stdout]    ✔  And I force close subtask "Done step"
[INFO] [stdout]    ✔  And I run tk epic with JSON
[INFO] [stdout]    ✔  Then the epic output shows "Progressing feature" with 1 of 2 done
[INFO] [stdout]   Scenario: No epics shows empty output
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "task" with title "Regular task"
[INFO] [stdout]    ✔  When I run tk epic with JSON
[INFO] [stdout]    ✔  Then the JSON output is an empty array
[INFO] [stdout] Feature: Automatic epic status sync
[INFO] [stdout]   Scenario: Epic stays open when all children are open
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "epic" with title "Fresh epic" and tag "epic"
[INFO] [stdout]    ✔  When I create a subtask of "epic" with title "Task A"
[INFO] [stdout]    ✔  And I create a subtask of "epic" with title "Task B"
[INFO] [stdout]    ✔  And I show task "epic" in JSON
[INFO] [stdout]    ✔  Then the task details show status "open"
[INFO] [stdout]   Scenario: Epic becomes in_progress when first child closes
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "epic" with title "Active epic" and tag "epic"
[INFO] [stdout]    ✔  When I create a subtask of "epic" with title "Done step"
[INFO] [stdout]    ✔  And I create a subtask of "epic" with title "Open step"
[INFO] [stdout]    ✔  And I force close subtask "Done step"
[INFO] [stdout]    ✔  And I show task "epic" in JSON
[INFO] [stdout]    ✔  Then the task details show status "in_progress"
[INFO] [stdout]   Scenario: Epic becomes done when all children close
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "epic" with title "Complete epic" and tag "epic"
[INFO] [stdout]    ✔  When I create a subtask of "epic" with title "Step one"
[INFO] [stdout]    ✔  And I create a subtask of "epic" with title "Step two"
[INFO] [stdout]    ✔  And I force close subtask "Step one"
[INFO] [stdout]    ✔  And I force close subtask "Step two"
[INFO] [stdout]    ✔  And I show task "epic" in JSON
[INFO] [stdout]    ✔  Then the task details show status "done"
[INFO] [stdout]   Scenario: Adding a new subtask to done epic reverts to in_progress
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "epic" with title "Reopened epic" and tag "epic"
[INFO] [stdout]    ✔  When I create a subtask of "epic" with title "Done step"
[INFO] [stdout]    ✔  And I force close subtask "Done step"
[INFO] [stdout]    ✔  And I show task "epic" in JSON
[INFO] [stdout]    ✔  Then the task details show status "done"
[INFO] [stdout]    ✔  When I create a subtask of "epic" with title "New work"
[INFO] [stdout]    ✔  And I show task "epic" in JSON
[INFO] [stdout]    ✔  Then the task details show status "in_progress"
[INFO] [stdout]   Scenario: Claiming a child moves epic to in_progress
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "epic" with title "Open epic" and tag "epic"
[INFO] [stdout]    ✔  When I create a subtask of "epic" with title "WIP step"
[INFO] [stdout]    ✔  And I create a subtask of "epic" with title "Other step"
[INFO] [stdout]    ✔  And I claim subtask "WIP step"
[INFO] [stdout]    ✔  And I show task "epic" in JSON
[INFO] [stdout]    ✔  Then the task details show status "in_progress"
[INFO] [stdout]   Scenario: Reopening a child reverts done epic to in_progress
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "epic" with title "Reverted epic" and tag "epic"
[INFO] [stdout]    ✔  When I create a subtask of "epic" with title "Step one"
[INFO] [stdout]    ✔  And I force close subtask "Step one"
[INFO] [stdout]    ✔  And I show task "epic" in JSON
[INFO] [stdout]    ✔  Then the task details show status "done"
[INFO] [stdout]    ✔  When I reopen subtask "Step one"
[INFO] [stdout]    ✔  And I show task "epic" in JSON
[INFO] [stdout]    ✔  Then the task details show status "open"
[INFO] [stdout] Feature: Epic auto-tagging
[INFO] [stdout]   Scenario: Creating a subtask auto-tags parent as epic
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "parent" with title "Parent task"
[INFO] [stdout]    ✔  When I create a subtask of "parent" with title "Child task"
[INFO] [stdout]    ✔  And I show task "parent" in JSON
[INFO] [stdout]    ✔  Then the task details include tag "epic"
[INFO] [stdout]   Scenario: Auto-tag does not duplicate epic tag
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "parent" with title "Already epic" and tag "epic"
[INFO] [stdout]    ✔  When I create a subtask of "parent" with title "Another child"
[INFO] [stdout]    ✔  And I show task "parent" in JSON
[INFO] [stdout]    ✔  Then the task details show exactly one "epic" tag
[INFO] [stdout]   Scenario: Creating a subtask assigns parent ID
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "parent" with title "Top level"
[INFO] [stdout]    ✔  When I create a subtask of "parent" with title "Sub level"
[INFO] [stdout]    ✔  Then the subtask has parent ID matching "parent"
[INFO] [stdout] Feature: List filtering
[INFO] [stdout]   Scenario: tk list -s done shows only closed tasks
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "open_task" with title "Still open"
[INFO] [stdout]    ✔  And I have a task called "done_task" with title "Already done"
[INFO] [stdout]    ✔  And I close the task "done_task"
[INFO] [stdout]    ✔  When I list tasks filtered by status "done"
[INFO] [stdout]    ✔  Then the filtered list contains "Already done"
[INFO] [stdout]    ✔  And the filtered list does not contain "Still open"
[INFO] [stdout]   Scenario: tk list -p 1 shows only priority 1 tasks
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "p1" with title "High priority task" and priority 1
[INFO] [stdout]    ✔  And I have a task called "p2" with title "Medium priority task" and priority 2
[INFO] [stdout]    ✔  When I list tasks filtered by priority 1
[INFO] [stdout]    ✔  Then the filtered list contains "High priority task"
[INFO] [stdout]    ✔  And the filtered list does not contain "Medium priority task"
[INFO] [stdout]   Scenario: tk list -t backend shows only tasks with that tag
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "be" with title "Backend service" and tag "backend"
[INFO] [stdout]    ✔  And I have a task called "fe" with title "Frontend UI" and tag "frontend"
[INFO] [stdout]    ✔  When I list tasks filtered by tag "backend"
[INFO] [stdout]    ✔  Then the filtered list contains "Backend service"
[INFO] [stdout]    ✔  And the filtered list does not contain "Frontend UI"
[INFO] [stdout]   Scenario: tk list -a shows all tasks including closed
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "open_t" with title "Open one"
[INFO] [stdout]    ✔  And I have a task called "done_t" with title "Closed one"
[INFO] [stdout]    ✔  And I close the task "done_t"
[INFO] [stdout]    ✔  When I list all tasks including closed
[INFO] [stdout]    ✔  Then the filtered list contains "Open one"
[INFO] [stdout]    ✔  And the filtered list contains "Closed one"
[INFO] [stdout]   Scenario: tk list by default hides closed tasks
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "active" with title "Active task"
[INFO] [stdout]    ✔  And I have a task called "finished" with title "Finished task"
[INFO] [stdout]    ✔  And I close the task "finished"
[INFO] [stdout]    ✔  When I list tasks with default settings
[INFO] [stdout]    ✔  Then the filtered list contains "Active task"
[INFO] [stdout]    ✔  And the filtered list does not contain "Finished task"
[INFO] [stdout] Feature: Inline editing of task fields
[INFO] [stdout]   Scenario: Edit title saves via API
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔> And a task "Sample task" exists via API
[INFO] [stdout]    ✔  When I PATCH the task with '{"title": "Updated title"}'
[INFO] [stdout]    ✔  Then the task title should be "Updated title"
[INFO] [stdout]   Scenario: Edit status saves via API
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔> And a task "Sample task" exists via API
[INFO] [stdout]    ✔  When I PATCH the task with '{"status": "in_progress"}'
[INFO] [stdout]    ✔  Then the task status should be "in_progress"
[INFO] [stdout]   Scenario: Edit priority saves via API
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔> And a task "Sample task" exists via API
[INFO] [stdout]    ✔  When I PATCH the task with '{"priority": 2}'
[INFO] [stdout]    ✔  Then the task priority should be 2
[INFO] [stdout]   Scenario: Edit assignee saves via API
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔> And a task "Sample task" exists via API
[INFO] [stdout]    ✔  When I PATCH the task with '{"assignee": "alice"}'
[INFO] [stdout]    ✔  Then the task assignee should be "alice"
[INFO] [stdout]   Scenario: Edit tags saves via API
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔> And a task "Sample task" exists via API
[INFO] [stdout]    ✔  When I PATCH the task with '{"tags": ["ui", "backend"]}'
[INFO] [stdout]    ✔  Then the task tags should include "ui"
[INFO] [stdout]    ✔  And the task tags should include "backend"
[INFO] [stdout]   Scenario: Edit description saves via API
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔> And a task "Sample task" exists via API
[INFO] [stdout]    ✔  When I PATCH the task with '{"description": "new desc"}'
[INFO] [stdout]    ✔  Then the task description should be "new desc"
[INFO] [stdout]   Scenario: Idempotent update with original value leaves field unchanged
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔> And a task "Sample task" exists via API
[INFO] [stdout]    ✔  When I PATCH the task with '{"title": "Sample task"}'
[INFO] [stdout]    ✔  Then the task title should be "Sample task"
[INFO] [stdout]   Scenario: Datetime fields are not affected by title update
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔> And a task "Sample task" exists via API
[INFO] [stdout]    ✔  Given the task created_at is stored
[INFO] [stdout]    ✔  When I PATCH the task with '{"title": "Different title"}'
[INFO] [stdout]    ✔  Then the task created_at should not change
[INFO] [stdout] Feature: Markdown rendering in web views
[INFO] [stdout]   Scenario: Task detail page renders markdown heading in description
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Heading task" and description "## Heading" as "heading-task"
[INFO] [stdout]    ✔  When I GET the HTML task "heading-task"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "<h2>Heading</h2>"
[INFO] [stdout]   Scenario: Task detail page renders inline code in description
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Code task" and description "Use `cargo build` to compile." as "code-task"
[INFO] [stdout]    ✔  When I GET the HTML task "code-task"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "<code>cargo build</code>"
[INFO] [stdout]   Scenario: Task detail page wraps rendered description in markdown-body class
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Styled task" and description "## Styled" as "styled-task"
[INFO] [stdout]    ✔  When I GET the HTML task "styled-task"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "markdown-body"
[INFO] [stdout]   Scenario: Task detail page shows fallback dash when description is absent
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "No-desc task" as "nodesc-task"
[INFO] [stdout]    ✔  When I GET the HTML task "nodesc-task"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "—"
[INFO] [stdout]   Scenario: Task modal fragment renders markdown heading in description
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Modal heading task" and description "## Modal Heading" as "modal-md-task"
[INFO] [stdout]    ✔  When I HTMX GET the task "modal-md-task"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "<h2>Modal Heading</h2>"
[INFO] [stdout]   Scenario: Task modal fragment shows fallback dash when description is absent
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Modal no-desc task" as "modal-nodesc-task"
[INFO] [stdout]    ✔  When I HTMX GET the task "modal-nodesc-task"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "—"
[INFO] [stdout]   Scenario: Epic detail page renders markdown heading in description
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Epic task" and description "## Epic Heading" as "epic-parent"
[INFO] [stdout]    ✔  And I created a subtask via API with title "Child task" under "epic-parent" as "epic-child"
[INFO] [stdout]    ✔  When I GET the HTML epic "epic-parent"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "<h2>Epic Heading</h2>"
[INFO] [stdout]   Scenario: Epic detail page wraps rendered description in markdown-body class
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Epic styled" and description "## Styled Epic" as "epic-styled"
[INFO] [stdout]    ✔  And I created a subtask via API with title "Epic child" under "epic-styled" as "epic-styled-child"
[INFO] [stdout]    ✔  When I GET the HTML epic "epic-styled"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "markdown-body"
[INFO] [stdout]   Scenario: Task detail page renders markdown in comments
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Comment markdown task" as "comment-md-task"
[INFO] [stdout]    ✔  And I posted a comment "## Comment Heading" on API task "comment-md-task"
[INFO] [stdout]    ✔  When I GET the HTML task "comment-md-task"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "<h2>Comment Heading</h2>"
[INFO] [stdout]   Scenario: Task detail page renders bold text in comment
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Bold comment task" as "bold-comment-task"
[INFO] [stdout]    ✔  And I posted a comment "**important**" on API task "bold-comment-task"
[INFO] [stdout]    ✔  When I GET the HTML task "bold-comment-task"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "<strong>important</strong>"
[INFO] [stdout] Feature: Notes as mutable working context
[INFO] [stdout]   Scenario: Setting notes on a task
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "work" with title "Feature work"
[INFO] [stdout]    ✔  When I update task "work" with notes "Started implementation"
[INFO] [stdout]    ✔  And I show task "work" in JSON
[INFO] [stdout]    ✔  Then the task details show notes "Started implementation"
[INFO] [stdout]   Scenario: Notes overwrite previous value
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "work" with title "Iterating"
[INFO] [stdout]    ✔  When I update task "work" with notes "First draft"
[INFO] [stdout]    ✔  And I update task "work" with notes "Revised approach"
[INFO] [stdout]    ✔  And I show task "work" in JSON
[INFO] [stdout]    ✔  Then the task details show notes "Revised approach"
[INFO] [stdout]   Scenario: Task without notes shows null
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  When I create a task with title "No notes task"
[INFO] [stdout]    ✔  And I show the task
[INFO] [stdout]    ✔  Then the task details have no notes
[INFO] [stdout] Feature: Filter tasks by parent
[INFO] [stdout]   Scenario: Listing tasks with --parent shows only children
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "epic" with title "Big project"
[INFO] [stdout]    ✔  And I have a task called "other" with title "Unrelated task"
[INFO] [stdout]    ✔  When I create a subtask of "epic" with title "Sub A"
[INFO] [stdout]    ✔  And I create a subtask of "epic" with title "Sub B"
[INFO] [stdout]    ✔  And I list tasks with parent "epic"
[INFO] [stdout]    ✔  Then the filtered list contains "Sub A"
[INFO] [stdout]    ✔  And the filtered list contains "Sub B"
[INFO] [stdout]    ✔  And the filtered list does not contain "Unrelated task"
[INFO] [stdout]    ✔  And the filtered list does not contain "Big project"
[INFO] [stdout] Feature: Task reparenting
[INFO] [stdout]   Scenario: Reparent a top-level task under an epic
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "epic" with title "Big project"
[INFO] [stdout]    ✔  And I have a task called "task1" with title "Some work"
[INFO] [stdout]    ✔  When I reparent "task1" under "epic"
[INFO] [stdout]    ✔  And I show task "task1" in JSON
[INFO] [stdout]    ✔  Then the JSON field "parent_id" equals the ID of "epic"
[INFO] [stdout]   Scenario: New parent is auto-tagged as epic on reparent
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "parent" with title "Becomes epic"
[INFO] [stdout]    ✔  And I have a task called "child" with title "Move me"
[INFO] [stdout]    ✔  When I reparent "child" under "parent"
[INFO] [stdout]    ✔  And I show task "parent" in JSON
[INFO] [stdout]    ✔  Then the task details include tag "epic"
[INFO] [stdout]   Scenario: Promote a subtask to top-level
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "epic" with title "Big project"
[INFO] [stdout]    ✔  And I have a subtask of "epic" called "sub" with title "Subtask"
[INFO] [stdout]    ✔  When I reparent "sub" under "none"
[INFO] [stdout]    ✔  And I show task "sub" in JSON
[INFO] [stdout]    ✔  Then the JSON field "parent_id" is null
[INFO] [stdout]   Scenario: Task retains original ID after reparent
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "epic" with title "Big project"
[INFO] [stdout]    ✔  And I have a task called "task1" with title "Keep my ID"
[INFO] [stdout]    ✔  When I store the ID of "task1"
[INFO] [stdout]    ✔  And I reparent "task1" under "epic"
[INFO] [stdout]    ✔  And I show task "task1" in JSON
[INFO] [stdout]    ✔  Then the task ID matches the stored ID
[INFO] [stdout]   Scenario: Reject self-parenting
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "task1" with title "Self ref"
[INFO] [stdout]    ✔  When I try to reparent "task1" under "task1"
[INFO] [stdout]    ✔  Then the command should fail
[INFO] [stdout]    ✔  And the error output contains "cannot reparent a task under itself"
[INFO] [stdout]   Scenario: Reject reparent under non-existent task
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "task1" with title "Orphan"
[INFO] [stdout]    ✔  When I run tk update for "task1" with --parent "tk-9999"
[INFO] [stdout]    ✔  Then the command should fail
[INFO] [stdout]    ✔  And the error output contains "parent task not found"
[INFO] [stdout]   Scenario: Reject reparent under a subtask (max depth 1)
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "epic" with title "Top level"
[INFO] [stdout]    ✔  And I have a subtask of "epic" called "sub" with title "Child"
[INFO] [stdout]    ✔  And I have a task called "task1" with title "Move me"
[INFO] [stdout]    ✔  When I try to reparent "task1" under "sub"
[INFO] [stdout]    ✔  Then the command should fail
[INFO] [stdout]    ✔  And the error output contains "already a subtask"
[INFO] [stdout]   Scenario: Reparent between epics
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given I have a task called "epic1" with title "First epic" and tag "epic"
[INFO] [stdout]    ✔  And I have a subtask of "epic1" called "sub" with title "Shared work"
[INFO] [stdout]    ✔  And I have a task called "epic2" with title "Second epic" and tag "epic"
[INFO] [stdout]    ✔  When I reparent "sub" under "epic2"
[INFO] [stdout]    ✔  And I show task "sub" in JSON
[INFO] [stdout]    ✔  Then the JSON field "parent_id" equals the ID of "epic2"
[INFO] [stdout] Feature: Web server
[INFO] [stdout]   Scenario: Server responds to index page
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given the web server is running
[INFO] [stdout]    ✔  When I GET "/"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "Tacks"
[INFO] [stdout]   Scenario: Server serves static assets
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given the web server is running
[INFO] [stdout]    ✔  When I GET "/static/htmx.min.js"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  When I GET "/static/pico.min.css"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]   Scenario: Server returns 404 for unknown routes
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given the web server is running
[INFO] [stdout]    ✔  When I GET "/nonexistent"
[INFO] [stdout]    ✔  Then the response status is 404
[INFO] [stdout]   Scenario: Server responds with HTML content type
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  Given the web server is running
[INFO] [stdout]    ✔  When I GET "/"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "<html"
[INFO] [stdout]    ✔  And the response body contains "</html>"
[INFO] [stdout] Feature: Task lifecycle
[INFO] [stdout]   Scenario: Creating a task shows it in the task list
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  When I create a task with title "Implement login"
[INFO] [stdout]    ✔  Then the task list contains "Implement login"
[INFO] [stdout]   Scenario: Showing a task displays its details
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  When I create a task with title "Write tests"
[INFO] [stdout]    ✔  And I show the task
[INFO] [stdout]    ✔  Then the task details show title "Write tests"
[INFO] [stdout]    ✔  And the task details show status "open"
[INFO] [stdout]   Scenario: Closing a task removes it from the active list
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  When I create a task with title "Fix bug"
[INFO] [stdout]    ✔  And I close the task
[INFO] [stdout]    ✔  Then the task list does not contain "Fix bug"
[INFO] [stdout]   Scenario: Closing a task marks it as done
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  When I create a task with title "Deploy service"
[INFO] [stdout]    ✔  And I close the task
[INFO] [stdout]    ✔  And I show the task
[INFO] [stdout]    ✔  Then the task details show status "done"
[INFO] [stdout]   Scenario: Creating a task with priority and tags
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔  When I create a task with title "Urgent fix" and priority 1 and tags "backend,critical"
[INFO] [stdout]    ✔  Then the task list contains "Urgent fix"
[INFO] [stdout]    ✔  When I show the task
[INFO] [stdout]    ✔  Then the task details show title "Urgent fix"
[INFO] [stdout]    ✔  And the task details show priority 1
[INFO] [stdout] Feature: REST API endpoints
[INFO] [stdout]   Scenario: POST /api/tasks creates a task and returns 201
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I POST "/api/tasks" with body '{"title":"Buy milk","priority":2}'
[INFO] [stdout]    ✔  Then the response status is 201
[INFO] [stdout]    ✔  And the response JSON has field "id"
[INFO] [stdout]    ✔  And the response JSON field "title" equals "Buy milk"
[INFO] [stdout]    ✔  And the response JSON field "status" equals "open"
[INFO] [stdout]   Scenario: POST /api/tasks with tags stores them on the task
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I POST "/api/tasks" with body '{"title":"Tagged task","tags":["backend","urgent"]}'
[INFO] [stdout]    ✔  Then the response status is 201
[INFO] [stdout]    ✔  And the response JSON field "title" equals "Tagged task"
[INFO] [stdout]   Scenario: POST /api/tasks with missing title returns 422
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I POST "/api/tasks" with body '{"priority":1}'
[INFO] [stdout]    ✔  Then the response status is 422
[INFO] [stdout]   Scenario: GET /api/tasks returns all open tasks
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Alpha task" as "alpha"
[INFO] [stdout]    ✔  And I created a task via API with title "Beta task" as "beta"
[INFO] [stdout]    ✔  When I GET "/api/tasks"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response JSON array contains a task with title "Alpha task"
[INFO] [stdout]    ✔  And the response JSON array contains a task with title "Beta task"
[INFO] [stdout]   Scenario: GET /api/tasks?status=done excludes open tasks
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Open task" as "open"
[INFO] [stdout]    ✔  And I created a task via API with title "Done task" as "done"
[INFO] [stdout]    ✔  And I closed the API task "done"
[INFO] [stdout]    ✔  When I GET "/api/tasks?status=done"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response JSON array contains a task with title "Done task"
[INFO] [stdout]    ✔  And the response JSON array does not contain a task with title "Open task"
[INFO] [stdout]   Scenario: GET /api/tasks?priority=1 filters by priority
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "P1 task" and priority 1 as "p1"
[INFO] [stdout]    ✔  And I created a task via API with title "P3 task" and priority 3 as "p3"
[INFO] [stdout]    ✔  When I GET "/api/tasks?priority=1"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response JSON array contains a task with title "P1 task"
[INFO] [stdout]    ✔  And the response JSON array does not contain a task with title "P3 task"
[INFO] [stdout]   Scenario: GET /api/tasks?tag=backend filters by tag
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Backend task" and tag "backend" as "be"
[INFO] [stdout]    ✔  And I created a task via API with title "Frontend task" and tag "frontend" as "fe"
[INFO] [stdout]    ✔  When I GET "/api/tasks?tag=backend"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response JSON array contains a task with title "Backend task"
[INFO] [stdout]    ✔  And the response JSON array does not contain a task with title "Frontend task"
[INFO] [stdout]   Scenario: GET /api/tasks/:id returns task details
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Detailed task" as "detail"
[INFO] [stdout]    ✔  When I GET the API task "detail"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response JSON field "title" equals "Detailed task"
[INFO] [stdout]    ✔  And the response JSON has field "id"
[INFO] [stdout]    ✔  And the response JSON has field "status"
[INFO] [stdout]    ✔  And the response JSON has field "priority"
[INFO] [stdout]   Scenario: GET /api/tasks/:id returns 404 for unknown id
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I GET "/api/tasks/tk-0000"
[INFO] [stdout]    ✔  Then the response status is 404
[INFO] [stdout]   Scenario: PATCH /api/tasks/:id updates the title
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Old title" as "updatable"
[INFO] [stdout]    ✔  When I PATCH the API task "updatable" with body '{"title":"New title"}'
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response JSON field "title" equals "New title"
[INFO] [stdout]   Scenario: PATCH /api/tasks/:id updates the status
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Status task" as "status-task"
[INFO] [stdout]    ✔  When I PATCH the API task "status-task" with body '{"status":"in_progress"}'
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response JSON field "status" equals "in_progress"
[INFO] [stdout]   Scenario: PATCH /api/tasks/:id updates the priority
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Priority task" as "prio-task"
[INFO] [stdout]    ✔  When I PATCH the API task "prio-task" with body '{"priority":1}'
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response JSON field "priority" equals 1
[INFO] [stdout]   Scenario: PATCH /api/tasks/:id returns 404 for unknown id
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I PATCH "/api/tasks/tk-0000" with body '{"title":"Ghost"}'
[INFO] [stdout]    ✔  Then the response status is 404
[INFO] [stdout]   Scenario: POST /api/tasks/:id/close closes a task
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Task to close" as "closeable"
[INFO] [stdout]    ✔  When I POST the close endpoint for API task "closeable" with body '{"reason":"done"}'
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response JSON field "status" equals "done"
[INFO] [stdout]    ✔  And the response JSON field "close_reason" equals "done"
[INFO] [stdout]   Scenario: POST /api/tasks/:id/close with a comment stores it
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Task with comment" as "comment-task"
[INFO] [stdout]    ✔  When I POST the close endpoint for API task "comment-task" with body '{"reason":"duplicate","comment":"Covered by tk-0001"}'
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response JSON field "status" equals "done"
[INFO] [stdout]   Scenario: POST /api/tasks/:id/close with invalid reason returns 422
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Bad close task" as "bad-close"
[INFO] [stdout]    ✔  When I POST the close endpoint for API task "bad-close" with body '{"reason":"bogus"}'
[INFO] [stdout]    ✔  Then the response status is 422
[INFO] [stdout]   Scenario: POST /api/tasks/:id/close returns 404 for unknown id
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I POST "/api/tasks/tk-0000/close" with body '{"reason":"done"}'
[INFO] [stdout]    ✔  Then the response status is 404
[INFO] [stdout]   Scenario: GET /api/tasks/ready returns unblocked tasks
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Unblocked task" as "free"
[INFO] [stdout]    ✔  When I GET "/api/tasks/ready"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response JSON array contains a task with title "Unblocked task"
[INFO] [stdout]   Scenario: GET /api/tasks/ready excludes blocked tasks
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Blocker" as "blocker"
[INFO] [stdout]    ✔  And I created a task via API with title "Blocked by blocker" as "blocked"
[INFO] [stdout]    ✔  And I added API dependency so "blocked" is blocked by "blocker"
[INFO] [stdout]    ✔  When I GET "/api/tasks/ready"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response JSON array does not contain a task with title "Blocked by blocker"
[INFO] [stdout]   Scenario: GET /api/tasks/ready?limit=1 returns at most one task
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Ready A" as "ra"
[INFO] [stdout]    ✔  And I created a task via API with title "Ready B" as "rb"
[INFO] [stdout]    ✔  When I GET "/api/tasks/ready?limit=1"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response JSON array has length 1
[INFO] [stdout]   Scenario: GET /api/tasks/blocked returns tasks with open blockers
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Prerequisite" as "prereq"
[INFO] [stdout]    ✔  And I created a task via API with title "Waiting task" as "waiter"
[INFO] [stdout]    ✔  And I added API dependency so "waiter" is blocked by "prereq"
[INFO] [stdout]    ✔  When I GET "/api/tasks/blocked"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response JSON array contains a task with title "Waiting task"
[INFO] [stdout]   Scenario: GET /api/tasks/blocked excludes unblocked tasks
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Free task" as "free2"
[INFO] [stdout]    ✔  When I GET "/api/tasks/blocked"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response JSON array does not contain a task with title "Free task"
[INFO] [stdout]   Scenario: POST /api/tasks/:id/deps adds a dependency
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Dep parent" as "dep-parent"
[INFO] [stdout]    ✔  And I created a task via API with title "Dep child" as "dep-child"
[INFO] [stdout]    ✔  When I POST the deps endpoint for API task "dep-child" with body '{"parent_id":"dep-parent"}'
[INFO] [stdout]    ✔  Then the response status is 201
[INFO] [stdout]   Scenario: POST /api/tasks/:id/deps returns 409 on cycle
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Cycle A" as "cyc-a"
[INFO] [stdout]    ✔  And I created a task via API with title "Cycle B" as "cyc-b"
[INFO] [stdout]    ✔  And I added API dependency so "cyc-b" is blocked by "cyc-a"
[INFO] [stdout]    ✔  When I POST the deps endpoint for API task "cyc-a" with body '{"parent_id":"cyc-b"}'
[INFO] [stdout]    ✔  Then the response status is 409
[INFO] [stdout]   Scenario: DELETE /api/tasks/:child/deps/:parent removes a dependency
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Parent dep" as "rem-parent"
[INFO] [stdout]    ✔  And I created a task via API with title "Child dep" as "rem-child"
[INFO] [stdout]    ✔  And I added API dependency so "rem-child" is blocked by "rem-parent"
[INFO] [stdout]    ✔  When I DELETE the API dependency from "rem-child" to "rem-parent"
[INFO] [stdout]    ✔  Then the response status is 204
[INFO] [stdout]   Scenario: POST /api/tasks/:id/comments adds a comment
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Commented task" as "comm-task"
[INFO] [stdout]    ✔  When I POST the comments endpoint for API task "comm-task" with body '{"body":"Work in progress"}'
[INFO] [stdout]    ✔  Then the response status is 201
[INFO] [stdout]    ✔  And the response JSON has field "id"
[INFO] [stdout]    ✔  And the response JSON field "body" equals "Work in progress"
[INFO] [stdout]   Scenario: GET /api/tasks/:id/comments lists all comments
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Multi-comment task" as "multi-comm"
[INFO] [stdout]    ✔  And I posted a comment "First note" on API task "multi-comm"
[INFO] [stdout]    ✔  And I posted a comment "Second note" on API task "multi-comm"
[INFO] [stdout]    ✔  When I GET the comments endpoint for API task "multi-comm"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response JSON array contains a comment with body "First note"
[INFO] [stdout]    ✔  And the response JSON array contains a comment with body "Second note"
[INFO] [stdout]   Scenario: GET /api/tasks/:id/comments returns empty array when no comments
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "No-comment task" as "no-comm"
[INFO] [stdout]    ✔  When I GET the comments endpoint for API task "no-comm"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response JSON is an empty array
[INFO] [stdout]   Scenario: GET /api/stats returns structured counts
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Stats task" as "stats1"
[INFO] [stdout]    ✔  When I GET "/api/stats"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response JSON has field "by_status"
[INFO] [stdout]    ✔  And the response JSON has field "by_priority"
[INFO] [stdout]    ✔  And the response JSON has field "by_tag"
[INFO] [stdout]   Scenario: GET /api/stats reflects closed tasks in done count
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Open one" as "so1"
[INFO] [stdout]    ✔  And I created a task via API with title "Done one" as "sd1"
[INFO] [stdout]    ✔  And I closed the API task "sd1"
[INFO] [stdout]    ✔  When I GET "/api/stats"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response JSON nested field "by_status.done" equals 1
[INFO] [stdout]   Scenario: GET /api/tasks/:id/children returns subtasks
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Epic parent" as "epic"
[INFO] [stdout]    ✔  And I created a subtask via API with title "Child one" under "epic" as "child1"
[INFO] [stdout]    ✔  And I created a subtask via API with title "Child two" under "epic" as "child2"
[INFO] [stdout]    ✔  When I GET the children endpoint for API task "epic"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response JSON array contains a task with title "Child one"
[INFO] [stdout]    ✔  And the response JSON array contains a task with title "Child two"
[INFO] [stdout]   Scenario: GET /api/tasks/:id/children returns empty array for task with no children
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Childless task" as "childless"
[INFO] [stdout]    ✔  When I GET the children endpoint for API task "childless"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response JSON is an empty array
[INFO] [stdout] Feature: Web view pages
[INFO] [stdout]   Scenario: Task list page returns HTML
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I GET "/tasks"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response content type is "text/html"
[INFO] [stdout]    ✔  And the response body contains "<html"
[INFO] [stdout]   Scenario: Task list page contains a task table
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I GET "/tasks"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "<table"
[INFO] [stdout]   Scenario: Task list page shows created task titles
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Write documentation" as "doc-task"
[INFO] [stdout]    ✔  And I created a task via API with title "Fix login bug" as "bug-task"
[INFO] [stdout]    ✔  When I GET "/tasks"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "Write documentation"
[INFO] [stdout]    ✔  And the response body contains "Fix login bug"
[INFO] [stdout]   Scenario: Task list page filters by status=open
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Open task" as "open-t"
[INFO] [stdout]    ✔  And I created a task via API with title "Done task" as "done-t"
[INFO] [stdout]    ✔  And I closed the API task "done-t"
[INFO] [stdout]    ✔  When I GET "/tasks?status=open"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "Open task"
[INFO] [stdout]   Scenario: Task list page filters by priority
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "High priority task" and priority 1 as "p1-view"
[INFO] [stdout]    ✔  And I created a task via API with title "Low priority task" and priority 3 as "p3-view"
[INFO] [stdout]    ✔  When I GET "/tasks?priority=1"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "High priority task"
[INFO] [stdout]   Scenario: Task detail page returns HTML with task title
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Detail view task" as "detail-task"
[INFO] [stdout]    ✔  When I GET the HTML task "detail-task"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response content type is "text/html"
[INFO] [stdout]    ✔  And the response body contains "Detail view task"
[INFO] [stdout]   Scenario: Task detail page shows task status and priority
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Status check task" and priority 2 as "status-view"
[INFO] [stdout]    ✔  When I GET the HTML task "status-view"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "open"
[INFO] [stdout]    ✔  And the response body contains "2"
[INFO] [stdout]   Scenario: Task detail page shows task description
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Described task" and description "This task has a detailed description" as "desc-task"
[INFO] [stdout]    ✔  When I GET the HTML task "desc-task"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "This task has a detailed description"
[INFO] [stdout]   Scenario: Task detail page returns 404 for unknown id
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I GET "/tasks/tk-0000"
[INFO] [stdout]    ✔  Then the response status is 404
[INFO] [stdout]   Scenario: Board page returns HTML
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I GET "/board"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response content type is "text/html"
[INFO] [stdout]    ✔  And the response body contains "<html"
[INFO] [stdout]   Scenario: Board page has four status column headers
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I GET "/board"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "Open"
[INFO] [stdout]    ✔  And the response body contains "In Progress"
[INFO] [stdout]    ✔  And the response body contains "Blocked"
[INFO] [stdout]    ✔  And the response body contains "Done"
[INFO] [stdout]   Scenario: Board page shows tasks in their correct columns
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Open board task" as "board-open"
[INFO] [stdout]    ✔  When I GET "/board"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "Open board task"
[INFO] [stdout]   Scenario: Epics page returns HTML
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I GET "/epics"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response content type is "text/html"
[INFO] [stdout]    ✔  And the response body contains "<html"
[INFO] [stdout]   Scenario: Epics page shows epic progress table
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I GET "/epics"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "<table"
[INFO] [stdout]   Scenario: Epics page lists epics with subtasks
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Main epic" as "epic-parent"
[INFO] [stdout]    ✔  And I created a subtask via API with title "Epic subtask" under "epic-parent" as "epic-child"
[INFO] [stdout]    ✔  When I GET "/epics"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "Main epic"
[INFO] [stdout]   Scenario: Create task form returns HTML
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I GET "/tasks/new"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response content type is "text/html"
[INFO] [stdout]    ✔  And the response body contains "<html"
[INFO] [stdout]   Scenario: Create task form contains a form element
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I GET "/tasks/new"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "<form"
[INFO] [stdout]   Scenario: Create task form has title input field
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I GET "/tasks/new"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "title"
[INFO] [stdout]   Scenario: Create task form has priority input field
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I GET "/tasks/new"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "priority"
[INFO] [stdout]   Scenario: Create task form has description input field
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I GET "/tasks/new"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "description"
[INFO] [stdout]   Scenario: HTMX request for task detail returns fragment without full page wrapper
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Modal task" as "modal-task"
[INFO] [stdout]    ✔  When I HTMX GET the task "modal-task"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "Modal task"
[INFO] [stdout]    ✔  And the response body contains "<article"
[INFO] [stdout]    ✔  And the response body does not contain "<!DOCTYPE"
[INFO] [stdout]    ✔  And the response body does not contain "<html"
[INFO] [stdout]   Scenario: HTMX fragment includes status badge
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Badge task" as "badge-task"
[INFO] [stdout]    ✔  When I HTMX GET the task "badge-task"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "badge status-"
[INFO] [stdout]   Scenario: HTMX fragment includes close button
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Closable task" as "close-task"
[INFO] [stdout]    ✔  When I HTMX GET the task "close-task"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "aria-label="
[INFO] [stdout]   Scenario: Direct request for task detail returns full page
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  Given I created a task via API with title "Full page task" as "full-task"
[INFO] [stdout]    ✔  When I GET the HTML task "full-task"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "<!DOCTYPE html"
[INFO] [stdout]    ✔  And the response body contains "Full page task"
[INFO] [stdout]   Scenario: Task list page includes navigation
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I GET "/tasks"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "<nav"
[INFO] [stdout]   Scenario: Board page includes navigation
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I GET "/board"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "<nav"
[INFO] [stdout]   Scenario: Epics page includes navigation
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I GET "/epics"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "<nav"
[INFO] [stdout]   Scenario: Task list page includes full HTML document structure
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I GET "/tasks"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "<!DOCTYPE html"
[INFO] [stdout]    ✔  And the response body contains "<head"
[INFO] [stdout]    ✔  And the response body contains "<body"
[INFO] [stdout]    ✔  And the response body contains "</html>"
[INFO] [stdout]   Scenario: Board page includes full HTML document structure
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I GET "/board"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "<!DOCTYPE html"
[INFO] [stdout]    ✔  And the response body contains "</html>"
[INFO] [stdout]   Scenario: Task list page has link to board view
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I GET "/tasks"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "/board"
[INFO] [stdout]   Scenario: Task list page has link to epics view
[INFO] [stdout]    ✔> Given a tacks database is initialized
[INFO] [stdout]    ✔> And the web server is running
[INFO] [stdout]    ✔  When I GET "/tasks"
[INFO] [stdout]    ✔  Then the response status is 200
[INFO] [stdout]    ✔  And the response body contains "/epics"
[INFO] [stdout] [Summary]
[INFO] [stdout] 24 features
[INFO] [stdout] 195 scenarios (195 passed)
[INFO] [stdout] 1229 steps (1229 passed)
[INFO] [stderr]    Doc-tests tacks
[INFO] [stdout] 
[INFO] [stdout] running 0 tests
[INFO] [stdout] 
[INFO] [stdout] test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
[INFO] [stdout] 
[INFO] running `Command { std: "docker" "inspect" "78970a144f9e563cb118851caec0379738db551dfcc39dbad28a902dd8c96592", kill_on_drop: false }`
[INFO] running `Command { std: "docker" "rm" "-f" "78970a144f9e563cb118851caec0379738db551dfcc39dbad28a902dd8c96592", kill_on_drop: false }`
[INFO] [stdout] 78970a144f9e563cb118851caec0379738db551dfcc39dbad28a902dd8c96592
