twining_decide
Record development decisions with full rationale, alternatives considered, and traceability. Creates structured decision records and cross-posts to a shared blackboard for team coordination.
Instructions
Record a decision with full rationale, alternatives considered, and traceability. Creates a decision record and cross-posts to the blackboard.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| domain | Yes | Decision domain (e.g., "architecture", "implementation", "testing") | |
| scope | Yes | What part of the codebase this affects | |
| summary | Yes | One-line decision statement | |
| context | Yes | Situation that prompted this decision | |
| rationale | Yes | Reasoning for the choice | |
| constraints | No | What limited the options | |
| alternatives | No | Alternatives that were considered | |
| depends_on | No | IDs of prerequisite decisions | |
| supersedes | No | ID of decision this replaces | |
| confidence | No | Confidence level (default: "medium") | |
| reversible | No | Whether this decision is easily reversible (default: true) | |
| affected_files | No | File paths affected by this decision | |
| affected_symbols | No | Function/class names affected | |
| agent_id | No | Identifier for the deciding agent (default: "main") | |
| commit_hash | No | Git commit hash to associate with this decision |
Implementation Reference
- src/tools/decision-tools.ts:15-103 (registration)Tool registration for "twining_decide" in `src/tools/decision-tools.ts`. It takes a comprehensive input schema of decision details and calls the `engine.decide(args)` method to perform the action.
server.registerTool( "twining_decide", { description: "Record a decision with full rationale, alternatives considered, and traceability. Creates a decision record and cross-posts to the blackboard.", inputSchema: { domain: z .string() .describe( 'Decision domain (e.g., "architecture", "implementation", "testing")', ), scope: z .string() .describe("What part of the codebase this affects"), summary: z.string().describe("One-line decision statement"), context: z.string().describe("Situation that prompted this decision"), rationale: z.string().describe("Reasoning for the choice"), constraints: z .array(z.string()) .optional() .describe("What limited the options"), alternatives: z .array( z.object({ option: z.string().describe("Alternative option considered"), pros: z .array(z.string()) .optional() .describe("Advantages of this alternative"), cons: z .array(z.string()) .optional() .describe("Disadvantages of this alternative"), reason_rejected: z .string() .describe("Why this alternative was rejected"), }), ) .optional() .describe("Alternatives that were considered"), depends_on: z .array(z.string()) .optional() .describe("IDs of prerequisite decisions"), supersedes: z .string() .optional() .describe("ID of decision this replaces"), confidence: z .enum(["high", "medium", "low"]) .optional() .describe('Confidence level (default: "medium")'), reversible: z .boolean() .optional() .describe("Whether this decision is easily reversible (default: true)"), affected_files: z .array(z.string()) .optional() .describe("File paths affected by this decision"), affected_symbols: z .array(z.string()) .optional() .describe("Function/class names affected"), agent_id: z .string() .optional() .describe('Identifier for the deciding agent (default: "main")'), commit_hash: z .string() .optional() .describe("Git commit hash to associate with this decision"), }, }, async (args) => { try { const result = await engine.decide(args); return toolResult(result); } catch (e) { if (e instanceof TwiningError) { return toolError(e.message, e.code); } return toolError( e instanceof Error ? e.message : "Unknown error", "INTERNAL_ERROR", ); } }, );