Context
The direct-dev GitHub workflow/content sync path is still blocked by the Husky pre-commit guard after #11582/#11583 merged. The operator reproduced the failure on dev in /Users/Shared/github/neomjs/neo while trying to commit generated resources/content/** sync output:
chore: gh workflow sync [skip ci]
Error: Sync-data leakage detected.
Branch 'dev' (in root '/Users/Shared/github/neomjs/neo') is not a designated data-sync branch (e.g., 'chore/sync-*' or 'agent/sync-*').
The following data files are staged for commit:
- resources/content/_index.json
- resources/content/archive/discussions/v8.30.0/chunk-1/discussion-5408.md
- resources/content/discussions/chunk-1/discussion-10040.md
- resources/content/discussions/chunk-1/discussion-10073.md
The Problem
#11582/#11583 restored the SyncService auto-commit path by setting NEO_SYNC_AUTOCOMMIT=1 for git commit -m "chore: ticket sync [skip ci]". That does not cover the operator's direct-dev generated sync commit surface. Renaming the commit message does not affect the failure because buildScripts/util/check-chore-sync.mjs does not inspect the commit subject; it gates only branch, staged paths, and NEO_SYNC_AUTOCOMMIT.
V-B-A evidence from the live failing checkout:
$ git -C /Users/Shared/github/neomjs/neo status --short --branch
<h2 class="neo-h2" data-record-id="4">dev...origin/dev</h2>
M resources/content/_index.json
... 126 staged generated sync paths total
$ NEO_SYNC_AUTOCOMMIT=1 node buildScripts/util/check-chore-sync.mjs
<h1 class="neo-h1" data-record-id="5">passes</h1>
$ node buildScripts/util/check-chore-sync.mjs
Error: Sync-data leakage detected.
Branch 'dev' (in root '/Users/Shared/github/neomjs/neo') is not a designated data-sync branch ...
A generated-only staged diff on dev is legitimate for this repository's direct sync workflow. The hook currently treats it as leakage unless the caller knows to set a hidden environment variable or moves to a synthetic sync branch, which contradicts the direct-dev data-sync pipeline reality.
The Architectural Reality
Relevant surfaces:
.husky/pre-commit invokes node ./buildScripts/util/check-chore-sync.mjs unconditionally.
buildScripts/util/check-chore-sync.mjs allows chore/sync-*, agent/sync-*, or NEO_SYNC_AUTOCOMMIT=1; otherwise any staged generated resources/content/** file is rejected.
ai/services/github-workflow/SyncService.mjs wraps its own auto-commit with NEO_SYNC_AUTOCOMMIT=1, but that is only one commit surface.
package.json exposes ai:sync-github-workflow, and the repository's sync workflow is dev-branch-owned; routing generated sync commits through feature branches plus PRs is the wrong substrate for this cache data.
The Fix
Update buildScripts/util/check-chore-sync.mjs so generated-only sync-data commits on dev pass the hook, while mixed generated + source commits on dev still fail. Keep the env-var bypass for explicit automation and retain non-dev feature-branch leakage protection.
Expected shape:
- Compute staged generated sync files and non-sync files before branch rejection.
- Permit
branch === 'dev' only when every staged path is generated sync content.
- Reject
branch === 'dev' when generated sync files are staged alongside non-sync paths.
- Preserve existing
NEO_SYNC_AUTOCOMMIT=1 strict sync-only behavior.
- Add focused unit coverage in
test/playwright/unit/ai/buildScripts/util/check-chore-sync.spec.mjs.
Acceptance Criteria
Out of Scope
- Changing the GitHub workflow sync data model.
- Changing GraphQL retry behavior from #11585/#11587.
- Changing generated
resources/content/** output.
- Introducing PR-based review flow for routine generated sync data commits.
Avoided Traps
- Do not key behavior off commit message text. The hook executes before the commit object exists and message renames are not a reliable authorization primitive.
- Do not require direct-dev generated sync output to go through feature branches; that moves regeneratable cache updates into the human PR lane.
- Do not broadly allow all
dev commits through the hook. The permission must be generated-only.
Related
- #11580 — original branch-context / automated-sync hook bug report
- #11582 / #11583 — prior fix for SyncService direct-dev auto-push path
- #11585 / #11587 — GraphQL transient retry path
Origin Session ID: 8591bc48-0ddc-48bf-aa47-58e53ea81a57
Retrieval Hint: check-chore-sync NEO_SYNC_AUTOCOMMIT dev generated-only Sync-data leakage
Context
The direct-dev GitHub workflow/content sync path is still blocked by the Husky pre-commit guard after #11582/#11583 merged. The operator reproduced the failure on
devin/Users/Shared/github/neomjs/neowhile trying to commit generatedresources/content/**sync output:The Problem
#11582/#11583 restored the
SyncServiceauto-commit path by settingNEO_SYNC_AUTOCOMMIT=1forgit commit -m "chore: ticket sync [skip ci]". That does not cover the operator's direct-dev generated sync commit surface. Renaming the commit message does not affect the failure becausebuildScripts/util/check-chore-sync.mjsdoes not inspect the commit subject; it gates only branch, staged paths, andNEO_SYNC_AUTOCOMMIT.V-B-A evidence from the live failing checkout:
A generated-only staged diff on
devis legitimate for this repository's direct sync workflow. The hook currently treats it as leakage unless the caller knows to set a hidden environment variable or moves to a synthetic sync branch, which contradicts the direct-dev data-sync pipeline reality.The Architectural Reality
Relevant surfaces:
.husky/pre-commitinvokesnode ./buildScripts/util/check-chore-sync.mjsunconditionally.buildScripts/util/check-chore-sync.mjsallowschore/sync-*,agent/sync-*, orNEO_SYNC_AUTOCOMMIT=1; otherwise any staged generatedresources/content/**file is rejected.ai/services/github-workflow/SyncService.mjswraps its own auto-commit withNEO_SYNC_AUTOCOMMIT=1, but that is only one commit surface.package.jsonexposesai:sync-github-workflow, and the repository's sync workflow is dev-branch-owned; routing generated sync commits through feature branches plus PRs is the wrong substrate for this cache data.The Fix
Update
buildScripts/util/check-chore-sync.mjsso generated-only sync-data commits ondevpass the hook, while mixed generated + source commits ondevstill fail. Keep the env-var bypass for explicit automation and retain non-dev feature-branch leakage protection.Expected shape:
branch === 'dev'only when every staged path is generated sync content.branch === 'dev'when generated sync files are staged alongside non-sync paths.NEO_SYNC_AUTOCOMMIT=1strict sync-only behavior.test/playwright/unit/ai/buildScripts/util/check-chore-sync.spec.mjs.Acceptance Criteria
resources/content/**diff ondevpassescheck-chore-sync.mjswithout requiringNEO_SYNC_AUTOCOMMIT=1.devcontaining generated sync files and non-sync files fails.NEO_SYNC_AUTOCOMMIT=1.chore/sync-*,agent/sync-*, andNEO_SYNC_AUTOCOMMIT=1behavior remains covered.Out of Scope
resources/content/**output.Avoided Traps
devcommits through the hook. The permission must be generated-only.Related
Origin Session ID: 8591bc48-0ddc-48bf-aa47-58e53ea81a57
Retrieval Hint:
check-chore-sync NEO_SYNC_AUTOCOMMIT dev generated-only Sync-data leakage