knowcode 0.1.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.
- knowcode-0.1.0.dist-info/METADATA +175 -0
- knowcode-0.1.0.dist-info/RECORD +63 -0
- knowcode-0.1.0.dist-info/WHEEL +4 -0
- knowcode-0.1.0.dist-info/entry_points.txt +2 -0
- runtime/__init__.py +4 -0
- runtime/artifact/__init__.py +1 -0
- runtime/artifact/builder.py +179 -0
- runtime/cli/__init__.py +1 -0
- runtime/cli/animation.py +278 -0
- runtime/cli/app.py +309 -0
- runtime/cli/auth.py +171 -0
- runtime/cli/telemetry.py +91 -0
- runtime/exceptions/__init__.py +1 -0
- runtime/exceptions/errors.py +99 -0
- runtime/repository/__init__.py +13 -0
- runtime/repository/discovery.py +64 -0
- runtime/repository/models.py +103 -0
- runtime/repository/paths.py +50 -0
- runtime/repository/validator.py +100 -0
- runtime/services/__init__.py +1 -0
- runtime/services/ingest_service.py +105 -0
- runtime/services/init_service.py +45 -0
- runtime/services/semantic_sync_service.py +55 -0
- runtime/services/status_service.py +40 -0
- runtime/services/sync_service.py +57 -0
- runtime/templates/KNOWCODE_LOADER.md.j2 +24 -0
- runtime/templates/README_KNOWLEDGE.md.j2 +12 -0
- runtime/templates/README_STRUCTURE.md.j2 +19 -0
- runtime/templates/__init__.py +1 -0
- runtime/templates/active_context.md.j2 +3 -0
- runtime/templates/ingest_legacy.md.j2 +15 -0
- runtime/templates/raw_readme.md.j2 +9 -0
- runtime/templates/sync_reconciliation.md.j2 +17 -0
- runtime/templates/synthesize_knowledge.md.j2 +32 -0
- runtime/templates/track_intent.md.j2 +14 -0
- structural_engine/__init__.py +3 -0
- structural_engine/diff/__init__.py +1 -0
- structural_engine/diff/generator.py +92 -0
- structural_engine/diff/models.py +48 -0
- structural_engine/engine.py +192 -0
- structural_engine/logs/__init__.py +1 -0
- structural_engine/logs/generator.py +33 -0
- structural_engine/parser/__init__.py +7 -0
- structural_engine/parser/discovery.py +165 -0
- structural_engine/parser/extractors/base.py +44 -0
- structural_engine/parser/languages/javascript/adapter.py +149 -0
- structural_engine/parser/languages/python/adapter.py +174 -0
- structural_engine/parser/languages/typescript/adapter.py +165 -0
- structural_engine/parser/models.py +186 -0
- structural_engine/parser/parser.py +160 -0
- structural_engine/parser/resolvers/calls.py +105 -0
- structural_engine/parser/tree_sitter/registry.py +61 -0
- structural_engine/reports/__init__.py +1 -0
- structural_engine/reports/generator.py +77 -0
- structural_engine/results.py +54 -0
- structural_engine/revisions/__init__.py +1 -0
- structural_engine/revisions/tracker.py +32 -0
- structural_engine/snapshot/__init__.py +1 -0
- structural_engine/snapshot/generator.py +58 -0
- structural_engine/snapshot/loader.py +59 -0
- structural_engine/state/__init__.py +1 -0
- structural_engine/state/manager.py +169 -0
- structural_engine/state/models.py +34 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Services subsystem.
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"""Ingest service.
|
|
2
|
+
|
|
3
|
+
Handles the Runtime orchestration for the 'knowcode ingest-semantic' command.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import structlog
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from pydantic import BaseModel
|
|
11
|
+
|
|
12
|
+
from runtime.exceptions.errors import KnowcodeError
|
|
13
|
+
from runtime.repository.discovery import discover_repository
|
|
14
|
+
from runtime.repository.paths import build_paths
|
|
15
|
+
from structural_engine.state.manager import StateManager
|
|
16
|
+
|
|
17
|
+
logger = structlog.get_logger(__name__)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class IngestSemanticResult(BaseModel):
|
|
21
|
+
"""Result of a semantic ingestion."""
|
|
22
|
+
message: str
|
|
23
|
+
semantic_revision: str
|
|
24
|
+
deleted_files: list[str]
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def run_ingest(cwd: Path, target_file: str) -> IngestSemanticResult:
|
|
28
|
+
"""Execute the semantic ingestion workflow.
|
|
29
|
+
|
|
30
|
+
1. Discover repository
|
|
31
|
+
2. Validate that the target_file is within the raw/ inbox
|
|
32
|
+
3. Delete the target file(s)
|
|
33
|
+
4. Increment the semantic_revision in state.yaml
|
|
34
|
+
|
|
35
|
+
Parameters
|
|
36
|
+
----------
|
|
37
|
+
cwd : Path
|
|
38
|
+
Current working directory to start discovery.
|
|
39
|
+
target_file : str
|
|
40
|
+
The specific file to delete, or "." to empty the inbox.
|
|
41
|
+
|
|
42
|
+
Returns
|
|
43
|
+
-------
|
|
44
|
+
IngestSemanticResult
|
|
45
|
+
The result of the ingestion.
|
|
46
|
+
|
|
47
|
+
Raises
|
|
48
|
+
------
|
|
49
|
+
KnowcodeError
|
|
50
|
+
If the target_file resolves outside the raw directory sandbox.
|
|
51
|
+
"""
|
|
52
|
+
repo = discover_repository(cwd)
|
|
53
|
+
paths = build_paths(repo)
|
|
54
|
+
|
|
55
|
+
deleted_files = []
|
|
56
|
+
|
|
57
|
+
if target_file == ".":
|
|
58
|
+
# Bulk deletion: safely iterate over raw directory
|
|
59
|
+
if paths.raw_knowledge_dir.exists():
|
|
60
|
+
for child in paths.raw_knowledge_dir.iterdir():
|
|
61
|
+
if child.is_file() and child.name != "README.md":
|
|
62
|
+
child.unlink()
|
|
63
|
+
deleted_files.append(child.name)
|
|
64
|
+
|
|
65
|
+
if not deleted_files:
|
|
66
|
+
return IngestSemanticResult(
|
|
67
|
+
message="Inbox is already empty.",
|
|
68
|
+
semantic_revision="No change",
|
|
69
|
+
deleted_files=[]
|
|
70
|
+
)
|
|
71
|
+
else:
|
|
72
|
+
# Single file deletion: resolve and validate security boundary
|
|
73
|
+
# target_file could be an absolute path or relative to cwd.
|
|
74
|
+
target_path = Path(target_file).resolve()
|
|
75
|
+
raw_path = paths.raw_knowledge_dir.resolve()
|
|
76
|
+
|
|
77
|
+
# Security validation: MUST be inside raw directory
|
|
78
|
+
if not target_path.is_relative_to(raw_path):
|
|
79
|
+
raise KnowcodeError(
|
|
80
|
+
f"Security Violation: Target '{target_file}' is not inside the raw inbox directory.\n"
|
|
81
|
+
f"Resolved target: {target_path}\n"
|
|
82
|
+
f"Allowed sandbox: {raw_path}"
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
if not target_path.exists():
|
|
86
|
+
raise KnowcodeError(f"Target file does not exist: {target_path}")
|
|
87
|
+
|
|
88
|
+
if target_path.name == "README.md":
|
|
89
|
+
raise KnowcodeError("Cannot delete the inbox README.md placeholder.")
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
target_path.unlink()
|
|
93
|
+
deleted_files.append(target_path.name)
|
|
94
|
+
|
|
95
|
+
# Commit the state update
|
|
96
|
+
state_manager = StateManager()
|
|
97
|
+
new_rev = state_manager.increment_semantic_revision(paths)
|
|
98
|
+
|
|
99
|
+
logger.info("semantic_sync.ingest_flushed", deleted_count=len(deleted_files))
|
|
100
|
+
|
|
101
|
+
return IngestSemanticResult(
|
|
102
|
+
message=f"Ingested {len(deleted_files)} file(s).",
|
|
103
|
+
semantic_revision=new_rev,
|
|
104
|
+
deleted_files=deleted_files
|
|
105
|
+
)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""Init service.
|
|
2
|
+
|
|
3
|
+
Handles the Runtime orchestration for the 'know .' command.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
from runtime.artifact.builder import ArtifactBuilder
|
|
11
|
+
from runtime.repository.discovery import discover_repository
|
|
12
|
+
from runtime.repository.paths import build_paths
|
|
13
|
+
from runtime.repository.validator import validate_for_init
|
|
14
|
+
from structural_engine.engine import StructuralEngine
|
|
15
|
+
from structural_engine.results import InitializationResult
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def run_init(cwd: Path) -> InitializationResult:
|
|
19
|
+
"""Execute the initialization workflow.
|
|
20
|
+
|
|
21
|
+
1. Discover repository
|
|
22
|
+
2. Validate preconditions
|
|
23
|
+
3. Build artifact directories and templates
|
|
24
|
+
4. Call StructuralEngine.initialize()
|
|
25
|
+
|
|
26
|
+
Parameters
|
|
27
|
+
----------
|
|
28
|
+
cwd : Path
|
|
29
|
+
Current working directory to start discovery.
|
|
30
|
+
|
|
31
|
+
Returns
|
|
32
|
+
-------
|
|
33
|
+
InitializationResult
|
|
34
|
+
The result from the engine.
|
|
35
|
+
"""
|
|
36
|
+
repo = discover_repository(cwd)
|
|
37
|
+
paths = build_paths(repo)
|
|
38
|
+
|
|
39
|
+
validate_for_init(paths)
|
|
40
|
+
|
|
41
|
+
builder = ArtifactBuilder(paths)
|
|
42
|
+
builder.build()
|
|
43
|
+
|
|
44
|
+
engine = StructuralEngine()
|
|
45
|
+
return engine.initialize(paths)
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""Semantic Sync service.
|
|
2
|
+
|
|
3
|
+
Handles the Runtime orchestration for the 'know sync-semantic' command.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
import structlog
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from pydantic import BaseModel
|
|
11
|
+
|
|
12
|
+
from runtime.repository.discovery import discover_repository
|
|
13
|
+
from runtime.repository.paths import build_paths
|
|
14
|
+
from structural_engine.state.manager import StateManager
|
|
15
|
+
|
|
16
|
+
logger = structlog.get_logger(__name__)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class SemanticSyncResult(BaseModel):
|
|
20
|
+
"""Result of a semantic synchronization."""
|
|
21
|
+
message: str
|
|
22
|
+
semantic_revision: str
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def run_semantic_sync(cwd: Path) -> SemanticSyncResult:
|
|
26
|
+
"""Execute the semantic synchronization workflow.
|
|
27
|
+
|
|
28
|
+
1. Discover repository
|
|
29
|
+
2. Increment the semantic_revision in state.yaml
|
|
30
|
+
3. Delete the previous_context.md file, flushing the queue
|
|
31
|
+
|
|
32
|
+
Parameters
|
|
33
|
+
----------
|
|
34
|
+
cwd : Path
|
|
35
|
+
Current working directory to start discovery.
|
|
36
|
+
|
|
37
|
+
Returns
|
|
38
|
+
-------
|
|
39
|
+
SemanticSyncResult
|
|
40
|
+
The result of the sync.
|
|
41
|
+
"""
|
|
42
|
+
repo = discover_repository(cwd)
|
|
43
|
+
paths = build_paths(repo)
|
|
44
|
+
|
|
45
|
+
state_manager = StateManager()
|
|
46
|
+
new_rev = state_manager.increment_semantic_revision(paths)
|
|
47
|
+
|
|
48
|
+
if paths.previous_context_file.exists():
|
|
49
|
+
paths.previous_context_file.unlink()
|
|
50
|
+
logger.info("semantic_sync.memory_flushed", file=str(paths.previous_context_file))
|
|
51
|
+
|
|
52
|
+
return SemanticSyncResult(
|
|
53
|
+
message="Semantic Knowledge Synchronized.",
|
|
54
|
+
semantic_revision=new_rev
|
|
55
|
+
)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""Status service.
|
|
2
|
+
|
|
3
|
+
Handles the Runtime orchestration for the 'know status' command.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
from runtime.repository.discovery import discover_repository
|
|
11
|
+
from runtime.repository.paths import build_paths
|
|
12
|
+
from runtime.repository.validator import validate_for_sync
|
|
13
|
+
from structural_engine.engine import StructuralEngine
|
|
14
|
+
from structural_engine.results import StructuralStatusResult
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def run_status(cwd: Path) -> StructuralStatusResult:
|
|
18
|
+
"""Execute the status workflow.
|
|
19
|
+
|
|
20
|
+
1. Discover repository
|
|
21
|
+
2. Validate preconditions
|
|
22
|
+
3. Call StructuralEngine.status()
|
|
23
|
+
|
|
24
|
+
Parameters
|
|
25
|
+
----------
|
|
26
|
+
cwd : Path
|
|
27
|
+
Current working directory to start discovery.
|
|
28
|
+
|
|
29
|
+
Returns
|
|
30
|
+
-------
|
|
31
|
+
StructuralStatusResult
|
|
32
|
+
The result from the engine.
|
|
33
|
+
"""
|
|
34
|
+
repo = discover_repository(cwd)
|
|
35
|
+
paths = build_paths(repo)
|
|
36
|
+
|
|
37
|
+
validate_for_sync(paths)
|
|
38
|
+
|
|
39
|
+
engine = StructuralEngine()
|
|
40
|
+
return engine.status(paths)
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"""Sync service.
|
|
2
|
+
|
|
3
|
+
Handles the Runtime orchestration for the 'know sync' command.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
from runtime.repository.discovery import discover_repository
|
|
11
|
+
from runtime.repository.paths import build_paths
|
|
12
|
+
from runtime.repository.validator import validate_for_sync
|
|
13
|
+
from structural_engine.engine import StructuralEngine
|
|
14
|
+
from structural_engine.results import SyncResult
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def run_sync(cwd: Path) -> SyncResult:
|
|
18
|
+
"""Execute the synchronization workflow.
|
|
19
|
+
|
|
20
|
+
1. Discover repository
|
|
21
|
+
2. Validate preconditions
|
|
22
|
+
3. Call StructuralEngine.sync()
|
|
23
|
+
|
|
24
|
+
Parameters
|
|
25
|
+
----------
|
|
26
|
+
cwd : Path
|
|
27
|
+
Current working directory to start discovery.
|
|
28
|
+
|
|
29
|
+
Returns
|
|
30
|
+
-------
|
|
31
|
+
SyncResult
|
|
32
|
+
The result from the engine.
|
|
33
|
+
"""
|
|
34
|
+
repo = discover_repository(cwd)
|
|
35
|
+
paths = build_paths(repo)
|
|
36
|
+
|
|
37
|
+
validate_for_sync(paths)
|
|
38
|
+
|
|
39
|
+
engine = StructuralEngine()
|
|
40
|
+
result = engine.sync(paths)
|
|
41
|
+
|
|
42
|
+
# Rollover the active context memory if structural changes occurred
|
|
43
|
+
if result.changes_detected and paths.active_context_file.exists():
|
|
44
|
+
active_content = paths.active_context_file.read_text(encoding="utf-8")
|
|
45
|
+
|
|
46
|
+
if paths.previous_context_file.exists():
|
|
47
|
+
with open(paths.previous_context_file, "a", encoding="utf-8") as f:
|
|
48
|
+
f.write("\n\n---\n\n" + active_content)
|
|
49
|
+
else:
|
|
50
|
+
paths.previous_context_file.write_text(active_content, encoding="utf-8")
|
|
51
|
+
|
|
52
|
+
import jinja2
|
|
53
|
+
env = jinja2.Environment(loader=jinja2.PackageLoader("runtime", "templates"))
|
|
54
|
+
template = env.get_template("active_context.md.j2")
|
|
55
|
+
paths.active_context_file.write_text(template.render(), encoding="utf-8")
|
|
56
|
+
|
|
57
|
+
return result
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
name: knowcode-loader
|
|
2
|
+
description: Initializes Knowcode governance for the current session.
|
|
3
|
+
trigger: /knowcode
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Knowcode Session Initialization
|
|
7
|
+
|
|
8
|
+
You have just been invoked via the `/knowcode` command. You are now acting as the Knowcode Governance Agent for this repository.
|
|
9
|
+
|
|
10
|
+
### Immediate Actions Required:
|
|
11
|
+
1. **Load the Passive Tracker:** You must immediately read and internalize the rules defined in `.agent/skills/track_intent.md`. You must run this skill continuously in the background for every subsequent prompt in this session.
|
|
12
|
+
2. **Acknowledge:** Reply to the user with exactly this message:
|
|
13
|
+
> *"Knowcode governance active. I am now silently tracking your architectural intent. Code normally, and type `/know-sync` when you are ready to synchronize."*
|
|
14
|
+
|
|
15
|
+
### Tool Boundary Constraint
|
|
16
|
+
While you may explore external packages or documentation to assist the developer, you must **never** attempt to read, debug, or modify the source code of the `know` CLI itself (e.g., the directory where the `knowcode` package is installed). The internal logic of the Knowcode engine is strictly off-limits.
|
|
17
|
+
|
|
18
|
+
### Knowcode CLI Reference
|
|
19
|
+
You have access to the `know` CLI terminal utility to manage structural and semantic state. Do not invent arguments.
|
|
20
|
+
|
|
21
|
+
- **`know sync`**: Computes structural diffs, generates a report (`R-XXX.md`), and rolls active memory over to `previous_context.md`. (Run this during `/know-sync`).
|
|
22
|
+
- **`know sync-semantic`**: Commits semantic knowledge, increments `semantic_revision`, and flushes `previous_context.md`. (Run this after synthesis).
|
|
23
|
+
- **`know ingest-semantic .`**: Wipes the `.knowcode/knowledge/raw/` inbox and increments the semantic revision. (Run this after legacy ingestion).
|
|
24
|
+
- **`know status`**: Displays current revisions, sync timestamps, and artifact locations.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Knowledge Maintenance Protocol
|
|
2
|
+
|
|
3
|
+
This directory contains the human-facing architectural guidelines, constraints, conventions, and component documentation for the repository.
|
|
4
|
+
|
|
5
|
+
## Organization
|
|
6
|
+
- `architecture/`: High-level system design, sub-system descriptions, and boundaries.
|
|
7
|
+
- `decisions/`: ADRs (Architecture Decision Records) explaining *why* a particular path was chosen.
|
|
8
|
+
- `constraints/`: System invariants and "Trap" documentation. These are rules that must not be broken.
|
|
9
|
+
- `conventions/`: Style, formatting, and language-specific rules.
|
|
10
|
+
- `components/`: Specific component contracts and behaviors.
|
|
11
|
+
|
|
12
|
+
This structure allows AI agents to orient themselves, understand system boundaries, and avoid regressions by reading explicitly defined constraints.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# KnowCode Instance: {{ project_name }}
|
|
2
|
+
|
|
3
|
+
This directory (`.agent/`) is the active governance and behavior root for this repository. It defines how autonomous agents should interact with, maintain, and evolve the codebase.
|
|
4
|
+
|
|
5
|
+
## The Dual-Folder Architecture
|
|
6
|
+
|
|
7
|
+
* **`.agent/` (Behavior & Governance):** You are here. This directory contains instructions, workflows, and skills that dictate *how* the AI operates.
|
|
8
|
+
* **`.knowcode/` (Passive Knowledge & State):** The sibling directory. It contains deterministic AST snapshots, reports, logs, and persistent semantic state. `.knowcode/` has no operational governance.
|
|
9
|
+
|
|
10
|
+
## Subsystems
|
|
11
|
+
|
|
12
|
+
* **Runtime:** Orchestrates operations and manages this artifact structure.
|
|
13
|
+
* **Structural Engine:** Owns `state.yaml` and parses the repository into deterministic snapshots.
|
|
14
|
+
|
|
15
|
+
## Directory Structure
|
|
16
|
+
- `skills/`: Markdown definitions of agent capabilities and functions.
|
|
17
|
+
- `workflows/`: Orchestration sequences defining how agents tackle complex, multi-step goals.
|
|
18
|
+
|
|
19
|
+
**Note:** The state lockfile (`.knowcode/state.yaml`) is managed exclusively by the Structural Engine. Do not edit it manually.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Brain artifact templates.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ingest_legacy
|
|
3
|
+
description: Orchestrates the processing and cleanup of legacy knowledge documents.
|
|
4
|
+
trigger: /know-ingest
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Legacy Ingestion Workflow
|
|
8
|
+
|
|
9
|
+
When the user invokes `/know-ingest`, you must process the raw inbox.
|
|
10
|
+
|
|
11
|
+
### Execution Sequence:
|
|
12
|
+
1. **Inbox Check:** List the files in `.knowcode/knowledge/raw/`. If it is empty (or only contains `README.md`), stop the workflow and inform the user.
|
|
13
|
+
2. **Synthesis:** Load the skill `.agent/skills/synthesize_knowledge.md` and execute its instructions to process the raw documents.
|
|
14
|
+
3. **Semantic Commit & Cleanup:** Once synthesis is written to disk, run the terminal command `know ingest-semantic .`. This will bump the semantic revision and the CLI will delete all the raw files.
|
|
15
|
+
4. **Completion:** Summarize the knowledge you extracted and which buckets you updated.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Raw Knowledge Inbox
|
|
2
|
+
|
|
3
|
+
This directory (`.knowcode/knowledge/raw/`) is the inbox for legacy or unstructured documentation.
|
|
4
|
+
|
|
5
|
+
## Workflow
|
|
6
|
+
|
|
7
|
+
1. **Drop files here:** Drop your old PDFs, markdown files, or text documents into this folder.
|
|
8
|
+
2. **Agent Synthesis:** Ask the Semantic Agent to read the files and distribute the knowledge into the proper architectural documents (e.g., `architecture.md`, `decisions.md`).
|
|
9
|
+
3. **Commit & Cleanup:** Once the agent is done extracting information from a file, it will run `know ingest-semantic <filename>` to delete the file and safely bump the knowledge base revision. Alternatively, the agent can run `know ingest-semantic .` to wipe the entire inbox at once.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sync_reconciliation
|
|
3
|
+
description: Orchestrates the Knowcode sync and reconciliation loop.
|
|
4
|
+
trigger: /know-sync
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Sync Reconciliation Workflow
|
|
8
|
+
|
|
9
|
+
When the user invokes `/know-sync`, you must execute the complete reconciliation loop. Do not skip any steps.
|
|
10
|
+
|
|
11
|
+
### Execution Sequence:
|
|
12
|
+
1. **Structural Sync:** Run the terminal command `know sync`. Wait for it to complete.
|
|
13
|
+
2. **Buffer Check:** Check if `.agent/memory/previous_context.md` exists.
|
|
14
|
+
- *Note: If this file does not exist, it means there were no structural changes. Stop the workflow here and inform the user.*
|
|
15
|
+
3. **Synthesis:** Load the skill `.agent/skills/synthesize_knowledge.md` and execute its instructions to synthesize the sync state.
|
|
16
|
+
4. **Semantic Commit:** Once synthesis is written to disk, run the terminal command `know sync-semantic`. This will bump the semantic revision and the CLI will delete the previous context buffer.
|
|
17
|
+
5. **Completion:** Summarize the architectural updates you just made to the user.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: synthesize_knowledge
|
|
3
|
+
description: Skill to reconcile staged intent or legacy documents and update the permanent knowledge base.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Knowledge Synthesis & Classification
|
|
7
|
+
|
|
8
|
+
When called upon to synthesize knowledge, you are acting as the Chief Architect. You must classify information and deposit it into the correct buckets.
|
|
9
|
+
|
|
10
|
+
### Step 1: Branching Execution
|
|
11
|
+
**If invoked by `/know-sync`:**
|
|
12
|
+
1. Read `.agent/memory/previous_context.md` (The Intent/Why).
|
|
13
|
+
2. Read the latest `.knowcode/reports/R-XXX.md` report (The Reality/What).
|
|
14
|
+
3. Reconcile: Compare the intent against reality. Did the structural changes match the intent? If there is a contradiction, the structural report is the absolute truth.
|
|
15
|
+
|
|
16
|
+
**If invoked by `/know-ingest`:**
|
|
17
|
+
1. Read the raw documents located in `.knowcode/knowledge/raw/`.
|
|
18
|
+
2. Do NOT cross-reference structural reports. Simply extract the architectural knowledge from the legacy files.
|
|
19
|
+
|
|
20
|
+
### Step 2: Knowledge Distribution
|
|
21
|
+
Take the validated insights and append them to the appropriate Markdown files within `.knowcode/knowledge/`:
|
|
22
|
+
|
|
23
|
+
- `architecture/architecture.md`: High-level system design, data flow, subsystem responsibilities, and boundaries.
|
|
24
|
+
- `decisions/decisions.md`: Architecture Decision Records (ADRs). The choice made, alternatives considered, and the trade-off rationale.
|
|
25
|
+
- `constraints/constraints.md`: System invariants, import firewalls, security boundaries, and strict rules that must not be broken.
|
|
26
|
+
- `conventions/conventions.md`: Styling, naming patterns, file structure, and formatting rules.
|
|
27
|
+
- `components/components.md`: Specific component behaviors, public API contracts, and state machines.
|
|
28
|
+
|
|
29
|
+
### Formatting Rules:
|
|
30
|
+
- Append to existing files. Do not overwrite.
|
|
31
|
+
- Use clear markdown `##` headings for new topics.
|
|
32
|
+
- Keep descriptions precise and factual.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: track_intent
|
|
3
|
+
description: The passive skill for distilling developer intent into the active context buffer.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Intent Tracking (The Prime Directive)
|
|
7
|
+
|
|
8
|
+
This is a passive background skill. While you are pair-programming, writing code, and answering questions, you must continuously distill the *Why* behind the development session.
|
|
9
|
+
|
|
10
|
+
### Rules for Tracking:
|
|
11
|
+
1. **Listen for Intent:** Identify design decisions, architectural shifts, new constraints discovered, and the reasoning behind code changes.
|
|
12
|
+
2. **Append Silently:** Write these insights as 1-2 sentence bullet points into `.agent/memory/active_context.md`. Do this silently in the background without asking the user for permission.
|
|
13
|
+
3. **No Code:** Do NOT log raw code snippets. The physical code is tracked by Git. You are tracking the *Why*.
|
|
14
|
+
4. **Append-Only:** Never overwrite or truncate `active_context.md`. Only append. Never flush this file manually.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Diff subsystem.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"""Diff generator.
|
|
2
|
+
|
|
3
|
+
Calculates the delta between two snapshots.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from structural_engine.diff.models import StructuralDiff
|
|
9
|
+
from structural_engine.parser.models import Entity, Relationship, StructuralSnapshot
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def generate(previous: StructuralSnapshot, current: StructuralSnapshot) -> StructuralDiff:
|
|
13
|
+
"""Generate the structural difference between two snapshots.
|
|
14
|
+
|
|
15
|
+
Parameters
|
|
16
|
+
----------
|
|
17
|
+
previous : StructuralSnapshot
|
|
18
|
+
The older state.
|
|
19
|
+
current : StructuralSnapshot
|
|
20
|
+
The newer state.
|
|
21
|
+
|
|
22
|
+
Returns
|
|
23
|
+
-------
|
|
24
|
+
StructuralDiff
|
|
25
|
+
The computed delta.
|
|
26
|
+
"""
|
|
27
|
+
prev_entities = {e.id: e for e in previous.entities}
|
|
28
|
+
curr_entities = {e.id: e for e in current.entities}
|
|
29
|
+
|
|
30
|
+
added_entities: list[Entity] = []
|
|
31
|
+
removed_entities: list[Entity] = []
|
|
32
|
+
modified_entities: list[Entity] = []
|
|
33
|
+
affected_components: set[str] = set()
|
|
34
|
+
|
|
35
|
+
def _track_component(entity_id: str) -> None:
|
|
36
|
+
"""Extract top-level directory from an ID to mark component as affected."""
|
|
37
|
+
# e.g., src/auth.py::verify_token -> src
|
|
38
|
+
# or tests/test_auth.py -> tests
|
|
39
|
+
path_part = entity_id.split("::")[0]
|
|
40
|
+
if "/" in path_part:
|
|
41
|
+
component = path_part.split("/")[0]
|
|
42
|
+
affected_components.add(component)
|
|
43
|
+
else:
|
|
44
|
+
affected_components.add("root")
|
|
45
|
+
|
|
46
|
+
for e_id, e_curr in curr_entities.items():
|
|
47
|
+
if e_id not in prev_entities:
|
|
48
|
+
added_entities.append(e_curr)
|
|
49
|
+
_track_component(e_id)
|
|
50
|
+
else:
|
|
51
|
+
e_prev = prev_entities[e_id]
|
|
52
|
+
# Simple line or property shift check
|
|
53
|
+
if (
|
|
54
|
+
e_curr.start_line != e_prev.start_line
|
|
55
|
+
or e_curr.end_line != e_prev.end_line
|
|
56
|
+
or e_curr.type != e_prev.type
|
|
57
|
+
or e_curr.parent_id != e_prev.parent_id
|
|
58
|
+
):
|
|
59
|
+
modified_entities.append(e_curr)
|
|
60
|
+
_track_component(e_id)
|
|
61
|
+
|
|
62
|
+
for e_id, e_prev in prev_entities.items():
|
|
63
|
+
if e_id not in curr_entities:
|
|
64
|
+
removed_entities.append(e_prev)
|
|
65
|
+
_track_component(e_id)
|
|
66
|
+
|
|
67
|
+
# Relationship diffs
|
|
68
|
+
# Relationships are identified by the tuple (source_id, target_id, type)
|
|
69
|
+
prev_rels = {(r.source_id, r.target_id, r.type.name): r for r in previous.relationships}
|
|
70
|
+
curr_rels = {(r.source_id, r.target_id, r.type.name): r for r in current.relationships}
|
|
71
|
+
|
|
72
|
+
added_rels: list[Relationship] = []
|
|
73
|
+
removed_rels: list[Relationship] = []
|
|
74
|
+
|
|
75
|
+
for key, r_curr in curr_rels.items():
|
|
76
|
+
if key not in prev_rels:
|
|
77
|
+
added_rels.append(r_curr)
|
|
78
|
+
_track_component(r_curr.source_id)
|
|
79
|
+
|
|
80
|
+
for key, r_prev in prev_rels.items():
|
|
81
|
+
if key not in curr_rels:
|
|
82
|
+
removed_rels.append(r_prev)
|
|
83
|
+
_track_component(r_prev.source_id)
|
|
84
|
+
|
|
85
|
+
return StructuralDiff(
|
|
86
|
+
entities_added=tuple(added_entities),
|
|
87
|
+
entities_removed=tuple(removed_entities),
|
|
88
|
+
entities_modified=tuple(modified_entities),
|
|
89
|
+
relationships_added=tuple(added_rels),
|
|
90
|
+
relationships_removed=tuple(removed_rels),
|
|
91
|
+
affected_components=frozenset(affected_components),
|
|
92
|
+
)
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""Diff domain models.
|
|
2
|
+
|
|
3
|
+
Represents the structural delta between two snapshots.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from dataclasses import dataclass, field
|
|
9
|
+
|
|
10
|
+
from structural_engine.parser.models import Entity, Relationship
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass(frozen=True)
|
|
14
|
+
class StructuralDiff:
|
|
15
|
+
"""The delta between two structural states.
|
|
16
|
+
|
|
17
|
+
Identifies exactly what changed structurally, ignoring pure logic
|
|
18
|
+
modifications that don't shift AST bounds or signatures.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
entities_added: tuple[Entity, ...] = field(default_factory=tuple)
|
|
22
|
+
"""Entities present in current but not in previous."""
|
|
23
|
+
|
|
24
|
+
entities_removed: tuple[Entity, ...] = field(default_factory=tuple)
|
|
25
|
+
"""Entities present in previous but not in current."""
|
|
26
|
+
|
|
27
|
+
entities_modified: tuple[Entity, ...] = field(default_factory=tuple)
|
|
28
|
+
"""Entities whose lines shifted or properties changed, but ID matched."""
|
|
29
|
+
|
|
30
|
+
relationships_added: tuple[Relationship, ...] = field(default_factory=tuple)
|
|
31
|
+
"""Relationships present in current but not in previous."""
|
|
32
|
+
|
|
33
|
+
relationships_removed: tuple[Relationship, ...] = field(default_factory=tuple)
|
|
34
|
+
"""Relationships present in previous but not in current."""
|
|
35
|
+
|
|
36
|
+
affected_components: frozenset[str] = field(default_factory=frozenset)
|
|
37
|
+
"""Top-level directories (components) affected by these changes."""
|
|
38
|
+
|
|
39
|
+
@property
|
|
40
|
+
def has_changes(self) -> bool:
|
|
41
|
+
"""Return True if any structural change occurred."""
|
|
42
|
+
return bool(
|
|
43
|
+
self.entities_added
|
|
44
|
+
or self.entities_removed
|
|
45
|
+
or self.entities_modified
|
|
46
|
+
or self.relationships_added
|
|
47
|
+
or self.relationships_removed
|
|
48
|
+
)
|