koinome 0.0.0a1__tar.gz
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.
- koinome-0.0.0a1/LICENSE +21 -0
- koinome-0.0.0a1/PKG-INFO +119 -0
- koinome-0.0.0a1/README.md +104 -0
- koinome-0.0.0a1/koinome/__init__.py +2 -0
- koinome-0.0.0a1/koinome/cli.py +275 -0
- koinome-0.0.0a1/koinome/evaluation.py +281 -0
- koinome-0.0.0a1/koinome/exit_codes.py +12 -0
- koinome-0.0.0a1/koinome/importers/__pycache__/migrate_obsidian.cpython-314.pyc +0 -0
- koinome-0.0.0a1/koinome/importers/distill-seeds.md +57 -0
- koinome-0.0.0a1/koinome/importers/seed_extract.py +281 -0
- koinome-0.0.0a1/koinome/importers.py +109 -0
- koinome-0.0.0a1/koinome/manifest.py +92 -0
- koinome-0.0.0a1/koinome/paths.py +276 -0
- koinome-0.0.0a1/koinome/release_check.py +393 -0
- koinome-0.0.0a1/koinome/scaffold.py +141 -0
- koinome-0.0.0a1/koinome/template/.gitattributes +4 -0
- koinome-0.0.0a1/koinome/template/.github/workflows/koinome-check.yml +23 -0
- koinome-0.0.0a1/koinome/template/.gitignore +19 -0
- koinome-0.0.0a1/koinome/template/.koinome-manifest.json +178 -0
- koinome-0.0.0a1/koinome/template/.scripts/check_corpus.py +157 -0
- koinome-0.0.0a1/koinome/template/.scripts/check_staged_snapshot.py +102 -0
- koinome-0.0.0a1/koinome/template/.scripts/gen_mocs.py +171 -0
- koinome-0.0.0a1/koinome/template/.scripts/graph_report.py +276 -0
- koinome-0.0.0a1/koinome/template/.scripts/koinome-sync.sh +10 -0
- koinome-0.0.0a1/koinome/template/.scripts/koinome-sync.systemd +27 -0
- koinome-0.0.0a1/koinome/template/.scripts/koinome.config.json +68 -0
- koinome-0.0.0a1/koinome/template/.scripts/koinome_sync.py +403 -0
- koinome-0.0.0a1/koinome/template/.scripts/pre-commit +23 -0
- koinome-0.0.0a1/koinome/template/.scripts/synthesis_status.py +119 -0
- koinome-0.0.0a1/koinome/template/.scripts/validate_corpus.py +504 -0
- koinome-0.0.0a1/koinome/template/.skills/koinome-adr/SKILL.md +30 -0
- koinome-0.0.0a1/koinome/template/.skills/koinome-distill-seeds/SKILL.md +45 -0
- koinome-0.0.0a1/koinome/template/.skills/koinome-fix-validation/SKILL.md +44 -0
- koinome-0.0.0a1/koinome/template/.skills/koinome-init/SKILL.md +61 -0
- koinome-0.0.0a1/koinome/template/.skills/koinome-new-note/SKILL.md +27 -0
- koinome-0.0.0a1/koinome/template/.skills/koinome-session-close/SKILL.md +31 -0
- koinome-0.0.0a1/koinome/template/.skills/koinome-setup-domains/SKILL.md +42 -0
- koinome-0.0.0a1/koinome/template/.skills/koinome-synthesize/SKILL.md +41 -0
- koinome-0.0.0a1/koinome/template/.skills/koinome-todo/SKILL.md +39 -0
- koinome-0.0.0a1/koinome/template/.skills/koinome-weekly-review/SKILL.md +33 -0
- koinome-0.0.0a1/koinome/template/60-decisions/adr-0001-corpus-structure.md +36 -0
- koinome-0.0.0a1/koinome/template/60-decisions/index.md +15 -0
- koinome-0.0.0a1/koinome/template/72-tasks/todo.txt +3 -0
- koinome-0.0.0a1/koinome/template/90-templates/1on1.md +16 -0
- koinome-0.0.0a1/koinome/template/90-templates/adr.md +34 -0
- koinome-0.0.0a1/koinome/template/90-templates/concept.md +23 -0
- koinome-0.0.0a1/koinome/template/90-templates/entity.md +23 -0
- koinome-0.0.0a1/koinome/template/90-templates/governance-finding.md +19 -0
- koinome-0.0.0a1/koinome/template/90-templates/meeting.md +18 -0
- koinome-0.0.0a1/koinome/template/90-templates/project-doc.md +18 -0
- koinome-0.0.0a1/koinome/template/90-templates/source.md +15 -0
- koinome-0.0.0a1/koinome/template/90-templates/stakeholder.md +18 -0
- koinome-0.0.0a1/koinome/template/90-templates/weekly-review.md +17 -0
- koinome-0.0.0a1/koinome/template/AGENTS.md +98 -0
- koinome-0.0.0a1/koinome/template/CLAUDE.md +1 -0
- koinome-0.0.0a1/koinome/template/GEMINI.md +5 -0
- koinome-0.0.0a1/koinome/template/README.md +45 -0
- koinome-0.0.0a1/koinome/template/bootstrap.sh +202 -0
- koinome-0.0.0a1/koinome/template/docs/ARCHITECTURE.md +52 -0
- koinome-0.0.0a1/koinome/template/docs/CONFLICTS.md +24 -0
- koinome-0.0.0a1/koinome/template/docs/FIXING.md +42 -0
- koinome-0.0.0a1/koinome/template/docs/OPERATIONS.md +114 -0
- koinome-0.0.0a1/koinome/template/docs/SETUP.md +104 -0
- koinome-0.0.0a1/koinome/template/docs/SYNTHESIS.md +42 -0
- koinome-0.0.0a1/koinome/upgrade.py +615 -0
- koinome-0.0.0a1/koinome/version.py +17 -0
- koinome-0.0.0a1/koinome/wizard.py +151 -0
- koinome-0.0.0a1/koinome.egg-info/PKG-INFO +119 -0
- koinome-0.0.0a1/koinome.egg-info/SOURCES.txt +93 -0
- koinome-0.0.0a1/koinome.egg-info/dependency_links.txt +1 -0
- koinome-0.0.0a1/koinome.egg-info/entry_points.txt +2 -0
- koinome-0.0.0a1/koinome.egg-info/requires.txt +1 -0
- koinome-0.0.0a1/koinome.egg-info/top_level.txt +1 -0
- koinome-0.0.0a1/pyproject.toml +58 -0
- koinome-0.0.0a1/setup.cfg +4 -0
- koinome-0.0.0a1/tests/test_bootstrap.py +118 -0
- koinome-0.0.0a1/tests/test_cli_smoke.py +97 -0
- koinome-0.0.0a1/tests/test_conformance.py +106 -0
- koinome-0.0.0a1/tests/test_doc_consistency.py +131 -0
- koinome-0.0.0a1/tests/test_evaluation.py +25 -0
- koinome-0.0.0a1/tests/test_exit_status.py +149 -0
- koinome-0.0.0a1/tests/test_imports.py +68 -0
- koinome-0.0.0a1/tests/test_koinome_migration.py +209 -0
- koinome-0.0.0a1/tests/test_manifest_freshness.py +40 -0
- koinome-0.0.0a1/tests/test_naming_consistency.py +90 -0
- koinome-0.0.0a1/tests/test_package_data.py +106 -0
- koinome-0.0.0a1/tests/test_reference_corpora.py +49 -0
- koinome-0.0.0a1/tests/test_release_check.py +53 -0
- koinome-0.0.0a1/tests/test_release_policy.py +55 -0
- koinome-0.0.0a1/tests/test_scaffold_validation.py +47 -0
- koinome-0.0.0a1/tests/test_staged_snapshot.py +193 -0
- koinome-0.0.0a1/tests/test_sync.py +146 -0
- koinome-0.0.0a1/tests/test_upgrade.py +233 -0
- koinome-0.0.0a1/tests/test_validator.py +463 -0
- koinome-0.0.0a1/tests/test_versioning.py +42 -0
koinome-0.0.0a1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Gilmar Souza
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
koinome-0.0.0a1/PKG-INFO
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: koinome
|
|
3
|
+
Version: 0.0.0a1
|
|
4
|
+
Summary: Koinome CLI: create and maintain provider-independent, agent-readable markdown corpora.
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Project-URL: Homepage, https://github.com/gilmar/koinome
|
|
7
|
+
Project-URL: Repository, https://github.com/gilmar/koinome
|
|
8
|
+
Project-URL: Documentation, https://github.com/gilmar/koinome/blob/master/docs/USAGE.md
|
|
9
|
+
Project-URL: Changelog, https://github.com/gilmar/koinome/blob/master/CHANGELOG.md
|
|
10
|
+
Requires-Python: >=3.10
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Requires-Dist: pyyaml>=6.0
|
|
14
|
+
Dynamic: license-file
|
|
15
|
+
|
|
16
|
+
# Koinome
|
|
17
|
+
|
|
18
|
+
**Koinome is a local-first, plain-Markdown system for creating and maintaining a personal knowledge corpus for a person and their AI agents, with a deterministic validation gate.**
|
|
19
|
+
|
|
20
|
+
> **Koinome** is the product and tooling. A **corpus** is a portable, governed body of knowledge maintained by an individual and usable by that individual and their authorised AI agents. The `koinome` command creates and maintains corpora.
|
|
21
|
+
|
|
22
|
+
Koinome currently provides a complete local-first corpus for individual use.
|
|
23
|
+
|
|
24
|
+
The individual corpus and its local tooling are free and open-source and are intended to remain so.
|
|
25
|
+
|
|
26
|
+
## Current scope
|
|
27
|
+
|
|
28
|
+
The current Koinome release manages individual corpora, one corpus at a time. Cross-corpus sharing, transfer, combination, and federation are not implemented.
|
|
29
|
+
|
|
30
|
+
## Free and open-source commitment
|
|
31
|
+
|
|
32
|
+
Koinome for individual use is a complete local-first product, not a limited edition of a hosted service. The individual corpus format, local tooling, validation, agent workflows, imports, exports, synthesis, migration, synchronisation, backup, and recovery are free and open-source and are intended to remain so.
|
|
33
|
+
|
|
34
|
+
You can create, maintain, and use local corpora without a Koinome account, subscription, or hosted service.
|
|
35
|
+
|
|
36
|
+
## The problem
|
|
37
|
+
|
|
38
|
+
AI agents are amnesiac. Every session starts from zero, so context, decisions, and durable facts evaporate between sessions.
|
|
39
|
+
|
|
40
|
+
Judge any fix with the turn-it-off test: delete the tooling. With Koinome, delete every script and the corpus still works — notes open in any editor, git still diffs them, grep still finds them.
|
|
41
|
+
|
|
42
|
+
Memory corruption compounds quietly. For work knowledge, decisions, and governance records, the rule is absolute: nothing rewrites authoritative knowledge while you sleep.
|
|
43
|
+
|
|
44
|
+
## The idea
|
|
45
|
+
|
|
46
|
+
The files are the product. Three commitments follow:
|
|
47
|
+
|
|
48
|
+
1. **Open standards only.** CommonMark, YAML frontmatter, git, and todo.txt. Any human or agent can read a corpus with no adapter.
|
|
49
|
+
2. **Governed, not free-form.** Deterministic validation and an optional git hook enforce the corpus contract. AI assists around the gate, never inside it.
|
|
50
|
+
3. **Authored, not compiled.** Derived synthesis pages cite sources and pass the same gate as authored notes.
|
|
51
|
+
|
|
52
|
+
## Guarantees
|
|
53
|
+
|
|
54
|
+
1. **Every note opens as plain text** with no Koinome tooling installed.
|
|
55
|
+
2. **Validation is deterministic.** No model, no network, no server.
|
|
56
|
+
3. **AI assists around the gate, never inside it.** With every agent offline you can still read, write, validate, and commit.
|
|
57
|
+
4. **No Koinome process rewrites your notes unattended.** The optional scheduled job is git sync only.
|
|
58
|
+
5. **Derived pages cite their sources.** The validator rejects synthesis without provenance.
|
|
59
|
+
6. **Sensitive boundaries are physical.** Keep sensitive material in a separate private corpus on a path no agent reaches.
|
|
60
|
+
|
|
61
|
+
## Quick start
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# run in place, no install
|
|
65
|
+
./koinome-cli new
|
|
66
|
+
|
|
67
|
+
# or install the command
|
|
68
|
+
pipx install . # or: uv tool install .
|
|
69
|
+
koinome new
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Interactive, or fully scriptable:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
koinome new --name my-work --path ~/my-work
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Or pass domains when the layout is already known:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
koinome new --name my-work --path ~/my-work \
|
|
82
|
+
--domain 10-projects=projects \
|
|
83
|
+
--domain 20-governance=governance
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
This creates the corpus, installs the git hook, and sets up shared folders. Point your agent at it and run the `koinome-init` skill to finish setup. Requires Python 3.10+ and PyYAML.
|
|
87
|
+
|
|
88
|
+
## End-to-end individual workflow
|
|
89
|
+
|
|
90
|
+
1. **Install** — `uv tool install .` or run `./koinome-cli`.
|
|
91
|
+
2. **Create a corpus** — `koinome new --name my-corpus --path ~/my-corpus`.
|
|
92
|
+
3. **Connect an agent** — open the corpus in Claude Code, Codex, Gemini CLI, or Cursor; run `koinome-init`.
|
|
93
|
+
4. **Author or import** — add notes, import exports with `koinome seed`, or distill seeds with `koinome-distill-seeds`.
|
|
94
|
+
5. **Validate** — `koinome doctor ~/my-corpus` or `python3 .scripts/validate_corpus.py --all` inside the corpus.
|
|
95
|
+
6. **Retrieve and synthesise** — use MOCs, grep, and `koinome-synthesize` for provenance-backed synthesis.
|
|
96
|
+
7. **Synchronise** — commit and push with git; optional `koinome_sync.py` for automated sync.
|
|
97
|
+
8. **Upgrade safely** — `koinome upgrade ~/my-corpus` refreshes managed tooling without touching your notes.
|
|
98
|
+
9. **Recover** — roll back from `.koinome/backups/` or git history; validation failures block bad commits.
|
|
99
|
+
10. **Remove tooling** — delete Koinome scripts; your Markdown and git history remain.
|
|
100
|
+
|
|
101
|
+
## Commands
|
|
102
|
+
|
|
103
|
+
| command | what it does |
|
|
104
|
+
| --- | --- |
|
|
105
|
+
| `koinome new` | Create a new corpus |
|
|
106
|
+
| `koinome seed` | Normalise a provider export to an import staging area |
|
|
107
|
+
| `koinome doctor CORPUS` | Validate a corpus and refresh navigation maps |
|
|
108
|
+
| `koinome check CORPUS` | Read-only conformance check (CI-safe) |
|
|
109
|
+
| `koinome upgrade CORPUS` | Upgrade Koinome-managed tooling without modifying user-authored knowledge |
|
|
110
|
+
|
|
111
|
+
See [docs/USAGE.md](docs/USAGE.md) for full reference.
|
|
112
|
+
|
|
113
|
+
## Migrating from AuxMem
|
|
114
|
+
|
|
115
|
+
If you have an existing AuxMem folder, run `koinome upgrade` — see [docs/MIGRATION.md](docs/MIGRATION.md).
|
|
116
|
+
|
|
117
|
+
## Licence
|
|
118
|
+
|
|
119
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Koinome
|
|
2
|
+
|
|
3
|
+
**Koinome is a local-first, plain-Markdown system for creating and maintaining a personal knowledge corpus for a person and their AI agents, with a deterministic validation gate.**
|
|
4
|
+
|
|
5
|
+
> **Koinome** is the product and tooling. A **corpus** is a portable, governed body of knowledge maintained by an individual and usable by that individual and their authorised AI agents. The `koinome` command creates and maintains corpora.
|
|
6
|
+
|
|
7
|
+
Koinome currently provides a complete local-first corpus for individual use.
|
|
8
|
+
|
|
9
|
+
The individual corpus and its local tooling are free and open-source and are intended to remain so.
|
|
10
|
+
|
|
11
|
+
## Current scope
|
|
12
|
+
|
|
13
|
+
The current Koinome release manages individual corpora, one corpus at a time. Cross-corpus sharing, transfer, combination, and federation are not implemented.
|
|
14
|
+
|
|
15
|
+
## Free and open-source commitment
|
|
16
|
+
|
|
17
|
+
Koinome for individual use is a complete local-first product, not a limited edition of a hosted service. The individual corpus format, local tooling, validation, agent workflows, imports, exports, synthesis, migration, synchronisation, backup, and recovery are free and open-source and are intended to remain so.
|
|
18
|
+
|
|
19
|
+
You can create, maintain, and use local corpora without a Koinome account, subscription, or hosted service.
|
|
20
|
+
|
|
21
|
+
## The problem
|
|
22
|
+
|
|
23
|
+
AI agents are amnesiac. Every session starts from zero, so context, decisions, and durable facts evaporate between sessions.
|
|
24
|
+
|
|
25
|
+
Judge any fix with the turn-it-off test: delete the tooling. With Koinome, delete every script and the corpus still works — notes open in any editor, git still diffs them, grep still finds them.
|
|
26
|
+
|
|
27
|
+
Memory corruption compounds quietly. For work knowledge, decisions, and governance records, the rule is absolute: nothing rewrites authoritative knowledge while you sleep.
|
|
28
|
+
|
|
29
|
+
## The idea
|
|
30
|
+
|
|
31
|
+
The files are the product. Three commitments follow:
|
|
32
|
+
|
|
33
|
+
1. **Open standards only.** CommonMark, YAML frontmatter, git, and todo.txt. Any human or agent can read a corpus with no adapter.
|
|
34
|
+
2. **Governed, not free-form.** Deterministic validation and an optional git hook enforce the corpus contract. AI assists around the gate, never inside it.
|
|
35
|
+
3. **Authored, not compiled.** Derived synthesis pages cite sources and pass the same gate as authored notes.
|
|
36
|
+
|
|
37
|
+
## Guarantees
|
|
38
|
+
|
|
39
|
+
1. **Every note opens as plain text** with no Koinome tooling installed.
|
|
40
|
+
2. **Validation is deterministic.** No model, no network, no server.
|
|
41
|
+
3. **AI assists around the gate, never inside it.** With every agent offline you can still read, write, validate, and commit.
|
|
42
|
+
4. **No Koinome process rewrites your notes unattended.** The optional scheduled job is git sync only.
|
|
43
|
+
5. **Derived pages cite their sources.** The validator rejects synthesis without provenance.
|
|
44
|
+
6. **Sensitive boundaries are physical.** Keep sensitive material in a separate private corpus on a path no agent reaches.
|
|
45
|
+
|
|
46
|
+
## Quick start
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# run in place, no install
|
|
50
|
+
./koinome-cli new
|
|
51
|
+
|
|
52
|
+
# or install the command
|
|
53
|
+
pipx install . # or: uv tool install .
|
|
54
|
+
koinome new
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Interactive, or fully scriptable:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
koinome new --name my-work --path ~/my-work
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Or pass domains when the layout is already known:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
koinome new --name my-work --path ~/my-work \
|
|
67
|
+
--domain 10-projects=projects \
|
|
68
|
+
--domain 20-governance=governance
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
This creates the corpus, installs the git hook, and sets up shared folders. Point your agent at it and run the `koinome-init` skill to finish setup. Requires Python 3.10+ and PyYAML.
|
|
72
|
+
|
|
73
|
+
## End-to-end individual workflow
|
|
74
|
+
|
|
75
|
+
1. **Install** — `uv tool install .` or run `./koinome-cli`.
|
|
76
|
+
2. **Create a corpus** — `koinome new --name my-corpus --path ~/my-corpus`.
|
|
77
|
+
3. **Connect an agent** — open the corpus in Claude Code, Codex, Gemini CLI, or Cursor; run `koinome-init`.
|
|
78
|
+
4. **Author or import** — add notes, import exports with `koinome seed`, or distill seeds with `koinome-distill-seeds`.
|
|
79
|
+
5. **Validate** — `koinome doctor ~/my-corpus` or `python3 .scripts/validate_corpus.py --all` inside the corpus.
|
|
80
|
+
6. **Retrieve and synthesise** — use MOCs, grep, and `koinome-synthesize` for provenance-backed synthesis.
|
|
81
|
+
7. **Synchronise** — commit and push with git; optional `koinome_sync.py` for automated sync.
|
|
82
|
+
8. **Upgrade safely** — `koinome upgrade ~/my-corpus` refreshes managed tooling without touching your notes.
|
|
83
|
+
9. **Recover** — roll back from `.koinome/backups/` or git history; validation failures block bad commits.
|
|
84
|
+
10. **Remove tooling** — delete Koinome scripts; your Markdown and git history remain.
|
|
85
|
+
|
|
86
|
+
## Commands
|
|
87
|
+
|
|
88
|
+
| command | what it does |
|
|
89
|
+
| --- | --- |
|
|
90
|
+
| `koinome new` | Create a new corpus |
|
|
91
|
+
| `koinome seed` | Normalise a provider export to an import staging area |
|
|
92
|
+
| `koinome doctor CORPUS` | Validate a corpus and refresh navigation maps |
|
|
93
|
+
| `koinome check CORPUS` | Read-only conformance check (CI-safe) |
|
|
94
|
+
| `koinome upgrade CORPUS` | Upgrade Koinome-managed tooling without modifying user-authored knowledge |
|
|
95
|
+
|
|
96
|
+
See [docs/USAGE.md](docs/USAGE.md) for full reference.
|
|
97
|
+
|
|
98
|
+
## Migrating from AuxMem
|
|
99
|
+
|
|
100
|
+
If you have an existing AuxMem folder, run `koinome upgrade` — see [docs/MIGRATION.md](docs/MIGRATION.md).
|
|
101
|
+
|
|
102
|
+
## Licence
|
|
103
|
+
|
|
104
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
"""Koinome command-line interface.
|
|
2
|
+
|
|
3
|
+
Subcommands:
|
|
4
|
+
koinome new create a corpus (interactive wizard, or flag-driven)
|
|
5
|
+
koinome seed stage 1 of seeding: normalize a provider export to staging
|
|
6
|
+
koinome doctor validate a corpus and refresh navigation
|
|
7
|
+
koinome check read-only conformance check (CI-safe)
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import argparse
|
|
11
|
+
import sys
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
from . import importers, scaffold, wizard
|
|
15
|
+
from . import upgrade as upgrade_mod
|
|
16
|
+
from .exit_codes import NON_CONFORMANT, OK, OPERATION_FAILED
|
|
17
|
+
|
|
18
|
+
EPILOG = """
|
|
19
|
+
where to run commands
|
|
20
|
+
All koinome subcommands run from any directory. You do not need to cd into a
|
|
21
|
+
corpus folder first. When a command needs an existing corpus, pass its path as
|
|
22
|
+
an argument (or as --dest).
|
|
23
|
+
|
|
24
|
+
Setup (no corpus yet):
|
|
25
|
+
new create a corpus at the path you choose (shared folders only);
|
|
26
|
+
run the koinome-init skill inside the folder to finish setup
|
|
27
|
+
|
|
28
|
+
Existing corpus (pass the folder path):
|
|
29
|
+
check PATH read-only validation + MOC freshness (for CI)
|
|
30
|
+
doctor PATH validate and refresh navigation maps
|
|
31
|
+
upgrade PATH upgrade Koinome-managed tooling without modifying notes
|
|
32
|
+
|
|
33
|
+
Outside any corpus (import prep):
|
|
34
|
+
seed EXPORT write an import staging area (default ./seed-staging); stage 2
|
|
35
|
+
is an agent step run from inside the target corpus
|
|
36
|
+
|
|
37
|
+
Inside the corpus (not koinome subcommands):
|
|
38
|
+
./bootstrap.sh, agent skills, python3 .scripts/validate_corpus.py — see
|
|
39
|
+
AGENTS.md for day-to-day work.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def cmd_upgrade(args):
|
|
44
|
+
try:
|
|
45
|
+
result = upgrade_mod.upgrade(args.dest, force=args.force, dry_run=args.dry_run)
|
|
46
|
+
except upgrade_mod.UpgradeError as e:
|
|
47
|
+
print(f"error: {e}", file=sys.stderr)
|
|
48
|
+
return 1
|
|
49
|
+
if result["status"] == "up-to-date":
|
|
50
|
+
print(f"already at template version {result['version']}. Use --force to re-apply.")
|
|
51
|
+
return 0
|
|
52
|
+
if result["status"] == "dry-run":
|
|
53
|
+
print(f"dry-run: {result['from']} -> {result['to']}")
|
|
54
|
+
if result.get("deprecated"):
|
|
55
|
+
print("\nDeprecated (left in place):")
|
|
56
|
+
for item in result["deprecated"]:
|
|
57
|
+
print(f" {item}")
|
|
58
|
+
print("\nPlanned changes:")
|
|
59
|
+
for change in result["changes"]:
|
|
60
|
+
print(f" {change}")
|
|
61
|
+
if result["conflicts"]:
|
|
62
|
+
print(f"\nLikely conflicts ({len(result['conflicts'])}):")
|
|
63
|
+
for rel in result["conflicts"]:
|
|
64
|
+
print(f" {rel}")
|
|
65
|
+
expected = result.get("post_validation_expected")
|
|
66
|
+
if expected is True:
|
|
67
|
+
print("\nPost-upgrade validation: expected to pass")
|
|
68
|
+
elif expected is False:
|
|
69
|
+
print("\nPost-upgrade validation: expected to FAIL")
|
|
70
|
+
if result.get("post_detail"):
|
|
71
|
+
print(result["post_detail"])
|
|
72
|
+
print("\n(dry-run made no changes)")
|
|
73
|
+
return OK
|
|
74
|
+
if result["status"] == "failed":
|
|
75
|
+
print(f"upgrade failed and was rolled back: {args.dest}")
|
|
76
|
+
if result.get("post_phase"):
|
|
77
|
+
print(f"{result['post_phase']} failed:")
|
|
78
|
+
print(result.get("post_detail", ""))
|
|
79
|
+
return result.get("post_exit_code", OPERATION_FAILED)
|
|
80
|
+
print(f"upgraded {args.dest}: {result['from']} -> {result['to']}")
|
|
81
|
+
for c in result["changes"]:
|
|
82
|
+
print(f" {c}")
|
|
83
|
+
print(f"\nbackup: {result['backup']}")
|
|
84
|
+
print(f"report: {Path(args.dest) / '00-inbox'} (upgrade-report-*.md)")
|
|
85
|
+
if result["conflicts"]:
|
|
86
|
+
print(f"\n{len(result['conflicts'])} file(s) need manual review (see report).")
|
|
87
|
+
post_code = result.get("post_exit_code", OK)
|
|
88
|
+
if post_code == OPERATION_FAILED:
|
|
89
|
+
print(f"\n{result['post_phase']} failed after upgrade:")
|
|
90
|
+
print(result["post_detail"])
|
|
91
|
+
return OPERATION_FAILED
|
|
92
|
+
if post_code == NON_CONFORMANT:
|
|
93
|
+
print("\nValidation did not pass after upgrade:")
|
|
94
|
+
print(result["post_detail"])
|
|
95
|
+
return NON_CONFORMANT
|
|
96
|
+
print("\nvalidation clean.")
|
|
97
|
+
return OK
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def cmd_new(args):
|
|
101
|
+
if args.name and args.path:
|
|
102
|
+
try:
|
|
103
|
+
domains = scaffold.parse_domains(args.domain) if args.domain else {}
|
|
104
|
+
result = scaffold.scaffold(args.name, args.path, domains,
|
|
105
|
+
run_bootstrap=not args.no_bootstrap)
|
|
106
|
+
except scaffold.ScaffoldError as e:
|
|
107
|
+
print(f"error: {e}", file=sys.stderr)
|
|
108
|
+
return 1
|
|
109
|
+
print(f"Created corpus at {result['dest']}.")
|
|
110
|
+
print("Next: point your agent at the corpus and run the koinome-init skill.")
|
|
111
|
+
if domains:
|
|
112
|
+
print(" (domains are pre-configured; init will confirm and finish setup)")
|
|
113
|
+
else:
|
|
114
|
+
print(" (init will interview you and set up subject domains)")
|
|
115
|
+
return 0
|
|
116
|
+
# any flags missing -> interactive
|
|
117
|
+
try:
|
|
118
|
+
wizard.run()
|
|
119
|
+
except scaffold.ScaffoldError as e:
|
|
120
|
+
print(f"error: {e}", file=sys.stderr)
|
|
121
|
+
return 1
|
|
122
|
+
except KeyboardInterrupt:
|
|
123
|
+
print("\ncancelled.")
|
|
124
|
+
return 130
|
|
125
|
+
return 0
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def cmd_seed(args):
|
|
129
|
+
rc, out, err = importers.extract_export(
|
|
130
|
+
args.export_file, args.staging, provider=args.provider,
|
|
131
|
+
since=args.since, min_messages=args.min_messages)
|
|
132
|
+
print(out or err)
|
|
133
|
+
if rc == 0:
|
|
134
|
+
print("\nStage 2: distill the staging area into notes with an agent.")
|
|
135
|
+
print("Run your CLI agent from the target corpus and point it at:")
|
|
136
|
+
print(f" {importers.IMPORTERS / 'distill-seeds.md'}")
|
|
137
|
+
return rc if rc != 0 else OK
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def cmd_doctor(args):
|
|
141
|
+
try:
|
|
142
|
+
exit_code, message = importers.validate_and_moc(args.dest)
|
|
143
|
+
except importers.ImportError_ as e:
|
|
144
|
+
print(f"error: {e}", file=sys.stderr)
|
|
145
|
+
return OPERATION_FAILED
|
|
146
|
+
print(message)
|
|
147
|
+
return exit_code
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def cmd_check(args):
|
|
151
|
+
try:
|
|
152
|
+
exit_code, message = importers.check_conformance(
|
|
153
|
+
args.dest, manifest=args.manifest, git=args.git
|
|
154
|
+
)
|
|
155
|
+
except importers.ImportError_ as e:
|
|
156
|
+
print(f"error: {e}", file=sys.stderr)
|
|
157
|
+
return OPERATION_FAILED
|
|
158
|
+
print(message)
|
|
159
|
+
return exit_code
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
def build_parser():
|
|
163
|
+
p = argparse.ArgumentParser(
|
|
164
|
+
prog="koinome",
|
|
165
|
+
description=(
|
|
166
|
+
"Koinome CLI — create and maintain corpora (governed markdown knowledge "
|
|
167
|
+
"for AI agents). Run from any directory; pass a corpus path when a "
|
|
168
|
+
"command needs an existing folder."
|
|
169
|
+
),
|
|
170
|
+
epilog=EPILOG,
|
|
171
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
172
|
+
)
|
|
173
|
+
sub = p.add_subparsers(
|
|
174
|
+
dest="cmd",
|
|
175
|
+
title="commands",
|
|
176
|
+
metavar="COMMAND",
|
|
177
|
+
help="run koinome COMMAND --help for details",
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
n = sub.add_parser(
|
|
181
|
+
"new",
|
|
182
|
+
help="create a new corpus (no existing corpus needed)",
|
|
183
|
+
description=(
|
|
184
|
+
"Create a new corpus with shared folders only. Run from anywhere; writes to "
|
|
185
|
+
"--path. Finish setup with the koinome-init skill, or pass --domain when the "
|
|
186
|
+
"layout is already known."
|
|
187
|
+
),
|
|
188
|
+
)
|
|
189
|
+
n.add_argument("--name")
|
|
190
|
+
n.add_argument("--path")
|
|
191
|
+
n.add_argument("--domain", action="append", metavar="NN-folder=slug",
|
|
192
|
+
help="optional; repeatable — omit to defer domains to koinome-init")
|
|
193
|
+
n.add_argument("--no-bootstrap", action="store_true", help="skip folder/hook/validate setup")
|
|
194
|
+
n.set_defaults(func=cmd_new)
|
|
195
|
+
|
|
196
|
+
s = sub.add_parser(
|
|
197
|
+
"seed",
|
|
198
|
+
help="normalize an export to staging (outside any corpus)",
|
|
199
|
+
description=(
|
|
200
|
+
"Stage 1 of seeding: normalize a provider export into a staging folder "
|
|
201
|
+
"(default ./seed-staging). Does not modify a corpus. Stage 2 (distill into "
|
|
202
|
+
"notes) is an agent step run from inside the target corpus."
|
|
203
|
+
),
|
|
204
|
+
)
|
|
205
|
+
s.add_argument("export_file")
|
|
206
|
+
s.add_argument("--staging", default="./seed-staging",
|
|
207
|
+
help="output folder, usually outside the corpus (default: ./seed-staging)")
|
|
208
|
+
s.add_argument("--provider", choices=["claude", "chatgpt", "gemini"])
|
|
209
|
+
s.add_argument("--since")
|
|
210
|
+
s.add_argument("--min-messages", type=int)
|
|
211
|
+
s.set_defaults(func=cmd_seed)
|
|
212
|
+
|
|
213
|
+
d = sub.add_parser(
|
|
214
|
+
"doctor",
|
|
215
|
+
help="validate an existing corpus and refresh its MOCs",
|
|
216
|
+
description=(
|
|
217
|
+
"Validate a corpus and regenerate its navigation maps. Run from anywhere; "
|
|
218
|
+
"pass the corpus path as the argument."
|
|
219
|
+
),
|
|
220
|
+
)
|
|
221
|
+
d.add_argument("dest", metavar="CORPUS", help="path to the corpus folder")
|
|
222
|
+
d.set_defaults(func=cmd_doctor)
|
|
223
|
+
|
|
224
|
+
c = sub.add_parser(
|
|
225
|
+
"check",
|
|
226
|
+
help="read-only conformance check for an existing corpus",
|
|
227
|
+
description=(
|
|
228
|
+
"Validate a corpus and verify MOC freshness without modifying any files. "
|
|
229
|
+
"Appropriate for CI. Use doctor to regenerate stale MOCs."
|
|
230
|
+
),
|
|
231
|
+
)
|
|
232
|
+
c.add_argument("dest", metavar="CORPUS", help="path to the corpus folder")
|
|
233
|
+
c.add_argument(
|
|
234
|
+
"--manifest",
|
|
235
|
+
action="store_true",
|
|
236
|
+
help="also verify managed tooling files listed in .koinome/manifest.json",
|
|
237
|
+
)
|
|
238
|
+
c.add_argument(
|
|
239
|
+
"--git",
|
|
240
|
+
action="store_true",
|
|
241
|
+
help="also require a clean git working tree",
|
|
242
|
+
)
|
|
243
|
+
c.set_defaults(func=cmd_check)
|
|
244
|
+
|
|
245
|
+
u = sub.add_parser(
|
|
246
|
+
"upgrade",
|
|
247
|
+
help="migrate an existing corpus to the current template",
|
|
248
|
+
description=(
|
|
249
|
+
"Upgrade Koinome-managed tooling to the current template version. Run from anywhere; "
|
|
250
|
+
"pass the corpus folder path as the argument. Never touches your notes."
|
|
251
|
+
),
|
|
252
|
+
)
|
|
253
|
+
u.add_argument("dest", metavar="CORPUS", help="path to the corpus to upgrade")
|
|
254
|
+
u.add_argument("--force", action="store_true", help="re-apply even if already current")
|
|
255
|
+
u.add_argument(
|
|
256
|
+
"--dry-run",
|
|
257
|
+
action="store_true",
|
|
258
|
+
help="report planned changes without modifying the corpus",
|
|
259
|
+
)
|
|
260
|
+
u.set_defaults(func=cmd_upgrade)
|
|
261
|
+
|
|
262
|
+
return p
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
def main(argv=None):
|
|
266
|
+
parser = build_parser()
|
|
267
|
+
args = parser.parse_args(argv)
|
|
268
|
+
if args.cmd is None:
|
|
269
|
+
parser.print_help()
|
|
270
|
+
return 0
|
|
271
|
+
return args.func(args)
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
if __name__ == "__main__":
|
|
275
|
+
sys.exit(main())
|