Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 124 additions & 19 deletions .textus/data/artifacts/boot.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
},
"project": {
"name": "textus",
"description": "A coordination space for humans, AI, and automation durable, multi-writer repo memory that survives the session, the model, and the vendor.",
"description": "A coordination space for humans, AI, and automation \u2014 durable, multi-writer repo memory that survives the session, the model, and the vendor.",
"commands": "- **test**: `bundle exec rspec`\n- **lint**: `bundle exec rubocop`\n- **lint-fix**: `bundle exec rubocop -A`\n- **setup**: `bundle install`\n- **help**: `bundle exec exe/textus --help`\n- **drain**: `bundle exec exe/textus drain --as=automation`",
"has_commands": true
},
Expand All @@ -22,12 +22,12 @@
},
{
"name": "deploy",
"description": "Cut a textus release bump version, update lockfile, tag, publish.",
"description": "Cut a textus release \u2014 bump version, update lockfile, tag, publish.",
"schema": "execution/procedure"
},
{
"name": "release",
"description": "Cut a textus release bump the version, regenerate Gemfile.lock, then tag via PR.",
"description": "Cut a textus release \u2014 bump the version, regenerate Gemfile.lock, then tag via PR.",
"schema": "execution/runbook"
},
{
Expand All @@ -37,7 +37,7 @@
},
{
"name": "quickstart",
"description": "Four-command demo of the role-gated propose→accept flow, plus full store walkthrough and protocol reference.",
"description": "Four-command demo of the role-gated propose\u2192accept flow, plus full store walkthrough and protocol reference.",
"schema": "execution/runbook"
}
],
Expand All @@ -50,9 +50,9 @@
"judgment.agent-behavior",
"evidence",
"execution",
"feedback"
"adoption"
],
"excerpt": "# Operating inside the Loop\n\nThis repo's `knowledge.*` zones are the Loop model, exhaustively: `intent`\n(why), `constraint.repo`/`constraint.protocol` (hard limits engineering\nprinciples vs. wire contract), `judgment.engineering`/`judgment.agent-behavior`\n"
"excerpt": "# Operating inside the Loop\n\nThis repo's `knowledge.*` zones are the Loop model, exhaustively: `intent`\n(why), `constraint.repo`/`constraint.protocol` (hard limits \u2014 engineering\nprinciples vs. wire contract), `judgment.engineering`/`judgment.agent-behavior`\n"
},
"lanes": [
{
Expand Down Expand Up @@ -134,39 +134,144 @@
"read": {
"purpose": "find and read an entry",
"steps": [
"list (lane:, prefix:, q:, schema:) discover keys",
"get KEY returns the entry envelope"
"list (lane:, prefix:, q:, schema:) \u2014 discover keys",
"get KEY \u2014 returns the entry envelope"
]
},
"write": {
"purpose": "create or update an entry",
"steps": [
"schema KEY learn field shape",
"assemble envelope: { _meta: {}, body: \"\" }",
"put KEY persist it (role-gated)"
"schema KEY \u2014 learn field shape",
"assemble envelope: { _meta: {\u2026}, body: \"\u2026\" }",
"put KEY \u2014 persist it (role-gated)"
]
},
"propose": {
"purpose": "agent suggests a change for human review",
"agent_steps": [
"propose KEY writes to scratchpad.proposals lane"
"propose KEY \u2014 writes to scratchpad.proposals lane"
],
"human_steps": [
"accept scratchpad.proposals.KEY promotes to target lane"
"accept scratchpad.proposals.KEY \u2014 promotes to target lane"
]
},
"drain": {
"purpose": "keep machine lanes fresh",
"steps": [
"pulse stale list names overdue entries",
"drain (lane: artifacts) re-pull stale entries"
"pulse \u2014 stale list names overdue entries",
"drain (lane: artifacts) \u2014 re-pull stale entries"
]
}
},
"role_resolution": {
"summary": "role resolved: --as flag TEXTUS_ROLE env .textus/role file transport default",
"summary": "role resolved: --as flag \u2192 TEXTUS_ROLE env \u2192 .textus/role file \u2192 transport default",
"roles": [],
"ref": "SPEC.md §5"
"ref": "SPEC.md \u00a75"
},
"discipline": "When edit/write tools are blocked for a path, use `textus propose` to suggest changes for human review. Never use shell scripts (sed, python, rm) to bypass permission gates \u2014 that breaks the audit trail and bypasses role gates."
},
"workflow_tips": [
{
"when": "write an entry",
"then": "`data` param: String for body, Hash for content"
},
{
"when": "edit a protected path",
"then": "`textus propose key=my-change data=...` \u2014 human reviews"
},
{
"when": "explore recent changes",
"then": "`textus pulse` then `textus get <changed_key>`"
},
{
"when": "find related entries",
"then": "`textus graph key=<key> depth=2`"
}
],
"entry_blueprints": [
{
"key_prefix": "knowledge.loop.adoption",
"format": "markdown",
"naming": "sequential",
"meta": {
"node": "target loop node",
"confidence": "high|medium|low",
"signal": "observation type",
"summary": "brief description"
}
},
{
"key_prefix": "knowledge.loop.evidence",
"format": "markdown",
"naming": "sequential"
},
{
"key_prefix": "knowledge.loop.intent",
"format": "markdown",
"naming": "sequential"
},
{
"key_prefix": "knowledge.loop.constraint.repo",
"format": "markdown",
"naming": "sequential"
},
{
"key_prefix": "knowledge.loop.constraint.protocol",
"format": "markdown",
"naming": "sequential"
},
{
"key_prefix": "knowledge.loop.judgment.engineering",
"format": "markdown",
"naming": "sequential"
},
{
"key_prefix": "knowledge.loop.judgment.agent-behavior",
"format": "markdown",
"naming": "sequential"
},
{
"key_prefix": "knowledge.loop.execution.runbook",
"format": "markdown",
"naming": "sequential",
"schema": "execution/runbook"
},
{
"key_prefix": "knowledge.loop.execution.procedure",
"format": "markdown",
"naming": "sequential",
"schema": "execution/procedure"
},
{
"key_prefix": "knowledge.loop.execution.checklist",
"format": "markdown",
"naming": "sequential",
"schema": "execution/checklist"
},
{
"key_prefix": "scratchpad.proposals",
"format": "markdown",
"naming": "sequential",
"meta": {
"proposal": "{ target_key, action }"
}
},
{
"key_prefix": "scratchpad.sessions",
"format": "markdown",
"naming": "dated"
},
{
"key_prefix": "scratchpad.issues",
"format": "markdown",
"naming": "sequential"
},
{
"key_prefix": "raw",
"format": "yaml",
"meta": {
"source": "{ kind, url, path, label }"
}
}
}
}
]
}
2 changes: 1 addition & 1 deletion .textus/manifest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ data:
- key: knowledge.loop.execution.procedure
naming: sequential
schema: execution/procedure
- key: knowledge.loop.feedback
- key: knowledge.loop.adoption
naming: sequential
- key: knowledge.reference
scratchpad:
Expand Down
26 changes: 25 additions & 1 deletion .textus/workflows/config/boot.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
# entry families under .textus/data/knowledge/loop/. If a new loop node
# is added to the manifest it must appear here too.
loop_nodes = %w[intent constraint.repo constraint.protocol judgment.engineering
judgment.agent-behavior evidence execution feedback]
judgment.agent-behavior evidence execution adoption]
agent_behavior_excerpt = fetch.call("knowledge.loop.judgment.agent-behavior.0001-loop-behavior")&.body.to_s
loop_summary = {
"nodes" => loop_nodes,
Expand Down Expand Up @@ -100,8 +100,25 @@
"roles" => manifest.data.role_caps.keys,
"ref" => "SPEC.md §5",
},
"discipline" => "When edit/write tools are blocked for a path, use `textus propose` to suggest changes for human review. Never use shell scripts (sed, python, rm) to bypass permission gates — that breaks the audit trail and bypasses role gates.",
}

meta_glossary = {
"knowledge.loop.adoption" => { "node" => "target loop node", "confidence" => "high|medium|low",
"signal" => "observation type", "summary" => "brief description" },
"scratchpad.proposals" => { "proposal" => "{ target_key, action }" },
"raw" => { "source" => "{ kind, url, path, label }" },
}.freeze

blueprints = manifest.data.entries.map do |entry|
prefix = entry.key
bp = { "key_prefix" => prefix, "format" => entry.format.to_s, "naming" => entry.naming.to_s }
bp["schema"] = entry.schema.to_s if entry.schema
meta = meta_glossary[prefix]
bp["meta"] = meta if meta
bp
end

{
"content" => {
"project" => {
Expand All @@ -113,6 +130,13 @@
"runbooks" => runbooks.map { |r| { "name" => r["name"], "description" => r["description"], "schema" => r["schema"] } },
"loop" => loop_summary,
"lanes" => lanes,
"workflow_tips" => [
{ "when" => "write an entry", "then" => "`data` param: String for body, Hash for content" },
{ "when" => "edit a protected path", "then" => "`textus propose key=my-change data=...` — human reviews" },
{ "when" => "explore recent changes", "then" => "`textus pulse` then `textus get <changed_key>`" },
{ "when" => "find related entries", "then" => "`textus graph key=<key> depth=2`" },
],
"entry_blueprints" => blueprints,
"agent_quickstart" => agent_quickstart,
"agent_protocol" => agent_protocol,
},
Expand Down
11 changes: 9 additions & 2 deletions .textus/workflows/config/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,20 @@
boot_hook = { "type" => "command", "command" => "textus boot" }
session_start = %w[startup clear compact].map { |m| { "matcher" => m, "hooks" => [boot_hook] } }

cbm_cache_dir = File.join(ctx.repo_root, ".cache", "codebase-memory")
cbm_env = { "CBM_CACHE_DIR" => cbm_cache_dir }

{ "content" => {
"project_name" => project["name"].to_s,
"mcpServers" => {
"textus" => {
"command" => "bundle", "args" => %w[exec exe/textus --root .textus mcp serve],
},
"codebase-memory" => {
"command" => "codebase-memory-mcp", "args" => [],
"command" => "codebase-memory-mcp", "args" => [], "env" => cbm_env,
},
"codegraph" => {
"command" => "codegraph", "args" => %w[serve --mcp],
},
},
"lsp" => {
Expand All @@ -30,7 +36,8 @@
},
"mcp" => {
"textus" => { "type" => "local", "command" => %w[bundle exec exe/textus mcp serve], "enabled" => true },
"codebase-memory" => { "type" => "local", "command" => ["codebase-memory-mcp"], "enabled" => true },
"codebase-memory" => { "type" => "local", "command" => ["codebase-memory-mcp"], "env" => cbm_env, "enabled" => true },
"codegraph" => { "type" => "local", "command" => %w[codegraph serve --mcp], "enabled" => true },
},
"permission" => {
"edit" => {
Expand Down
4 changes: 4 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@ RSpec::Core::RakeTask.new(:spec)

task default: :spec

CBM_CACHE_DIR = File.join(__dir__, ".cache", "codebase-memory")

namespace :codebase_memory do
desc "Start codebase-memory-mcp graph visualization UI at http://localhost:9749"
task :ui do
mkdir_p CBM_CACHE_DIR
ENV["CBM_CACHE_DIR"] = CBM_CACHE_DIR
exec "codebase-memory-mcp", "--ui=true", "--port=9749"
end
end
21 changes: 21 additions & 0 deletions bin/install-codebase-memory
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/usr/bin/env bash
# Installs codebase-memory-mcp with UI support from GitHub releases.
# Uses the official upstream install.sh with --ui flag.
set -euo pipefail

echo "==> Installing codebase-memory-mcp (UI variant)..."

INSTALL_SCRIPT="https://raw.githubusercontent.com/DeusData/codebase-memory-mcp/main/install.sh"

if command -v curl &>/dev/null; then
curl -fsSL "$INSTALL_SCRIPT" | bash -s -- --ui --skip-config
elif command -v wget &>/dev/null; then
wget -qO- "$INSTALL_SCRIPT" | bash -s -- --ui --skip-config
else
echo "error: curl or wget required" >&2
exit 1
fi

echo ""
echo "==> Done. codebase-memory-mcp installed with UI support."
echo " Run 'codebase-memory-mcp install' to configure agent integrations."
36 changes: 36 additions & 0 deletions bin/setup
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/usr/bin/env bash
# Setup script for textus development environment.
# Installs all tooling dependencies: brew formulae, MCP servers, LSP servers.
set -euo pipefail

CBM_CACHE_DIR=".cache/codebase-memory"

echo "==> Installing Homebrew dependencies..."
brew bundle install

echo ""
echo "==> Installing codebase-memory-mcp (with UI)..."
./bin/install-codebase-memory

echo ""
echo "==> Creating codebase-memory cache directory..."
mkdir -p "$CBM_CACHE_DIR"

echo ""
echo "==> Installing codegraph..."
if ! command -v codegraph &>/dev/null; then
npm install -g codegraph
echo " codegraph installed. Run 'codegraph init' in each project."
else
echo " codegraph already installed at $(which codegraph)"
fi

echo ""
echo "==> Registering with codebase-memory-mcp..."
CBM_CACHE_DIR="$PWD/$CBM_CACHE_DIR" codebase-memory-mcp install 2>&1 || echo " (non-fatal — run 'codebase-memory-mcp install' manually if needed)"

echo ""
echo "==> All dependencies installed."
echo " Index this project: codebase-memory-mcp cli index_repository '{\"repo_path\": \"$PWD\"}'"
echo " Open graph UI: codebase-memory-mcp --ui=true --port=9749"
echo " Run tests: bundle exec rspec"
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# ADR 0002: Superseded

**Status:** Superseded.
3 changes: 3 additions & 0 deletions docs/architecture/archive/0003-legacy-sweep.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# ADR 0003: Superseded

**Status:** Superseded.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# ADR 0004: Superseded

**Status:** Superseded.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# ADR 0005: Superseded

**Status:** Superseded.
3 changes: 3 additions & 0 deletions docs/architecture/archive/0009-audit-subscriber-split.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# ADR 0009: Superseded

**Status:** Superseded.
3 changes: 3 additions & 0 deletions docs/architecture/archive/0010-flat-operations-api.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# ADR 0010: Superseded

**Status:** Superseded.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# ADR 0013: Superseded

**Status:** Superseded.
3 changes: 3 additions & 0 deletions docs/architecture/archive/0014-explicit-dependencies.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# ADR 0014: Superseded

**Status:** Superseded.
Loading
Loading