pub struct WorkspaceScanner {
pub concurrency: usize,
}Expand description
Scans downstream workspaces for installed catalog assets.
Construct with WorkspaceScanner::new. The scanner is Clone + Send
and safe to share across tokio tasks via Arc.
Fields§
§concurrency: usizeMaximum number of workspaces scanned concurrently.
Implementations§
Source§impl WorkspaceScanner
impl WorkspaceScanner
Sourcepub fn new(concurrency: usize) -> Self
pub fn new(concurrency: usize) -> Self
Create a scanner with the given concurrency limit.
concurrency controls how many workspace scans run simultaneously via
tokio tasks. The default recommended value is 8 (Req 23.1).
Sourcepub fn parse_export_metadata(content: &str) -> Option<ExportMeta>
pub fn parse_export_metadata(content: &str) -> Option<ExportMeta>
Parse the # VFA-EXPORT: {json} metadata comment format (Req 7.7).
Searches content line-by-line (up to 20 lines) for a line whose
trimmed form starts with # VFA-EXPORT: (case-sensitive). The JSON
payload after the colon is parsed with serde_json.
Returns None for any malformed or missing line without panicking.
Sourcepub fn match_content_signature(
first_50_lines: &str,
canonical_first_50: &str,
) -> bool
pub fn match_content_signature( first_50_lines: &str, canonical_first_50: &str, ) -> bool
Conservative content-similarity heuristic for the first 50 lines.
Heuristic: normalise both sides (trim whitespace, lowercase), split into a set of non-empty lines, and compute the Jaccard-like overlap:
overlap = |file_lines ∩ template_lines| / |template_lines|Returns true when overlap >= 0.40 AND both sides have at least 3
non-empty lines. This threshold is deliberately conservative to avoid
false positives on short boilerplate. Callers should treat this as a
supporting signal only; confirmation requires a second agreeing strategy.
Sourcepub fn scan_harness_dir(
&self,
_workspace_path: &Path,
harness: &HarnessDir,
dir: &Path,
index: &CatalogIndex,
) -> Vec<InstalledAsset>
pub fn scan_harness_dir( &self, _workspace_path: &Path, harness: &HarnessDir, dir: &Path, index: &CatalogIndex, ) -> Vec<InstalledAsset>
Scan a single harness directory and return detected assets.
Per-harness file-extension filters (Req 7.8):
| Harness | Extensions scanned |
|---|---|
| Claude | *.md |
| Cursor | *.json |
| Kiro | *.md |
| Codex | plugin.json only |
| Opencode | *.toml, *.yaml, *.yml |
Validates the layout before walking (Req 7.6); returns empty vec with a
warn! if the layout does not match any known pattern.
Sourcepub fn scan_workspace(
&self,
ws: &ResolvedWorkspace,
index: &CatalogIndex,
) -> Vec<InstalledAsset>
pub fn scan_workspace( &self, ws: &ResolvedWorkspace, index: &CatalogIndex, ) -> Vec<InstalledAsset>
Scan a single resolved workspace, returning all detected assets sorted
by asset_id (Req 27.2).
Harness directories that do not match any known layout are warned and skipped (Req 7.6).
Bug #2: Recursively checks for agents/ and skills/ subdirectories within
each harness root (e.g., .claude/agents/, .cursor/agents/, etc.).
Sourcepub async fn scan_all(
&self,
workspaces: &[ResolvedWorkspace],
index: &CatalogIndex,
) -> HashMap<PathBuf, Vec<InstalledAsset>>
pub async fn scan_all( &self, workspaces: &[ResolvedWorkspace], index: &CatalogIndex, ) -> HashMap<PathBuf, Vec<InstalledAsset>>
Scan all workspaces in parallel (up to self.concurrency simultaneous
tasks) and return a map from workspace canonical path → installed assets.
Uses a Semaphore to bound concurrency (Req 23.1). Each workspace
scan runs in its own tokio::spawn task so I/O does not block the
executor.
Offline/unavailable workspaces are skipped silently here; callers should
pre-filter or mark them based on ResolvedWorkspace::status.
Trait Implementations§
Source§impl Clone for WorkspaceScanner
impl Clone for WorkspaceScanner
Source§fn clone(&self) -> WorkspaceScanner
fn clone(&self) -> WorkspaceScanner
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl Freeze for WorkspaceScanner
impl RefUnwindSafe for WorkspaceScanner
impl Send for WorkspaceScanner
impl Sync for WorkspaceScanner
impl Unpin for WorkspaceScanner
impl UnsafeUnpin for WorkspaceScanner
impl UnwindSafe for WorkspaceScanner
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more