Module: KairosMcp::Daemon::ScopeClassifier

Defined in:
lib/kairos_mcp/daemon/scope_classifier.rb

Overview

ScopeClassifier โ€” deterministic path โ†’ scope mapping.

Design (P3.2 v0.2 ยง2):

Pure function. No side effects. No LLM involvement.
.kairos/ is a closed namespace: unmatched .kairos/** โ†’ L0 (fail-closed).
Only paths outside .kairos/ and KairosChain_mcp_server/ default to L2.

Class Method Summary collapse

Class Method Details

.classify(absolute_path, workspace_root: Dir.pwd) ⇒ Hash

Returns frozen { scope:, auto_approve:, reason:, matched_rule: }.

Parameters:

  • absolute_path (String)

    must be an absolute path

  • workspace_root (String) (defaults to: Dir.pwd)

    workspace root directory

Returns:

  • (Hash)

    frozen { scope:, auto_approve:, reason:, matched_rule: }

Raises:

  • (ArgumentError)


15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/kairos_mcp/daemon/scope_classifier.rb', line 15

def self.classify(absolute_path, workspace_root: Dir.pwd)
  raise ArgumentError, 'path must be absolute' unless absolute_path.start_with?('/')

  rel = rel_path(absolute_path, workspace_root)
  return rule(:core_code,      :l0)              if rel.start_with?('KairosChain_mcp_server/')
  return rule(:skills_dsl,     :l0)              if rel.start_with?('.kairos/skills/')
  return rule(:knowledge,      :l1)              if rel.start_with?('.kairos/knowledge/')
  return rule(:context,        :l2, auto: true)  if rel.start_with?('.kairos/context/')
  return rule(:skillset,       :l0)              if rel.start_with?('.kairos/skillsets/')
  # Fail-closed: ANY unmatched .kairos/ path is L0
  return rule(:kairos_unknown, :l0)              if rel.start_with?('.kairos/') || rel == '.kairos'
  rule(:general_workspace, :l2, auto: true)
end

.rel_path(abs, root) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Raises:

  • (ArgumentError)


36
37
38
39
40
41
# File 'lib/kairos_mcp/daemon/scope_classifier.rb', line 36

def self.rel_path(abs, root)
  abs_n  = File.expand_path(abs)
  root_n = File.expand_path(root)
  raise ArgumentError, 'path escapes workspace' unless abs_n.start_with?(root_n + '/')
  abs_n[(root_n.length + 1)..]
end

.rule(name, scope, auto: false) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



30
31
32
33
# File 'lib/kairos_mcp/daemon/scope_classifier.rb', line 30

def self.rule(name, scope, auto: false)
  { scope: scope, auto_approve: auto,
    reason: "matched #{name}", matched_rule: name }.freeze
end