hkos 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (162) hide show
  1. hkos/__init__.py +37 -0
  2. hkos/api/__init__.py +0 -0
  3. hkos/campaign/__init__.py +0 -0
  4. hkos/config/__init__.py +0 -0
  5. hkos/config/hkos-development.yaml +151 -0
  6. hkos/config/hkos-production.yaml +125 -0
  7. hkos/config/logging.yaml +44 -0
  8. hkos/context/__init__.py +58 -0
  9. hkos/context/context_builder.py +199 -0
  10. hkos/context/context_manager.py +113 -0
  11. hkos/context/context_optimizer.py +184 -0
  12. hkos/context/context_serializer.py +154 -0
  13. hkos/context/context_statistics.py +48 -0
  14. hkos/context/context_validator.py +90 -0
  15. hkos/context/exceptions.py +21 -0
  16. hkos/context/models.py +98 -0
  17. hkos/context/snapshot_loader.py +72 -0
  18. hkos/context/token_estimator.py +76 -0
  19. hkos/core/__init__.py +0 -0
  20. hkos/core/bootstrap.py +94 -0
  21. hkos/core/config.py +150 -0
  22. hkos/core/constants.py +48 -0
  23. hkos/core/engine.py +72 -0
  24. hkos/core/exceptions.py +42 -0
  25. hkos/core/health.py +71 -0
  26. hkos/core/hkos.py +75 -0
  27. hkos/core/logger.py +103 -0
  28. hkos/core/registry.py +79 -0
  29. hkos/core/state.py +88 -0
  30. hkos/core/types.py +72 -0
  31. hkos/core/version.py +67 -0
  32. hkos/index/__init__.py +77 -0
  33. hkos/index/entity_index.py +78 -0
  34. hkos/index/exceptions.py +29 -0
  35. hkos/index/index_builder.py +159 -0
  36. hkos/index/index_cache.py +85 -0
  37. hkos/index/index_engine.py +158 -0
  38. hkos/index/index_manager.py +178 -0
  39. hkos/index/index_store.py +116 -0
  40. hkos/index/index_updater.py +174 -0
  41. hkos/index/index_validator.py +184 -0
  42. hkos/index/keyword_index.py +114 -0
  43. hkos/index/query_contract.py +288 -0
  44. hkos/index/relationship_index.py +171 -0
  45. hkos/index/statistics_index.py +65 -0
  46. hkos/index/tag_index.py +94 -0
  47. hkos/index/validation.py +46 -0
  48. hkos/integration/__init__.py +5 -0
  49. hkos/integration/hermes/__init__.py +30 -0
  50. hkos/integration/hermes/agent_lock.py +97 -0
  51. hkos/integration/hermes/audit.py +90 -0
  52. hkos/integration/hermes/doctor.py +196 -0
  53. hkos/integration/hermes/fallback.py +71 -0
  54. hkos/integration/hermes/hooks.py +173 -0
  55. hkos/integration/hermes/migration_commands.py +79 -0
  56. hkos/integration/hermes/migration_tools.py +298 -0
  57. hkos/integration/hermes/schemas.py +110 -0
  58. hkos/integration/hermes/security.py +174 -0
  59. hkos/kernel/__init__.py +9 -0
  60. hkos/kernel/snapshot_document.py +93 -0
  61. hkos/knowledge/__init__.py +0 -0
  62. hkos/librarian/__init__.py +0 -0
  63. hkos/mcp_server/__init__.py +9 -0
  64. hkos/mcp_server/context.py +82 -0
  65. hkos/mcp_server/jsonrpc.py +32 -0
  66. hkos/mcp_server/persistence.py +74 -0
  67. hkos/mcp_server/server.py +175 -0
  68. hkos/mcp_server/tools.py +288 -0
  69. hkos/migration/__init__.py +46 -0
  70. hkos/migration/backup_manager.py +115 -0
  71. hkos/migration/exceptions.py +42 -0
  72. hkos/migration/migration_engine.py +322 -0
  73. hkos/migration/migration_executor.py +74 -0
  74. hkos/migration/migration_history.py +68 -0
  75. hkos/migration/migration_manager.py +196 -0
  76. hkos/migration/migration_registry.py +165 -0
  77. hkos/migration/migration_validator.py +294 -0
  78. hkos/migration/rollback_manager.py +121 -0
  79. hkos/migration/schema_detector.py +146 -0
  80. hkos/migration/version_manifest.py +125 -0
  81. hkos/performance/__init__.py +70 -0
  82. hkos/performance/cache_manager.py +94 -0
  83. hkos/performance/context_profiles.py +147 -0
  84. hkos/performance/exceptions.py +13 -0
  85. hkos/performance/integration.py +213 -0
  86. hkos/performance/latency_tracker.py +59 -0
  87. hkos/performance/metrics_engine.py +95 -0
  88. hkos/performance/performance_manager.py +233 -0
  89. hkos/performance/profiler.py +57 -0
  90. hkos/performance/resource_monitor.py +110 -0
  91. hkos/project/__init__.py +0 -0
  92. hkos/repository/__init__.py +64 -0
  93. hkos/repository/artifact_repository.py +66 -0
  94. hkos/repository/base_repository.py +229 -0
  95. hkos/repository/campaign_repository.py +153 -0
  96. hkos/repository/decision_repository.py +95 -0
  97. hkos/repository/exceptions.py +31 -0
  98. hkos/repository/knowledge_relations.py +136 -0
  99. hkos/repository/knowledge_repository.py +133 -0
  100. hkos/repository/models.py +295 -0
  101. hkos/repository/project_repository.py +103 -0
  102. hkos/repository/repository_manager.py +71 -0
  103. hkos/retrieval/__init__.py +44 -0
  104. hkos/retrieval/candidate_builder.py +152 -0
  105. hkos/retrieval/exceptions.py +21 -0
  106. hkos/retrieval/knowledge_filter.py +50 -0
  107. hkos/retrieval/knowledge_selector.py +34 -0
  108. hkos/retrieval/query_parser.py +203 -0
  109. hkos/retrieval/ranking_engine.py +324 -0
  110. hkos/retrieval/relationship_traverser.py +124 -0
  111. hkos/retrieval/retrieval_engine.py +474 -0
  112. hkos/retrieval/retriever.py +140 -0
  113. hkos/services/__init__.py +103 -0
  114. hkos/services/campaign_factory.py +90 -0
  115. hkos/services/campaign_manager.py +370 -0
  116. hkos/services/campaign_service.py +90 -0
  117. hkos/services/campaign_state.py +141 -0
  118. hkos/services/campaign_statistics.py +142 -0
  119. hkos/services/campaign_validator.py +101 -0
  120. hkos/services/classification_policy.py +144 -0
  121. hkos/services/exceptions.py +53 -0
  122. hkos/services/librarian/__init__.py +60 -0
  123. hkos/services/librarian/canonicalizer.py +73 -0
  124. hkos/services/librarian/category_merge.py +32 -0
  125. hkos/services/librarian/confidence_engine.py +125 -0
  126. hkos/services/librarian/conflict_detector.py +109 -0
  127. hkos/services/librarian/exceptions.py +29 -0
  128. hkos/services/librarian/knowledge_classifier.py +99 -0
  129. hkos/services/librarian/knowledge_history.py +145 -0
  130. hkos/services/librarian/knowledge_merger.py +100 -0
  131. hkos/services/librarian/knowledge_status.py +169 -0
  132. hkos/services/librarian/librarian.py +338 -0
  133. hkos/services/memory_service.py +304 -0
  134. hkos/services/project_factory.py +68 -0
  135. hkos/services/project_manager.py +267 -0
  136. hkos/services/project_service.py +85 -0
  137. hkos/services/project_state.py +117 -0
  138. hkos/services/project_validator.py +139 -0
  139. hkos/snapshot/__init__.py +39 -0
  140. hkos/snapshot/exceptions.py +25 -0
  141. hkos/snapshot/snapshot_builder.py +199 -0
  142. hkos/snapshot/snapshot_diff.py +122 -0
  143. hkos/snapshot/snapshot_engine.py +165 -0
  144. hkos/snapshot/snapshot_history.py +76 -0
  145. hkos/snapshot/snapshot_loader.py +114 -0
  146. hkos/snapshot/snapshot_manager.py +211 -0
  147. hkos/snapshot/snapshot_serializer.py +49 -0
  148. hkos/snapshot/snapshot_validator.py +119 -0
  149. hkos/storage/__init__.py +41 -0
  150. hkos/storage/atomic_writer.py +104 -0
  151. hkos/storage/exceptions.py +46 -0
  152. hkos/storage/file_store.py +116 -0
  153. hkos/storage/json_store.py +240 -0
  154. hkos/storage/path_manager.py +199 -0
  155. hkos/storage/storage_engine.py +187 -0
  156. hkos/utils/__init__.py +0 -0
  157. hkos-1.0.0.dist-info/METADATA +307 -0
  158. hkos-1.0.0.dist-info/RECORD +162 -0
  159. hkos-1.0.0.dist-info/WHEEL +5 -0
  160. hkos-1.0.0.dist-info/entry_points.txt +2 -0
  161. hkos-1.0.0.dist-info/licenses/LICENSE +21 -0
  162. hkos-1.0.0.dist-info/top_level.txt +1 -0
hkos/__init__.py ADDED
@@ -0,0 +1,37 @@
1
+ """Hermes Knowledge OS (HKOS)
2
+ ============================
3
+ An object-oriented file-based engineering knowledge database.
4
+
5
+ DS-001 (Sprint 1): Foundation
6
+ - HKOS as an importable module
7
+ - Bootstrap, Configuration, Logger, Registry
8
+ - Version and Health management
9
+ """
10
+
11
+ from hkos.core.config import ConfigLoader
12
+ from hkos.core.exceptions import (
13
+ ConfigurationError,
14
+ HKOSError,
15
+ InitializationError,
16
+ RuntimeErrorHKOS,
17
+ ValidationError,
18
+ )
19
+ from hkos.core.health import HealthManager
20
+ from hkos.core.hkos import HKOS
21
+ from hkos.core.logger import HKOSLogger
22
+ from hkos.core.registry import Registry
23
+ from hkos.core.version import VersionManager
24
+
25
+ __all__ = [
26
+ "HKOS",
27
+ "VersionManager",
28
+ "ConfigLoader",
29
+ "HealthManager",
30
+ "Registry",
31
+ "HKOSLogger",
32
+ "HKOSError",
33
+ "ConfigurationError",
34
+ "InitializationError",
35
+ "RuntimeErrorHKOS",
36
+ "ValidationError",
37
+ ]
hkos/api/__init__.py ADDED
File without changes
File without changes
File without changes
@@ -0,0 +1,151 @@
1
+ # HKOS Development Configuration
2
+ # Document: HKOS-14, DS-001
3
+ # Version: 1.0.0
4
+
5
+ hkos:
6
+ version: "1.0.0"
7
+ root: ./hkos
8
+ enabled: true
9
+
10
+ core:
11
+ bootstrap:
12
+ auto_start: false
13
+ health_check_on_start: true
14
+ scheduler:
15
+ enabled: false
16
+
17
+ logging:
18
+ level: DEBUG
19
+ file: ./hkos/logs/hkos.log
20
+ format: "%(asctime)s [%(levelname)s] %(name)s: %(message)s"
21
+ max_size_mb: 10
22
+ backup_count: 3
23
+ namespace: hkos
24
+
25
+ health:
26
+ check_interval_seconds: 60
27
+ components:
28
+ - config
29
+ - logger
30
+ - registry
31
+
32
+
33
+ # ===== Retrieval Engine (DS-008) =====
34
+ retrieval:
35
+ ranking:
36
+ topic_weight: 0.25
37
+ confidence_weight: 0.15
38
+ project_weight: 0.10
39
+ freshness_weight: 0.10
40
+ usage_weight: 0.05
41
+ canonical_weight: 0.15
42
+ references_weight: 0.05
43
+ success_weight: 0.05
44
+ campaign_weight: 0.05
45
+ decision_weight: 0.05
46
+ freshness_half_life_days: 90
47
+ # Верхние границы нормализации факторов (0 — фактор выключен;
48
+ # текущее поведение: usage/references/confirmations выключены,
49
+ # активируются заданием caps — Audit Remediation DS-009A, задача 4).
50
+ usage_cap: 0
51
+ references_cap: 0
52
+ confirmations_cap: 0
53
+ # Базовое число кандидатов фазы-2 ранжирования (см. refine_limit).
54
+ refine_limit_base: 60
55
+ selector:
56
+ top_n: 20
57
+ builder:
58
+ max_candidates: 200
59
+ keyword_limit: 50
60
+ traverser:
61
+ max_depth: 1
62
+ max_related: 10
63
+ relation_decay: 0.8
64
+ parser:
65
+ projects:
66
+ openwrt: "OpenWrt"
67
+ phoenix contact: "Phoenix Contact"
68
+ "phoenix": "Phoenix Contact"
69
+ terminal blocks: "Terminal Blocks"
70
+ hermes: "Hermes"
71
+ topics:
72
+ - routing
73
+ - firewall
74
+ - tproxy
75
+ - dns
76
+ - nftables
77
+ - policy routing
78
+ - sing-box
79
+ - udp
80
+ - vpn
81
+ entities:
82
+ - tproxy
83
+ - tcp
84
+ - udp
85
+ - nftables
86
+ - fwmark
87
+ - sing-box
88
+ - openwrt
89
+ - warp
90
+ - iptables
91
+ - tun
92
+ intents:
93
+ diagnostics: ["почему", "не работает", "диагностик", "причина", "debug"]
94
+ implementation: ["реализовать", "сделать", "настроить", "установить", "implement"]
95
+ research: ["исследовать", "как работает", "изучить", "research"]
96
+ architecture: ["архитектур", "спроектировать", "design"]
97
+ comparison: ["сравнить", "vs", "или", "compare"]
98
+ validation: ["проверить", "валидировать", "verify"]
99
+ stopwords: ["для", "и", "в", "на", "с", "по", "из", "у", "к", "о", "что", "как", "это", "не", "при", "до", "от", "за"]
100
+
101
+
102
+ # ===== Context Builder (DS-009) =====
103
+ context:
104
+ token_estimator:
105
+ characters_per_token: 4
106
+ words_per_token: 0.75
107
+ profiles:
108
+ SMALL: 4000
109
+ MEDIUM: 8000
110
+ LARGE: 16000
111
+ FULL: 0
112
+ snapshot:
113
+ dir: "snapshots"
114
+ serializer:
115
+ body_limit: 200
116
+ sections:
117
+ - TASK
118
+ - PROJECT
119
+ - CURRENT STATE
120
+ - CANONICAL KNOWLEDGE
121
+ - DECISIONS
122
+ - FAILURES
123
+ - ARTIFACTS
124
+ - CONFIGURATION
125
+ - OPEN QUESTIONS
126
+
127
+
128
+ # ===== Hermes Integration Security (DS-012 §8) =====
129
+ security:
130
+ enabled: true
131
+ require_confirmation:
132
+ migration: true
133
+ rollback: true
134
+ audit_log:
135
+ enabled: true
136
+ fallback:
137
+ retrieval: true
138
+ librarian_queue: true
139
+
140
+
141
+ # ===== Performance Layer (DS-013 ЭТАП 5 §9) =====
142
+ performance:
143
+ enabled: true
144
+ cache:
145
+ enabled: true
146
+ max_entries: 1000
147
+ ttl_seconds: 3600
148
+ context:
149
+ compression: normal
150
+ metrics:
151
+ enabled: true
@@ -0,0 +1,125 @@
1
+ # HKOS Production Configuration
2
+ # Document: DS-015 (ЭТАП 2 — Production Readiness)
3
+ # Version: 1.0.0
4
+ # Профиль: production (ConfigLoader(profile="production"))
5
+
6
+ hkos:
7
+ version: "1.0.0"
8
+ root: ./hkos
9
+ enabled: true
10
+
11
+ core:
12
+ bootstrap:
13
+ auto_start: true
14
+ health_check_on_start: true
15
+ scheduler:
16
+ enabled: false
17
+
18
+ logging:
19
+ level: INFO
20
+ file: ./hkos/logs/hkos.log
21
+ format: "%(asctime)s [%(levelname)s] %(name)s: %(message)s"
22
+ max_size_mb: 10
23
+ backup_count: 5
24
+ namespace: hkos
25
+
26
+ health:
27
+ check_interval_seconds: 60
28
+ components:
29
+ - config
30
+ - logger
31
+ - registry
32
+
33
+ # ===== Retrieval Engine (DS-008) =====
34
+ # ===== Retrieval Engine (DS-008) =====
35
+ retrieval:
36
+ ranking:
37
+ topic_weight: 0.25
38
+ confidence_weight: 0.15
39
+ project_weight: 0.10
40
+ freshness_weight: 0.10
41
+ usage_weight: 0.05
42
+ canonical_weight: 0.15
43
+ references_weight: 0.05
44
+ success_weight: 0.05
45
+ campaign_weight: 0.05
46
+ decision_weight: 0.05
47
+ freshness_half_life_days: 90
48
+ # Верхние границы нормализации факторов (0 — фактор выключен;
49
+ # текущее поведение: usage/references/confirmations выключены,
50
+ # активируются заданием caps — Audit Remediation DS-009A, задача 4).
51
+ usage_cap: 0
52
+ references_cap: 0
53
+ confirmations_cap: 0
54
+ # Базовое число кандидатов фазы-2 ранжирования (см. refine_limit).
55
+ refine_limit_base: 60
56
+ selector:
57
+ top_n: 20
58
+ builder:
59
+ max_candidates: 200
60
+ keyword_limit: 50
61
+ traverser:
62
+ max_depth: 1
63
+ max_related: 10
64
+ relation_decay: 0.8
65
+ parser:
66
+ projects:
67
+ openwrt: "OpenWrt"
68
+ phoenix contact: "Phoenix Contact"
69
+ "phoenix": "Phoenix Contact"
70
+ terminal blocks: "Terminal Blocks"
71
+ hermes: "Hermes"
72
+ topics:
73
+ - routing
74
+ - firewall
75
+ - tproxy
76
+ - dns
77
+ - nftables
78
+ - policy routing
79
+ - sing-box
80
+ - udp
81
+ - vpn
82
+ entities:
83
+ - tproxy
84
+ - tcp
85
+ - udp
86
+ - nftables
87
+ - fwmark
88
+ - sing-box
89
+ - openwrt
90
+ - warp
91
+ - iptables
92
+ - tun
93
+ intents:
94
+ diagnostics: ["почему", "не работает", "диагностик", "причина", "debug"]
95
+ implementation: ["реализовать", "сделать", "настроить", "установить", "implement"]
96
+ research: ["исследовать", "как работает", "изучить", "research"]
97
+ architecture: ["архитектур", "спроектировать", "design"]
98
+ comparison: ["сравнить", "vs", "или", "compare"]
99
+ validation: ["проверить", "валидировать", "verify"]
100
+ stopwords: ["для", "и", "в", "на", "с", "по", "из", "у", "к", "о", "что", "как", "это", "не", "при", "до", "от", "за"]
101
+
102
+ # ===== Операционный режим (DS-015 ЭТАП 2) =====
103
+ operations:
104
+ auto_snapshot: true
105
+ auto_index: true
106
+ retrieve_before_task: true
107
+ save_after_task: true
108
+ context_profile: medium
109
+
110
+ # ===== Performance Layer (DS-013) =====
111
+ performance:
112
+ enabled: true
113
+ cache:
114
+ enabled: true
115
+ max_entries: 1000
116
+ ttl_seconds: 3600
117
+ context:
118
+ compression: normal
119
+ metrics:
120
+ enabled: true
121
+
122
+ # ===== Backup (DS-011/DS-015) =====
123
+ backup:
124
+ enabled: true
125
+ keep_n: 5
@@ -0,0 +1,44 @@
1
+ # HKOS Logging Configuration
2
+ version: 1
3
+ disable_existing_loggers: false
4
+
5
+ formatters:
6
+ standard:
7
+ format: "%(asctime)s [%(levelname)s] %(name)s: %(message)s"
8
+ detailed:
9
+ format: "%(asctime)s [%(levelname)s] %(name)s (%(filename)s:%(lineno)d): %(message)s"
10
+
11
+ handlers:
12
+ console:
13
+ class: logging.StreamHandler
14
+ level: DEBUG
15
+ formatter: standard
16
+ stream: ext://sys.stdout
17
+ file:
18
+ class: logging.handlers.RotatingFileHandler
19
+ level: DEBUG
20
+ formatter: detailed
21
+ filename: ./hkos/logs/hkos.log
22
+ maxBytes: 10485760
23
+ backupCount: 3
24
+ performance_file:
25
+ class: logging.handlers.RotatingFileHandler
26
+ level: INFO
27
+ formatter: detailed
28
+ filename: ./hkos/logs/performance.log
29
+ maxBytes: 10485760
30
+ backupCount: 3
31
+
32
+ loggers:
33
+ hkos:
34
+ level: DEBUG
35
+ handlers: [console, file]
36
+ propagate: false
37
+ hkos.performance:
38
+ level: INFO
39
+ handlers: [performance_file]
40
+ propagate: false
41
+
42
+ root:
43
+ level: WARNING
44
+ handlers: [console]
@@ -0,0 +1,58 @@
1
+ """HKOS Context Layer (DS-009)
2
+ ===========================
3
+ Context Builder — формирование оптимального инженерного контекста
4
+ из RetrievalResult (минимальный по объёму, максимальный по полезности).
5
+
6
+ Использует: RetrievalResult (DS-008), SnapshotLoader (read-only),
7
+ Query Contract. Запрещены: StorageEngine/IndexStore/JSON/поиск.
8
+ """
9
+
10
+ from hkos.context.context_builder import (
11
+ PROFILE_FULL,
12
+ PROFILE_LARGE,
13
+ PROFILE_MEDIUM,
14
+ PROFILE_SMALL,
15
+ VALID_PROFILES,
16
+ ContextBuilder,
17
+ )
18
+ from hkos.context.context_manager import ContextManager
19
+ from hkos.context.context_optimizer import ContextOptimizer
20
+ from hkos.context.context_serializer import ContextSerializer
21
+ from hkos.context.context_statistics import ContextStatistics
22
+ from hkos.context.context_validator import ContextValidator
23
+ from hkos.context.exceptions import ContextError, ContextValidationError
24
+ from hkos.context.models import (
25
+ ContextDocument,
26
+ ContextExplanation,
27
+ ContextItem,
28
+ )
29
+ from hkos.context.snapshot_loader import (
30
+ SnapshotDocument,
31
+ SnapshotLoader,
32
+ SnapshotReader,
33
+ )
34
+ from hkos.context.token_estimator import TokenEstimate, TokenEstimator
35
+
36
+ __all__ = [
37
+ "ContextBuilder",
38
+ "ContextManager",
39
+ "ContextOptimizer",
40
+ "ContextSerializer",
41
+ "ContextValidator",
42
+ "ContextStatistics",
43
+ "TokenEstimator",
44
+ "TokenEstimate",
45
+ "SnapshotLoader",
46
+ "SnapshotReader",
47
+ "SnapshotDocument",
48
+ "ContextDocument",
49
+ "ContextItem",
50
+ "ContextExplanation",
51
+ "ContextError",
52
+ "ContextValidationError",
53
+ "PROFILE_SMALL",
54
+ "PROFILE_MEDIUM",
55
+ "PROFILE_LARGE",
56
+ "PROFILE_FULL",
57
+ "VALID_PROFILES",
58
+ ]
@@ -0,0 +1,199 @@
1
+ """HKOS Context Builder (DS-009 §4-6, IP-009)
2
+ ==========================================
3
+ Публичный фасад Context Layer.
4
+
5
+ Публичный API (ровно эти методы):
6
+ build, optimize, serialize, statistics, validate,
7
+ estimate_tokens, explain
8
+
9
+ Допустимые зависимости: RepositoryManager (не используется напрямую —
10
+ через RetrievalResult), RetrievalEngine, SnapshotLoader, Query Contract.
11
+
12
+ Запрещено: поиск, StorageEngine, IndexStore, JSON, изменение
13
+ Repository/Snapshot/RetrievalResult (архитектурные тесты).
14
+ """
15
+
16
+
17
+ from hkos.context.context_manager import ContextManager
18
+ from hkos.context.context_optimizer import ContextOptimizer
19
+ from hkos.context.context_serializer import ContextSerializer
20
+ from hkos.context.context_statistics import ContextStatistics
21
+ from hkos.context.context_validator import ContextValidator
22
+ from hkos.context.models import ContextDocument, ContextExplanation
23
+ from hkos.context.snapshot_loader import SnapshotLoader
24
+ from hkos.context.token_estimator import TokenEstimate, TokenEstimator
25
+ from hkos.core.config import ConfigLoader
26
+ from hkos.core.logger import HKOSLogger
27
+ from hkos.index.validation import ValidationResult
28
+ from hkos.retrieval.retrieval_engine import RetrievalResult
29
+
30
+ __all__ = ["ContextBuilder"]
31
+
32
+ PROFILE_SMALL: str = "SMALL"
33
+ PROFILE_MEDIUM: str = "MEDIUM"
34
+ PROFILE_LARGE: str = "LARGE"
35
+ PROFILE_FULL: str = "FULL"
36
+
37
+ VALID_PROFILES: frozenset[str] = frozenset({
38
+ PROFILE_SMALL, PROFILE_MEDIUM, PROFILE_LARGE, PROFILE_FULL,
39
+ })
40
+
41
+
42
+ class ContextBuilder:
43
+ """Публичный фасад Context Builder (7 методов)."""
44
+
45
+ def __init__(
46
+ self,
47
+ config: ConfigLoader,
48
+ logger: HKOSLogger,
49
+ loader: SnapshotLoader | None = None,
50
+ manager: ContextManager | None = None,
51
+ ) -> None:
52
+ """Инициализация Context Builder.
53
+
54
+ Args:
55
+ config: ConfigLoader (секция context.*).
56
+ logger: HKOSLogger.
57
+ loader: SnapshotLoader (read-only); по умолчанию без снимков.
58
+ manager: ContextManager; создаётся по умолчанию из конфигурации.
59
+
60
+ """
61
+ self._config = config
62
+ self._logger = logger
63
+
64
+ # Коэффициенты из конфигурации (без захардкоженных чисел)
65
+ cpt = config.get("context.token_estimator.characters_per_token", 4)
66
+ wpt = config.get("context.token_estimator.words_per_token", 1)
67
+ characters_per_token = float(cpt) if isinstance(cpt, (int, float)) else 4.0
68
+ words_per_token = float(wpt) if isinstance(wpt, (int, float)) else 1.0
69
+ self._estimator = TokenEstimator(characters_per_token, words_per_token)
70
+
71
+ # Профили (лимиты токенов)
72
+ raw_profiles = config.get("context.profiles", {})
73
+ profile_limits: dict[str, int] = {}
74
+ if isinstance(raw_profiles, dict):
75
+ for name, limit in raw_profiles.items():
76
+ if isinstance(limit, int):
77
+ profile_limits[str(name)] = limit
78
+
79
+ # Секции сериализатора
80
+ raw_sections = config.get("context.serializer.sections", None)
81
+ sections = (
82
+ [str(s) for s in raw_sections]
83
+ if isinstance(raw_sections, list)
84
+ else None
85
+ )
86
+
87
+ self._loader = loader if loader is not None else SnapshotLoader()
88
+ body_limit_raw = config.get("context.serializer.body_limit", 200)
89
+ body_limit = int(body_limit_raw) if isinstance(body_limit_raw, int) else 200
90
+ self._serializer = ContextSerializer(sections, body_limit=body_limit)
91
+ self._optimizer = ContextOptimizer(self._estimator, profile_limits)
92
+ self._validator = ContextValidator(self._serializer)
93
+ self._manager = (
94
+ manager
95
+ if manager is not None
96
+ else ContextManager(
97
+ self._loader, self._optimizer, self._serializer,
98
+ self._validator, self._estimator,
99
+ )
100
+ )
101
+
102
+ # --- Публичный API ---
103
+
104
+ def build(
105
+ self,
106
+ result: RetrievalResult,
107
+ project_id: str,
108
+ campaign_id: str | None = None,
109
+ profile: str = PROFILE_MEDIUM,
110
+ include_history: bool = False,
111
+ ) -> ContextDocument:
112
+ """Построить контекст (полный конвейер).
113
+
114
+ Args:
115
+ result: RetrievalResult (DS-008).
116
+ project_id: UUID проекта.
117
+ campaign_id: UUID кампании (опционально).
118
+ profile: SMALL/MEDIUM/LARGE/FULL.
119
+ include_history: Включить исторические статусы.
120
+
121
+ Returns:
122
+ ContextDocument.
123
+
124
+ """
125
+ self._logger.info("Context Started")
126
+ if profile not in VALID_PROFILES:
127
+ profile = PROFILE_MEDIUM
128
+ context = self._manager.build(
129
+ result, project_id, campaign_id, profile, include_history
130
+ )
131
+ self._logger.info("Snapshot Loaded")
132
+ self._logger.info("Knowledge Added")
133
+ self._logger.info("Knowledge Removed")
134
+ self._logger.info("Optimization Completed")
135
+ self._logger.info("Serialization Completed")
136
+ self._logger.info("Context Delivered")
137
+ return context
138
+
139
+ def optimize(
140
+ self, context: ContextDocument, include_history: bool = False
141
+ ) -> ContextDocument:
142
+ """Оптимизировать контекст (dedup/фильтры/canonical merge/бюджет)."""
143
+ return self._optimizer.optimize(context, include_history)
144
+
145
+ def serialize(self, context: ContextDocument) -> str:
146
+ """Сериализовать контекст (стабильный порядок секций)."""
147
+ return self._serializer.serialize(context)
148
+
149
+ def statistics(self, context: ContextDocument) -> dict[str, object]:
150
+ """Статистика контекста."""
151
+ return ContextStatistics.calculate(context)
152
+
153
+ def validate(self, context: ContextDocument) -> ValidationResult:
154
+ """Проверить документ контекста."""
155
+ return self._validator.validate(context)
156
+
157
+ def estimate_tokens(self, text: str) -> TokenEstimate:
158
+ """Оценить размер текста (Characters/Words/Estimated Tokens)."""
159
+ return self._estimator.estimate(text)
160
+
161
+ def explain(self, context: ContextDocument) -> list[ContextExplanation]:
162
+ """Объяснение каждого элемента (почему включён/исключён,
163
+ источник, экономия токенов).
164
+ """
165
+ explanations: list[ContextExplanation] = []
166
+ for item in context.items:
167
+ explanations.append(
168
+ ContextExplanation(
169
+ entity_id=getattr(item.entity, "id", ""),
170
+ why_included=(
171
+ f"{item.reason} (source={item.source}, "
172
+ f"score={item.score:.2f})"
173
+ ),
174
+ why_excluded="",
175
+ source=item.source,
176
+ token_savings=0,
177
+ )
178
+ )
179
+ for item in context.excluded:
180
+ text = str(
181
+ getattr(item.entity, "title", "")
182
+ or getattr(item.entity, "name", "")
183
+ or ""
184
+ )
185
+ explanations.append(
186
+ ContextExplanation(
187
+ entity_id=getattr(item.entity, "id", ""),
188
+ why_included="",
189
+ why_excluded=item.excluded_reason,
190
+ source=item.source,
191
+ token_savings=self._estimator.estimate(text).estimated_tokens,
192
+ )
193
+ )
194
+ return explanations
195
+
196
+ @property
197
+ def loader(self) -> SnapshotLoader:
198
+ """SnapshotLoader (read-only)."""
199
+ return self._loader