Twining MCP Server
The Problem
You spend two hours with Claude Code making architectural decisions. You choose PostgreSQL over MongoDB. You settle on JWT for auth. You flag a race condition in the payment module. Then the session ends.
Tomorrow you start a new session. Claude has no idea what happened. The decisions are gone. The warnings are gone. The rationale is gone. You re-explain everything — or worse, Claude silently contradicts yesterday's choices.
This gets worse with multiple agents. Agent A decides on REST. Agent B picks gRPC for the same service. Neither knows the other exists. You find out when the code doesn't compile.
Context windows are ephemeral. Your project's decisions shouldn't be.
Related MCP server: CollabMCP
How Twining Fixes It
Twining is an MCP server that gives your AI agents persistent project memory. Decisions survive context resets. New sessions start informed. Multi-agent work stays coordinated.
# Install in 10 seconds
/plugin marketplace add daveangulo/twining-mcp
/plugin install twining@twining-marketplaceRecord what you did — in natural language:
twining_record({
summary: "Added Redis caching to UserService",
decisions: ["Chose Redis over Memcached — need persistence across restarts"],
assumptions: ["Read-heavy workload (10:1 ratio)"],
scope: "src/services/"
})Twining parses your decisions into structured records — extracting rationale, rejected alternatives, and domain automatically. One tool call, no forms.
Start a new session. Get caught up instantly:
twining_assemble({ task: "optimize the caching layer", scope: "src/services/" })Twining scores every decision, warning, and finding by relevance to your task, then fills a token budget in priority order. You get exactly the context you need — no firehose, no re-explaining.
Ask why things are the way they are:
twining_why({ scope: "src/auth/middleware.ts" })Returns the full decision chain for any file: what was decided, when, why, what alternatives were rejected, and which commit implemented it.
Why Not Just Use CLAUDE.md?
CLAUDE.md is static. You write it once and update it manually. It doesn't capture decisions as they happen, doesn't track rationale or alternatives, doesn't detect conflicts between agents, and can't selectively assemble context within a token budget.
Twining is dynamic. Every twining_decide call records a structured decision. Every twining_post shares a finding or warning. Every twining_assemble scores relevance and delivers precisely what the current task needs. The .twining/ directory is your project's living institutional memory.
Why Not an Orchestrator?
Orchestrators (like agent swarms and hierarchical coordinators) route work by assigning tasks. Twining coordinates by sharing state. The difference matters:
Orchestrators hold coordination context in their own context window — a single point of failure that degrades as the window fills
Twining's blackboard persists coordination state outside any agent's window, surviving context resets without information loss
Agents self-select into work by reading the blackboard. No central bottleneck. No relay that drops context. Every agent sees every other agent's decisions and warnings, directly.
Install
Plugin Install (Recommended)
# Add the marketplace (one-time)
/plugin marketplace add daveangulo/twining-mcp
# Install the plugin
/plugin install twining@twining-marketplaceIncludes the MCP server, skills, lifecycle hooks, and pre-commit enforcement. Two gates: twining_assemble before working, twining_record before committing — hooks enforce both automatically.
Team Auto-Install
Commit this to your repo's .claude/settings.json so every team member gets Twining on clone:
{
"extraKnownMarketplaces": {
"twining-marketplace": {
"source": {
"source": "github",
"repo": "daveangulo/twining-mcp"
}
}
},
"enabledPlugins": {
"twining@twining-marketplace": true
}
}When team members trust the repository folder, Claude Code automatically installs the marketplace and plugin.
MCP-Only Install
For non-Claude-Code clients (Cursor, Windsurf, etc.):
claude mcp add twining -- npx -y twining-mcp --project .Or add to .mcp.json:
{
"mcpServers": {
"twining": {
"command": "npx",
"args": ["-y", "twining-mcp", "--project", "."]
}
}
}MCP server instructions are included automatically in the initialize response.
Upgrading from Manual Install
If you previously configured Twining manually, switch to the plugin:
Remove manual MCP server:
claude mcp remove twiningInstall plugin:
/plugin marketplace add daveangulo/twining-mcpthen/plugin install twining@twining-marketplaceClean up: remove Twining hooks from
.claude/settings.json, remove.claude/agents/twining-aware.mdif present, remove Twining sections fromCLAUDE.md(skills handle this now)Keep:
.twining/directory (all state preserved)Verify:
/twining:status
Get the Most Out of It
The plugin handles agent instructions automatically via skills. For the MCP-only install path, add Twining instructions to your project's CLAUDE.md so agents use it automatically — see docs/CLAUDE_TEMPLATE.md for a ready-to-copy template.
Dashboard
A web dashboard starts automatically at http://localhost:24282 — browse decisions, blackboard entries, knowledge graph, and agent state. Configurable via TWINING_DASHBOARD_PORT.
What's Inside
Core Tools (always available)
These are the tools agents use in every session:
Tool | What It Does |
| Gate 1: Build tailored context for a task — decisions, warnings, handoffs, within a token budget |
| Gate 2: Record what you did and any choices made — natural language in, structured decisions out |
| Share findings, warnings, needs, or status during work |
| Check what decisions constrain a file before modifying it |
| Periodic maintenance — archive, deduplicate, surface stale decisions (dry-run by default). Optional |
| Archive caller-confirmed candidate IDs from staleness or merge-sweep review. Decisions move to |
twining_record accepts natural language decisions like "Chose Redis over Memcached — need persistence" and automatically parses them into structured records with rationale, rejected alternatives, and inferred domain. It also accepts assumptions, constraints, affected files, and dependency chains — everything the decision store needs for high-fidelity context assembly.
Extended Tools (available with full_surface: true)
For advanced workflows — deep decision management, graph exploration, multi-agent coordination:
Category | Tools |
Decisions |
|
Blackboard |
|
Context |
|
Graph |
|
Coordination |
|
Lifecycle |
|
Enable with .twining/config.yml:
tools:
full_surface: trueHow It Works
All state lives in .twining/ as plain files — JSONL for the blackboard, JSON for decisions, graph, agents, and handoffs. Everything is jq-queryable, grep-able, and git-diffable. No database. No cloud. No accounts.
Architecture layers:
Storage — File-backed stores with locking for concurrent access
Engine — Decision tracking, blackboard, graph traversal, context assembly with token budgeting, agent coordination
Embeddings — Local all-MiniLM-L6-v2 via
@huggingface/transformers, lazy-loaded, with keyword fallback. The server never fails to start because of embedding issues.Dashboard — Read-only web UI with cytoscape.js graph visualization and vis-timeline
Tools — MCP tool definitions validated with Zod, mapping 1:1 to the tool surface
See TWINING-DESIGN-SPEC.md for the full specification.
FAQ
Does Twining slow down Claude Code? No. It's a local MCP server — tool calls are local file reads/writes. Semantic search loads lazily on first use.
Can I use it with Cursor, Windsurf, or other MCP clients? Yes. Twining is a standard MCP server. Any MCP host can connect to it.
Where does my data go?
All coordination state is local in .twining/. Tool call metrics are stored locally in .twining/metrics.jsonl (gitignored). Optional anonymous telemetry can be enabled — see Analytics below.
Is Twining an agent orchestrator? No. It's a coordination state layer. It captures what agents decided and why, and makes that knowledge available to future agents. Use it alongside orchestrators, agent teams, or standalone sessions.
Analytics
Twining includes a three-layer analytics system to help you understand the value it provides.
Insights Dashboard Tab
The web dashboard includes an Insights tab showing:
Value Metrics — Blind decision prevention rate, warning acknowledgment, test coverage via
tested_bygraph relations, commit traceability, decision lifecycle, knowledge graph stats, and agent coordination metricsTool Usage — Call counts, error rates, average/P95 latency per tool
Error Breakdown — Errors grouped by tool and error code
All value metrics are computed from existing .twining/ data — no new data collection needed.
Tool Call Metrics
Every MCP tool call is automatically instrumented with timing and success/error tracking. Metrics are stored locally in .twining/metrics.jsonl (gitignored — operational data, not architectural).
To disable local metrics collection, set in .twining/config.yml:
analytics:
metrics:
enabled: falseOpt-in Telemetry
Anonymous aggregate usage data can optionally be sent to PostHog to help improve Twining. Disabled by default. To enable, add to .twining/config.yml:
analytics:
telemetry:
enabled: trueThat's it — the PostHog project key is built into the source code. If you run your own PostHog instance, you can override with posthog_api_key and posthog_host.
What is sent: tool names, call durations, success/failure booleans, server version, OS, architecture.
What is never sent: file paths, decision content, agent names, error messages, tool arguments, environment variables.
Privacy safeguards:
DO_NOT_TRACK=1environment variable always overrides configCI=trueauto-disables telemetryIdentity is a SHA-256 hash of hostname + project root (never raw paths)
Network failures are silent — no retries
posthog-nodeis an optional dependency — graceful no-op if not installed
Development
npm install # Install dependencies
npm run build # Build
npm test # Run tests (800+ tests)
npm run test:watchRequires Node.js >= 18.
CI/CD
Two GitHub Actions workflows automate build verification and publishing:
CI (.github/workflows/ci.yml) — runs on every PR and push to main:
Builds and tests across Node 18, 20, and 22
Cancels in-progress runs when a new push arrives on the same branch
Publish (.github/workflows/publish.yml) — runs on v* tag push:
Builds with
POSTHOG_API_KEYbaked in for published packagesRuns the full test suite as defense-in-depth
Publishes to npm with
--provenancefor supply chain attestationCreates a GitHub Release with auto-generated release notes
Supports manual trigger via
workflow_dispatchwith a dry-run option
To publish a new version:
npm version patch # or minor, major
git push && git push --tagsRequired secrets (configured in GitHub repo Settings > Secrets):
Secret | Purpose |
| npm access token (granular, scoped to |
| PostHog ingest key for published packages |
License
Available Tools
15 toolstwining_add_entityA
Add or update a knowledge graph entity. Uses upsert semantics: if an entity with the same name and type exists, its properties are merged and updated. Returns the entity ID.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Entity name (e.g., class name, file path, concept) | |
| type | Yes | Entity type: "module", "function", "class", "file", "concept", "pattern", "dependency", "api_endpoint" | |
| properties | No | Key-value properties for this entity (max 50 entries, values ≤1000 chars) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description carries full burden. Discloses upsert semantics and property merging, but does not elaborate on merge behavior (e.g., overwrite vs additive) or any side effects. No contradictions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with action and key semantics. No filler words, every sentence adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Provides core behavior and return value. Lacks details on error conditions or output structure, but schema descriptions and clear semantics compensate. Suitable for upsert operation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Input schema covers all parameters with descriptions (100% coverage). Description adds context that name+type form the identity for upsert, providing extra value beyond schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states it adds or updates a knowledge graph entity with upsert semantics, distinguishing it from sibling tools like 'twining_add_relation' which adds relationships. Returns entity ID.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Implies usage through description ('Add or update entity') but does not explicitly mention when to use vs alternatives like 'twining_add_relation' or 'twining_graph_query'. No when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
twining_add_relationA
Add a relation between two knowledge graph entities. Source and target can be entity IDs or names. Returns an error for ambiguous name matches. Upsert semantics: re-adding the same (source, target, type) merges properties instead of duplicating the edge. Relations are provenance-marked: agent-typed edges get properties.origin "declared", auto-populated edges "derived", absent means legacy/unknown.
| Name | Required | Description | Default |
|---|---|---|---|
| type | Yes | Relation type: "depends_on", "implements", "decided_by", "affects", "tested_by", "calls", "imports", "related_to" | |
| source | Yes | Source entity ID or name | |
| target | Yes | Target entity ID or name | |
| properties | No | Key-value properties for this relation (max 50 entries, values ≤1000 chars) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It discloses upsert semantics (merging properties on re-add), provenance marking behavior (origin values), and error handling for ambiguous names. This is rich, useful behavioral transparency beyond the basic 'adds a relation'.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is efficient—four sentences, each adding critical information. It is front-loaded with the main purpose and then covers edge cases and behavior. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has no output schema and no annotations, the description covers input flexibility, error conditions, upsert semantics, and provenance. It does not explicitly describe the return value or side effects beyond property merging, but for a mutation tool this is sufficient and above the minimum viable bar.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents all parameters. The description adds extra meaning by explaining source/target can be IDs or names (already in schema), but focuses on upsert and provenance properties, which are not in the schema. This adds value beyond schema, justifying a 4 rather than baseline 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with 'Add a relation between two knowledge graph entities', a specific verb+resource+action. This clearly distinguishes it from sibling tools like twining_add_entity, which adds entities rather than relations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides clear context on when to use the tool (when adding a relation) and how to specify source/target (IDs or names). It also warns about ambiguous name matches, which acts as a usage caution. However, it does not explicitly contrast with alternatives or state when not to use it, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
twining_archiveA
Archive old blackboard entries. Moves entries older than a cutoff timestamp to an archive file, preserving decision entries and unresolved need/warning/question entries (#40 — an item counts as resolved when explicitly resolved via twining_resolve or when a later entry references it via relates_to). Optionally posts a summary finding. WARNING: the cutoff defaults to now, so an argument-free call archives everything archivable — pass before or retain unless a full sweep is intended.
| Name | Required | Description | Default |
|---|---|---|---|
| before | No | ISO timestamp cutoff — archive entries before this time (default: now) | |
| retain | No | Keep the newest N archivable entries on the board regardless of age (D4 count-based retention — an age cutoff cannot bound a same-hour burst). Default 0 = no retention. | |
| summarize | No | Whether to post a summary finding after archiving (default: true) | |
| keep_decisions | No | Whether to keep decision entries in the blackboard (default: true) | |
| keep_open_needs_warnings | No | Whether to exempt unresolved need/warning entries from age-based archiving (default: true). Set false to force a full sweep. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden. It discloses preservation of decision entries and unresolved needs/warnings, the definition of resolved (#40), optional summary posting, and the potentially dangerous default cutoff of now. This gives the agent a thorough understanding of side effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences, front-loaded with the core action, and includes an essential WARNING about the default cutoff. Every sentence adds value, no filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Despite having no annotations or output schema, the description covers purpose, side effects, preservation rules, defaults, and cautionary usage. This is sufficient for a mutation tool with nuanced retention logic.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema covers all 5 parameters with descriptions, so baseline is 3. The description adds valuable context about defaults (cutoff now, retain N), which entries are exempt, and how resolved status is determined, enhancing understanding beyond raw schema definitions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool archives old blackboard entries and explains the mechanism (moves entries older than a cutoff to an archive file). However, it does not explicitly differentiate from sibling tool twining_archive_stale, which may have overlapping functionality.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides clear context including the cutoff default of now and advice to pass `before` or `retain` unless a full sweep is intended. It also explains what entries are preserved. It does not mention when to prefer this tool over alternatives or provide explicit when-not-to-use conditions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
twining_archive_staleA
Archive a list of stale items by ID — typically the candidate IDs returned by twining_housekeeping with staleness_review: true. Decisions move to status "archived" (excluded from assemble/why; reversible via twining_unarchive). Blackboard entries are DELETED from the live board, with a tombstone (full entry + reason) appended to .twining/archive/ — twining_unarchive does NOT restore them.
| Name | Required | Description | Default |
|---|---|---|---|
| ids | Yes | IDs to archive (mix of decision and blackboard IDs) | |
| reason | No | Optional rationale for the archive — recorded as a finding for the audit trail | |
| reasons | No | Optional per-item rationale keyed by ID — recorded per item in the audit-trail finding so a future reviewer can spot bad calls (#16, semantic review) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description thoroughly discloses side effects: decisions move to status 'archived' and are excluded from assemble/why, and blackboard entries are DELETED with a tombstone. It explicitly states that twining_unarchive does NOT restore blackboard entries, which is a critical irreversible behavior. With no annotations, this description fully carries the burden.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences and packs a lot of information, but it's well-structured with dashes and semicolons. It front-loads the main purpose and follows with behavioral details. It's slightly dense but not overly verbose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema and no annotations, the description covers the key aspects: what it does, when to use it, and the different consequences for decisions and blackboard entries. It explains reversibility and irreversibility, and the tombstone behavior. The reason parameters are described in the schema, so this is sufficient for the tool's complexity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already provides 100% coverage for all three parameters, with detailed descriptions for reason and reasons. The description adds little beyond 'by ID' and the mention of reason in the tombstone context. Per the rubric, baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it archives a list of stale items by ID, using a specific verb and resource. It distinguishes itself from siblings by referencing twining_housekeeping and explaining distinct handling for decisions vs blackboard entries. The explicit mention of exclusion from assemble/why and the reversible/unreversible nature adds clarity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides a clear when-to-use by indicating 'typically the candidate IDs returned by twining_housekeeping with staleness_review: true'. It also gives context on reversibility and irreversibility for different item types, but it doesn't explicitly list when-not-to-use or name alternative archive tools like twining_archive. This is clear context but lacks explicit exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
twining_assembleA
Your FIRST call every session. Returns a briefing with decisions to respect, warnings to address, and handoff context from previous agents. Call BEFORE reading code or making changes. token_estimate ≈ max_tokens is the signature of budget truncation: the briefing (and decisions_count) was clipped — re-call with a larger max_tokens (e.g. 100000) for complete coverage. decisions_count is the briefing selection, not a scope census; use twining_why total_in_scope for populations.
| Name | Required | Description | Default |
|---|---|---|---|
| task | Yes | Description of what the agent is about to do | |
| scope | Yes | File path, module, or area of codebase (e.g., "src/auth/" or "project") | |
| agent_id | No | Agent identifier for assembly tracking (default: main) | |
| max_tokens | No | Token budget (default: from config, typically 4000) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full burden. It discloses that the briefing may be truncated when token_estimate ≈ max_tokens, explains the meaning of decisions_count, and clarifies that the briefing content is not a scope census. These are important behavioral traits that help the agent interpret the output correctly.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is somewhat wordy but each sentence serves a purpose: purpose, usage, truncation behavior, and clarification of a field. It is front-loaded with the most critical information (when to call). The structure could be tighter, but it is not excessively verbose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given that there is no output schema, the description explains the return value (briefing with decisions, warnings, handoff context) and mentions key fields like token_estimate and decisions_count. It also provides context on truncation and alternatives, making it reasonably complete. However, it does not fully specify the exact structure of the briefing, so a 5 is not warranted.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already provides clear descriptions for all parameters (task, scope, agent_id, max_tokens) with 100% coverage. The tool description adds no additional meaning to these parameters; it only references max_tokens in the context of truncation, which does not enhance parameter understanding.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: returning a briefing with decisions, warnings, and handoff context. It also specifies when to call it ('FIRST call every session'), which distinguishes it from other tools. However, the purpose is slightly buried under additional behavioral notes, so it doesn't earn a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit usage instructions are provided: 'Call BEFORE reading code or making changes' and 'Your FIRST call every session.' It also mentions an alternative tool ('use twining_why total_in_scope for populations'), making the when-to-use and when-not-to-use clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
twining_graph_queryA
Search the knowledge graph for entities by name or property substring match. Case-insensitive. Returns matching entities with their properties.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum results to return (default: 10) | |
| query | Yes | Substring to search for in entity names and properties | |
| entity_types | No | Filter to only these entity types |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description discloses case-insensitivity and return content but lacks details on pagination, authentication, or edge cases. Adequate but not rich.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences: one for purpose, one for feature. No redundant information, highly efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description explains return format briefly. Sufficient for a simple search tool but could specify result ordering or count.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the description adds little beyond what is already in the schema. It clarifies query parameter usage but does not enhance understanding of entity_types or limit.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool searches the knowledge graph for entities by substring match, with case-insensitivity. It distinguishes from sibling tools like twining_add_entity and twining_neighbors.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for text-based search but does not explicitly state when to use this tool vs alternatives like twining_neighbors. No when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
twining_housekeepingA
Run periodic maintenance on Twining stores. Preview by default (dry run); preview simulates the full pass pipeline, so its counts match what execute will do on the same state (#39). Removes duplicates, surfaces stale decisions and dangling warnings, prunes orphaned graph entities, rotates old metrics, and backfills missing superseded_by back-links on superseded decisions. The blackboard archive pass is OPT-IN (archive: true): it sweeps every archivable entry regardless of age, keeping decisions, unresolved need/warning/question entries (#40), and the newest archive.retain_recent entries (D4). Pass staleness_review: true to also flag entries whose scope/files/branch are gone. Pass execute: true to apply changes.
| Name | Required | Description | Default |
|---|---|---|---|
| archive | No | Defaults to FALSE (D4) — housekeeping no longer sweeps the board as a side effect; repairs like compact_archives can run with execute: true safely. Set archive: true to run the blackboard archive pass: it takes no age cutoff, archiving every archivable entry except decisions, unresolved need/warning/question entries, and the newest archive.retain_recent entries (default 200). | |
| execute | No | Set to true to apply changes. Default is false (preview only). | |
| stale_days | No | Flag provisional decisions older than this many days (default: 7) | |
| merge_sweep | No | Set to true to detect branches deleted since the last housekeeping run (typically post-merge cleanup) and flag entries provenance-stamped with those branches. First call records the initial branch snapshot and returns no candidates. The branch snapshot is advanced only when execute=true; preview passes leave the baseline untouched so deletions stay visible across multiple previews. Returns candidates only; use twining_archive_stale to act on them. When run alongside staleness_review, branch-gone duplicates are removed from staleness_review (merge_sweep is the more specific signal). | |
| repair_index | No | Files backend only: detect decision files on disk that are missing from decisions/index.json (index desync — such decisions are invisible to every read path). Preview reports orphan ids; with execute: true, orphans that are recognizably decisions (id matches filename, core fields present) are appended to the index under the index lock; anything else counts in skipped_invalid and is never modified or deleted. This pass runs last, so other housekeeping passes see salvaged decisions on the NEXT call, not this one. On the sqlite backend this reports index_repair_error instead of silently succeeding. | |
| dedup_relations | No | Dedup legacy duplicate (source, target, type) graph relations left from before the 2.11 upsert. Survivor is the edge live upserts already merge into (seq-first; the created-at-oldest on the file backend); later duplicates fold their properties in under origin precedence (derived never downgrades declared) and are removed. Duplicates with non-unique ids and groups that fail to fold (e.g. dangling endpoints) are skipped and counted in the report, never silently dropped. Preview by default; execute applies. | |
| amend_candidates | No | Report candidate affected_files for active decisions whose list is empty (scope walk ranked by term overlap). ALWAYS report-only regardless of execute — confirm per record with twining_amend({decision_id, add_affected_files}). Caps: 50 decisions/run, 500 files/scope, 5 candidates each; truncation is reported, never silent. | |
| compact_archives | No | Set to true to scan .twining/archive/*.jsonl for junk generated by the pre-1.24.0 auto-archive feedback loop ('Archive: N entries archived' summary findings, #35) and report how much is reclaimable. With execute: true, junk lines are dropped (streaming, atomic rewrite), archive files left empty are deleted, and an audit-trail finding is posted. Only entries matching the archiver's exact signature are dropped — everything else, including unparseable lines, is preserved. | |
| staleness_review | No | Set to true to scan blackboard entries and decisions for staleness — flags items whose scope path, affected files, or originating branch no longer exist. Returns candidates only; use twining_archive_stale to act on them. | |
| promote_provisionals | No | Set to true to auto-promote stale provisional decisions to active. Default is false (report only). | |
| repair_entity_scopes | No | Set to true to recompute knowledge-graph entity scopes from their decided_by relations. Before scopes became a union, a decision in one scope overwrote the scope another decision had stamped on the same file — leaving entities asserting a single scope that was merely the most recent. Reports what would change; with execute: true, rewrites them. Safe to run repeatedly. | |
| metrics_retention_days | No | Remove metrics older than this many days (default: 30) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden and succeeds. It discloses that preview is a full dry-run simulation whose counts match execute, that the blackboard archive pass is opt-in and ignores age, and that execute:true is required to apply changes. This gives an agent a clear and honest safety model for a multi-pass maintenance tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the preview/execute safety model, then gives a compact summary of passes, then adds opt-in flags. At roughly 200 words for a 12-parameter tool, it is dense but appropriate; a little redundancy with the parameter schema prevents a perfect score.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex, mutation-capable tool with 12 parameters and no output schema, the description is complete enough: it explains the default safe mode, how to opt into destructive passes, and what the preview simulates. The highly detailed parameter schemas fill in per-pass semantics, and the sibling references for acting on candidates cover the main workflow handoffs.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and each parameter already has a rich, behavior-focused description (e.g., merge_sweep baseline semantics, repair_index backend differences, compact_archives audit-trail behavior). The top-level description adds only a few parameter pointers like archive:true and staleness_review:true, so it does not elevate meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the job ('Run periodic maintenance on Twining stores') and enumerates concrete passes: removing duplicates, surfacing stale decisions, pruning orphaned graph entities, rotating metrics, and backfilling back-links. This distinguishes it from focused siblings like twining_prune_graph or twining_archive_stale, though it does not explicitly name those alternatives.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives actionable invocation rules: preview by default, use execute:true to apply changes, set archive:true for the blackboard pass, and set staleness_review:true for broader staleness detection. The parameter descriptions further point to twining_archive_stale for acting on candidates, which provides explicit alternative routing for some passes, though not for every sibling overlap.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
twining_neighborsA
Traverse the knowledge graph from an entity, returning neighbors up to a given depth (max 3). Supports filtering by relation type. Useful for understanding how entities connect.
| Name | Required | Description | Default |
|---|---|---|---|
| depth | No | Traversal depth (1-3, default: 1) | |
| entity | Yes | Entity ID or name to start traversal from | |
| relation_types | No | Filter to only these relation types |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description must fully disclose behavior. It mentions depth limit and filtering, which is helpful, but it does not state whether the tool is read-only, if it returns directed edges, or any performance implications. The description is adequate but lacks depth.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise: two sentences with no unnecessary words. It front-loads the core functionality and then adds a use case. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has three parameters and no output schema, the description explains traversal and filtering but does not describe the return format (e.g., list of entities or edges) or any default behavior beyond depth. It is adequate for a simple tool but could be more complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 100% description coverage, so the schema already explains each parameter. The description adds minimal value by stating 'max 3' for depth (already in schema) and 'filtering by relation type' (already in schema). Baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool traverses neighbors from an entity with a depth limit and supports filtering. It uses a specific verb 'traverse' and resource 'neighbors', but does not explicitly differentiate from the sibling tool 'twining_graph_query' which might also do graph traversal.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description notes it is 'useful for understanding how entities connect', which implies a use case. However, it does not provide explicit guidance on when to use this tool over alternatives (e.g., twining_graph_query) nor any exclusions or prerequisites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
twining_postB
Share a finding, warning, need, or status update with other agents. Post a 'status' entry before ending each session. Does NOT accept entry_type 'decision' — use twining_decide instead.
| Name | Required | Description | Default |
|---|---|---|---|
| tags | No | Domain tags for filtering | |
| scope | No | File path, module name, or "project" | |
| detail | No | Full context and details | |
| summary | Yes | One-line summary (max 200 chars). Lead with the most important information — it carries the most weight in similarity search. | |
| agent_id | No | Identifier for the posting agent | |
| entry_type | Yes | Type of blackboard entry | |
| relates_to | No | IDs of related entries. Back-referencing an open need/question/warning marks it resolved out of the open triage lane (e.g. an answer posted with relates_to: [question_id]). For an explicit, durable resolution prefer twining_resolve. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description must fully disclose behavioral traits. It only states that entries are shared with other agents, but omits important behaviors like the side effect of back-referencing via relates_to (resolving open items) or the distinction from twining_resolve. The description adds minimal behavioral context beyond the basic action.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three concise sentences, each earning its place: purpose, usage guideline, and exclusion. It is front-loaded and easy to parse. However, the exclusion sentence conflicts with the schema, slightly undermining its structural effectiveness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With 7 parameters and no output schema, the description should provide more orientation about side effects, related sibling tools, and when to use this tool over alternatives. It only addresses the 'decision' exclusion, omitting the important resolution behavior of relates_to and the differentiation from tools like twining_status or twining_resolve.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so a baseline of 3 would typically apply. However, the description directly contradicts the schema by claiming that entry_type 'decision' is not accepted, while the schema's enum explicitly includes 'decision'. This is a serious contradiction that misleads the agent about valid parameter values, providing no useful semantic addition.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Share a finding, warning, need, or status update with other agents.' It uses a specific verb (share) and resource (entry types), and differentiates from siblings by explicitly noting it does not accept 'decision' entries and points to twining_decide instead.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit usage guidance: 'Post a status entry before ending each session' and 'Does NOT accept entry_type decision — use twining_decide instead.' This includes both when to use and when not to use, with a clear alternative, satisfying the highest bar for this dimension.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
twining_prune_graphA
Remove orphaned knowledge graph entities that have no relations. Use this to clean up stale or disconnected entities. Optionally filter by entity type to only prune certain kinds.
| Name | Required | Description | Default |
|---|---|---|---|
| dry_run | No | If true, report orphans without removing them (default: false) | |
| entity_types | No | Only prune orphans of these types (e.g., ["concept", "file"]). If omitted, prunes all orphan types. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It explains that the tool removes orphans and discloses the dry_run behavior for safe reporting. It does not cover potential side effects, permissions, or what happens if no orphans exist, but for a simple prune operation it is reasonably transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences and a brief note about optional filtering; every word earns its place. The description is front-loaded with the core purpose and is highly efficient with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema is provided, and the description does not explain what the tool returns (e.g., list of removed IDs, count). It also does not differentiate from sibling tools like twining_archive_stale or twining_housekeeping, which may overlap in functionality.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the description adds minimal new meaning beyond the schema descriptions. It restates 'only prune orphans of these types' for entity_types and 'report orphans without removing them' for dry_run, which adds slight clarity but does not significantly enrich the schema information.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('remove') and the resource ('orphaned knowledge graph entities') with an explicit definition of orphaned (no relations). It distinguishes this tool from sibling operations like twining_add_entity or twining_neighbors by focusing on cleanup of stale, disconnected entries.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly says 'Use this to clean up stale or disconnected entities' and mentions optional filtering. However, it does not specify when NOT to use (e.g., if you need to archive or delete specific entities) or mention alternatives like twining_archive_stale or twining_housekeeping.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
twining_recordA
Record what you did, any choices you made, and anything you discovered. Call before committing or ending a session. The summary becomes a status post. Decisions become tracked records with rationale. Findings become blackboard entries visible to future agents. Scope is auto-inferred from git diff if omitted.
| Name | Required | Description | Default |
|---|---|---|---|
| scope | No | Area of codebase affected. Auto-inferred from git diff if omitted. | |
| summary | Yes | What you did this session — one or two sentences. Kept to 200 characters — longer text is truncated with the full text preserved in the entry detail. Lead with the most important information: similarity search weighs the opening of the text most heavily. | |
| agent_id | No | Agent identifier (default: main) | |
| findings | No | Discoveries, warnings, needs, and surprises — anything the next session would want to know that is not visible from the diff: odd patterns you noticed, fragile spots, dead ends you ruled out, things that did not work as expected. Prefix with "warning:" or "need:" for severity. E.g. ["Auth tokens stored in localStorage — fails SOC2", "warning: No token rotation exists", "need: Add rate limiting before launch"]. A substantial change with zero findings is usually under-recording, not a clean run. Lead each finding with the most important information — the first ~200 characters carry the most weight in similarity search. | |
| resolves | No | Blackboard entry IDs (needs/questions/warnings from twining_assemble or twining_triage) that this session's work handled — they are marked resolved and leave the open lane, and the status post back-references them | |
| decisions | No | Choices you made. Each item is either a natural-language sentence ("Chose X over Y — reason") or a structured object ({ summary, rationale, alternatives: [{ option, reason_rejected }] }) when the content is too long or too structured for the NL parser to split cleanly. | |
| depends_on | No | IDs of prior decisions that your decisions depend on (from twining_assemble or twining_why output) | |
| reversible | No | Whether your decisions are easily reversible (default: true) | |
| supersedes | No | ID of a prior decision that your work replaces or invalidates. Requires exactly ONE decision in this call — with multiple decisions the superseding record is ambiguous, so the supersession is SKIPPED and reported (supersedes_skipped). A target id that does not exist is also reported (supersedes_dangling), not silently ignored. | |
| assumptions | No | Conditions your decisions depend on. E.g. ["Data is relational", "No strict ordering required"] | |
| commit_hash | No | Git commit hash to associate with these decisions | |
| constraints | No | What limited your options. E.g. ["Must support Node 18+", "Cannot add new dependencies"] | |
| affected_files | No | File paths you changed or that are affected by your decisions | |
| affected_symbols | No | Function/class/method names affected by your decisions |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full disclosure burden and does so well: it reveals persistent side effects ('summary becomes a status post', 'findings become blackboard entries visible to future agents') and the auto-inference behavior ('Scope is auto-inferred from git diff if omitted'). Supplementary schema text adds truncation and similarity-weighting behavior. It does not explicitly flag that this is a mutating write operation, but the creation language makes that evident.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact — five short sentences that front-load the action, then give timing, then enumerate the three output side effects, then the auto-inference note. No filler or redundant phrasing. It loses one point only because the schema descriptions that follow are verbose, though that is schema, not description, territory.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity (14 parameters) and the absence of both annotations and an output schema, the description covers the core purpose, timing, and side effects but omits success/return behavior — the agent is not told what comes back on completion (e.g., entry IDs or confirmation). For a workflow tool of this complexity, a note on return or error semantics would round it out, though the main record flow is well established.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema itself documents all 14 parameters richly (truncation rules, warning/need prefixes, decision structure, supersedes constraints). The description adds only 'Scope is auto-inferred from git diff if omitted,' which duplicates the schema's own scope text. Per the rubric, high coverage yields a baseline 3, and the description contributes little unique parameter meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+resource: 'Record what you did, any choices you made, and anything you discovered.' It then spells out the distinct outputs ('The summary becomes a status post. Decisions become tracked records with rationale. Findings become blackboard entries visible to future agents'), which clearly differentiates this session-logging tool from siblings like twining_post, twining_status, and twining_assemble.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit timing guidance ('Call before committing or ending a session') that tells the agent when to invoke this tool. It does not name sibling alternatives or state exclusions, but the workflow role is clear enough that an agent can infer when twining_record applies versus querying (twining_why, twining_graph_query) or maintenance (twining_housekeeping) tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
twining_resolveA
Mark open blackboard items (needs, questions, warnings) as handled. Persists status "resolved" with resolver identity and an optional note; the entry leaves the open triage/assemble lane but stays on the board as searchable history. This is the everyday exit for open items — use twining_dismiss only for noise that should never have been recorded.
| Name | Required | Description | Default |
|---|---|---|---|
| ids | Yes | Entry IDs to mark resolved | |
| note | No | How the item was handled — stored as resolution_note | |
| agent_id | No | Identifier for the resolving agent |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully carries behavioral disclosure. It states that the tool persists a 'resolved' status with resolver identity and an optional note, that the entry leaves the open triage/assemble lane, and that it remains as searchable history. This clearly communicates side effects and outcomes.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no filler. It front-loads the core action and then provides valuable usage context and a distinction from a sibling tool. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity, no output schema, and no annotations, the description covers purpose, usage, behavior, and retention. It could mention return values or error conditions, but these are not essential for this straightforward resolution action. The description is sufficient for an agent to select and invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all three parameters. The description adds no incremental parameter-specific detail beyond what the schema provides; it only paraphrases the 'resolver identity' and 'optional note' aspects already covered.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('mark') and resource ('open blackboard items'), enumerates item types (needs, questions, warnings), and clearly distinguishes itself from twining_dismiss. The phrase 'everyday exit for open items' reinforces the tool's role.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use this tool and contrasts it with an alternative: 'This is the everyday exit for open items — use twining_dismiss only for noise that should never have been recorded.' This provides clear contextual guidance relative to siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
twining_statusA
Overall health check of the Twining state. Shows blackboard entry count, decision counts, graph entity/relation counts, actionable warnings, the server_version and resolved storage backend, and a human-readable summary. provisional_decisions is the canonical ratify-queue count — a direct index count no query can distort (scoped variant: twining_triage counts.open.by_kind.decision). Note: twining_assemble now includes a status summary — use this only when you need the full detailed health check.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It discloses that it shows counts, warnings, server_version, and storage backend, and clarifies that provisional_decisions is a canonical index count. It does not explicitly state it is read-only or side-effect-free, but the content strongly implies a read-only health check. Since it does not mention any mutating behavior, the absence of explicit safety disclosure is acceptable but not perfect.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences and front-loads the purpose. It packs specific details (counts, warnings, server_version, storage backend) without verbosity. The note about twining_assemble is relevant and adds value. It is not overly long and each sentence earns its place, though it could be slightly tightened by removing the parenthetical scoped variant detail.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a no-parameter, no-output-schema tool, the description thoroughly covers what the tool returns, including a human-readable summary and specific metrics. It also explains an important distinction (canonical count) and provides guidance on when to use it relative to siblings. This is complete for a health check tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the baseline is 4. The schema coverage is 100% (vacuously). The description adds meaningful context about exact outputs and the canonical nature of provisional_decisions, which is helpful even though there are no parameters to explain.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it is an 'Overall health check of the Twining state' and lists specific outputs (blackboard entry count, decision counts, graph counts, warnings, server_version, storage backend, summary). It also distinguishes from sibling twining_assemble by noting that twining_assemble includes a status summary and that this tool should be used when 'full detailed health check' is needed, thus differentiating the purpose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit usage guidance: 'use this only when you need the full detailed health check' and contrasts with twining_assemble which includes a status summary. It also mentions a scoped variant (twining_triage counts.open.by_kind.decision) for a narrower query, giving clear context on when to use this tool versus alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
twining_unarchiveA
Restore archived decisions — the undo for twining_archive_stale. Each decision returns to its PRE-ARCHIVE status (archived_from): a provisional goes back to the ratification queue, a superseded decision stays retired, and only previously-active decisions become authoritative again. Records archived by a pre-2.7 server carry no archived_from marker — those restore to "active" as an ASSUMPTION, reported per-id in assumed_active and via a warning post (if one was provisional, that restore ratified it; re-check with twining_reconsider). Archived decisions are excluded from assemble/why (assemble reports them as archived_excluded_count). Only decisions currently in status "archived" are restored; other IDs are reported back untouched.
| Name | Required | Description | Default |
|---|---|---|---|
| ids | Yes | Decision IDs to restore to their pre-archive status | |
| reason | No | Why these decisions are being restored — recorded in the audit-trail finding |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully owns behavioral disclosure. It details exactly what happens per status (provisional→ratification queue, superseded→stays retired, previously-active→authoritative). It discloses the pre-2.7 assumption (assumed_active) and the side effect on assemble/why exclusion. This is comprehensive transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single well-structured paragraph that is information-dense yet concise. It front-loads the main purpose, then details status-specific behaviors and caveats. No redundant sentences; every clause carries necessary information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (varying behaviors by archived_from, pre-2.7 edge cases, interaction with assemble/why), the description covers all critical aspects: restoration nuances, assumption handling, reporting (assumed_active, warning post), and exclusion counts. It even flags a follow-up action (twining_reconsider) when needed. No output schema exists, but the description hints at response contents (assumed_active). This is thorough.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with descriptions for both ids and reason. The description adds context about how ids map to behavior (e.g., only archived ones restored) and how reason is recorded, but these are mostly behavioral details rather than parameter semantics. Baseline 3 is appropriate; the description adds some value beyond schema but doesn't radically enhance parameter understanding.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+object: 'Restore archived decisions' and explicitly positions it as 'the undo for twining_archive_stale'. This clearly distinguishes it from sibling tools like twining_archive and twining_archive_stale. The follow-up details about status restoration make the purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly states when to use (restore archived decisions) and nuances: only status='archived' are restored, others reported back untouched. It also directs users to twining_reconsider for pre-2.7 cases, giving an alternative tool. This provides clear context and exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
twining_whyA
Before modifying a file, check what decisions constrain it. Shows rationale and alternatives so you don't contradict prior choices. Results are ranked by relevance and bounded by a token budget; overflow decisions appear as one-liners in more — pass their ids back via ids for full detail.
| Name | Required | Description | Default |
|---|---|---|---|
| ids | No | Return full detail (rationale, context, alternatives) for exactly these decision ids | |
| scope | No | File path, module name, or symbol to query (required unless ids is set) | |
| lineage | No | Resolve each excluded superseded/overridden record's lineage HEAD (walks superseded_by to the current answer). Off by default. | |
| max_tokens | No | Token budget for the full-detail tier (default 4000) | |
| include_superseded | No | Include superseded decisions (excluded by default) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. It discloses several behavioral traits: results are 'ranked by relevance', bounded by a 'token budget', and overflow appears as 'one-liners in `more`' with a mechanism to get full detail via `ids`. It does not mention safety/auth, but the read-only nature is implied by 'check'. It provides useful context beyond the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences, front-loaded with the primary use case ('Before modifying a file, check what decisions constrain it'). It packs pagination, ranking, and token budget details into a compact, readable format, with every sentence contributing meaningful information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has 5 parameters, no output schema, and no annotations. The description explains the core workflow, ranking, overflow handling, and id-based expansion. It does not fully describe the response structure or edge cases (e.g., no decisions found), but for a query tool this is adequate. The absence of an output schema makes some return-value explanation expected, and the description gives a reasonable overview.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so baseline is 3. The description adds value by explaining the `ids` parameter in the context of overflow ('pass their ids back via `ids` for full detail') and implicitly explaining `max_tokens` through the token budget mention. It does not elaborate on `lineage` or `include_superseded`, but those are already well-described in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Before modifying a file, check what decisions constrain it.' It uses a specific verb ('check') and resource ('decisions constraining a file'), and it distinguishes itself from siblings by focusing on querying rationale, not recording or modifying decisions.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit context for when to use the tool: 'Before modifying a file, check what decisions constrain it.' It does not name alternatives or state when not to use it, but the sibling list includes tools like twining_record and twining_assemble, making the query intent clear. Slight deduction for lacking explicit exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
3 tool updates
v2.16.0- Changed
twining_housekeeping2 fields changed- changed
Input schema / properties / dedup_relations / descriptionPrevious value: -"Dedup legacy duplicate (source, target, type) graph relations left from before the 2.11 upsert. Survivor is the oldest edge; later duplicates fold their properties in under origin precedence (derived never downgrades declared) and are removed. Preview by default; execute applies."New value: +"Dedup legacy duplicate (source, target, type) graph relations left from before the 2.11 upsert. Survivor is the edge live upserts already merge into (seq-first; the created-at-oldest on the file backend); later duplicates fold their properties in under origin precedence (derived never downgrades declared) and are removed. Duplicates with non-unique ids and groups that fail to fold (e.g. dangling endpoints) are skipped and counted in the report, never silently dropped. Preview by default; execute applies." - added
Input schema / properties / repair_indexAdded value: +{ + "description": "Files backend only: detect decision files on disk that are missing from decisions/index.json (index desync — such decisions are invisible to every read path). Preview reports orphan ids; with execute: true, orphans that are recognizably decisions (id matches filename, core fields present) are appended to the index under the index lock; anything else counts in skipped_invalid and is never modified or deleted. This pass runs last, so other housekeeping passes see salvaged decisions on the NEXT call, not this one. On the sqlite backend this reports index_repair_error instead of silently succeeding.", + "type": "boolean" +}
- Changed
twining_record1 field changed- changed
Input schema / properties / decisions / items / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "additionalProperties": false, - "properties": { - "affected_files": { - "description": "File paths THIS decision governs (overrides the session-level affected_files for this decision; falls back to it when omitted). Enables scope-based retrieval via twining_why and the drift check.", - "items": { - "type": "string" - }, - "type": "array" - }, - "affected_symbols": { - "description": "Function/class/method names THIS decision governs (overrides the session-level affected_symbols for this decision; falls back to it when omitted)", - "items": { - "type": "string" - }, - "type": "array" - }, - "alternatives": { - "description": "Alternatives that were considered and rejected", - "items": { - "additionalProperties": false, - "properties": { - "cons": { - "items": { - "type": "string" - }, - "type": "array" - }, - "option": { - "type": "string" - }, - "pros": { - "items": { - "type": "string" - }, - "type": "array" - }, - "reason_rejected": { - "type": "string" - } - }, - "required": [ - "option", - "reason_rejected" - ], - "type": "object" - }, - "type": "array" - }, - "assumptions": { - "description": "Assumptions this decision depends on (overrides the session-level assumptions for this decision)", - "items": { - "type": "string" - }, - "type": "array" - }, - "confidence": { - "description": "Confidence level (default: \"medium\")", - "enum": [ - "high", - "medium", - "low" - ], - "type": "string" - }, - "constraints": { - "description": "What limited the options (overrides the session-level constraints for this decision)", - "items": { - "type": "string" - }, - "type": "array" - }, - "context": { - "description": "Situation that prompted this decision (falls back to the session summary)", - "type": "string" - }, - "domain": { - "description": "Decision domain (e.g., \"architecture\", \"implementation\"). Inferred from content when omitted.", - "type": "string" - }, - "rationale": { - "description": "Reasoning for the choice. Skips the NL parser when provided.", - "type": "string" - }, - "status": { - "description": "Initial lifecycle status for THIS decision (default: \"active\"). \"provisional\" records it as awaiting ratification — it sits in the triage open lane until confirmed (twining_promote) or vetoed (twining_override). Requires tools.full_surface: true (the drain tools are full-surface). Cannot be combined with supersedes — the target would be retired before ratification. WARNING: twining_housekeeping with promote_provisionals + execute bulk-promotes provisionals older than 7 days with NO per-item review; leave that flag off if provisional is serving as your ratification queue.", - "enum": [ - "active", - "provisional" - ], - "type": "string" - }, - "summary": { - "description": "One-line decision statement", - "type": "string" - } - }, - "required": [ - "summary" - ], - "type": "object" - } -]New value: +[ + { + "type": "string" + }, + { + "additionalProperties": false, + "properties": { + "affected_files": { + "description": "File paths THIS decision governs (overrides the session-level affected_files for this decision; falls back to it when omitted). Enables scope-based retrieval via twining_why and the drift check.", + "items": { + "type": "string" + }, + "type": "array" + }, + "affected_symbols": { + "description": "Function/class/method names THIS decision governs (overrides the session-level affected_symbols for this decision; falls back to it when omitted)", + "items": { + "type": "string" + }, + "type": "array" + }, + "alternatives": { + "description": "Alternatives that were considered and rejected", + "items": { + "additionalProperties": false, + "properties": { + "cons": { + "items": { + "type": "string" + }, + "type": "array" + }, + "option": { + "type": "string" + }, + "pros": { + "items": { + "type": "string" + }, + "type": "array" + }, + "reason_rejected": { + "type": "string" + } + }, + "required": [ + "option" + ], + "type": "object" + }, + "type": "array" + }, + "assumptions": { + "description": "Assumptions this decision depends on (overrides the session-level assumptions for this decision)", + "items": { + "type": "string" + }, + "type": "array" + }, + "confidence": { + "description": "Confidence level (default: \"medium\")", + "enum": [ + "high", + "medium", + "low" + ], + "type": "string" + }, + "constraints": { + "description": "What limited the options (overrides the session-level constraints for this decision)", + "items": { + "type": "string" + }, + "type": "array" + }, + "context": { + "description": "Situation that prompted this decision (falls back to the session summary)", + "type": "string" + }, + "domain": { + "description": "Decision domain (e.g., \"architecture\", \"implementation\"). Inferred from content when omitted.", + "type": "string" + }, + "rationale": { + "description": "Reasoning for the choice. Skips the NL parser when provided.", + "type": "string" + }, + "status": { + "description": "Initial lifecycle status for THIS decision (default: \"active\"). \"provisional\" records it as awaiting ratification — it sits in the triage open lane until confirmed (twining_promote) or vetoed (twining_override). Requires tools.full_surface: true (the drain tools are full-surface). Cannot be combined with supersedes — the target would be retired before ratification. WARNING: twining_housekeeping with promote_provisionals + execute bulk-promotes provisionals older than 7 days with NO per-item review; leave that flag off if provisional is serving as your ratification queue.", + "enum": [ + "active", + "provisional" + ], + "type": "string" + }, + "summary": { + "description": "One-line decision statement", + "type": "string" + } + }, + "required": [ + "summary" + ], + "type": "object" + } +]
- Changed
twining_unarchive1 field changed- changed
Input schema / properties / ids / descriptionPrevious value: -"Decision IDs to restore to active status"New value: +"Decision IDs to restore to their pre-archive status"
7 tool updates
v2.12.0- Changed
twining_archive1 field changed- added
Input schema / properties / retainAdded value: +{ + "description": "Keep the newest N archivable entries on the board regardless of age (D4 count-based retention — an age cutoff cannot bound a same-hour burst). Default 0 = no retention.", + "minimum": 0, + "type": "integer" +}
- Changed
twining_housekeeping3 fields changed- added
Input schema / properties / amend_candidatesAdded value: +{ + "description": "Report candidate affected_files for active decisions whose list is empty (scope walk ranked by term overlap). ALWAYS report-only regardless of execute — confirm per record with twining_amend({decision_id, add_affected_files}). Caps: 50 decisions/run, 500 files/scope, 5 candidates each; truncation is reported, never silent.", + "type": "boolean" +} - changed
Input schema / properties / archive / descriptionPrevious value: -"Defaults to true. Set to false to skip the blackboard archive pass while still running the other passes. The archive pass takes no cutoff, so with execute: true it archives the ENTIRE live board, not just old entries — pass archive: false when you want a targeted repair (notably compact_archives, which needs execute: true to do real work) without sweeping the board."New value: +"Defaults to FALSE (D4) — housekeeping no longer sweeps the board as a side effect; repairs like compact_archives can run with execute: true safely. Set archive: true to run the blackboard archive pass: it takes no age cutoff, archiving every archivable entry except decisions, unresolved need/warning/question entries, and the newest archive.retain_recent entries (default 200)." - added
Input schema / properties / dedup_relationsAdded value: +{ + "description": "Dedup legacy duplicate (source, target, type) graph relations left from before the 2.11 upsert. Survivor is the oldest edge; later duplicates fold their properties in under origin precedence (derived never downgrades declared) and are removed. Preview by default; execute applies.", + "type": "boolean" +}
- Changed
twining_post1 field changed- changed
Input schema / properties / relates_to / descriptionPrevious value: -"IDs of related entries"New value: +"IDs of related entries. Back-referencing an open need/question/warning marks it resolved out of the open triage lane (e.g. an answer posted with relates_to: [question_id]). For an explicit, durable resolution prefer twining_resolve."
- Changed
twining_record3 fields changed- changed
Input schema / properties / decisions / items / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "additionalProperties": false, - "properties": { - "alternatives": { - "description": "Alternatives that were considered and rejected", - "items": { - "additionalProperties": false, - "properties": { - "cons": { - "items": { - "type": "string" - }, - "type": "array" - }, - "option": { - "type": "string" - }, - "pros": { - "items": { - "type": "string" - }, - "type": "array" - }, - "reason_rejected": { - "type": "string" - } - }, - "required": [ - "option", - "reason_rejected" - ], - "type": "object" - }, - "type": "array" - }, - "assumptions": { - "description": "Assumptions this decision depends on (overrides the session-level assumptions for this decision)", - "items": { - "type": "string" - }, - "type": "array" - }, - "confidence": { - "description": "Confidence level (default: \"medium\")", - "enum": [ - "high", - "medium", - "low" - ], - "type": "string" - }, - "constraints": { - "description": "What limited the options (overrides the session-level constraints for this decision)", - "items": { - "type": "string" - }, - "type": "array" - }, - "context": { - "description": "Situation that prompted this decision (falls back to the session summary)", - "type": "string" - }, - "domain": { - "description": "Decision domain (e.g., \"architecture\", \"implementation\"). Inferred from content when omitted.", - "type": "string" - }, - "rationale": { - "description": "Reasoning for the choice. Skips the NL parser when provided.", - "type": "string" - }, - "status": { - "description": "Initial lifecycle status for THIS decision (default: \"active\"). \"provisional\" records it as awaiting ratification — it sits in the triage open lane until confirmed (twining_promote) or vetoed (twining_override). Requires tools.full_surface: true (the drain tools are full-surface). Cannot be combined with supersedes — the target would be retired before ratification. WARNING: twining_housekeeping with promote_provisionals + execute bulk-promotes provisionals older than 7 days with NO per-item review; leave that flag off if provisional is serving as your ratification queue.", - "enum": [ - "active", - "provisional" - ], - "type": "string" - }, - "summary": { - "description": "One-line decision statement", - "type": "string" - } - }, - "required": [ - "summary" - ], - "type": "object" - } -]New value: +[ + { + "type": "string" + }, + { + "additionalProperties": false, + "properties": { + "affected_files": { + "description": "File paths THIS decision governs (overrides the session-level affected_files for this decision; falls back to it when omitted). Enables scope-based retrieval via twining_why and the drift check.", + "items": { + "type": "string" + }, + "type": "array" + }, + "affected_symbols": { + "description": "Function/class/method names THIS decision governs (overrides the session-level affected_symbols for this decision; falls back to it when omitted)", + "items": { + "type": "string" + }, + "type": "array" + }, + "alternatives": { + "description": "Alternatives that were considered and rejected", + "items": { + "additionalProperties": false, + "properties": { + "cons": { + "items": { + "type": "string" + }, + "type": "array" + }, + "option": { + "type": "string" + }, + "pros": { + "items": { + "type": "string" + }, + "type": "array" + }, + "reason_rejected": { + "type": "string" + } + }, + "required": [ + "option", + "reason_rejected" + ], + "type": "object" + }, + "type": "array" + }, + "assumptions": { + "description": "Assumptions this decision depends on (overrides the session-level assumptions for this decision)", + "items": { + "type": "string" + }, + "type": "array" + }, + "confidence": { + "description": "Confidence level (default: \"medium\")", + "enum": [ + "high", + "medium", + "low" + ], + "type": "string" + }, + "constraints": { + "description": "What limited the options (overrides the session-level constraints for this decision)", + "items": { + "type": "string" + }, + "type": "array" + }, + "context": { + "description": "Situation that prompted this decision (falls back to the session summary)", + "type": "string" + }, + "domain": { + "description": "Decision domain (e.g., \"architecture\", \"implementation\"). Inferred from content when omitted.", + "type": "string" + }, + "rationale": { + "description": "Reasoning for the choice. Skips the NL parser when provided.", + "type": "string" + }, + "status": { + "description": "Initial lifecycle status for THIS decision (default: \"active\"). \"provisional\" records it as awaiting ratification — it sits in the triage open lane until confirmed (twining_promote) or vetoed (twining_override). Requires tools.full_surface: true (the drain tools are full-surface). Cannot be combined with supersedes — the target would be retired before ratification. WARNING: twining_housekeeping with promote_provisionals + execute bulk-promotes provisionals older than 7 days with NO per-item review; leave that flag off if provisional is serving as your ratification queue.", + "enum": [ + "active", + "provisional" + ], + "type": "string" + }, + "summary": { + "description": "One-line decision statement", + "type": "string" + } + }, + "required": [ + "summary" + ], + "type": "object" + } +] - added
Input schema / properties / resolvesAdded value: +{ + "description": "Blackboard entry IDs (needs/questions/warnings from twining_assemble or twining_triage) that this session's work handled — they are marked resolved and leave the open lane, and the status post back-references them", + "items": { + "type": "string" + }, + "type": "array" +} - changed
Input schema / properties / supersedes / descriptionPrevious value: -"ID of a prior decision that your work replaces or invalidates"New value: +"ID of a prior decision that your work replaces or invalidates. Requires exactly ONE decision in this call — with multiple decisions the superseding record is ambiguous, so the supersession is SKIPPED and reported (supersedes_skipped). A target id that does not exist is also reported (supersedes_dangling), not silently ignored."
- Added
twining_resolve - Added
twining_unarchive - Changed
twining_why1 field changed- added
Input schema / properties / lineageAdded value: +{ + "description": "Resolve each excluded superseded/overridden record's lineage HEAD (walks superseded_by to the current answer). Off by default.", + "type": "boolean" +}
1 tool update
v2.6.0- Changed
twining_housekeeping2 fields changed- added
Input schema / properties / archiveAdded value: +{ + "description": "Defaults to true. Set to false to skip the blackboard archive pass while still running the other passes. The archive pass takes no cutoff, so with execute: true it archives the ENTIRE live board, not just old entries — pass archive: false when you want a targeted repair (notably compact_archives, which needs execute: true to do real work) without sweeping the board.", + "type": "boolean" +} - added
Input schema / properties / repair_entity_scopesAdded value: +{ + "description": "Set to true to recompute knowledge-graph entity scopes from their decided_by relations. Before scopes became a union, a decision in one scope overwrote the scope another decision had stamped on the same file — leaving entities asserting a single scope that was merely the most recent. Reports what would change; with execute: true, rewrites them. Safe to run repeatedly.", + "type": "boolean" +}
5 tool updates
v2.5.0- Changed
twining_archive1 field changed- added
Input schema / properties / keep_open_needs_warningsAdded value: +{ + "description": "Whether to exempt unresolved need/warning entries from age-based archiving (default: true). Set false to force a full sweep.", + "type": "boolean" +}
- Changed
twining_archive_stale1 field changed- added
Input schema / properties / reasonsAdded value: +{ + "additionalProperties": { + "type": "string" + }, + "description": "Optional per-item rationale keyed by ID — recorded per item in the audit-trail finding so a future reviewer can spot bad calls (#16, semantic review)", + "type": "object" +}
- Changed
twining_housekeeping1 field changed- added
Input schema / properties / compact_archivesAdded value: +{ + "description": "Set to true to scan .twining/archive/*.jsonl for junk generated by the pre-1.24.0 auto-archive feedback loop ('Archive: N entries archived' summary findings, #35) and report how much is reclaimable. With execute: true, junk lines are dropped (streaming, atomic rewrite), archive files left empty are deleted, and an audit-trail finding is posted. Only entries matching the archiver's exact signature are dropped — everything else, including unparseable lines, is preserved.", + "type": "boolean" +}
- Changed
twining_record1 field changed- changed
Input schema / properties / decisions / items / anyOfPrevious value: -[ - { - "type": "string" - }, - { - "additionalProperties": false, - "properties": { - "alternatives": { - "description": "Alternatives that were considered and rejected", - "items": { - "additionalProperties": false, - "properties": { - "cons": { - "items": { - "type": "string" - }, - "type": "array" - }, - "option": { - "type": "string" - }, - "pros": { - "items": { - "type": "string" - }, - "type": "array" - }, - "reason_rejected": { - "type": "string" - } - }, - "required": [ - "option", - "reason_rejected" - ], - "type": "object" - }, - "type": "array" - }, - "assumptions": { - "description": "Assumptions this decision depends on (overrides the session-level assumptions for this decision)", - "items": { - "type": "string" - }, - "type": "array" - }, - "confidence": { - "description": "Confidence level (default: \"medium\")", - "enum": [ - "high", - "medium", - "low" - ], - "type": "string" - }, - "constraints": { - "description": "What limited the options (overrides the session-level constraints for this decision)", - "items": { - "type": "string" - }, - "type": "array" - }, - "context": { - "description": "Situation that prompted this decision (falls back to the session summary)", - "type": "string" - }, - "domain": { - "description": "Decision domain (e.g., \"architecture\", \"implementation\"). Inferred from content when omitted.", - "type": "string" - }, - "rationale": { - "description": "Reasoning for the choice. Skips the NL parser when provided.", - "type": "string" - }, - "summary": { - "description": "One-line decision statement", - "type": "string" - } - }, - "required": [ - "summary" - ], - "type": "object" - } -]New value: +[ + { + "type": "string" + }, + { + "additionalProperties": false, + "properties": { + "alternatives": { + "description": "Alternatives that were considered and rejected", + "items": { + "additionalProperties": false, + "properties": { + "cons": { + "items": { + "type": "string" + }, + "type": "array" + }, + "option": { + "type": "string" + }, + "pros": { + "items": { + "type": "string" + }, + "type": "array" + }, + "reason_rejected": { + "type": "string" + } + }, + "required": [ + "option", + "reason_rejected" + ], + "type": "object" + }, + "type": "array" + }, + "assumptions": { + "description": "Assumptions this decision depends on (overrides the session-level assumptions for this decision)", + "items": { + "type": "string" + }, + "type": "array" + }, + "confidence": { + "description": "Confidence level (default: \"medium\")", + "enum": [ + "high", + "medium", + "low" + ], + "type": "string" + }, + "constraints": { + "description": "What limited the options (overrides the session-level constraints for this decision)", + "items": { + "type": "string" + }, + "type": "array" + }, + "context": { + "description": "Situation that prompted this decision (falls back to the session summary)", + "type": "string" + }, + "domain": { + "description": "Decision domain (e.g., \"architecture\", \"implementation\"). Inferred from content when omitted.", + "type": "string" + }, + "rationale": { + "description": "Reasoning for the choice. Skips the NL parser when provided.", + "type": "string" + }, + "status": { + "description": "Initial lifecycle status for THIS decision (default: \"active\"). \"provisional\" records it as awaiting ratification — it sits in the triage open lane until confirmed (twining_promote) or vetoed (twining_override). Requires tools.full_surface: true (the drain tools are full-surface). Cannot be combined with supersedes — the target would be retired before ratification. WARNING: twining_housekeeping with promote_provisionals + execute bulk-promotes provisionals older than 7 days with NO per-item review; leave that flag off if provisional is serving as your ratification queue.", + "enum": [ + "active", + "provisional" + ], + "type": "string" + }, + "summary": { + "description": "One-line decision statement", + "type": "string" + } + }, + "required": [ + "summary" + ], + "type": "object" + } +]
- Changed
twining_why5 fields changed- added
Input schema / properties / idsAdded value: +{ + "description": "Return full detail (rationale, context, alternatives) for exactly these decision ids", + "items": { + "type": "string" + }, + "type": "array" +} - added
Input schema / properties / include_supersededAdded value: +{ + "description": "Include superseded decisions (excluded by default)", + "type": "boolean" +} - added
Input schema / properties / max_tokensAdded value: +{ + "description": "Token budget for the full-detail tier (default 4000)", + "type": "number" +} - changed
Input schema / properties / scope / descriptionPrevious value: -"File path, module name, or symbol to query"New value: +"File path, module name, or symbol to query (required unless ids is set)" - removed
Input schema / requiredRemoved value: -[ - "scope" -]
2 tool updates
v1.24.1- Changed
twining_post1 field changed- changed
Input schema / properties / summary / descriptionPrevious value: -"One-line summary (max 200 chars)"New value: +"One-line summary (max 200 chars). Lead with the most important information — it carries the most weight in similarity search."
- Changed
twining_record2 fields changed- changed
Input schema / properties / findings / descriptionPrevious value: -"Discoveries, warnings, or needs. Prefix with \"warning:\" or \"need:\" for severity. E.g. [\"Auth tokens stored in localStorage — fails SOC2\", \"warning: No token rotation exists\", \"need: Add rate limiting before launch\"]"New value: +"Discoveries, warnings, needs, and surprises — anything the next session would want to know that is not visible from the diff: odd patterns you noticed, fragile spots, dead ends you ruled out, things that did not work as expected. Prefix with \"warning:\" or \"need:\" for severity. E.g. [\"Auth tokens stored in localStorage — fails SOC2\", \"warning: No token rotation exists\", \"need: Add rate limiting before launch\"]. A substantial change with zero findings is usually under-recording, not a clean run. Lead each finding with the most important information — the first ~200 characters carry the most weight in similarity search." - changed
Input schema / properties / summary / descriptionPrevious value: -"What you did this session — one or two sentences"New value: +"What you did this session — one or two sentences. Kept to 200 characters — longer text is truncated with the full text preserved in the entry detail. Lead with the most important information: similarity search weighs the opening of the text most heavily."
25 tool updates
v1.20.0- Removed
twining_acknowledge - Removed
twining_agents - Added
twining_archive_stale - Removed
twining_commits - Removed
twining_decide - Removed
twining_delegate - Removed
twining_discover - Removed
twining_dismiss - Removed
twining_export - Removed
twining_handoff - Added
twining_housekeeping - Removed
twining_link_commit - Removed
twining_override - Removed
twining_promote - Removed
twining_query - Removed
twining_read - Removed
twining_recent - Removed
twining_reconsider - Added
twining_record - Removed
twining_register - Removed
twining_search_decisions - Removed
twining_summarize - Removed
twining_trace - Removed
twining_verify - Removed
twining_what_changed
32 tool updates
v1.9.0- First observed
twining_acknowledge - First observed
twining_add_entity - First observed
twining_add_relation - First observed
twining_agents - First observed
twining_archive - First observed
twining_assemble - First observed
twining_commits - First observed
twining_decide - First observed
twining_delegate - First observed
twining_discover - First observed
twining_dismiss - First observed
twining_export - First observed
twining_graph_query - First observed
twining_handoff - First observed
twining_link_commit - First observed
twining_neighbors - First observed
twining_override - First observed
twining_post - First observed
twining_promote - First observed
twining_prune_graph - First observed
twining_query - First observed
twining_read - First observed
twining_recent - First observed
twining_reconsider - First observed
twining_register - First observed
twining_search_decisions - First observed
twining_status - First observed
twining_summarize - First observed
twining_trace - First observed
twining_verify - First observed
twining_what_changed - First observed
twining_why
TDQS
Several tools have overlapping responsibilities: twining_record and twining_post both create entries, twining_archive, twining_archive_stale, and twining_housekeeping all handle archiving, and twining_prune_graph overlaps with housekeeping's pruning. While descriptions include differentiators, an agent could easily misselect. Additionally, twining_resolve references twining_dismiss which doesn't exist, confusing the exit paths for open items.
All tools share the 'twining_' prefix, but the suffixes are inconsistent: some are verbs (record, resolve, archive), some are nouns (neighbors, status, housekeeping), and 'why' is an adverb. Also 'graph_query' inverts the typical verb_noun pattern (e.g., 'add_entity', 'prune_graph'). This mixed naming makes predictable tool selection harder.
15 tools is within the typical well-scoped range, but the set feels slightly bloated due to redundant maintenance/archiving tools (twining_prune_graph could be folded into twining_housekeeping). Nonetheless, the count is not excessive and each tool has a distinct name, so it earns a 4.
The tool surface has notable gaps: twining_post references a twining_decide tool that doesn't exist, and twining_resolve references twining_dismiss which also isn't provided. There is no way to delete entities or relations (only pruning orphaned entities), and decision lifecycle management is incomplete (no explicit retire/update path beyond archiving). These absences will force agents to use twining_record for decisions despite the separate intent.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Cross-agent artifact workspace with provenance across Claude Code, Codex, Cursor, LangGraph.
Intelligent context infrastructure for AI teams: knowledge graph, sessions, tasks, documents.
Shared memory for coding agents. Stop re-explaining your codebase every session.
Project memory, semantic code search, and grounded agent context.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceA local, persistent, semantically-aware knowledge graph for AI coding agents like Claude Code, providing efficient session memory with minimal token cost and zero runtime network calls.MIT
- AlicenseAqualityBmaintenanceProvides shared real-time context for Claude Code agents, including scope awareness, prior decisions, and anti-overlap, using only files in the repo.5MIT
- AlicenseNot gradedqualityBmaintenanceProvides a local long-term memory layer for AI coding tools like Cursor and Claude Code, enabling cross-session, cross-tool sharing of project facts, user preferences, decisions, and workflows.252MIT
- AlicenseNot gradedqualityBmaintenanceProvides a unified context system for AI coding agents with memory, knowledge graph, specs, and code graph subsystems, all stored in SQLite. Enables persistent recall of decisions, conventions, errors, project knowledge, and code structure.1,7921MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/daveangulo/twining-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server