(name, args, ctx)
| 73 | // ─── tool branches ─────────────────────────────────────────────────────────── |
| 74 | |
| 75 | async function executeContractTool(name, args, ctx) { |
| 76 | const store = getStore(ctx.cwd || process.cwd()); |
| 77 | |
| 78 | switch (name) { |
| 79 | case 'contract_status': { |
| 80 | const payload = statusPayload(store); |
| 81 | return { result: formatStatus(payload), payload }; |
| 82 | } |
| 83 | |
| 84 | case 'contract_create': { |
| 85 | const title = String(args.title || '').trim() || 'Untitled contract'; |
| 86 | const brief = String(args.brief || '').trim(); |
| 87 | const assertions = args.assertions; |
| 88 | if (!assertions || (Array.isArray(assertions) && assertions.length === 0)) { |
| 89 | return { error: 'contract_create requires at least one assertion (array of strings).' }; |
| 90 | } |
| 91 | const c = store.create({ title, brief, assertions }); |
| 92 | store.activate(c.id); |
| 93 | const payload = statusPayload(store); |
| 94 | return { |
| 95 | result: `Created and activated contract ${c.id} with ${c.assertions.length} assertions.\n\n${formatStatus(payload)}`, |
| 96 | contract_id: c.id, |
| 97 | payload, |
| 98 | }; |
| 99 | } |
| 100 | |
| 101 | case 'contract_assert_pass': |
| 102 | case 'contract_assert_fail': |
| 103 | case 'contract_assert_skip': { |
| 104 | const aid = String(args.assertion_id || '').trim(); |
| 105 | if (!aid) return { error: `${name}: assertion_id is required.` }; |
| 106 | |
| 107 | const state = name === 'contract_assert_pass' ? STATES.PASSED |
| 108 | : name === 'contract_assert_fail' ? STATES.FAILED |
| 109 | : STATES.SKIPPED; |
| 110 | |
| 111 | const evidence = args.evidence || args.reason || ''; |
| 112 | const lastCheck = (args.command || args.exit_code !== undefined) |
| 113 | ? { |
| 114 | command: String(args.command || ''), |
| 115 | exit_code: Number.isFinite(args.exit_code) ? args.exit_code : 0, |
| 116 | observation: String(args.evidence || args.reason || '').slice(0, 200), |
| 117 | timestamp: new Date().toISOString(), |
| 118 | } |
| 119 | : null; |
| 120 | |
| 121 | let updated; |
| 122 | try { |
| 123 | updated = store.markAssertion(aid, state, { evidence, lastCheck }); |
| 124 | } catch (e) { |
| 125 | return { error: `${name}: ${e.message}` }; |
| 126 | } |
| 127 | |
| 128 | const payload = statusPayload(store); |
| 129 | const verb = state === STATES.PASSED ? 'passed' |
| 130 | : state === STATES.FAILED ? 'failed' |
| 131 | : 'skipped'; |
| 132 | return { |
no test coverage detected