Skip to content

change check rejects unchanged Git LFS assets through the whole-workspace evidence digest #789

Description

@0xGaspar

Summary

SpecSync 6.0.0 cannot finish change check in a repository containing unchanged, tracked Git LFS assets, even when the change only touches code/specs and the asset directories are outside the configured source scope and listed in SDD ignored_paths.

Confirmed by rerunning the real command in CorvidLabs/peck and tracing the matching v6.0.0 source. This is a workspace-evidence compatibility problem, not a Godot failure or missing requirement-evidence row.

Reproduced environment

  • macOS; specsync --version → specsync 6.0.0.
  • Consumer: CorvidLabs/peck at a3f08ca, branch refactor/enemy-scene-presentation.
  • Approved change: let-enemy-scenes-own-animation-facing-and-damage-presentation-without-changing-combat-rules.
  • The change's tasks and requirement-evidence table are populated. The strict module/spec coverage check passes; all 18 Godot suites passed separately.
  • No asset archives or NFT sources changed between the refactor base 03a1082 and this head.

Relevant .specsync/config.toml:

source_dirs = ["godot"]
source_extensions = ["gd"]
exclude_dirs = [".godot", "build", "content", "fonts"]

Relevant .specsync/sdd.json:

{
  "meaningful_paths": ["godot/", "tools/asset-library/", "scripts/godot-preview-plugin.mjs", "fledge.toml", ".specsync/sdd.json", ".specsync/config.toml", ".specsync/registry.toml", ".specsync/version"],
  "ignored_paths": [".specsync/", "specs/", "assets/archives/", "assets/nfts/"]
}

.gitattributes:

assets/archives/*.tar.zst filter=lfs diff=lfs merge=lfs -text
assets/nfts/**/*.png filter=lfs diff=lfs merge=lfs -text

Actual reproduction

In that checkout, using the existing installed binary:

specsync change check let-enemy-scenes-own-animation-facing-and-damage-presentation-without-changing-combat-rules

Exits 1:

error: Git `filter` attribute is not supported for canonical evidence: `assets/archives/2d-animals-mega-pack-1.tar.zst`

Checks establishing why this is unrelated to the implementation:

git check-attr filter -- assets/archives/2d-animals-mega-pack-1.tar.zst
# assets/archives/2d-animals-mega-pack-1.tar.zst: filter: lfs

git diff --name-only 03a1082 a3f08ca -- assets/archives assets/nfts
# no output

fledge run spec-check
# 4 specs passed, 0 warnings/failures; 90/90 source coverage

The preceding player-scene change hits the same archive/error. No LFS fetching or tool installation is necessary to establish the attribute rejection; it also occurred when the local archives were LFS pointer files. Current reproduction confirms attribute rejection without modifying the asset configuration.

Source trace (v6.0.0)

  1. check_change verification construction records workspace_digest: project_input_digest(root)? after the spec/code evaluation.
  2. project_input_digest_uncached calls stable_discovered_evidence(root, None, ...), i.e. without scoped paths. Git inventory includes tracked files; filtering here uses the hardcoded volatile-path predicate, not SDD ignored_paths.
  3. stable_discovered_evidence_with_hook_internal discovers that inventory and passes it into Git inspection.
  4. inspect_git_candidates validates content attributes for clean, present regular files.
  5. validate_git_attribute_output rejects any filter value other than unspecified/unset, including lfs, producing the exact observed error.

The same implementation was present in the inspected upstream main source at c8518b9b91176c664256d290fed4310ec0c12929. I did not build or run a separate upstream binary.

Expected outcome / acceptance

  • A supported, integrity-preserving route for completing scoped changes in repositories with Git LFS assets.
  • Explicit canonical semantics for LFS pointer versus hydrated content, or a documented evidence-scope policy that safely excludes unrelated asset trees. Do not blanket-disable content-attribute validation or make protected evidence silently skippable.
  • Regression coverage for an otherwise valid approved source-only change plus an unchanged tracked LFS pointer outside its scope and in ignored_paths.
  • Coverage for both pointer-only and hydrated checkouts, and an in-scope LFS input so the chosen policy cannot hide meaningful changes.
  • Clarify that current ignored_paths controls meaningful-change policy but does not exclude files from the whole-workspace digest. The current error gives no usable recovery path for this normal repository layout.

Duplicate check

Searched all-state issue results for LFS and the exact phrase canonical evidence, and inspected recent reports. No matching issue was returned. Peck's earlier consumer-side report is CorvidLabs/peck#13; that ticket is closed, but the failure remains reproducible with the installed 6.0.0 binary and the configurations above.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:product-bugRuntime or CLI behavior is incorrectbugSomething isn't workingpriority:p2Important but not immediately release-blockingscope:specsync-6Applies to current SpecSync 6 behavior or release contract

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions