Task — engineering-spec@1

Status page provenance stamp becomes a corpus fingerprint (byte-stable)

doneTASK-IMP-082
module improvement · class product · priority p0 · created 2026-07-16 · shipped 2026-07-16
depends on none · blocks none

TASK-IMP-082: Status page provenance stamp becomes a corpus fingerprint (byte-stable)

Summary

Change the status renderer's default provenance stamp from the current git HEAD to a deterministic fingerprint of the render inputs themselves. Today every bare re-render on an advanced HEAD differs by exactly the stamp, and committing the page advances HEAD again - a self-chasing loop the renderer's own comment describes but only mitigates behind an env pin nobody sets. A corpus fingerprint ends the chase in every flow: re-renders are byte-stable until the task corpus, CHANGELOG, or VERSION actually changes.

Problem

The stamp default is repo position, not corpus content:

<untrusted_content source="tools/docs-site/render-status-hub.mjs:304-307"> // CYBEROS_COMMIT pins the provenance stamp. A page staged by the pre-commit hook necessarily // carries the PARENT commit's sha (the new one does not exist yet), so a later re-render would // differ from it by the stamp alone. Pinning lets a freshness check compare CONTENT. const COMMIT = process.env.CYBEROS_COMMIT || gitCommit(ROOT); </untrusted_content>

No production caller (install, migrate, status-page.sh, run-gates, the pre-commit hooks) sets CYBEROS_COMMIT, so the mitigation is dead code in practice. Reproduced twice on the sachviet consumer repo on 2026-07-16: each re-install on an unchanged corpus dirtied the tree by one stamp; committing that (df24cb3) armed the next diff. A tracked, generated file that can never be clean is a standing false-positive in every git status.

Proposed Solution

Make the default stamp a content fingerprint: the first 12 hex chars of sha256 over the ordered render inputs the script already reads (every task spec's bytes in sorted path order, CHANGELOG.md, VERSION). Properties: no git invocation on the default path, no wall clock, identical corpus in means identical page out - including the hook flow, because the page itself is not a render input. CYBEROS_COMMIT keeps winning when set, so any caller that wants a git sha can still pin one. The visible label shape ("built from <stamp>", footer, cs-data commit field) stays as is; only the value's derivation changes.

Alternatives Considered

Success Metrics

Scope

In scope: the stamp derivation in render-status-hub.mjs, its three output surfaces (header meta, footer, cs-data JSON), and a regression suite.

Out of scope / Non-Goals

Dependencies

AI Authorship Disclosure

1. Description (normative)

2. Acceptance criteria

3. Edge cases

4. Out of scope / non-goals

Duplicated intentionally with ## Scope for template conformance: hooks, freshness CLI, and all other renderer features are untouched.

5. Protected invariants this task must not weaken

End of TASK-IMP-082.

Audit

TASK-IMP-082-status-stamp-byte-stable spec audit - audit_rubric@2.0

Families walked: FM (all pass - task@1, title <=72, closed enums, ISO created_at, no UNREVIEWED markers, corpus extras additive), SEC (seven H2s present and non-empty, one H1), COND (COND-004 three labeled bullets present; others not triggered), QA (metrics carry baseline/target/deadline grounded in run evidence; >=3 distinct alternatives; Out-of-scope subsection; no unsourced numeric targets; no cross-team claims), SAFE (one sourced block, closed, unnested, clean scan), TRACE (every numbered clause cited by >=1 AC; every AC names a test or a justified ops verification; every test path is in new_files or exists on disk; draft status exempts TRACE-004; no deferred slices).

ISSUE ISS-001 (TRACE-001, fixed): the empty-corpus edge case cited t02 without the AC naming that shape - AC 2 now says "on a populated AND an empty corpus". ISSUE ISS-002 (QA-004, wontfix-info): the fp- prefix length choice (12 hex) is a design constant, not a metric; documented in 1.1, no target fabricated.

SUMMARY verdict: pass issues_open: 0 issues_human: 0 iterations: 2 next_action: ship

§gate-log

Populated during implementation (ship-tasks testing phase).