witan-council 0.2.0__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 (117) hide show
  1. witan_council-0.2.0/.gitignore +38 -0
  2. witan_council-0.2.0/PKG-INFO +342 -0
  3. witan_council-0.2.0/README.md +323 -0
  4. witan_council-0.2.0/cluster.yaml +20 -0
  5. witan_council-0.2.0/config/claude.json +18 -0
  6. witan_council-0.2.0/config/copilot.json +19 -0
  7. witan_council-0.2.0/config/operator-config.example.yaml +31 -0
  8. witan_council-0.2.0/config/pi.json +18 -0
  9. witan_council-0.2.0/docs/CLI_REFERENCE.md +443 -0
  10. witan_council-0.2.0/docs/USER_GUIDE.md +247 -0
  11. witan_council-0.2.0/docs/adr/0001-write-path-content-scanning.md +310 -0
  12. witan_council-0.2.0/docs/adr/0002-witan-cedar-authorization-bundle.md +127 -0
  13. witan_council-0.2.0/docs/adr/0003-atomic-task-claims-cas.md +95 -0
  14. witan_council-0.2.0/docs/adr/0004-optional-task-phase-tag.md +158 -0
  15. witan_council-0.2.0/docs/migration-runbook.md +258 -0
  16. witan_council-0.2.0/docs/write-path-scanning.md +266 -0
  17. witan_council-0.2.0/examples/example-scanner-plugin/README.md +67 -0
  18. witan_council-0.2.0/examples/example-scanner-plugin/pyproject.toml +19 -0
  19. witan_council-0.2.0/examples/example-scanner-plugin/src/example_scanner_plugin/__init__.py +64 -0
  20. witan_council-0.2.0/install.sh +77 -0
  21. witan_council-0.2.0/policy/.gitignore +3 -0
  22. witan_council-0.2.0/policy/README.md +148 -0
  23. witan_council-0.2.0/policy/bridge.policy.yaml +61 -0
  24. witan_council-0.2.0/policy/check.sh +47 -0
  25. witan_council-0.2.0/policy/cluster.yaml +64 -0
  26. witan_council-0.2.0/policy/code-graph.policy.yaml +97 -0
  27. witan_council-0.2.0/policy/find.gq +5 -0
  28. witan_council-0.2.0/policy/lint_bundles.py +167 -0
  29. witan_council-0.2.0/policy/memory.policy.yaml +65 -0
  30. witan_council-0.2.0/policy/schema/stub.pg +8 -0
  31. witan_council-0.2.0/policy/server.policy.yaml +44 -0
  32. witan_council-0.2.0/policy/tests/bridge.tests.yaml +57 -0
  33. witan_council-0.2.0/policy/tests/code-graph.tests.yaml +114 -0
  34. witan_council-0.2.0/policy/tests/memory.tests.yaml +48 -0
  35. witan_council-0.2.0/policy/tests/server.tests.yaml +16 -0
  36. witan_council-0.2.0/pyproject.toml +60 -0
  37. witan_council-0.2.0/pyrightconfig.json +5 -0
  38. witan_council-0.2.0/queries/mutations.gq +457 -0
  39. witan_council-0.2.0/queries/read.gq +791 -0
  40. witan_council-0.2.0/schema/schema.pg +240 -0
  41. witan_council-0.2.0/tests/__init__.py +0 -0
  42. witan_council-0.2.0/tests/conftest.py +88 -0
  43. witan_council-0.2.0/tests/test_allowlist.py +155 -0
  44. witan_council-0.2.0/tests/test_audit.py +181 -0
  45. witan_council-0.2.0/tests/test_cli.py +505 -0
  46. witan_council-0.2.0/tests/test_cli_scan.py +119 -0
  47. witan_council-0.2.0/tests/test_codebranch.py +155 -0
  48. witan_council-0.2.0/tests/test_composition.py +36 -0
  49. witan_council-0.2.0/tests/test_config.py +768 -0
  50. witan_council-0.2.0/tests/test_context.py +499 -0
  51. witan_council-0.2.0/tests/test_contracts.py +99 -0
  52. witan_council-0.2.0/tests/test_detach.py +45 -0
  53. witan_council-0.2.0/tests/test_detectors.py +198 -0
  54. witan_council-0.2.0/tests/test_elicit.py +307 -0
  55. witan_council-0.2.0/tests/test_enforce.py +284 -0
  56. witan_council-0.2.0/tests/test_example_plugin.py +57 -0
  57. witan_council-0.2.0/tests/test_graph.py +86 -0
  58. witan_council-0.2.0/tests/test_maintenance.py +185 -0
  59. witan_council-0.2.0/tests/test_memory.py +281 -0
  60. witan_council-0.2.0/tests/test_migrate.py +368 -0
  61. witan_council-0.2.0/tests/test_provenance.py +90 -0
  62. witan_council-0.2.0/tests/test_ranking.py +114 -0
  63. witan_council-0.2.0/tests/test_readiness.py +85 -0
  64. witan_council-0.2.0/tests/test_recall.py +108 -0
  65. witan_council-0.2.0/tests/test_redact.py +97 -0
  66. witan_council-0.2.0/tests/test_repo.py +191 -0
  67. witan_council-0.2.0/tests/test_scan.py +218 -0
  68. witan_council-0.2.0/tests/test_session_state.py +46 -0
  69. witan_council-0.2.0/tests/test_setup.py +328 -0
  70. witan_council-0.2.0/tests/test_setup_cmd.py +196 -0
  71. witan_council-0.2.0/tests/test_tasks.py +335 -0
  72. witan_council-0.2.0/tests/test_visualize.py +187 -0
  73. witan_council-0.2.0/tests/test_workflow.py +476 -0
  74. witan_council-0.2.0/uv.lock +1511 -0
  75. witan_council-0.2.0/witan/__init__.py +1 -0
  76. witan_council-0.2.0/witan/__main__.py +4 -0
  77. witan_council-0.2.0/witan/_detach.py +26 -0
  78. witan_council-0.2.0/witan/cli/__init__.py +136 -0
  79. witan_council-0.2.0/witan/cli/_common.py +102 -0
  80. witan_council-0.2.0/witan/cli/graph.py +80 -0
  81. witan_council-0.2.0/witan/cli/hooks.py +73 -0
  82. witan_council-0.2.0/witan/cli/maintenance.py +96 -0
  83. witan_council-0.2.0/witan/cli/memory.py +44 -0
  84. witan_council-0.2.0/witan/cli/migrate.py +196 -0
  85. witan_council-0.2.0/witan/cli/projects.py +526 -0
  86. witan_council-0.2.0/witan/cli/run_helpers.py +211 -0
  87. witan_council-0.2.0/witan/cli/scan.py +138 -0
  88. witan_council-0.2.0/witan/cli/session.py +122 -0
  89. witan_council-0.2.0/witan/cli/setup_cmd.py +217 -0
  90. witan_council-0.2.0/witan/cli/tasks.py +529 -0
  91. witan_council-0.2.0/witan/cli/traces.py +140 -0
  92. witan_council-0.2.0/witan/config.py +666 -0
  93. witan_council-0.2.0/witan/context.py +485 -0
  94. witan_council-0.2.0/witan/elicit.py +99 -0
  95. witan_council-0.2.0/witan/extensions/pi/workflow-context.ts +37 -0
  96. witan_council-0.2.0/witan/graph.py +297 -0
  97. witan_council-0.2.0/witan/hooks/workflow-context-inject.sh +4 -0
  98. witan_council-0.2.0/witan/hooks/workflow-session-checkpoint.sh +4 -0
  99. witan_council-0.2.0/witan/maintenance.py +117 -0
  100. witan_council-0.2.0/witan/readiness.py +88 -0
  101. witan_council-0.2.0/witan/repo.py +220 -0
  102. witan_council-0.2.0/witan/scan/__init__.py +45 -0
  103. witan_council-0.2.0/witan/scan/allowlist.py +91 -0
  104. witan_council-0.2.0/witan/scan/audit.py +121 -0
  105. witan_council-0.2.0/witan/scan/detectors.py +232 -0
  106. witan_council-0.2.0/witan/scan/enforce.py +198 -0
  107. witan_council-0.2.0/witan/scan/models.py +84 -0
  108. witan_council-0.2.0/witan/scan/redact.py +58 -0
  109. witan_council-0.2.0/witan/scan/registry.py +161 -0
  110. witan_council-0.2.0/witan/server.py +3510 -0
  111. witan_council-0.2.0/witan/session_state.py +28 -0
  112. witan_council-0.2.0/witan/setup.py +289 -0
  113. witan_council-0.2.0/witan/skills/witan-memory/SKILL.md +216 -0
  114. witan_council-0.2.0/witan/skills/witan-project-tracker/SKILL.md +204 -0
  115. witan_council-0.2.0/witan/skills/witan-task/SKILL.md +137 -0
  116. witan_council-0.2.0/witan/skills/witan-workflow/SKILL.md +135 -0
  117. witan_council-0.2.0/witan/visualize.py +385 -0
@@ -0,0 +1,38 @@
1
+ # Dependencies
2
+ node_modules/
3
+ .venv/
4
+ __pycache__/
5
+ *.pyc
6
+
7
+ # Environment / secrets
8
+ .env
9
+ .env.local
10
+ .env.*.local
11
+ *.secret
12
+
13
+ # Editor
14
+ .vscode/settings.json
15
+ .idea/
16
+ *.swp
17
+ *.swo
18
+
19
+ # OS
20
+ .DS_Store
21
+ Thumbs.db
22
+
23
+ # Build artifacts
24
+ dist/
25
+ build/
26
+ *.egg-info/
27
+ # omnigraph binary downloaded by hatch_build.py — not committed
28
+ _bin/
29
+ # omnigraph cluster state (populated by `omnigraph cluster import`)
30
+ __cluster/
31
+
32
+ # MCP server logs / caches
33
+ .mcp-cache/
34
+ mcp-server.log
35
+ .ruff_cache/
36
+
37
+ # agent-config-kit remote skill/hook fetch cache
38
+ .agent-config-kit-cache/
@@ -0,0 +1,342 @@
1
+ Metadata-Version: 2.4
2
+ Name: witan-council
3
+ Version: 0.2.0
4
+ Summary: witan — agent memory, planning, and collaboration graph (work-coordination layer + umbrella CLI)
5
+ Project-URL: Homepage, https://github.com/mitodl/agent-kit/tree/main/mcp/servers/witan
6
+ Project-URL: Repository, https://github.com/mitodl/agent-kit
7
+ Project-URL: Documentation, https://github.com/mitodl/agent-kit/blob/main/mcp/servers/witan/README.md
8
+ Project-URL: Issues, https://github.com/mitodl/agent-kit/issues
9
+ License-Expression: BSD-3-Clause
10
+ Keywords: agent,coding-agent,knowledge-graph,mcp,memory,task-tracking
11
+ Classifier: Programming Language :: Python :: 3
12
+ Requires-Python: >=3.11
13
+ Requires-Dist: agent-config-kit<1,>=0.1
14
+ Requires-Dist: cyclopts<5,>=4
15
+ Requires-Dist: fastmcp<4,>=3.4.2
16
+ Requires-Dist: pydantic<3,>=2
17
+ Requires-Dist: rich>=13
18
+ Description-Content-Type: text/markdown
19
+
20
+ # witan
21
+
22
+ > Pronounced `WIT-ən` (/ˈwɪtən/) — rhymes with "written" minus the r. From
23
+ > Old English *witan*, the king's council of advisors.
24
+
25
+ A team-wide shared knowledge graph for coding agents, backed by
26
+ [Omnigraph](https://github.com/ModernRelay/omnigraph). Stores coding patterns,
27
+ project/repo facts, lessons, and agent context. Exposed over MCP so every
28
+ agent platform (pi, Claude Desktop, GitHub Copilot) can read and write without
29
+ platform-specific code.
30
+
31
+ ## Documentation
32
+
33
+ See the [User Guide](https://github.com/mitodl/agent-kit/blob/main/mcp/servers/witan/docs/USER_GUIDE.md)
34
+ for a task-oriented walkthrough (install, setup, day-to-day loop, operating
35
+ modes, troubleshooting) and the [CLI Reference](https://github.com/mitodl/agent-kit/blob/main/mcp/servers/witan/docs/CLI_REFERENCE.md)
36
+ for the full `witan` command surface.
37
+
38
+ ## Quick Start
39
+
40
+ `witan setup` installs the omnigraph binary, copies hooks/skills, and wires the
41
+ MCP server entry into your agent config in one step. Run it once; re-run after
42
+ upgrades to refresh installed files.
43
+
44
+ The omnigraph binary step always downloads the release pinned by
45
+ `_OMNIGRAPH_VERSION` in [`witan/setup.py`](./witan/setup.py) straight from
46
+ GitHub releases into `~/.local/bin/omnigraph` — there is no build-time
47
+ bundling, so re-running `witan setup` is also how you pick up an omnigraph
48
+ version bump (a Renovate PR bumps the pin; see `renovate.json`'s
49
+ `omnigraph-version` customManager). When `witan-code` is also installed
50
+ (importable in this environment — e.g. via the `--with` in the `uv tool
51
+ install`/MCP server's `uvx` invocation below), `witan setup` folds its skill
52
+ and hooks into the same install pass — registered as `witan code …`, so the
53
+ hooks only need `witan` on `PATH`, not a separate `witan-code` binary — and
54
+ skips a separate MCP entry, since `witan serve` already mounts witan-code's
55
+ tools in-process. One `witan setup` then covers both packages. Installed
56
+ standalone (without `witan`), `witan-code` has its own equivalent `witan-code
57
+ setup` (or the mounted `witan code setup`) — see its
58
+ [README](../witan-code/README.md#install).
59
+
60
+ **With persistent CLI** — required for **Claude Code** and **Pi** (and `--agent all`),
61
+ whose hooks/extensions call the `witan` command directly, so it must stay on your `PATH`.
62
+ Install `witan-code` alongside it with `--with` so its `witan code …` hooks
63
+ work too (omit `--with` for a witan-only install):
64
+
65
+ ```bash
66
+ # Install the latest release from PyPI …
67
+ uv tool install --with witan-code witan-council
68
+ # … or, to track pre-release/unreleased code, from the git repo directly:
69
+ uv tool install --with git+https://github.com/mitodl/agent-kit#subdirectory=mcp/servers/witan-code \
70
+ git+https://github.com/mitodl/agent-kit#subdirectory=mcp/servers/witan
71
+ # … or editable from a local checkout, at the repo root:
72
+ uv tool install --editable --with ./mcp/servers/witan-code mcp/servers/witan
73
+
74
+ # then run setup:
75
+ witan setup --agent claude # or: pi | all
76
+ ```
77
+
78
+ **Without persistent CLI** — enough for the **MCP-only agents** (Copilot, OpenCode,
79
+ Kilo), whose server runs via `uvx`, so no install is needed:
80
+
81
+ ```bash
82
+ # From PyPI …
83
+ uvx --from witan-council witan setup --agent copilot # or: opencode | kilo
84
+ # … or, to track pre-release/unreleased code, from the git repo directly:
85
+ uvx --from git+https://github.com/mitodl/agent-kit#subdirectory=mcp/servers/witan \
86
+ witan setup --agent copilot # or: opencode | kilo
87
+ # … or from a local checkout, at the repo root:
88
+ uvx --from mcp/servers/witan witan setup --agent copilot
89
+ ```
90
+
91
+ ```bash
92
+ # Optional — set your author name (defaults to git config user.name or $USER):
93
+ export WITAN_AUTHOR="Your Name"
94
+ ```
95
+
96
+ > **Manual wiring** (if you prefer to configure agents by hand): run
97
+ > `./install.sh` to initialise the local graph, then copy the appropriate
98
+ > config snippet from `config/` into your agent's MCP config file.
99
+
100
+ > **Local development setup** (both servers, hooks, and skills wired from your
101
+ > checkout): see
102
+ > [Local Development Setup](../../../docs/agent-memory.md#local-development-setup).
103
+
104
+ ## Environment Variables
105
+
106
+ | Variable | Required | Default | Description |
107
+ |---|---|---|---|
108
+ | `WITAN_MEMORY_URI` | No | `~/.local/share/witan/graph.omni` | Graph URI — local path, `s3://`, or `http://` |
109
+ | `WITAN_MEMORY_TOKEN` | Only for `http://` | — | Bearer token for remote server auth |
110
+ | `WITAN_AUTHOR` | No | `$USER` | Attribution on every insert |
111
+ | `WITAN_REPO` | No | — | Repo slug override (bypasses git detection) |
112
+ | `WITAN_SCAN_ENABLED` | No | `true` | Write-path secret/PII scanning; set to `false` to opt out — see [Write-path content scanning](docs/write-path-scanning.md) |
113
+ | `WITAN_OPTIMIZE_INTERVAL` | No | `86400` | Throttle window (seconds) for the Stop hook's opportunistic background store compaction; `0` disables it |
114
+
115
+ ## MCP Tools
116
+
117
+ > **witan memory vs. your agent's built-in/session memory.** witan is the
118
+ > **shared, synced, team-wide** store; a coding agent's built-in memory (e.g.
119
+ > Claude Code's `memory/` files) is private to one machine and user. Durable,
120
+ > shareable engineering knowledge — project facts, patterns, lessons, decisions
121
+ > — belongs in witan so other agents and future sessions can find it; keep only
122
+ > private/ephemeral notes in built-in memory. The `witan-memory` skill and the
123
+ > MCP server instructions steer the agent accordingly.
124
+
125
+ ### Memory Tools
126
+
127
+ | Tool | Description |
128
+ |---|---|
129
+ | `memory_search` | Full-text BM25 search across all memories, with optional `repo`/`kind` filters |
130
+ | `memory_list` | List memories (no search), optionally filtered by `kind` and/or `repo`; ordered most-recent first |
131
+ | `memory_store` | Insert a new memory (pattern, project_fact, lesson, or agent_context) |
132
+ | `memory_get` | Fetch a single memory by slug |
133
+ | `memory_get_project_facts` | Return all project facts for the current (or specified) repo |
134
+ | `memory_list_patterns` | List coding patterns, optionally scoped to a repo and/or language |
135
+
136
+ ### Workflow Tracking Tools
137
+
138
+ Track engineering projects end-to-end across multiple Claude Code sessions.
139
+ See [`mcp/servers/witan/witan/skills/witan-project-tracker/SKILL.md`](./witan/skills/witan-project-tracker/SKILL.md) for usage.
140
+
141
+ | Tool | Description |
142
+ |---|---|
143
+ | `workflow_project_create` | Create a new project (`wp-` slug) to track an engineering objective |
144
+ | `workflow_project_get` | Fetch a single project by slug |
145
+ | `workflow_project_list` | List projects filtered by repo, status, or phase; defaults to active |
146
+ | `workflow_project_advance` | Advance a project to the next phase (discovery → spec → implementation → delivery) |
147
+ | `workflow_project_complete` | Mark project done; assembles a `WorkflowTrace` corpus record from all sessions |
148
+ | `workflow_project_link_memory` | Attach a memory (pattern/lesson/project_fact) to a project via an `Informed` edge |
149
+ | `workflow_project_block` | Declare that one project must complete before another can begin |
150
+ | `workflow_project_unblock` | Remove a project dependency declared with `workflow_project_block` |
151
+ | `workflow_project_get_blockers` | Return all projects currently blocking the given project |
152
+ | `workflow_session_start` | Link the current agent session to a project; writes a state file for the Stop hook |
153
+ | `workflow_session_end` | Close the session with a summary, tools used, and files changed |
154
+ | `workflow_trace_get` | Fetch a completed project's corpus `WorkflowTrace` by its `wt-`/`wp-` slug |
155
+
156
+ ### Task Tracking Tools
157
+
158
+ A dependency-aware, hierarchical task tracker (beads-like) in the same graph, so
159
+ tasks hard-link to projects, sessions, and memories. See
160
+ [`mcp/servers/witan/witan/skills/witan-task/SKILL.md`](./witan/skills/witan-task/SKILL.md)
161
+ (the `/witan-task` skill) for usage.
162
+
163
+ | Tool | Description |
164
+ |---|---|
165
+ | `task_create` | Create a task (`tk-` slug). Supports `parent` (epic → sub-issue), `blocked_by`, `project_slug`, `external_uri` (e.g. a GitHub issue), and `symbol_refs` |
166
+ | `task_get` | Fetch a single task by slug |
167
+ | `task_list` | List tasks filtered by repo, status, project, parent (epic children), or assignee |
168
+ | `task_update` | Update mutable fields — reassign, re-prioritise, re-parent, attach a URI (to *claim* for work, prefer `task_claim`) |
169
+ | `task_claim` | **Advisory claim** for parallel/multi-user agents: set `in_progress` under an `assignee` with a lease; refuses if actively held (use `force` to steal). Read-check-write, not an atomic lock — see `claimed_at` lease + the CAS follow-up |
170
+ | `task_release` | Drop a claim: clear assignee/lease, return the task to `open` |
171
+ | `task_close` | Close a task with an optional resolution; unblocks its dependents |
172
+ | `task_ready` | **Ready work**: open/unblocked tasks (plus `in_progress` tasks whose lease has lapsed) ordered by priority — the core coordination primitive |
173
+ | `task_link` | Link tasks: `blocks` / `parent` / `discovered_from`, or `addresses` a Memory node |
174
+ | `context_for_symbol` | Reverse lookup: given a code-graph symbol id (`repo#path::Name`), return the memories and tasks whose `symbolRefs` include it |
175
+
176
+ Tasks are **hierarchical** (an `epic` decomposes into sub-issues via `parent`, with
177
+ `parentSlug` denormalized for fast child lookup) and **dependency-aware** (`blocked_by`
178
+ maintains a denormalized `blockedBy` list that drives the `task_ready` query without
179
+ graph traversal). `external_uri` links a task to a GitHub issue/PR or any reference.
180
+
181
+ ### Code Branch Tracking
182
+
183
+ Links a git branch (repo + raw branch name, e.g. `feature/new-api` — never
184
+ witan-code's sanitized omnigraph branch name) to the task/project it's
185
+ carrying, so "which branch carries task X" and "which tasks are in flight on
186
+ branch B" are one-hop graph queries. Coordination state that lives in witan
187
+ (shared, durable), not witan-code's per-repo/bridge omnigraph stores (local,
188
+ re-derivable caches `branches --prune` may destroy at any time).
189
+
190
+ Wired in automatically, best-effort — no dedicated tool call needed:
191
+
192
+ - `workflow_session_start` upserts a `CodeBranch` for the current checkout's
193
+ repo+branch (when detected) and links it `ForProject` to the session's
194
+ project.
195
+ - `task_claim` upserts a `CodeBranch` on success and links it `WorksOn` the
196
+ claimed task; re-calling `task_claim` (lease renewal) does not duplicate
197
+ the edge.
198
+ - The `UserPromptSubmit` context-injection hook surfaces an **In-Flight
199
+ Branch** section when the current checkout's branch already carries an
200
+ open task — a signal that this session should likely continue that work
201
+ rather than pick up something new.
202
+
203
+ Both call sites no-op silently with no repo/branch context (detached HEAD,
204
+ outside a git repo, or a store that predates this feature and hasn't run
205
+ `witan migrate schema` yet) — this is metadata riding alongside a task/
206
+ workflow tool call, never a hard requirement for the tool it's attached to.
207
+
208
+ ## Write-path content scanning
209
+
210
+ Pluggable secret/PII scanning on every write (memories, tasks, projects,
211
+ sessions, traces), with block/redact/warn enforcement and a `witan.scanners`
212
+ entry-point mechanism so other organizations can add their own detection
213
+ rules without forking. Enabled by default (opt-out) — see
214
+ [`docs/write-path-scanning.md`](docs/write-path-scanning.md) for the full
215
+ config surface, the `witan scan test`/`witan scan rules` CLI, the audit
216
+ trail, and how to write a plugin, and
217
+ [ADR 0001](docs/adr/0001-write-path-content-scanning.md) for the design
218
+ rationale.
219
+
220
+ ## Migrating or merging stores
221
+
222
+ Moving a store to a new machine, merging two machines' local stores, or
223
+ moving a local store onto the shared multi-tenant server — same command in
224
+ all three cases:
225
+
226
+ ```bash
227
+ witan migrate merge <source> [--target <target>] [--dry-run]
228
+ ```
229
+
230
+ Reconciles slug collisions newest-record-wins (by timestamp) rather than
231
+ `omnigraph load --mode merge`'s raw last-loaded-wins overwrite, and is
232
+ repeatable — re-running against an already-merged target loads nothing new.
233
+ Never `mv`/copy a store directly (Lance embeds absolute paths). See
234
+ [`docs/migration-runbook.md`](docs/migration-runbook.md) for the full
235
+ procedure and what was verified about `--mode merge`'s actual collision
236
+ behavior.
237
+
238
+ ## Tests
239
+
240
+ Integration tests spin up throwaway omnigraph graphs and exercise the real query
241
+ files end-to-end (they skip automatically if the `omnigraph` binary is absent):
242
+
243
+ ```bash
244
+ uv run --group test pytest
245
+ ```
246
+
247
+ ## Exploring the graph (`witan`)
248
+
249
+ A cyclopts CLI for manual inspection of the work-coordination graph and the
250
+ indexed code graphs. Installed alongside the server (`uv run witan …`,
251
+ or `uv tool install` the package to get it on `PATH`):
252
+
253
+ | Command | Description |
254
+ |---|---|
255
+ | `setup [--agent claude\|pi\|…\|all]` | Install witan for one or all supported coding agents; also writes a starter `~/.config/witan/config.toml` if one doesn't exist yet |
256
+ | `tasks [--ready] [--status …] [--project wp-…] [--all-repos]` | Tasks for the current repo (closed elided by default — pass `--status closed` to see them); `--ready` = open with no open blockers |
257
+ | `task <tk-slug>` | One task's details, blockers, and sub-tasks |
258
+ | `task create <title>` | Create a task from the CLI |
259
+ | `task close\|claim\|release\|update\|link <tk-slug> …` | Drive task state transitions from the CLI |
260
+ | `run <tk-slug> [--agent claude\|pi] [--dry-run]` | Claim a task and launch an agent to execute it |
261
+ | `projects [--status …] [--all-repos]` | Workflow projects (default: active in this repo) |
262
+ | `project <wp-slug>` | A project with its sessions, tasks, and corpus trace |
263
+ | `project status <wp-slug> [--json]` | "What next" resume view — phase, ready tasks, last session, blockers |
264
+ | `project tasks <wp-slug> [--status …] [--detail]` | A project's tasks; `--detail` expands each task's blockers and dependents |
265
+ | `project create <title>` | Create a workflow project from the CLI |
266
+ | `project advance\|complete\|block\|unblock <wp-slug> …` | Drive project phase/dependency transitions from the CLI |
267
+ | `session start\|end\|list …` | Start/close a workflow session, or list a project's sessions |
268
+ | `memory [QUERY] [--kind …]` | BM25 memory search, or (with no query) list memories |
269
+ | `code repos` | Repositories with a code graph indexed (requires witan-code) |
270
+ | `scan test <text>` | Dry-run active detectors against an ad-hoc string; prints findings (never the matched text) |
271
+ | `scan rules` | List active write-path scan detectors, their category, source, and enforcement mode |
272
+ | `inject-context [--debug]` | The UserPromptSubmit hook body; `--debug` prints detection/read diagnostics to stderr (repo, branch, graph reads, counts, swallowed-failure reasons) to explain a blank block |
273
+ | `optimize [--store URI]` | Compact the store's Lance fragments (non-destructive) so query latency doesn't bloat; safe to run on a cron/systemd-timer |
274
+ | `cleanup [--keep N] [--older-than 7d] --yes` | Reclaim disk by GC-ing old Lance versions (destructive; requires `--yes`) |
275
+ | `serve` | Start the MCP server (memory + code tools when witan-code is installed) |
276
+
277
+ `run` claims the task (`in_progress` + your author), then hands the terminal to
278
+ the agent seeded with the task description and a reminder to `task_close` when
279
+ done — invoke it from the task's repo checkout. Use `--dry-run` to print the
280
+ prompt without launching.
281
+
282
+ ## Operating Modes
283
+
284
+ ### Local Disk (default)
285
+
286
+ No extra infrastructure. Memories persist at
287
+ `~/.local/share/witan/graph.omni`.
288
+
289
+ ```bash
290
+ # No env vars required.
291
+ export WITAN_AUTHOR="Alice Smith"
292
+ ```
293
+
294
+ ### Local RustFS (S3-compatible, for testing team mode)
295
+
296
+ ```bash
297
+ RUSTFS=1 ./install.sh
298
+ # Follow the printed export instructions.
299
+ ```
300
+
301
+ ### Remote Team Server
302
+
303
+ ```bash
304
+ export WITAN_MEMORY_URI=http://witan.internal:8080
305
+ export WITAN_MEMORY_TOKEN=<bearer-token>
306
+ export WITAN_AUTHOR="Alice Smith"
307
+ ```
308
+
309
+ See [`docs/agent-memory.md`](../../../docs/agent-memory.md) for full
310
+ deployment instructions, the graph schema, and the v2 roadmap.
311
+
312
+ ## Project Structure
313
+
314
+ ```
315
+ witan/
316
+ ├── README.md # This file
317
+ ├── install.sh # Initialise local graph (manual alternative to `witan setup`)
318
+ ├── pyproject.toml # Python package metadata
319
+ ├── schema/
320
+ │ └── schema.pg # Omnigraph graph schema
321
+ ├── queries/
322
+ │ ├── read.gq # Read queries
323
+ │ └── mutations.gq # Insert/update queries
324
+ ├── tests/ # Integration tests
325
+ ├── witan/ # Python package
326
+ │ ├── __init__.py
327
+ │ ├── __main__.py # Entry point
328
+ │ ├── server.py # FastMCP app + tool definitions
329
+ │ ├── cli.py # `witan` umbrella CLI (cyclopts)
330
+ │ ├── config.py # Config loaded from env vars
331
+ │ ├── context.py # inject-context / session-checkpoint helpers
332
+ │ ├── repo.py # Git remote → canonical repo slug
333
+ │ ├── graph.py # OmnigraphClient (CLI subprocess wrapper)
334
+ │ ├── setup.py # `witan setup` agent-installer + omnigraph fetch logic
335
+ │ ├── extensions/ # Agent extension configs (bundled by setup)
336
+ │ ├── hooks/ # Shell hooks (bundled by setup)
337
+ │ └── skills/ # Bundled agent skills
338
+ └── config/
339
+ ├── pi.json # Snippet for ~/.pi/agent/mcp.json
340
+ ├── claude.json # Snippet for claude_desktop_config.json
341
+ └── copilot.json # Snippet for .vscode/mcp.json
342
+ ```