You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
two-layer/orphan: pre-commit hook says casting/ belongs on squad-state, but state tools and casting writer keep registry/history on disk #2229
With stateBackend: "two-layer", three parts of Squad disagree about where .squad/casting/registry.json and history.json should live. As a result, no supported path persists a casting change.
packages/squad-cli/src/cli/commands/install-hooks.ts: the pre-commit hook refuses any staged path matching ^\.squad/(decisions\.md|agents/.+/history\.md|casting/|routing/) unless SQUAD_SYNC_ACTIVE is set. Its message says: "These paths belong on the 'squad-state' orphan branch, not in your normal commits". The post-commit comment says it syncs "decisions, histories, casting" onto squad-state.
packages/squad-sdk/src/tools/index.ts: MUTABLE_STATE_PATHS includes only casting/policy.json. squad_state_write key=casting/history.json is rejected with: "casting registry/history pair must only be changed through the atomic casting protocol".
packages/squad-sdk/src/casting/durable-registry.ts: commitCastingRegistryPair(castingDir, …) writes the pair to the on-disk .squad/casting/ directory. cast add and preset scaffold both use it.
Observed in a consumer repo
The squad-state branch had README.md, decisions.md, decisions/inbox/* and agents/*/history.md. It had no casting/ path, so nothing had moved the pair there.
squad_state_read key=casting/registry.json returned "State key not found". squad_state_list dir=casting returned an empty list.
To persist a registry model update, we had to call commitCastingRegistryPair and commit with SQUAD_SYNC_ACTIVE=1 to get past the hook.
Separate small bug
squad_state_list with no dir returns "Failed to list state: State key must not contain . or .. path segments". A root listing should either succeed or report a clearer error.
Questions
Under the two-layer and orphan backends, where should the canonical casting registry/history pair live: on disk in the working tree, or on the squad-state branch?
If on disk, should the pre-commit hook allowlist casting/registry.json, casting/history.json and the commit marker (and fix the hook/post-commit wording)?
If on squad-state, should the atomic writer target the state backend, and is a migration needed?
Versions: the source references above are from the indexed main commit 89d6302. The installed CLI (winget squad.exe) version was not checked against it.
Adding version-pinned ownership evidence for 1.1.0, plus a related documentation/enforcement mismatch. All links below use release commit c24da2aad2ab7576f6b68dec2bc50b2fe2dc7a8a.
The intended casting placement is explicitly stated in SDK initialization: casting is authoritative identity, belongs on main, and must not be ignored. The migration helper likewise deliberately leaves static casting/* files untouched.
However, the generated pre-commit hook rejects the entire .squad/casting/ directory and says those files belong on squad-state. The release's own state-backend documentation also calls casting disk-resident static config, then later documents blocking it. Filesystem casting persistence is therefore not itself evidence of a bug; the shipped ownership and commit-enforcement contracts conflict. Related: #2172.
There is a narrower safeguard mismatch worth resolving with that contract: the coordinator template lists memory and identity as runtime-managed paths under nonlocal backends and says handwritten files will be caught by the pre-commit hook. But the hook's regex does not include memory/ or identity/, and the generated ignore entries do not cover them either.
This is not a blanket claim that runtime files lack protection: the general ignore entries already cover logs, orchestration logs, decisions inbox, sessions, scratch, and cache. Different hook/ignore lists alone would not establish a bug. The issue is that the coordinator promises enforcement that those paths do not receive.
Could the intended ownership be reconciled across initialization, atomic casting writes, state-tool permissions, migration, coordinator instructions, and Git safeguards? The evidence does not justify moving the casting registry/history to orphan storage without first settling that contract.
Activity
dat-intellis commentedon Nov 8, 2026
Adding version-pinned ownership evidence for 1.1.0, plus a related documentation/enforcement mismatch. All links below use release commit
c24da2aad2ab7576f6b68dec2bc50b2fe2dc7a8a.The intended casting placement is explicitly stated in SDK initialization: casting is authoritative identity, belongs on
main, and must not be ignored. The migration helper likewise deliberately leaves staticcasting/*files untouched.However, the generated pre-commit hook rejects the entire
.squad/casting/directory and says those files belong onsquad-state. The release's own state-backend documentation also calls casting disk-resident static config, then later documents blocking it. Filesystem casting persistence is therefore not itself evidence of a bug; the shipped ownership and commit-enforcement contracts conflict. Related: #2172.There is a narrower safeguard mismatch worth resolving with that contract: the coordinator template lists memory and identity as runtime-managed paths under nonlocal backends and says handwritten files will be caught by the pre-commit hook. But the hook's regex does not include
memory/oridentity/, and the generated ignore entries do not cover them either.This is not a blanket claim that runtime files lack protection: the general ignore entries already cover logs, orchestration logs, decisions inbox, sessions, scratch, and cache. Different hook/ignore lists alone would not establish a bug. The issue is that the coordinator promises enforcement that those paths do not receive.
Could the intended ownership be reconciled across initialization, atomic casting writes, state-tool permissions, migration, coordinator instructions, and Git safeguards? The evidence does not justify moving the casting registry/history to orphan storage without first settling that contract.
fix(doctor): preserve legacy stray casting/policy.json detection in l…
fix(state): transactional governed-memory migration and source-branch…