twining_why
Retrieve decision chains with rationale and alternatives to understand why specific code changes were made for any file or module.
Instructions
Retrieve all decisions affecting a given scope or file. Shows the decision chain with rationale, confidence, and alternatives count. Essential for understanding "why was it done this way?"
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| scope | Yes | File path, module name, or symbol to query |
Implementation Reference
- src/tools/decision-tools.ts:105-128 (handler)Registration of the `twining_why` tool in `src/tools/decision-tools.ts`.
// twining_why — Retrieve decision chain for a scope or file server.registerTool( "twining_why", { description: 'Retrieve all decisions affecting a given scope or file. Shows the decision chain with rationale, confidence, and alternatives count. Essential for understanding "why was it done this way?"', inputSchema: { scope: z .string() .describe("File path, module name, or symbol to query"), }, }, async (args) => { try { const result = await engine.why(args.scope); return toolResult(result); } catch (e) { return toolError( e instanceof Error ? e.message : "Unknown error", "INTERNAL_ERROR", ); } }, ); - src/engine/decisions.ts:297-331 (handler)The implementation of the `why` method within the `DecisionEngine` class in `src/engine/decisions.ts`.
/** Retrieve decision chain for a scope or file. */ async why(scope: string): Promise<{ decisions: Array<{ id: string; summary: string; rationale: string; confidence: string; status: string; timestamp: string; alternatives_count: number; commit_hashes: string[]; }>; active_count: number; provisional_count: number; }> { const decisions = await this.decisionStore.getByScope(scope); const mapped = decisions.map((d) => ({ id: d.id, summary: d.summary, rationale: d.rationale, confidence: d.confidence, status: d.status, timestamp: d.timestamp, alternatives_count: d.alternatives.length, commit_hashes: d.commit_hashes ?? [], })); const active_count = decisions.filter((d) => d.status === "active").length; const provisional_count = decisions.filter( (d) => d.status === "provisional", ).length; return { decisions: mapped, active_count, provisional_count }; }