I2523 — A node's key is computed from the bytes its producer reads, the index membership it enumerates and the generation of the executable
Give every node of the derivation graph a deterministic SHA-256 key over its identity, its operation version, its declared inputs as the producer actually reads them, the keys of the nodes it depends on and the generation of the executable, with a schema version of its own.
BLOCKED wave 2 · p1 · implementation profile · runs alone
Blocked. This issue cannot start until I2522 is done. The status is derived from that, not declared.
Objective
Give every node of the derivation graph a deterministic SHA-256 key over its identity, its operation version, its declared inputs as the producer actually reads them, the keys of the nodes it depends on and the generation of the executable, with a schema version of its own.
Why
campaigns/majordomus-incremental-derive-prompt-pack/03_03_HASHES_FINGERPRINT.md asks for length-framed content keys that honour both git index membership and working-tree bytes and never rely on modification time or on the HEAD tree alone. The repository already has both halves in separate places and neither per producer: apps/majordomus-cli/src/generation.rs frames path and content lengths into a SHA-256 over the crate's sources, and scripts/generate-site-data hashes one list of every input of the whole site. majordomus generate enumerates through the index (--discovery vcs) and reads working-tree bytes, which scripts/derive states as the reason it refuses untracked files, so a key over either alone would be wrong.
Current state
One fingerprint covers all of stage B and none covers a target of majordomus generate. A change to any input of the site moves the one hash; a change to an input of a single target moves nothing that can be read.
Desired state
derivation::key computes, for a node, a digest over a domain separator, the key schema version, the node id, the operation version, each input in canonical order as kind, path, presence and length-framed bytes, the dependency keys, and crate_generation of the tree. A missing file differs from an empty one, a rename moves the key, a path entering or leaving the index moves the key of a node that enumerates it, a symbolic link is hashed as a link and never followed outside the root, and an input kind the function cannot read makes the node always regenerate. Amended on 2026-10-18 by the derive-performance plan: the key covers negative lookups (a path that would be enumerated if it were created), creation and deletion; derive explain reports the exact invalidation frontier of a change; and a detected fact never authorises a materialisation, so facts, inference, policy and permission stay separate.
Scope
- apps/majordomus-cli/src/derivation/key.rs
- apps/majordomus-cli/src/derivation/mod.rs
- apps/majordomus-cli/src/generation.rs
- apps/majordomus-cli/src/git
- apps/majordomus-cli/tests/derivation_key.rs
- apps/majordomus-cli/tests/properties.rs
- .ai/repo/project/issues/I2523.yaml
Out of scope
- Changing the fingerprint committed in site/data/generated/source.json or any stamp a generated file carries; those are I1409's
- A new hash algorithm or a new cryptographic dependency; the crate already uses sha2
- Remembering keys by modification time or size
Dependencies
What waits on this
Acceptance criteria
- The key is equal for every permutation of the input declarations and of directory listing order
- Editing, renaming, deleting or staging a new file under a declared selector changes the key, and the same change to an undeclared path does not
- A missing declared file and an empty one give different keys
- A different crate generation or operation version changes every key that depends on it
- A symbolic link pointing outside the repository root is not read, and its node is reported as always regenerating
- For each node, the declared inputs contain every path the producer was observed to read in I2521
- Creating a path that a node would enumerate, and deleting one it enumerated, each move that node's key
Validation
- bin/majordomus plan validate
- cargo test --manifest-path apps/majordomus-cli/Cargo.toml --lib derivation::key
- cargo test --manifest-path apps/majordomus-cli/Cargo.toml --test derivation_key
- cargo test --manifest-path apps/majordomus-cli/Cargo.toml --doc generation
Evidence required
- node_key_property_tests
- declared_inputs_cover_observed_reads
Evidence
None recorded. Every token above needs a command or an artifact behind it before this issue can be completed; narrative is refused.
Timeline
- started
- —
- verified
- —
- completed
- —
Those three fields, the evidence above and the state of the dependencies are all the status is made of. There is no status field to disagree with them.
Canonical record: .ai/repo/project/issues/I2523.yaml. Read it back with majordomus plan show I2523.