Skip to content

fix(loop-init): serialize asset bundling#80

Open
Jalendar10 wants to merge 2 commits into
cobusgreyling:mainfrom
Jalendar10:codex/fix-loop-init-bundle-race
Open

fix(loop-init): serialize asset bundling#80
Jalendar10 wants to merge 2 commits into
cobusgreyling:mainfrom
Jalendar10:codex/fix-loop-init-bundle-race

Conversation

@Jalendar10

Copy link
Copy Markdown

Summary

Fix loop-init asset bundling so concurrent rebuilds do not fail with EEXIST or partial directory cleanup races.

Changes

  • New pattern or starter (followed templates/pattern-template.md + updated registry.yaml)
  • Doc / example improvement
  • Tool change (loop-init)
  • Story (includes real failure or surprise + lesson)

Checklist (from CONTRIBUTING)

  • All required sections present for patterns
  • Links work from README, patterns/README, starters/README, docs/index
  • No secrets, tokens, internal company URLs
  • STATE.md* examples use .example suffix
  • Safety-related content references docs/safety.md
  • Ran node tools/loop-audit/dist/cli.js . (or on the starter) and addressed findings

Testing / Dogfood

  • loop-audit passes on affected starters or this repo
  • Manual review of generated state / skill output

Verification run locally:

npm run validate:registry && npm run check:loop-init && npm run test:tools && cd tools/goal-audit && npm test && cd ../.. && bash scripts/ci-audit-gates.sh && bash scripts/ci-validate-gates.sh

Screenshots / Examples (if UI or command output)

N/A


This template enforces the high bar this reference is known for.

@Jalendar10 Jalendar10 left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found and fixed a race in tools/loop-init/scripts/bundle-assets.mjs.

Repeated or concurrent npm test / npm run build runs could fail while replacing bundled starters/ and templates/ directories, with errors like EEXIST or partial cleanup failures. The fix serializes bundling with a small filesystem lock and replaces directories through a temp path.

Verified locally with:

npm run validate:registry && npm run check:loop-init && npm run test:tools && cd tools/goal-audit && npm test && cd ../.. && bash scripts/ci-audit-gates.sh && bash scripts/ci-validate-gates.sh'''

@Jalendar10 Jalendar10 marked this pull request as ready for review June 28, 2026 02:25
Copilot AI review requested due to automatic review settings June 28, 2026 02:25

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR hardens tools/loop-init asset bundling to avoid concurrent rebuild failures (e.g., EEXIST and directory cleanup races) by serializing the bundle step and using a temp-directory swap strategy.

Changes:

  • Add an inter-process lock (.bundle-assets.lock) around bundling to serialize concurrent rebuilds.
  • Bundle starters/ and templates/ via copy-to-temp then rename() into place to reduce partial-update windows.
  • Add a CLI test that runs two concurrent bundle-assets executions and asserts key bundled outputs exist.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
tools/loop-init/scripts/bundle-assets.mjs Adds lock + temp swap logic to make bundling robust under concurrent execution.
tools/loop-init/test/cli.test.mjs Adds a concurrency regression test for bundle-assets.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +45 to +64
async function sleep(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}

async function acquireLock() {
for (let attempt = 0; attempt < 100; attempt += 1) {
try {
await mkdir(LOCK_DIR);
return async () => rm(LOCK_DIR, { recursive: true, force: true });
} catch (err) {
if (err?.code !== 'EEXIST') {
throw err;
}
await sleep(50);
}
}
throw new Error(`bundle-assets: timed out waiting for ${LOCK_DIR}`);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants