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.
Files changed (63) hide show
  1. knowcode-0.1.0.dist-info/METADATA +175 -0
  2. knowcode-0.1.0.dist-info/RECORD +63 -0
  3. knowcode-0.1.0.dist-info/WHEEL +4 -0
  4. knowcode-0.1.0.dist-info/entry_points.txt +2 -0
  5. runtime/__init__.py +4 -0
  6. runtime/artifact/__init__.py +1 -0
  7. runtime/artifact/builder.py +179 -0
  8. runtime/cli/__init__.py +1 -0
  9. runtime/cli/animation.py +278 -0
  10. runtime/cli/app.py +309 -0
  11. runtime/cli/auth.py +171 -0
  12. runtime/cli/telemetry.py +91 -0
  13. runtime/exceptions/__init__.py +1 -0
  14. runtime/exceptions/errors.py +99 -0
  15. runtime/repository/__init__.py +13 -0
  16. runtime/repository/discovery.py +64 -0
  17. runtime/repository/models.py +103 -0
  18. runtime/repository/paths.py +50 -0
  19. runtime/repository/validator.py +100 -0
  20. runtime/services/__init__.py +1 -0
  21. runtime/services/ingest_service.py +105 -0
  22. runtime/services/init_service.py +45 -0
  23. runtime/services/semantic_sync_service.py +55 -0
  24. runtime/services/status_service.py +40 -0
  25. runtime/services/sync_service.py +57 -0
  26. runtime/templates/KNOWCODE_LOADER.md.j2 +24 -0
  27. runtime/templates/README_KNOWLEDGE.md.j2 +12 -0
  28. runtime/templates/README_STRUCTURE.md.j2 +19 -0
  29. runtime/templates/__init__.py +1 -0
  30. runtime/templates/active_context.md.j2 +3 -0
  31. runtime/templates/ingest_legacy.md.j2 +15 -0
  32. runtime/templates/raw_readme.md.j2 +9 -0
  33. runtime/templates/sync_reconciliation.md.j2 +17 -0
  34. runtime/templates/synthesize_knowledge.md.j2 +32 -0
  35. runtime/templates/track_intent.md.j2 +14 -0
  36. structural_engine/__init__.py +3 -0
  37. structural_engine/diff/__init__.py +1 -0
  38. structural_engine/diff/generator.py +92 -0
  39. structural_engine/diff/models.py +48 -0
  40. structural_engine/engine.py +192 -0
  41. structural_engine/logs/__init__.py +1 -0
  42. structural_engine/logs/generator.py +33 -0
  43. structural_engine/parser/__init__.py +7 -0
  44. structural_engine/parser/discovery.py +165 -0
  45. structural_engine/parser/extractors/base.py +44 -0
  46. structural_engine/parser/languages/javascript/adapter.py +149 -0
  47. structural_engine/parser/languages/python/adapter.py +174 -0
  48. structural_engine/parser/languages/typescript/adapter.py +165 -0
  49. structural_engine/parser/models.py +186 -0
  50. structural_engine/parser/parser.py +160 -0
  51. structural_engine/parser/resolvers/calls.py +105 -0
  52. structural_engine/parser/tree_sitter/registry.py +61 -0
  53. structural_engine/reports/__init__.py +1 -0
  54. structural_engine/reports/generator.py +77 -0
  55. structural_engine/results.py +54 -0
  56. structural_engine/revisions/__init__.py +1 -0
  57. structural_engine/revisions/tracker.py +32 -0
  58. structural_engine/snapshot/__init__.py +1 -0
  59. structural_engine/snapshot/generator.py +58 -0
  60. structural_engine/snapshot/loader.py +59 -0
  61. structural_engine/state/__init__.py +1 -0
  62. structural_engine/state/manager.py +169 -0
  63. structural_engine/state/models.py +34 -0
@@ -0,0 +1,175 @@
1
+ Metadata-Version: 2.4
2
+ Name: knowcode
3
+ Version: 0.1.0
4
+ Summary: Structural cognition engine for code repositories
5
+ Requires-Python: >=3.13
6
+ Requires-Dist: jinja2>=3.1.0
7
+ Requires-Dist: platformdirs>=4.0.0
8
+ Requires-Dist: pydantic>=2.11.0
9
+ Requires-Dist: questionary>=2.0.0
10
+ Requires-Dist: rich>=14.0.0
11
+ Requires-Dist: ruamel-yaml>=0.18.0
12
+ Requires-Dist: structlog>=25.0.0
13
+ Requires-Dist: tree-sitter-javascript>=0.25.0
14
+ Requires-Dist: tree-sitter-python>=0.25.0
15
+ Requires-Dist: tree-sitter-typescript>=0.23.2
16
+ Requires-Dist: tree-sitter>=0.25.2
17
+ Requires-Dist: typer>=0.15.0
18
+ Description-Content-Type: text/markdown
19
+
20
+ # KnowCode
21
+
22
+ [![Python Version](https://img.shields.io/badge/python-3.13%2B-blue.svg)](https://www.python.org/)
23
+ [![License](https://img.shields.io/badge/license-MIT-green.svg)](#license)
24
+
25
+ **KnowCode** is a structural cognition engine designed specifically for Agentic IDEs (like Cursor, Gemini, and Copilot). It bridges the gap between **physical repository code**, **deterministic structural snapshots**, and **semantic architectural knowledge**, allowing AI agents and human developers to seamlessly inspect, track, and maintain codebase architectures.
26
+
27
+ ---
28
+
29
+ ## Table of Contents
30
+
31
+ - [Overview](#overview)
32
+ - [Key Features](#key-features)
33
+ - [Installation](#installation)
34
+ - [Usage: The Agentic Workflow](#usage-the-agentic-workflow)
35
+ - [Ecosystem Layout](#ecosystem-layout)
36
+ - [CLI Reference & Manual Execution](#cli-reference--manual-execution)
37
+ - [License](#license)
38
+
39
+ ---
40
+
41
+ ## Overview
42
+
43
+ KnowCode completely flips the traditional documentation model. Instead of forcing developers to write specs *before* they code, KnowCode uses an AI agent to track your intent during a development session. When you sync your physical code changes, the AI agent is automatically invoked to synthesize your intent against the deterministic reality of the codebase, ensuring your architectural knowledge naturally accumulates as a byproduct of development.
44
+
45
+ KnowCode partitions codebase understanding into three clean domains:
46
+ 1. **Physical Reality:** The actual source files inside the repository.
47
+ 2. **Structural Truth:** Deterministic representation of files, components, and code symbols parsed via abstract syntax trees (ASTs).
48
+ 3. **Semantic Knowledge:** Permanent architectural rules, decisions, and constraints synthesized by your AI agent.
49
+
50
+ ---
51
+
52
+ ## Key Features
53
+
54
+ - **Native Agent Integration:** Built-in slash commands (`/knowcode`, `/know-sync`) that plug directly into Agentic IDEs without configuration.
55
+ - **Multi-Language AST Parsing**: Built on top of `tree-sitter`, with out-of-the-box support for **Python**, **JavaScript**, and **TypeScript**.
56
+ - **Deterministic State & Revision Tracking**: Tracks codebase changes across sequential revisions (`S-001`, `S-002`, etc.).
57
+ - **Diff & Report Generation**: Automatically computes additions, deletions, line-boundary modifications, and maps changes to their top-level affected components.
58
+
59
+ ---
60
+
61
+ ## Installation
62
+
63
+ ### Prerequisites
64
+ - [Python 3.13+](https://www.python.org/)
65
+ - [uv Package Manager](https://github.com/astral-sh/uv)
66
+
67
+ ### Installation
68
+
69
+ You can install Knowcode directly via pip or npm.
70
+
71
+ **Using pip:**
72
+ ```bash
73
+ pip install knowcode
74
+ ```
75
+
76
+ **Using npm:**
77
+ ```bash
78
+ npm install -g knowcode
79
+ ```
80
+
81
+ #### Development Setup
82
+
83
+ If you want to contribute or modify the code, clone the repository and install it in editable mode:
84
+
85
+ ```bash
86
+ git clone https://github.com/knowiki/knowcode.git
87
+ cd knowcode
88
+ uv sync
89
+ uv pip install -e .
90
+ ```
91
+
92
+ ---
93
+
94
+ ## Usage: The Agentic Workflow
95
+
96
+ KnowCode is designed to be driven by you and your AI agent in tandem.
97
+
98
+ ### 1. Initialize the Repository
99
+ Run the initialization command in your target repository terminal:
100
+ ```bash
101
+ know .
102
+ ```
103
+ This scaffolds the `.agent/` and `.knowcode/` directories, computes your first AST snapshot, and drops `knowcode.md` at your root.
104
+
105
+ *Note: To prevent polluting your repository, `know .` automatically adds `.knowcode/`, `.agent/`, and `knowcode.md` to your `.gitignore`. If you want to share your synthesized semantic knowledge with your team, you can selectively un-ignore `.knowcode/knowledge/`.*
106
+
107
+ ### 2. Activate the Agent
108
+ In your AI chat (Cursor, Copilot, Gemini), simply type:
109
+ ```text
110
+ /knowcode
111
+ ```
112
+ The agent will instantly read `knowcode.md`, lock into the KnowCode governance rules, and begin silently tracking your intent in `.agent/memory/active_context.md` while you code.
113
+
114
+ ### 3. Sync & Synthesize
115
+ After you finish a coding session or fix a bug, instruct the agent to synchronize by typing:
116
+ ```text
117
+ /know-sync
118
+ ```
119
+ The agent will orchestrate the entire lifecycle:
120
+ 1. Run `know sync` to compute structural AST diffs.
121
+ 2. Read the generated structural report (`R-XXX.md`).
122
+ 3. Reconcile the structural reality against your tracked intent.
123
+ 4. Distribute the extracted knowledge into the 5 semantic buckets (`architecture`, `decisions`, etc.).
124
+ 5. Run `know sync-semantic` to commit the knowledge and bump the revision.
125
+
126
+ ---
127
+
128
+ ## Ecosystem Layout
129
+
130
+ When KnowCode is initialized in a repository via `know .`, it generates a governed agent architecture:
131
+
132
+ ```text
133
+ /
134
+ ├── knowcode.md # The Agent Ignition Switch (Read by the AI)
135
+ ├── .agent/ # The Semantic Governance & Memory Layer
136
+ │ ├── memory/
137
+ │ │ ├── active_context.md # The AI's short-term intent tracking buffer
138
+ │ │ └── previous_context.md
139
+ │ ├── skills/
140
+ │ │ ├── track_intent.md # Background skill for tracking architectural intent
141
+ │ │ └── synthesize_knowledge.md
142
+ │ └── workflows/
143
+ │ ├── sync_reconciliation.md # The /know-sync workflow
144
+ │ └── ingest_legacy.md # The /know-ingest workflow
145
+
146
+ └── .knowcode/ # The Deterministic Knowledge Artifact
147
+ ├── state.yaml # Authoritative state registry (managed by the Engine)
148
+ ├── structure/ # Deterministic AST snapshots (e.g. S-001.json)
149
+ ├── reports/ # Change and diff analysis reports (e.g. R-001.md)
150
+ └── knowledge/ # Permanent semantic knowledge (AI synthesized)
151
+ ├── architecture/
152
+ ├── components/
153
+ ├── constraints/
154
+ ├── conventions/
155
+ ├── decisions/
156
+ └── raw/ # Inbox for legacy or unstructured documentation
157
+ ```
158
+
159
+ ---
160
+
161
+ ## CLI Reference & Manual Execution
162
+
163
+ While the Agentic Workflow relies on slash commands to orchestrate operations, developers can bypass the AI entirely and execute any step manually using the `know` CLI. This is useful for CI/CD pipelines, programmatic integration, or direct inspection.
164
+
165
+ - `know .`: Initializes Knowcode in the current directory.
166
+ - `know status`: Displays current structural and semantic revisions.
167
+ - `know sync`: Computes AST diffs, generates a report, and rolls over the memory buffer.
168
+ - `know sync-semantic`: Bumps the semantic revision after the AI (or a human) finishes synthesis.
169
+ - `know ingest-semantic .`: Wipes the raw documentation inbox and bumps the revision.
170
+
171
+ ---
172
+
173
+ ## License
174
+
175
+ This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,63 @@
1
+ runtime/__init__.py,sha256=0c4lglTsbtln7rOZLIn1ZU18mkFYYYf941b8Nagc-lA,302
2
+ runtime/artifact/__init__.py,sha256=7wWPhT1BomXdMiT_PR_IsVx9xG8kWEgSVqOZUFIc1uA,22
3
+ runtime/artifact/builder.py,sha256=49C89nSlHL1k1B8Lja2prb34YYJkqCbEbocvCw1s1kg,7502
4
+ runtime/cli/__init__.py,sha256=OQHDp0zovdmwfBkZXBD3A0VQWrMm2Tko49uhMCL490Y,17
5
+ runtime/cli/animation.py,sha256=gUgRj0qjq_dHxnnboLJSZ2VTB5Cpbsbt01H9mY88fUg,9310
6
+ runtime/cli/app.py,sha256=SxPBHouRsvjOeLSh2kp3aH1Umm-irgM8UBZZCR7xRTs,9764
7
+ runtime/cli/auth.py,sha256=d-n8yGTSwMSUd_v1snaIZ2IM4WBNokmf28P7xP52-J4,5817
8
+ runtime/cli/telemetry.py,sha256=hJZn6sv00eqCb8AGaWFuaev71tmcKmVN2E5Tfxqibq4,2975
9
+ runtime/exceptions/__init__.py,sha256=3MmXA3K6kXQJ_wuwnrbtABn-u_jcqjFunDR2AEd8Y3Y,31
10
+ runtime/exceptions/errors.py,sha256=dbGbZNHm5MWHS3N-sXYQf9hVafeU_2K3NTFixZhurXA,2738
11
+ runtime/repository/__init__.py,sha256=KUljhrbbh-lLfTQaOuvi7jvDQJ6E9EYo-0ZA_DhOpN4,426
12
+ runtime/repository/discovery.py,sha256=yOV2picNIg63C5Q_q-w0MSZCrqHNPxn5g9Ii4cQIPEc,1657
13
+ runtime/repository/models.py,sha256=s_6G3XfE9hUlVyXZjflY7QAAhOvaMs9lc9ZHCJXfA50,3324
14
+ runtime/repository/paths.py,sha256=iw8tpw9JvDXBh2YBtRZhfTaiDsZ-AAMtCXc1o4KoVfc,1592
15
+ runtime/repository/validator.py,sha256=VuIDL7wiACv9xZCVbTMzI27M2Obj3ejWORFRy99Cu-w,2961
16
+ runtime/services/__init__.py,sha256=-xV5NeGY0BUta_C-nkGOx8vMYh8keyjl8lh3PHCFJao,22
17
+ runtime/services/ingest_service.py,sha256=_8SZmx1xuFo5VLZBfgN_gqSxlZ5dQZQVcYOeMWDzV3Q,3372
18
+ runtime/services/init_service.py,sha256=EMK_SX0jWKXe_98codpgAk149UXkmFP9lm27J0PCpDs,1152
19
+ runtime/services/semantic_sync_service.py,sha256=KVw_W7PE-STyl9IEM3pHr-38ssyM67YN99kkgvqrY0o,1484
20
+ runtime/services/status_service.py,sha256=-lpueT0VTbBZ-NXlNtZyQiDyBZ6Fgg2ex2lcViSUsgU,988
21
+ runtime/services/sync_service.py,sha256=h1WgkDzobJ32px1vqB_diAg8-wpIrTttRxP3BpnZXng,1763
22
+ runtime/templates/KNOWCODE_LOADER.md.j2,sha256=7b9mW8BM-BKyPjqsflMae_IGapLN_aOJvYqieUTrECs,1809
23
+ runtime/templates/README_KNOWLEDGE.md.j2,sha256=q_QuWaD75drFpOnnSA6NMAmez-8qTyhh5o7-AY655w4,758
24
+ runtime/templates/README_STRUCTURE.md.j2,sha256=8XqowEl1oa8qSwo9mIC6Mz80lR-KYfgpjkUIbA3OPtY,1118
25
+ runtime/templates/__init__.py,sha256=NnQrQoGS3nEY-O-5f8x7OQV-SjGjsDD-KxuKdK4V70Y,28
26
+ runtime/templates/active_context.md.j2,sha256=xMkGZltRsB2iHo82gc0Cng41FR3xC_jOFbIuQGaWolg,68
27
+ runtime/templates/ingest_legacy.md.j2,sha256=up7bnA4qftnHwcnXPnZzC5nJ7sCzyMy0fZdWPE7TLVk,831
28
+ runtime/templates/raw_readme.md.j2,sha256=0YviMTI0FGWxdDoLx3L9wTs50B0yEIvLGnqUw4rGAA0,695
29
+ runtime/templates/sync_reconciliation.md.j2,sha256=s_pBhC1Oz-0REovU-13xy_0aVVT9HxibYatC_B48DRU,992
30
+ runtime/templates/synthesize_knowledge.md.j2,sha256=cqpmWi02ZXK_4gARVhMp1ckzGhVNT9IfKYvWfocow8c,1808
31
+ runtime/templates/track_intent.md.j2,sha256=IVsOleXActvBpF7m76Wl2knStE4I6naEEiyfC3xrSy8,925
32
+ structural_engine/__init__.py,sha256=4aKD0XYPmynvdaQpQJUpYt0UEn1bp0irHwOWVKdKKbE,253
33
+ structural_engine/engine.py,sha256=fvbkGy03MHH-0yDDBsph2T6D0Ymr9yxrdlxs9LQekc4,7150
34
+ structural_engine/results.py,sha256=04FvN5ZfdBMn3rsdYdSsEp9tvjflndof-xeljTtXK00,1328
35
+ structural_engine/diff/__init__.py,sha256=hRS19h1nMYrG35zz7Pd7Y7MrjFIXZ_s1hJzMVFbqGkU,18
36
+ structural_engine/diff/generator.py,sha256=jIa1W9bR5vjrIio9-9EzeALJDOmwDFqje85EzsWFBOc,3159
37
+ structural_engine/diff/models.py,sha256=Wkkabhs-SmwshJXkJw612r1UQ6jt5YamfqpxmnW-RUM,1650
38
+ structural_engine/logs/__init__.py,sha256=Quhx3OvDpdExMbQ7wD9uO9oroa1VkPVEZXyoNo9AXJo,18
39
+ structural_engine/logs/generator.py,sha256=RzQsRgTy0PLPUzXwkjdcghokXzqUKbG3revCm0YM6Hk,1025
40
+ structural_engine/parser/__init__.py,sha256=Nu7spM-b8GfhOUaJGaZ7VKuHkkZfQlIUJzniYzsppFI,251
41
+ structural_engine/parser/discovery.py,sha256=kHWHXeVPv8Mxmc8rVSj6sKV3WOsiObwrA2BLxGsYMYQ,4192
42
+ structural_engine/parser/models.py,sha256=kEdF9Z4_NG9SyTqmI4K7cmFgEquF4Ely2EcPBN26Drc,5153
43
+ structural_engine/parser/parser.py,sha256=2nBzGTT7Au0o78-HykZa0BSisCb98jzdsB5AkzG2G9M,5361
44
+ structural_engine/parser/extractors/base.py,sha256=GoZOzgg23FFqjninj7gu6dNnkJOCA6IXEKAWMuQyfFM,1372
45
+ structural_engine/parser/languages/javascript/adapter.py,sha256=OWoMV38xbyDRbzUzxaLoMr4dt95d8CE7rEXUHrdipOE,5960
46
+ structural_engine/parser/languages/python/adapter.py,sha256=4WbzlB4ni5XTExt_gWK2h7Jm0ZMX2-u_I1B1FJKPURo,7680
47
+ structural_engine/parser/languages/typescript/adapter.py,sha256=_XhhlQqSvRyPY-2DY86qGwQ73NZiBe1KHZ3aMryj10A,7320
48
+ structural_engine/parser/resolvers/calls.py,sha256=NfymGRMz11I0bPV0512Vob43DpiGIQZ2XnJZwU5VIsA,3970
49
+ structural_engine/parser/tree_sitter/registry.py,sha256=Kri5jSKPgAZYUlaKDEvZ0ec1ZiqClomj6NwbVbcc8FA,1570
50
+ structural_engine/reports/__init__.py,sha256=rTUfl21P_LhmeHZNeXSz8JuLDQiLDkS3GMryNjdhFUA,21
51
+ structural_engine/reports/generator.py,sha256=JNfblJ-Ko2ssyExrvXaNu33QBnE7Ajpdtybgf0dFKrs,2616
52
+ structural_engine/revisions/__init__.py,sha256=gMA7cjs6m6BQGQVrwbGnZiRTSjG7sZQQq2Zl6vnkQwc,23
53
+ structural_engine/revisions/tracker.py,sha256=qgS2HsmUVjbvucY1QfliWhqqMcLOJ8WUoKz_agJoJag,826
54
+ structural_engine/snapshot/__init__.py,sha256=k8w3zMhIg-rLVW8NJ8PxLXfmyXVdvW90DRQoN8QpSOw,22
55
+ structural_engine/snapshot/generator.py,sha256=a_HxuXyoDCHGLsX2859Vbl8Ng0ApZw3b7ZudnpQxNsQ,1689
56
+ structural_engine/snapshot/loader.py,sha256=xb3vFDkmNvFWNPpLMFDn2y4XYsAE4vBgLBk_DXldBKc,1545
57
+ structural_engine/state/__init__.py,sha256=6xEYvIwGtNsTnLsGeLYh-i8X9GIBMv1D_5Qwc1v7baQ,19
58
+ structural_engine/state/manager.py,sha256=n12mxMpUQlQd8l75xxiXsvVj0fZ8aRWbQz7txEmVS8c,5137
59
+ structural_engine/state/models.py,sha256=oF47LM32VgrVbi6BOTb966JXGXAQT4RsRhN-ZL5U6zM,997
60
+ knowcode-0.1.0.dist-info/METADATA,sha256=-mA9BTqcwrOdOQxMSw4LKRW5v4OzkAAIRM7WyBe2Lx4,7181
61
+ knowcode-0.1.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
62
+ knowcode-0.1.0.dist-info/entry_points.txt,sha256=AXPT3eqMqL_wZnTdfWiKBT-9bVltaIPaKjRIX5z_Rsc,45
63
+ knowcode-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.30.1
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ know = runtime.cli.app:app
runtime/__init__.py ADDED
@@ -0,0 +1,4 @@
1
+ # Runtime — the orchestration layer of the KnowCode ecosystem.
2
+ # Owns: CLI, commands, services, repository discovery, artifact creation,
3
+ # validation, configuration, output, exception handling, delegation.
4
+ # Never owns: parsing, snapshots, reports, logs, revisions, state, semantic knowledge.
@@ -0,0 +1 @@
1
+ # Artifact subsystem.
@@ -0,0 +1,179 @@
1
+ """Artifact Builder.
2
+
3
+ Scaffolds the initial ``.knowcode/`` directory structure and renders
4
+ static, human-facing knowledge templates.
5
+
6
+ Invariants
7
+ ----------
8
+ - **ZERO State Awareness:** This module never touches, reads, or writes
9
+ ``state.yaml``. State management belongs exclusively to the Structural Engine.
10
+ - **Idempotency:** Re-running the builder over an existing initialized
11
+ directory will safely assert directories exist without destructive overwrites,
12
+ although the Validator usually prevents this.
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import jinja2
18
+ import structlog
19
+ from importlib import resources
20
+
21
+ from runtime.repository.models import RepositoryPaths
22
+
23
+ logger = structlog.get_logger(__name__)
24
+
25
+
26
+ class ArtifactBuilder:
27
+ """Scaffolds the KnowCode artifact directory structure."""
28
+
29
+ def __init__(self, paths: RepositoryPaths) -> None:
30
+ """Initialize the builder.
31
+
32
+ Parameters
33
+ ----------
34
+ paths : RepositoryPaths
35
+ The canonical path contract for the repository.
36
+ """
37
+ self.paths = paths
38
+ # Setup Jinja2 environment loading templates from the runtime package
39
+ self.jinja_env = jinja2.Environment(
40
+ loader=jinja2.PackageLoader("runtime", "templates"),
41
+ autoescape=jinja2.select_autoescape(["html", "xml"]),
42
+ trim_blocks=True,
43
+ lstrip_blocks=True,
44
+ )
45
+
46
+ def build(self) -> None:
47
+ """Execute the scaffolding pipeline.
48
+
49
+ Creates all required directories and renders static templates.
50
+ """
51
+ logger.info("artifact_builder.started", knowcode_root=str(self.paths.knowcode_root))
52
+
53
+ self._create_directories()
54
+ self._render_templates()
55
+ self._update_gitignore()
56
+
57
+ logger.info("artifact_builder.complete")
58
+
59
+ def _create_directories(self) -> None:
60
+ """Create the directory tree."""
61
+ # Define all required subdirectories
62
+ dirs_to_create = [
63
+ self.paths.knowcode_root,
64
+ self.paths.structure_dir,
65
+ self.paths.snapshots_dir,
66
+ self.paths.reports_dir,
67
+ self.paths.logs_dir,
68
+ self.paths.knowledge_dir,
69
+ self.paths.knowledge_dir / "architecture",
70
+ self.paths.knowledge_dir / "decisions",
71
+ self.paths.knowledge_dir / "constraints",
72
+ self.paths.knowledge_dir / "conventions",
73
+ self.paths.knowledge_dir / "components",
74
+ self.paths.agent_dir,
75
+ self.paths.skills_dir,
76
+ self.paths.workflows_dir,
77
+ self.paths.memory_dir,
78
+ self.paths.raw_knowledge_dir,
79
+ ]
80
+
81
+ for directory in dirs_to_create:
82
+ directory.mkdir(parents=True, exist_ok=True)
83
+ logger.debug("artifact_builder.mkdir", path=str(directory))
84
+
85
+ def _render_templates(self) -> None:
86
+ """Render and write static markdown templates."""
87
+ # 1. Render README_STRUCTURE.md (formerly KNOWCODE.md)
88
+ struct_template = self.jinja_env.get_template("README_STRUCTURE.md.j2")
89
+ project_name = self.paths.repo_root.name
90
+
91
+ struct_content = struct_template.render(project_name=project_name)
92
+ struct_file = self.paths.knowcode_root / "README_STRUCTURE.md"
93
+ struct_file.write_text(struct_content, encoding="utf-8")
94
+ logger.debug("artifact_builder.render", file=str(struct_file))
95
+
96
+ # 2. Render README_KNOWLEDGE.md (formerly knowledge-maintenance.md)
97
+ km_template = self.jinja_env.get_template("README_KNOWLEDGE.md.j2")
98
+ km_content = km_template.render()
99
+
100
+ km_file = self.paths.knowledge_dir / "README_KNOWLEDGE.md"
101
+ km_file.write_text(km_content, encoding="utf-8")
102
+ logger.debug("artifact_builder.render", file=str(km_file))
103
+
104
+ # 3. Render placeholder README.md files for knowledge subdirectories
105
+ knowledge_subdirs = {
106
+ "architecture": "Architecture",
107
+ "decisions": "Decisions",
108
+ "constraints": "Constraints",
109
+ "conventions": "Conventions",
110
+ "components": "Components",
111
+ }
112
+ for dirname, title in knowledge_subdirs.items():
113
+ readme_path = self.paths.knowledge_dir / dirname / f"{dirname}.md"
114
+ readme_path.write_text(f"# {title}\n\n", encoding="utf-8")
115
+ logger.debug("artifact_builder.render", file=str(readme_path))
116
+
117
+ # 4. Render raw inbox README
118
+ raw_template = self.jinja_env.get_template("raw_readme.md.j2")
119
+ raw_content = raw_template.render()
120
+ raw_file = self.paths.raw_knowledge_dir / "README.md"
121
+ raw_file.write_text(raw_content, encoding="utf-8")
122
+ logger.debug("artifact_builder.render", file=str(raw_file))
123
+
124
+ # 5. Render active_context.md
125
+ ac_template = self.jinja_env.get_template("active_context.md.j2")
126
+ ac_content = ac_template.render()
127
+ self.paths.active_context_file.write_text(ac_content, encoding="utf-8")
128
+ logger.debug("artifact_builder.render", file=str(self.paths.active_context_file))
129
+
130
+ # 6. Render knowcode.md (Agent Loader)
131
+ loader_template = self.jinja_env.get_template("KNOWCODE_LOADER.md.j2")
132
+ loader_content = loader_template.render()
133
+ loader_file = self.paths.repo_root / "knowcode.md"
134
+ loader_file.write_text(loader_content, encoding="utf-8")
135
+ logger.debug("artifact_builder.render", file=str(loader_file))
136
+
137
+ # 7. Render Skills
138
+ skills = {
139
+ "track_intent.md.j2": "track_intent.md",
140
+ "synthesize_knowledge.md.j2": "synthesize_knowledge.md"
141
+ }
142
+ for template_name, file_name in skills.items():
143
+ template = self.jinja_env.get_template(template_name)
144
+ file_path = self.paths.skills_dir / file_name
145
+ file_path.write_text(template.render(), encoding="utf-8")
146
+ logger.debug("artifact_builder.render", file=str(file_path))
147
+
148
+ # 8. Render Workflows
149
+ workflows = {
150
+ "sync_reconciliation.md.j2": "sync_reconciliation.md",
151
+ "ingest_legacy.md.j2": "ingest_legacy.md"
152
+ }
153
+ for template_name, file_name in workflows.items():
154
+ template = self.jinja_env.get_template(template_name)
155
+ file_path = self.paths.workflows_dir / file_name
156
+ file_path.write_text(template.render(), encoding="utf-8")
157
+ logger.debug("artifact_builder.render", file=str(file_path))
158
+
159
+ def _update_gitignore(self) -> None:
160
+ """Add knowcode directories to .gitignore if not present."""
161
+ gitignore_path = self.paths.repo_root / ".gitignore"
162
+ entries_to_add = [".knowcode/", ".agent/", "knowcode.md"]
163
+
164
+ if not gitignore_path.exists():
165
+ content = "# Knowcode AI Governance\n" + "\n".join(entries_to_add) + "\n"
166
+ gitignore_path.write_text(content, encoding="utf-8")
167
+ logger.debug("artifact_builder.gitignore_created", path=str(gitignore_path))
168
+ return
169
+
170
+ content = gitignore_path.read_text(encoding="utf-8")
171
+ lines = set(line.strip() for line in content.splitlines())
172
+
173
+ missing = [entry for entry in entries_to_add if entry not in lines]
174
+ if missing:
175
+ with gitignore_path.open("a", encoding="utf-8") as f:
176
+ f.write("\n\n# Knowcode AI Governance\n")
177
+ for entry in missing:
178
+ f.write(f"{entry}\n")
179
+ logger.debug("artifact_builder.gitignore_updated", appended=missing)
@@ -0,0 +1 @@
1
+ # CLI subsystem.