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.
Files changed (95) hide show
  1. koinome-0.0.0a1/LICENSE +21 -0
  2. koinome-0.0.0a1/PKG-INFO +119 -0
  3. koinome-0.0.0a1/README.md +104 -0
  4. koinome-0.0.0a1/koinome/__init__.py +2 -0
  5. koinome-0.0.0a1/koinome/cli.py +275 -0
  6. koinome-0.0.0a1/koinome/evaluation.py +281 -0
  7. koinome-0.0.0a1/koinome/exit_codes.py +12 -0
  8. koinome-0.0.0a1/koinome/importers/__pycache__/migrate_obsidian.cpython-314.pyc +0 -0
  9. koinome-0.0.0a1/koinome/importers/distill-seeds.md +57 -0
  10. koinome-0.0.0a1/koinome/importers/seed_extract.py +281 -0
  11. koinome-0.0.0a1/koinome/importers.py +109 -0
  12. koinome-0.0.0a1/koinome/manifest.py +92 -0
  13. koinome-0.0.0a1/koinome/paths.py +276 -0
  14. koinome-0.0.0a1/koinome/release_check.py +393 -0
  15. koinome-0.0.0a1/koinome/scaffold.py +141 -0
  16. koinome-0.0.0a1/koinome/template/.gitattributes +4 -0
  17. koinome-0.0.0a1/koinome/template/.github/workflows/koinome-check.yml +23 -0
  18. koinome-0.0.0a1/koinome/template/.gitignore +19 -0
  19. koinome-0.0.0a1/koinome/template/.koinome-manifest.json +178 -0
  20. koinome-0.0.0a1/koinome/template/.scripts/check_corpus.py +157 -0
  21. koinome-0.0.0a1/koinome/template/.scripts/check_staged_snapshot.py +102 -0
  22. koinome-0.0.0a1/koinome/template/.scripts/gen_mocs.py +171 -0
  23. koinome-0.0.0a1/koinome/template/.scripts/graph_report.py +276 -0
  24. koinome-0.0.0a1/koinome/template/.scripts/koinome-sync.sh +10 -0
  25. koinome-0.0.0a1/koinome/template/.scripts/koinome-sync.systemd +27 -0
  26. koinome-0.0.0a1/koinome/template/.scripts/koinome.config.json +68 -0
  27. koinome-0.0.0a1/koinome/template/.scripts/koinome_sync.py +403 -0
  28. koinome-0.0.0a1/koinome/template/.scripts/pre-commit +23 -0
  29. koinome-0.0.0a1/koinome/template/.scripts/synthesis_status.py +119 -0
  30. koinome-0.0.0a1/koinome/template/.scripts/validate_corpus.py +504 -0
  31. koinome-0.0.0a1/koinome/template/.skills/koinome-adr/SKILL.md +30 -0
  32. koinome-0.0.0a1/koinome/template/.skills/koinome-distill-seeds/SKILL.md +45 -0
  33. koinome-0.0.0a1/koinome/template/.skills/koinome-fix-validation/SKILL.md +44 -0
  34. koinome-0.0.0a1/koinome/template/.skills/koinome-init/SKILL.md +61 -0
  35. koinome-0.0.0a1/koinome/template/.skills/koinome-new-note/SKILL.md +27 -0
  36. koinome-0.0.0a1/koinome/template/.skills/koinome-session-close/SKILL.md +31 -0
  37. koinome-0.0.0a1/koinome/template/.skills/koinome-setup-domains/SKILL.md +42 -0
  38. koinome-0.0.0a1/koinome/template/.skills/koinome-synthesize/SKILL.md +41 -0
  39. koinome-0.0.0a1/koinome/template/.skills/koinome-todo/SKILL.md +39 -0
  40. koinome-0.0.0a1/koinome/template/.skills/koinome-weekly-review/SKILL.md +33 -0
  41. koinome-0.0.0a1/koinome/template/60-decisions/adr-0001-corpus-structure.md +36 -0
  42. koinome-0.0.0a1/koinome/template/60-decisions/index.md +15 -0
  43. koinome-0.0.0a1/koinome/template/72-tasks/todo.txt +3 -0
  44. koinome-0.0.0a1/koinome/template/90-templates/1on1.md +16 -0
  45. koinome-0.0.0a1/koinome/template/90-templates/adr.md +34 -0
  46. koinome-0.0.0a1/koinome/template/90-templates/concept.md +23 -0
  47. koinome-0.0.0a1/koinome/template/90-templates/entity.md +23 -0
  48. koinome-0.0.0a1/koinome/template/90-templates/governance-finding.md +19 -0
  49. koinome-0.0.0a1/koinome/template/90-templates/meeting.md +18 -0
  50. koinome-0.0.0a1/koinome/template/90-templates/project-doc.md +18 -0
  51. koinome-0.0.0a1/koinome/template/90-templates/source.md +15 -0
  52. koinome-0.0.0a1/koinome/template/90-templates/stakeholder.md +18 -0
  53. koinome-0.0.0a1/koinome/template/90-templates/weekly-review.md +17 -0
  54. koinome-0.0.0a1/koinome/template/AGENTS.md +98 -0
  55. koinome-0.0.0a1/koinome/template/CLAUDE.md +1 -0
  56. koinome-0.0.0a1/koinome/template/GEMINI.md +5 -0
  57. koinome-0.0.0a1/koinome/template/README.md +45 -0
  58. koinome-0.0.0a1/koinome/template/bootstrap.sh +202 -0
  59. koinome-0.0.0a1/koinome/template/docs/ARCHITECTURE.md +52 -0
  60. koinome-0.0.0a1/koinome/template/docs/CONFLICTS.md +24 -0
  61. koinome-0.0.0a1/koinome/template/docs/FIXING.md +42 -0
  62. koinome-0.0.0a1/koinome/template/docs/OPERATIONS.md +114 -0
  63. koinome-0.0.0a1/koinome/template/docs/SETUP.md +104 -0
  64. koinome-0.0.0a1/koinome/template/docs/SYNTHESIS.md +42 -0
  65. koinome-0.0.0a1/koinome/upgrade.py +615 -0
  66. koinome-0.0.0a1/koinome/version.py +17 -0
  67. koinome-0.0.0a1/koinome/wizard.py +151 -0
  68. koinome-0.0.0a1/koinome.egg-info/PKG-INFO +119 -0
  69. koinome-0.0.0a1/koinome.egg-info/SOURCES.txt +93 -0
  70. koinome-0.0.0a1/koinome.egg-info/dependency_links.txt +1 -0
  71. koinome-0.0.0a1/koinome.egg-info/entry_points.txt +2 -0
  72. koinome-0.0.0a1/koinome.egg-info/requires.txt +1 -0
  73. koinome-0.0.0a1/koinome.egg-info/top_level.txt +1 -0
  74. koinome-0.0.0a1/pyproject.toml +58 -0
  75. koinome-0.0.0a1/setup.cfg +4 -0
  76. koinome-0.0.0a1/tests/test_bootstrap.py +118 -0
  77. koinome-0.0.0a1/tests/test_cli_smoke.py +97 -0
  78. koinome-0.0.0a1/tests/test_conformance.py +106 -0
  79. koinome-0.0.0a1/tests/test_doc_consistency.py +131 -0
  80. koinome-0.0.0a1/tests/test_evaluation.py +25 -0
  81. koinome-0.0.0a1/tests/test_exit_status.py +149 -0
  82. koinome-0.0.0a1/tests/test_imports.py +68 -0
  83. koinome-0.0.0a1/tests/test_koinome_migration.py +209 -0
  84. koinome-0.0.0a1/tests/test_manifest_freshness.py +40 -0
  85. koinome-0.0.0a1/tests/test_naming_consistency.py +90 -0
  86. koinome-0.0.0a1/tests/test_package_data.py +106 -0
  87. koinome-0.0.0a1/tests/test_reference_corpora.py +49 -0
  88. koinome-0.0.0a1/tests/test_release_check.py +53 -0
  89. koinome-0.0.0a1/tests/test_release_policy.py +55 -0
  90. koinome-0.0.0a1/tests/test_scaffold_validation.py +47 -0
  91. koinome-0.0.0a1/tests/test_staged_snapshot.py +193 -0
  92. koinome-0.0.0a1/tests/test_sync.py +146 -0
  93. koinome-0.0.0a1/tests/test_upgrade.py +233 -0
  94. koinome-0.0.0a1/tests/test_validator.py +463 -0
  95. koinome-0.0.0a1/tests/test_versioning.py +42 -0
@@ -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.
@@ -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,2 @@
1
+ """Koinome: create and manage provider-independent markdown corpora."""
2
+ __version__ = "0.0.0alpha1"
@@ -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())