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.
- hkos/__init__.py +37 -0
- hkos/api/__init__.py +0 -0
- hkos/campaign/__init__.py +0 -0
- hkos/config/__init__.py +0 -0
- hkos/config/hkos-development.yaml +151 -0
- hkos/config/hkos-production.yaml +125 -0
- hkos/config/logging.yaml +44 -0
- hkos/context/__init__.py +58 -0
- hkos/context/context_builder.py +199 -0
- hkos/context/context_manager.py +113 -0
- hkos/context/context_optimizer.py +184 -0
- hkos/context/context_serializer.py +154 -0
- hkos/context/context_statistics.py +48 -0
- hkos/context/context_validator.py +90 -0
- hkos/context/exceptions.py +21 -0
- hkos/context/models.py +98 -0
- hkos/context/snapshot_loader.py +72 -0
- hkos/context/token_estimator.py +76 -0
- hkos/core/__init__.py +0 -0
- hkos/core/bootstrap.py +94 -0
- hkos/core/config.py +150 -0
- hkos/core/constants.py +48 -0
- hkos/core/engine.py +72 -0
- hkos/core/exceptions.py +42 -0
- hkos/core/health.py +71 -0
- hkos/core/hkos.py +75 -0
- hkos/core/logger.py +103 -0
- hkos/core/registry.py +79 -0
- hkos/core/state.py +88 -0
- hkos/core/types.py +72 -0
- hkos/core/version.py +67 -0
- hkos/index/__init__.py +77 -0
- hkos/index/entity_index.py +78 -0
- hkos/index/exceptions.py +29 -0
- hkos/index/index_builder.py +159 -0
- hkos/index/index_cache.py +85 -0
- hkos/index/index_engine.py +158 -0
- hkos/index/index_manager.py +178 -0
- hkos/index/index_store.py +116 -0
- hkos/index/index_updater.py +174 -0
- hkos/index/index_validator.py +184 -0
- hkos/index/keyword_index.py +114 -0
- hkos/index/query_contract.py +288 -0
- hkos/index/relationship_index.py +171 -0
- hkos/index/statistics_index.py +65 -0
- hkos/index/tag_index.py +94 -0
- hkos/index/validation.py +46 -0
- hkos/integration/__init__.py +5 -0
- hkos/integration/hermes/__init__.py +30 -0
- hkos/integration/hermes/agent_lock.py +97 -0
- hkos/integration/hermes/audit.py +90 -0
- hkos/integration/hermes/doctor.py +196 -0
- hkos/integration/hermes/fallback.py +71 -0
- hkos/integration/hermes/hooks.py +173 -0
- hkos/integration/hermes/migration_commands.py +79 -0
- hkos/integration/hermes/migration_tools.py +298 -0
- hkos/integration/hermes/schemas.py +110 -0
- hkos/integration/hermes/security.py +174 -0
- hkos/kernel/__init__.py +9 -0
- hkos/kernel/snapshot_document.py +93 -0
- hkos/knowledge/__init__.py +0 -0
- hkos/librarian/__init__.py +0 -0
- hkos/mcp_server/__init__.py +9 -0
- hkos/mcp_server/context.py +82 -0
- hkos/mcp_server/jsonrpc.py +32 -0
- hkos/mcp_server/persistence.py +74 -0
- hkos/mcp_server/server.py +175 -0
- hkos/mcp_server/tools.py +288 -0
- hkos/migration/__init__.py +46 -0
- hkos/migration/backup_manager.py +115 -0
- hkos/migration/exceptions.py +42 -0
- hkos/migration/migration_engine.py +322 -0
- hkos/migration/migration_executor.py +74 -0
- hkos/migration/migration_history.py +68 -0
- hkos/migration/migration_manager.py +196 -0
- hkos/migration/migration_registry.py +165 -0
- hkos/migration/migration_validator.py +294 -0
- hkos/migration/rollback_manager.py +121 -0
- hkos/migration/schema_detector.py +146 -0
- hkos/migration/version_manifest.py +125 -0
- hkos/performance/__init__.py +70 -0
- hkos/performance/cache_manager.py +94 -0
- hkos/performance/context_profiles.py +147 -0
- hkos/performance/exceptions.py +13 -0
- hkos/performance/integration.py +213 -0
- hkos/performance/latency_tracker.py +59 -0
- hkos/performance/metrics_engine.py +95 -0
- hkos/performance/performance_manager.py +233 -0
- hkos/performance/profiler.py +57 -0
- hkos/performance/resource_monitor.py +110 -0
- hkos/project/__init__.py +0 -0
- hkos/repository/__init__.py +64 -0
- hkos/repository/artifact_repository.py +66 -0
- hkos/repository/base_repository.py +229 -0
- hkos/repository/campaign_repository.py +153 -0
- hkos/repository/decision_repository.py +95 -0
- hkos/repository/exceptions.py +31 -0
- hkos/repository/knowledge_relations.py +136 -0
- hkos/repository/knowledge_repository.py +133 -0
- hkos/repository/models.py +295 -0
- hkos/repository/project_repository.py +103 -0
- hkos/repository/repository_manager.py +71 -0
- hkos/retrieval/__init__.py +44 -0
- hkos/retrieval/candidate_builder.py +152 -0
- hkos/retrieval/exceptions.py +21 -0
- hkos/retrieval/knowledge_filter.py +50 -0
- hkos/retrieval/knowledge_selector.py +34 -0
- hkos/retrieval/query_parser.py +203 -0
- hkos/retrieval/ranking_engine.py +324 -0
- hkos/retrieval/relationship_traverser.py +124 -0
- hkos/retrieval/retrieval_engine.py +474 -0
- hkos/retrieval/retriever.py +140 -0
- hkos/services/__init__.py +103 -0
- hkos/services/campaign_factory.py +90 -0
- hkos/services/campaign_manager.py +370 -0
- hkos/services/campaign_service.py +90 -0
- hkos/services/campaign_state.py +141 -0
- hkos/services/campaign_statistics.py +142 -0
- hkos/services/campaign_validator.py +101 -0
- hkos/services/classification_policy.py +144 -0
- hkos/services/exceptions.py +53 -0
- hkos/services/librarian/__init__.py +60 -0
- hkos/services/librarian/canonicalizer.py +73 -0
- hkos/services/librarian/category_merge.py +32 -0
- hkos/services/librarian/confidence_engine.py +125 -0
- hkos/services/librarian/conflict_detector.py +109 -0
- hkos/services/librarian/exceptions.py +29 -0
- hkos/services/librarian/knowledge_classifier.py +99 -0
- hkos/services/librarian/knowledge_history.py +145 -0
- hkos/services/librarian/knowledge_merger.py +100 -0
- hkos/services/librarian/knowledge_status.py +169 -0
- hkos/services/librarian/librarian.py +338 -0
- hkos/services/memory_service.py +304 -0
- hkos/services/project_factory.py +68 -0
- hkos/services/project_manager.py +267 -0
- hkos/services/project_service.py +85 -0
- hkos/services/project_state.py +117 -0
- hkos/services/project_validator.py +139 -0
- hkos/snapshot/__init__.py +39 -0
- hkos/snapshot/exceptions.py +25 -0
- hkos/snapshot/snapshot_builder.py +199 -0
- hkos/snapshot/snapshot_diff.py +122 -0
- hkos/snapshot/snapshot_engine.py +165 -0
- hkos/snapshot/snapshot_history.py +76 -0
- hkos/snapshot/snapshot_loader.py +114 -0
- hkos/snapshot/snapshot_manager.py +211 -0
- hkos/snapshot/snapshot_serializer.py +49 -0
- hkos/snapshot/snapshot_validator.py +119 -0
- hkos/storage/__init__.py +41 -0
- hkos/storage/atomic_writer.py +104 -0
- hkos/storage/exceptions.py +46 -0
- hkos/storage/file_store.py +116 -0
- hkos/storage/json_store.py +240 -0
- hkos/storage/path_manager.py +199 -0
- hkos/storage/storage_engine.py +187 -0
- hkos/utils/__init__.py +0 -0
- hkos-1.0.0.dist-info/METADATA +307 -0
- hkos-1.0.0.dist-info/RECORD +162 -0
- hkos-1.0.0.dist-info/WHEEL +5 -0
- hkos-1.0.0.dist-info/entry_points.txt +2 -0
- hkos-1.0.0.dist-info/licenses/LICENSE +21 -0
- 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
|
hkos/config/__init__.py
ADDED
|
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
|
hkos/config/logging.yaml
ADDED
|
@@ -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]
|
hkos/context/__init__.py
ADDED
|
@@ -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
|