Skip to content

feat(core): hot reload for directory skill sources - #17

Draft
shoootyou wants to merge 5 commits into
devfrom
fork/skill-hot-reload
Draft

feat(core): hot reload for directory skill sources#17
shoootyou wants to merge 5 commits into
devfrom
fork/skill-hot-reload

Conversation

@shoootyou

Copy link
Copy Markdown
Owner

Under construction

⚠️ This PR is a work in progress. Do not merge.

This branch contains the hot reload implementation for directory-based skill sources. The feature watches the filesystem for changes in skill directories and reloads them automatically without requiring a restart.

Status

  • Implementation complete
  • Pending: upstream contribution readiness review
  • Pending: rebase on current upstream before promoting to upstream PR

shoootyouand others added 5 commits June 12, 2026 09:51
Subscribe to Watcher.Event.Updated in SkillV2.layer to invalidate the
cache for DirectorySource entries when files change. Extend
Watcher.Interface with watch() to register per-directory subscriptions
on first load.
- Cache entry cleared on file change under a DirectorySource path
- UrlSource and EmbeddedSource unaffected (no watch registration)
- Race safety via `invalidated` Set: concurrent loads discard stale results
- watcher.watch() is fire-and-forget via forkDetach — never blocks list()
- EventV2.Service and Watcher.Service are optional (Effect.serviceOption)
so existing layers without them continue to work
Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
- Deduplicate watcher.watch() calls via Set to prevent O(N) subscription
growth on repeated cache invalidations
- Subscribe watcher after Effect execution (not at construction time)
- Add catchCause logging to invalidation fiber for silent failure detection
- Declare EventV2 dep relationship in watcher locationLayer
- Fix race mid-load: reload once more when invalidated during load
- Add tests for path-prefix collision and absent Watcher.Service
- Fix @spec-handoff: document watch() as required, not optional
Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
- Exclude Cause.interrupt from hot-reload fiber error logging (clean shutdown)
- Document that Watcher.watch() is not idempotent; caller owns dedup
- Add assertion in T2: watch() called exactly once across invalidation cycles
- Add comment explaining double-load race safety heuristic
- Add T9: list() does not throw or interrupt caller during cache invalidation
Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
DirectorySource skills now reload automatically on file change without
requiring a process restart.
Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
Sign up for freeto 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.

1 participant

@shoootyou
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
feat(core): hot reload for directory skill sources by shoootyou · Pull Request #17 · shoootyou/opencode · GitHub
Skip to content

feat(core): hot reload for directory skill sources - #17

Draft
shoootyou wants to merge 5 commits into
devfrom
fork/skill-hot-reload
Draft

feat(core): hot reload for directory skill sources#17
shoootyou wants to merge 5 commits into
devfrom
fork/skill-hot-reload

Conversation

@shoootyou

Copy link
Copy Markdown
Owner

Under construction

⚠️ This PR is a work in progress. Do not merge.

This branch contains the hot reload implementation for directory-based skill sources. The feature watches the filesystem for changes in skill directories and reloads them automatically without requiring a restart.

Status

  • Implementation complete
  • Pending: upstream contribution readiness review
  • Pending: rebase on current upstream before promoting to upstream PR

shoootyouand others added 5 commits June 12, 2026 09:51
Subscribe to Watcher.Event.Updated in SkillV2.layer to invalidate the
cache for DirectorySource entries when files change. Extend
Watcher.Interface with watch() to register per-directory subscriptions
on first load.
- Cache entry cleared on file change under a DirectorySource path
- UrlSource and EmbeddedSource unaffected (no watch registration)
- Race safety via `invalidated` Set: concurrent loads discard stale results
- watcher.watch() is fire-and-forget via forkDetach — never blocks list()
- EventV2.Service and Watcher.Service are optional (Effect.serviceOption)
so existing layers without them continue to work
Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
- Deduplicate watcher.watch() calls via Set to prevent O(N) subscription
growth on repeated cache invalidations
- Subscribe watcher after Effect execution (not at construction time)
- Add catchCause logging to invalidation fiber for silent failure detection
- Declare EventV2 dep relationship in watcher locationLayer
- Fix race mid-load: reload once more when invalidated during load
- Add tests for path-prefix collision and absent Watcher.Service
- Fix @spec-handoff: document watch() as required, not optional
Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
- Exclude Cause.interrupt from hot-reload fiber error logging (clean shutdown)
- Document that Watcher.watch() is not idempotent; caller owns dedup
- Add assertion in T2: watch() called exactly once across invalidation cycles
- Add comment explaining double-load race safety heuristic
- Add T9: list() does not throw or interrupt caller during cache invalidation
Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
DirectorySource skills now reload automatically on file change without
requiring a process restart.
Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
Sign up for freeto 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.

1 participant

@shoootyou
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat(core): hot reload for directory skill sources by shoootyou · Pull Request #17 · shoootyou/opencode · GitHub
Skip to content

feat(core): hot reload for directory skill sources - #17

Draft
shoootyou wants to merge 5 commits into
devfrom
fork/skill-hot-reload
Draft

feat(core): hot reload for directory skill sources#17
shoootyou wants to merge 5 commits into
devfrom
fork/skill-hot-reload

Conversation

@shoootyou

Copy link
Copy Markdown
Owner

Under construction

⚠️ This PR is a work in progress. Do not merge.

This branch contains the hot reload implementation for directory-based skill sources. The feature watches the filesystem for changes in skill directories and reloads them automatically without requiring a restart.

Status

  • Implementation complete
  • Pending: upstream contribution readiness review
  • Pending: rebase on current upstream before promoting to upstream PR

shoootyouand others added 5 commits June 12, 2026 09:51
Subscribe to Watcher.Event.Updated in SkillV2.layer to invalidate the
cache for DirectorySource entries when files change. Extend
Watcher.Interface with watch() to register per-directory subscriptions
on first load.
- Cache entry cleared on file change under a DirectorySource path
- UrlSource and EmbeddedSource unaffected (no watch registration)
- Race safety via `invalidated` Set: concurrent loads discard stale results
- watcher.watch() is fire-and-forget via forkDetach — never blocks list()
- EventV2.Service and Watcher.Service are optional (Effect.serviceOption)
so existing layers without them continue to work
Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
- Deduplicate watcher.watch() calls via Set to prevent O(N) subscription
growth on repeated cache invalidations
- Subscribe watcher after Effect execution (not at construction time)
- Add catchCause logging to invalidation fiber for silent failure detection
- Declare EventV2 dep relationship in watcher locationLayer
- Fix race mid-load: reload once more when invalidated during load
- Add tests for path-prefix collision and absent Watcher.Service
- Fix @spec-handoff: document watch() as required, not optional
Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
- Exclude Cause.interrupt from hot-reload fiber error logging (clean shutdown)
- Document that Watcher.watch() is not idempotent; caller owns dedup
- Add assertion in T2: watch() called exactly once across invalidation cycles
- Add comment explaining double-load race safety heuristic
- Add T9: list() does not throw or interrupt caller during cache invalidation
Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
DirectorySource skills now reload automatically on file change without
requiring a process restart.
Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
Sign up for freeto 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.

1 participant

@shoootyou
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat(core): hot reload for directory skill sources by shoootyou · Pull Request #17 · shoootyou/opencode · GitHub
Skip to content

feat(core): hot reload for directory skill sources - #17

Draft
shoootyou wants to merge 5 commits into
devfrom
fork/skill-hot-reload
Draft

feat(core): hot reload for directory skill sources#17
shoootyou wants to merge 5 commits into
devfrom
fork/skill-hot-reload

Conversation

@shoootyou

Copy link
Copy Markdown
Owner

Under construction

⚠️ This PR is a work in progress. Do not merge.

This branch contains the hot reload implementation for directory-based skill sources. The feature watches the filesystem for changes in skill directories and reloads them automatically without requiring a restart.

Status

  • Implementation complete
  • Pending: upstream contribution readiness review
  • Pending: rebase on current upstream before promoting to upstream PR

shoootyouand others added 5 commits June 12, 2026 09:51
Subscribe to Watcher.Event.Updated in SkillV2.layer to invalidate the
cache for DirectorySource entries when files change. Extend
Watcher.Interface with watch() to register per-directory subscriptions
on first load.
- Cache entry cleared on file change under a DirectorySource path
- UrlSource and EmbeddedSource unaffected (no watch registration)
- Race safety via `invalidated` Set: concurrent loads discard stale results
- watcher.watch() is fire-and-forget via forkDetach — never blocks list()
- EventV2.Service and Watcher.Service are optional (Effect.serviceOption)
so existing layers without them continue to work
Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
- Deduplicate watcher.watch() calls via Set to prevent O(N) subscription
growth on repeated cache invalidations
- Subscribe watcher after Effect execution (not at construction time)
- Add catchCause logging to invalidation fiber for silent failure detection
- Declare EventV2 dep relationship in watcher locationLayer
- Fix race mid-load: reload once more when invalidated during load
- Add tests for path-prefix collision and absent Watcher.Service
- Fix @spec-handoff: document watch() as required, not optional
Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
- Exclude Cause.interrupt from hot-reload fiber error logging (clean shutdown)
- Document that Watcher.watch() is not idempotent; caller owns dedup
- Add assertion in T2: watch() called exactly once across invalidation cycles
- Add comment explaining double-load race safety heuristic
- Add T9: list() does not throw or interrupt caller during cache invalidation
Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
DirectorySource skills now reload automatically on file change without
requiring a process restart.
Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
Sign up for freeto 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.

1 participant

@shoootyou
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' feat(core): hot reload for directory skill sources by shoootyou · Pull Request #17 · shoootyou/opencode · GitHub
Skip to content

feat(core): hot reload for directory skill sources - #17

Draft
shoootyou wants to merge 5 commits into
devfrom
fork/skill-hot-reload
Draft

feat(core): hot reload for directory skill sources#17
shoootyou wants to merge 5 commits into
devfrom
fork/skill-hot-reload

Conversation

@shoootyou

Copy link
Copy Markdown
Owner

Under construction

⚠️ This PR is a work in progress. Do not merge.

This branch contains the hot reload implementation for directory-based skill sources. The feature watches the filesystem for changes in skill directories and reloads them automatically without requiring a restart.

Status

  • Implementation complete
  • Pending: upstream contribution readiness review
  • Pending: rebase on current upstream before promoting to upstream PR

shoootyouand others added 5 commits June 12, 2026 09:51
Subscribe to Watcher.Event.Updated in SkillV2.layer to invalidate the
cache for DirectorySource entries when files change. Extend
Watcher.Interface with watch() to register per-directory subscriptions
on first load.
- Cache entry cleared on file change under a DirectorySource path
- UrlSource and EmbeddedSource unaffected (no watch registration)
- Race safety via `invalidated` Set: concurrent loads discard stale results
- watcher.watch() is fire-and-forget via forkDetach — never blocks list()
- EventV2.Service and Watcher.Service are optional (Effect.serviceOption)
so existing layers without them continue to work
Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
- Deduplicate watcher.watch() calls via Set to prevent O(N) subscription
growth on repeated cache invalidations
- Subscribe watcher after Effect execution (not at construction time)
- Add catchCause logging to invalidation fiber for silent failure detection
- Declare EventV2 dep relationship in watcher locationLayer
- Fix race mid-load: reload once more when invalidated during load
- Add tests for path-prefix collision and absent Watcher.Service
- Fix @spec-handoff: document watch() as required, not optional
Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
- Exclude Cause.interrupt from hot-reload fiber error logging (clean shutdown)
- Document that Watcher.watch() is not idempotent; caller owns dedup
- Add assertion in T2: watch() called exactly once across invalidation cycles
- Add comment explaining double-load race safety heuristic
- Add T9: list() does not throw or interrupt caller during cache invalidation
Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
DirectorySource skills now reload automatically on file change without
requiring a process restart.
Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
Sign up for freeto 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.

1 participant

@shoootyou
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' feat(core): hot reload for directory skill sources by shoootyou · Pull Request #17 · shoootyou/opencode · GitHub
Skip to content

feat(core): hot reload for directory skill sources - #17

Draft
shoootyou wants to merge 5 commits into
devfrom
fork/skill-hot-reload
Draft

feat(core): hot reload for directory skill sources#17
shoootyou wants to merge 5 commits into
devfrom
fork/skill-hot-reload

Conversation

@shoootyou

Copy link
Copy Markdown
Owner

Under construction

⚠️ This PR is a work in progress. Do not merge.

This branch contains the hot reload implementation for directory-based skill sources. The feature watches the filesystem for changes in skill directories and reloads them automatically without requiring a restart.

Status

  • Implementation complete
  • Pending: upstream contribution readiness review
  • Pending: rebase on current upstream before promoting to upstream PR

shoootyouand others added 5 commits June 12, 2026 09:51
Subscribe to Watcher.Event.Updated in SkillV2.layer to invalidate the
cache for DirectorySource entries when files change. Extend
Watcher.Interface with watch() to register per-directory subscriptions
on first load.
- Cache entry cleared on file change under a DirectorySource path
- UrlSource and EmbeddedSource unaffected (no watch registration)
- Race safety via `invalidated` Set: concurrent loads discard stale results
- watcher.watch() is fire-and-forget via forkDetach — never blocks list()
- EventV2.Service and Watcher.Service are optional (Effect.serviceOption)
so existing layers without them continue to work
Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
- Deduplicate watcher.watch() calls via Set to prevent O(N) subscription
growth on repeated cache invalidations
- Subscribe watcher after Effect execution (not at construction time)
- Add catchCause logging to invalidation fiber for silent failure detection
- Declare EventV2 dep relationship in watcher locationLayer
- Fix race mid-load: reload once more when invalidated during load
- Add tests for path-prefix collision and absent Watcher.Service
- Fix @spec-handoff: document watch() as required, not optional
Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
- Exclude Cause.interrupt from hot-reload fiber error logging (clean shutdown)
- Document that Watcher.watch() is not idempotent; caller owns dedup
- Add assertion in T2: watch() called exactly once across invalidation cycles
- Add comment explaining double-load race safety heuristic
- Add T9: list() does not throw or interrupt caller during cache invalidation
Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
DirectorySource skills now reload automatically on file change without
requiring a process restart.
Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
Sign up for freeto 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.

1 participant

@shoootyou
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); feat(core): hot reload for directory skill sources by shoootyou · Pull Request #17 · shoootyou/opencode · GitHub
Skip to content

feat(core): hot reload for directory skill sources - #17

Draft
shoootyou wants to merge 5 commits into
devfrom
fork/skill-hot-reload
Draft

feat(core): hot reload for directory skill sources#17
shoootyou wants to merge 5 commits into
devfrom
fork/skill-hot-reload

Conversation

@shoootyou

Copy link
Copy Markdown
Owner

Under construction

⚠️ This PR is a work in progress. Do not merge.

This branch contains the hot reload implementation for directory-based skill sources. The feature watches the filesystem for changes in skill directories and reloads them automatically without requiring a restart.

Status

  • Implementation complete
  • Pending: upstream contribution readiness review
  • Pending: rebase on current upstream before promoting to upstream PR

shoootyouand others added 5 commits June 12, 2026 09:51
Subscribe to Watcher.Event.Updated in SkillV2.layer to invalidate the
cache for DirectorySource entries when files change. Extend
Watcher.Interface with watch() to register per-directory subscriptions
on first load.
- Cache entry cleared on file change under a DirectorySource path
- UrlSource and EmbeddedSource unaffected (no watch registration)
- Race safety via `invalidated` Set: concurrent loads discard stale results
- watcher.watch() is fire-and-forget via forkDetach — never blocks list()
- EventV2.Service and Watcher.Service are optional (Effect.serviceOption)
so existing layers without them continue to work
Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
- Deduplicate watcher.watch() calls via Set to prevent O(N) subscription
growth on repeated cache invalidations
- Subscribe watcher after Effect execution (not at construction time)
- Add catchCause logging to invalidation fiber for silent failure detection
- Declare EventV2 dep relationship in watcher locationLayer
- Fix race mid-load: reload once more when invalidated during load
- Add tests for path-prefix collision and absent Watcher.Service
- Fix @spec-handoff: document watch() as required, not optional
Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
- Exclude Cause.interrupt from hot-reload fiber error logging (clean shutdown)
- Document that Watcher.watch() is not idempotent; caller owns dedup
- Add assertion in T2: watch() called exactly once across invalidation cycles
- Add comment explaining double-load race safety heuristic
- Add T9: list() does not throw or interrupt caller during cache invalidation
Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
DirectorySource skills now reload automatically on file change without
requiring a process restart.
Co-authored-by: yui-soul <yui-soul@users.noreply.github.com>
Sign up for freeto 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.

1 participant

@shoootyou