1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
//! Per-resource bookkeeping shared by every wave width: the FJ-2701 input
//! cache and the FJ-2301 run metadata.
//!
//! Refs #412: both used to live in `resource_ops.rs` and be reachable only from
//! the width-1 path, so a `cache: true` task re-ran under `--parallel` and a
//! wide wave left `runs/<id>/meta.yaml` with an empty `resources:` map. They are
//! called from both widths now, and live here so `resource_ops.rs` stays under
//! the 500-line ceiling.
use *;
/// FJ-2701: Check if task inputs are unchanged since last successful run.
///
/// Returns Some(message) if the task should be skipped (cache hit).
/// Refs #412: shared with the wide-wave prepare phase, which used to skip the
/// cache entirely — the same `cache: true` task re-ran under `--parallel`.
///
/// forjar#501, three things the reader must agree with the writer on:
/// * the MACHINE. The lock's `input_hash` was taken on THIS host. For a
/// machine this host does not answer for it is a hash of the wrong tree
/// (or, since #501, absent), so the cache has no answer and the task runs
/// there — skipping a remote run from the controller's files was the
/// forjar#485 shape at this site.
/// * the BASE. `record_io_hashes` hashes relative to `probe_base_dir` —
/// `working_dir` — and `hash_inputs` folds the expanded path into the hash,
/// so hashing against the state directory's parent could never match it:
/// the cache was dead, and its deadness hid the machine half.
/// * the QUESTION. Inputs alone were the FJ-2701 test; the first live run of
/// it skipped a task whose output had been deleted (the plan said `output
/// artifact missing`, apply said `unchanged`). The reader now asks exactly
/// what the planner asks — [`probe_resource`] against what the lock
/// recorded, through [`staleness_reason`] — so a hit means inputs unchanged
/// AND outputs present and unmodified.
///
/// [`probe_resource`]: crate::core::task::probe::probe_resource
/// [`staleness_reason`]: crate::core::task::staleness_reason
pub
/// forjar#501: a cache hit satisfies the CURRENT spec. The row keeps its
/// observed I/O hashes — "inputs unchanged, outputs present" is what the hit
/// means — and takes the spec hash of the resource it was asked to converge,
/// so the next plan settles on `NoOp`. Measured before this: the plan said
/// `1 to change` and apply said `1 unchanged`, on every run, forever.
pub
/// Update meta.yaml with resource status after execution.
pub