Skip to content

I2847 — every file the site generator reads by a literal path is one of its declared inputs

scripts/generate-site-data declares among its inputs every file it reads by a literal \"$ROOT/...\" path: the programs it sources or runs (lib/*.sh, lib/*.awk, scripts/lib/*.jq, scripts/lib/*.awk, scripts/pages, itself), the hand-written pages under site/content-src, the workflow skeletons it counts, the Pages model, distribution.json and AGENTS.md. docs/generated/artifacts.json is read too but is not an input: derive's stage C rewrites it after this script runs, so hashing it would move the fingerprint on every derive (the order itself is I2864). Case 3246 refuses a literal read that the list does not cover.

READY wave 0 · p1 · implementation profile · runs alone

Part of a-derive-does-only-the-work-its-inputs-changed — A derive does only the work its inputs changed, and can say why.

Ready. Every dependency is done, so majordomus plan start I2847 will be accepted.

Objective

scripts/generate-site-data declares among its inputs every file it reads by a literal \"$ROOT/...\" path: the programs it sources or runs (lib/*.sh, lib/*.awk, scripts/lib/*.jq, scripts/lib/*.awk, scripts/pages, itself), the hand-written pages under site/content-src, the workflow skeletons it counts, the Pages model, distribution.json and AGENTS.md. docs/generated/artifacts.json is read too but is not an input: derive's stage C rewrites it after this script runs, so hashing it would move the fingerprint on every derive (the order itself is I2864). Case 3246 refuses a literal read that the list does not cover.

Why

Found on 2026-10-21 while measuring the derive for I2521. The input fingerprint that `scripts/pages current` compares was computed from a list that missed all of the files named above. Editing a hand-written page, a .jq projection or the Pages model left site/data/generated reading as current while it was stale. Only a full derive-check would catch it, and I2880 (skip stage B when the fingerprint matches) would have published the stale data. Agreed with a3, d3 (I0832) and 9c (I2880): 3e owns the INPUTS block, and I2880 waits for this.

Current state

The INPUTS list held 2093 entries and omitted the generator's own programs and several files it reads by literal path. Nothing checked the list against what the script reads.

Desired state

The INPUTS list covers every literal \"$ROOT/...\" read of the script. Case 3246 reads the script and refuses any such read, of a file or of every tracked file under a directory, that the list does not cover, unless it is an output the script writes or docs/generated/artifacts.json, which a later stage writes (I2864). Dropping a covered glob from the list is refused with the file named.

Scope

  • scripts/generate-site-data
  • test/cases/3246_every_file_the_site_generator_reads_is_an_input.sh
  • .ai/repo/project/issues/I2847.yaml

Out of scope

  • Paths the script builds from a variable (\"$ROOT/$path\", \"$ROOT/docs/$p\") and what the tool reads when the script calls it. Judging those needs a file-access trace, which is I2521's observed-reads measurement.
  • Any other change to scripts/generate-site-data: d3's I0832 owns its repeated work and I2880 its skip; neither touches INPUTS.

Dependencies

None. This issue is a root of the graph.

Acceptance criteria

  • Every literal \"$ROOT/...\" file read of scripts/generate-site-data is in its --inputs, or is one of its outputs
  • Every tracked file under a directory the script names by a literal path is in --inputs, unless the directory is an output
  • Removing scripts/lib/*.jq from the list makes case 3246 fail and name scripts/lib/cli-site.jq

Validation

  • bin/majordomus plan validate
  • bash test/run.sh 3246_every_file_the_site_generator_reads_is_an_input 10_site_data 56_derived_current_gate

Evidence required

  • every_literal_read_is_an_input_case

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/I2847.yaml. Read it back with majordomus plan show I2847.

Searches the titles and descriptions of every page this site publishes.