trellis 2.0.13 → 2.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +1 -1
- package/dist/embeddings/index.js +1 -1
- package/dist/{index-7gvjxt27.js → index-2917tjd8.js} +1 -1
- package/package.json +2 -10
- package/dist/transformers.node-bx3q9d7k.js +0 -33130
- package/src/cli/index.ts +0 -3356
- package/src/core/agents/harness.ts +0 -380
- package/src/core/agents/index.ts +0 -18
- package/src/core/agents/types.ts +0 -90
- package/src/core/index.ts +0 -118
- package/src/core/kernel/middleware.ts +0 -44
- package/src/core/kernel/trellis-kernel.ts +0 -593
- package/src/core/ontology/builtins.ts +0 -248
- package/src/core/ontology/index.ts +0 -34
- package/src/core/ontology/registry.ts +0 -209
- package/src/core/ontology/types.ts +0 -124
- package/src/core/ontology/validator.ts +0 -382
- package/src/core/persist/backend.ts +0 -74
- package/src/core/persist/sqlite-backend.ts +0 -298
- package/src/core/plugins/index.ts +0 -17
- package/src/core/plugins/registry.ts +0 -322
- package/src/core/plugins/types.ts +0 -126
- package/src/core/query/datalog.ts +0 -188
- package/src/core/query/engine.ts +0 -370
- package/src/core/query/index.ts +0 -34
- package/src/core/query/parser.ts +0 -481
- package/src/core/query/types.ts +0 -200
- package/src/core/store/eav-store.ts +0 -467
- package/src/decisions/auto-capture.ts +0 -136
- package/src/decisions/hooks.ts +0 -163
- package/src/decisions/index.ts +0 -261
- package/src/decisions/types.ts +0 -103
- package/src/embeddings/auto-embed.ts +0 -248
- package/src/embeddings/chunker.ts +0 -327
- package/src/embeddings/index.ts +0 -48
- package/src/embeddings/model.ts +0 -112
- package/src/embeddings/search.ts +0 -305
- package/src/embeddings/store.ts +0 -313
- package/src/embeddings/types.ts +0 -92
- package/src/engine.ts +0 -1125
- package/src/garden/cluster.ts +0 -330
- package/src/garden/garden.ts +0 -306
- package/src/garden/index.ts +0 -29
- package/src/git/git-exporter.ts +0 -286
- package/src/git/git-importer.ts +0 -329
- package/src/git/git-reader.ts +0 -189
- package/src/git/index.ts +0 -22
- package/src/identity/governance.ts +0 -211
- package/src/identity/identity.ts +0 -224
- package/src/identity/index.ts +0 -30
- package/src/identity/signing-middleware.ts +0 -97
- package/src/index.ts +0 -29
- package/src/links/index.ts +0 -49
- package/src/links/lifecycle.ts +0 -400
- package/src/links/parser.ts +0 -484
- package/src/links/ref-index.ts +0 -186
- package/src/links/resolver.ts +0 -314
- package/src/links/types.ts +0 -108
- package/src/mcp/index.ts +0 -22
- package/src/mcp/server.ts +0 -1278
- package/src/semantic/csharp-parser.ts +0 -493
- package/src/semantic/go-parser.ts +0 -585
- package/src/semantic/index.ts +0 -34
- package/src/semantic/java-parser.ts +0 -456
- package/src/semantic/python-parser.ts +0 -659
- package/src/semantic/ruby-parser.ts +0 -446
- package/src/semantic/rust-parser.ts +0 -784
- package/src/semantic/semantic-merge.ts +0 -210
- package/src/semantic/ts-parser.ts +0 -681
- package/src/semantic/types.ts +0 -175
- package/src/sync/http-transport.ts +0 -144
- package/src/sync/index.ts +0 -43
- package/src/sync/memory-transport.ts +0 -66
- package/src/sync/multi-repo.ts +0 -200
- package/src/sync/reconciler.ts +0 -237
- package/src/sync/sync-engine.ts +0 -258
- package/src/sync/types.ts +0 -104
- package/src/sync/ws-transport.ts +0 -145
- package/src/ui/client.html +0 -695
- package/src/ui/server.ts +0 -419
- package/src/vcs/blob-store.ts +0 -124
- package/src/vcs/branch.ts +0 -150
- package/src/vcs/checkpoint.ts +0 -64
- package/src/vcs/decompose.ts +0 -469
- package/src/vcs/diff.ts +0 -409
- package/src/vcs/engine-context.ts +0 -26
- package/src/vcs/index.ts +0 -23
- package/src/vcs/issue.ts +0 -800
- package/src/vcs/merge.ts +0 -425
- package/src/vcs/milestone.ts +0 -124
- package/src/vcs/ops.ts +0 -59
- package/src/vcs/types.ts +0 -213
- package/src/vcs/vcs-middleware.ts +0 -81
- package/src/watcher/fs-watcher.ts +0 -255
- package/src/watcher/index.ts +0 -9
- package/src/watcher/ingestion.ts +0 -116
package/src/decisions/hooks.ts
DELETED
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Decision Hook Registry
|
|
3
|
-
*
|
|
4
|
-
* External agent harnesses register pre/post hooks to enrich decision traces
|
|
5
|
-
* with rationale, alternatives, prompt context, etc.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import type {
|
|
9
|
-
DecisionPreHook,
|
|
10
|
-
DecisionPostHook,
|
|
11
|
-
DecisionContext,
|
|
12
|
-
DecisionEnrichment,
|
|
13
|
-
} from './types.js';
|
|
14
|
-
|
|
15
|
-
// ---------------------------------------------------------------------------
|
|
16
|
-
// Hook Registry
|
|
17
|
-
// ---------------------------------------------------------------------------
|
|
18
|
-
|
|
19
|
-
export class HookRegistry {
|
|
20
|
-
private preHooks: DecisionPreHook[] = [];
|
|
21
|
-
private postHooks: DecisionPostHook[] = [];
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Register a pre-hook that runs before a tool handler.
|
|
25
|
-
*/
|
|
26
|
-
registerPreHook(hook: DecisionPreHook): void {
|
|
27
|
-
this.preHooks.push(hook);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Register a post-hook that runs after a tool handler.
|
|
32
|
-
*/
|
|
33
|
-
registerPostHook(hook: DecisionPostHook): void {
|
|
34
|
-
this.postHooks.push(hook);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Remove a pre-hook by name.
|
|
39
|
-
*/
|
|
40
|
-
removePreHook(name: string): void {
|
|
41
|
-
this.preHooks = this.preHooks.filter((h) => h.name !== name);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Remove a post-hook by name.
|
|
46
|
-
*/
|
|
47
|
-
removePostHook(name: string): void {
|
|
48
|
-
this.postHooks = this.postHooks.filter((h) => h.name !== name);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Get all pre-hooks matching a tool name.
|
|
53
|
-
*/
|
|
54
|
-
getPreHooks(toolName: string): DecisionPreHook[] {
|
|
55
|
-
return this.preHooks.filter((h) => matchesPattern(h.toolPattern, toolName));
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Get all post-hooks matching a tool name.
|
|
60
|
-
*/
|
|
61
|
-
getPostHooks(toolName: string): DecisionPostHook[] {
|
|
62
|
-
return this.postHooks.filter((h) =>
|
|
63
|
-
matchesPattern(h.toolPattern, toolName),
|
|
64
|
-
);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Run all matching pre-hooks and merge their contexts.
|
|
69
|
-
*/
|
|
70
|
-
async runPreHooks(
|
|
71
|
-
toolName: string,
|
|
72
|
-
input: Record<string, unknown>,
|
|
73
|
-
): Promise<DecisionContext> {
|
|
74
|
-
const hooks = this.getPreHooks(toolName);
|
|
75
|
-
const merged: DecisionContext = {};
|
|
76
|
-
|
|
77
|
-
for (const hook of hooks) {
|
|
78
|
-
try {
|
|
79
|
-
const ctx = await hook.handler(toolName, input);
|
|
80
|
-
Object.assign(merged, ctx);
|
|
81
|
-
if (ctx.custom) {
|
|
82
|
-
merged.custom = { ...merged.custom, ...ctx.custom };
|
|
83
|
-
}
|
|
84
|
-
} catch {
|
|
85
|
-
// Hooks should not break tool execution
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
return merged;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Run all matching post-hooks and merge their enrichments.
|
|
94
|
-
*/
|
|
95
|
-
async runPostHooks(
|
|
96
|
-
toolName: string,
|
|
97
|
-
input: Record<string, unknown>,
|
|
98
|
-
output: unknown,
|
|
99
|
-
preContext: DecisionContext,
|
|
100
|
-
): Promise<DecisionEnrichment> {
|
|
101
|
-
const hooks = this.getPostHooks(toolName);
|
|
102
|
-
const merged: DecisionEnrichment = {};
|
|
103
|
-
|
|
104
|
-
for (const hook of hooks) {
|
|
105
|
-
try {
|
|
106
|
-
const enrichment = await hook.handler(
|
|
107
|
-
toolName,
|
|
108
|
-
input,
|
|
109
|
-
output,
|
|
110
|
-
preContext,
|
|
111
|
-
);
|
|
112
|
-
if (enrichment.rationale) merged.rationale = enrichment.rationale;
|
|
113
|
-
if (enrichment.alternatives)
|
|
114
|
-
merged.alternatives = enrichment.alternatives;
|
|
115
|
-
if (enrichment.confidence !== undefined)
|
|
116
|
-
merged.confidence = enrichment.confidence;
|
|
117
|
-
if (enrichment.relatedEntities) {
|
|
118
|
-
merged.relatedEntities = [
|
|
119
|
-
...(merged.relatedEntities ?? []),
|
|
120
|
-
...enrichment.relatedEntities,
|
|
121
|
-
];
|
|
122
|
-
}
|
|
123
|
-
if (enrichment.custom) {
|
|
124
|
-
merged.custom = { ...merged.custom, ...enrichment.custom };
|
|
125
|
-
}
|
|
126
|
-
} catch {
|
|
127
|
-
// Hooks should not break tool execution
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
return merged;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Clear all hooks.
|
|
136
|
-
*/
|
|
137
|
-
clear(): void {
|
|
138
|
-
this.preHooks = [];
|
|
139
|
-
this.postHooks = [];
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// ---------------------------------------------------------------------------
|
|
144
|
-
// Helpers
|
|
145
|
-
// ---------------------------------------------------------------------------
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Match a tool name against a glob-like pattern or RegExp.
|
|
149
|
-
* Supports `*` as a wildcard in string patterns (e.g. "trellis_issue_*").
|
|
150
|
-
*/
|
|
151
|
-
function matchesPattern(pattern: string | RegExp, toolName: string): boolean {
|
|
152
|
-
if (pattern instanceof RegExp) {
|
|
153
|
-
return pattern.test(toolName);
|
|
154
|
-
}
|
|
155
|
-
if (pattern === '*') return true;
|
|
156
|
-
if (!pattern.includes('*')) return pattern === toolName;
|
|
157
|
-
|
|
158
|
-
// Convert glob to regex: escape special chars, replace * with .*
|
|
159
|
-
const escaped = pattern
|
|
160
|
-
.replace(/[.+^${}()|[\]\\]/g, '\\$&')
|
|
161
|
-
.replace(/\*/g, '.*');
|
|
162
|
-
return new RegExp(`^${escaped}$`).test(toolName);
|
|
163
|
-
}
|
package/src/decisions/index.ts
DELETED
|
@@ -1,261 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Decision Traces Module
|
|
3
|
-
*
|
|
4
|
-
* Auto-captures agent decision traces from MCP tool invocations as
|
|
5
|
-
* first-class Decision entities in the EAV store.
|
|
6
|
-
*
|
|
7
|
-
* Public API:
|
|
8
|
-
* - recordDecision() — persist a decision as a vcs:decisionRecord op
|
|
9
|
-
* - queryDecisions() — filter/list decisions from the EAV store
|
|
10
|
-
* - getDecisionChain() — all decisions that affected a given entity
|
|
11
|
-
* - HookRegistry — pre/post hook registration for external harnesses
|
|
12
|
-
* - wrapToolHandler() — MCP middleware for auto-capture
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
export { HookRegistry } from './hooks.js';
|
|
16
|
-
export {
|
|
17
|
-
wrapToolHandler,
|
|
18
|
-
type ToolHandler,
|
|
19
|
-
type DecisionRecorder,
|
|
20
|
-
type AutoCaptureOpts,
|
|
21
|
-
} from './auto-capture.js';
|
|
22
|
-
export type {
|
|
23
|
-
Decision,
|
|
24
|
-
DecisionInput,
|
|
25
|
-
DecisionFilter,
|
|
26
|
-
DecisionContext,
|
|
27
|
-
DecisionEnrichment,
|
|
28
|
-
DecisionPreHook,
|
|
29
|
-
DecisionPostHook,
|
|
30
|
-
} from './types.js';
|
|
31
|
-
|
|
32
|
-
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
|
|
33
|
-
import { join, dirname } from 'path';
|
|
34
|
-
import { createVcsOp } from '../vcs/ops.js';
|
|
35
|
-
import { decisionEntityId } from '../vcs/types.js';
|
|
36
|
-
import type { VcsOp } from '../vcs/types.js';
|
|
37
|
-
import type { EngineContext } from '../vcs/engine-context.js';
|
|
38
|
-
import type { Decision, DecisionInput, DecisionFilter } from './types.js';
|
|
39
|
-
|
|
40
|
-
// ---------------------------------------------------------------------------
|
|
41
|
-
// Sequential Decision ID (file-based, matching issue counter pattern)
|
|
42
|
-
// ---------------------------------------------------------------------------
|
|
43
|
-
|
|
44
|
-
function getDecisionCounterPath(rootPath: string): string {
|
|
45
|
-
return join(rootPath, '.trellis', 'decision-counter.json');
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function nextDecisionId(rootPath: string): string {
|
|
49
|
-
const counterPath = getDecisionCounterPath(rootPath);
|
|
50
|
-
let counter = 0;
|
|
51
|
-
if (existsSync(counterPath)) {
|
|
52
|
-
try {
|
|
53
|
-
counter = JSON.parse(readFileSync(counterPath, 'utf-8')).counter ?? 0;
|
|
54
|
-
} catch {}
|
|
55
|
-
}
|
|
56
|
-
counter++;
|
|
57
|
-
const dir = dirname(counterPath);
|
|
58
|
-
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
59
|
-
writeFileSync(counterPath, JSON.stringify({ counter }, null, 2));
|
|
60
|
-
return `DEC-${counter}`;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// ---------------------------------------------------------------------------
|
|
64
|
-
// Record
|
|
65
|
-
// ---------------------------------------------------------------------------
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Record a decision trace as a vcs:decisionRecord op.
|
|
69
|
-
*/
|
|
70
|
-
export async function recordDecision(
|
|
71
|
-
ctx: EngineContext,
|
|
72
|
-
rootPath: string,
|
|
73
|
-
input: DecisionInput,
|
|
74
|
-
): Promise<VcsOp> {
|
|
75
|
-
const id = nextDecisionId(rootPath);
|
|
76
|
-
|
|
77
|
-
const op = await createVcsOp('vcs:decisionRecord', {
|
|
78
|
-
agentId: ctx.agentId,
|
|
79
|
-
previousHash: ctx.getLastOp()?.hash,
|
|
80
|
-
vcs: {
|
|
81
|
-
decisionId: id,
|
|
82
|
-
decisionToolName: input.toolName,
|
|
83
|
-
decisionToolInput: input.input ? JSON.stringify(input.input) : undefined,
|
|
84
|
-
decisionToolOutput: input.outputSummary,
|
|
85
|
-
decisionContext: input.context,
|
|
86
|
-
decisionRationale: input.rationale,
|
|
87
|
-
decisionAlternatives: input.alternatives
|
|
88
|
-
? JSON.stringify(input.alternatives)
|
|
89
|
-
: undefined,
|
|
90
|
-
},
|
|
91
|
-
});
|
|
92
|
-
ctx.applyOp(op);
|
|
93
|
-
|
|
94
|
-
// Store related entity links
|
|
95
|
-
if (input.relatedEntities) {
|
|
96
|
-
const eid = decisionEntityId(id);
|
|
97
|
-
const links = input.relatedEntities.map((target) => ({
|
|
98
|
-
e1: eid,
|
|
99
|
-
a: 'relatedTo',
|
|
100
|
-
e2: target,
|
|
101
|
-
}));
|
|
102
|
-
if (links.length > 0) {
|
|
103
|
-
ctx.store.addLinks(links);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
return op;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
// ---------------------------------------------------------------------------
|
|
111
|
-
// Query
|
|
112
|
-
// ---------------------------------------------------------------------------
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Build a Decision from EAV facts for a given entity ID.
|
|
116
|
-
*/
|
|
117
|
-
function buildDecision(ctx: EngineContext, entityId: string): Decision {
|
|
118
|
-
const facts = ctx.store.getFactsByEntity(entityId);
|
|
119
|
-
const get = (a: string) => {
|
|
120
|
-
const matches = facts.filter((f) => f.a === a);
|
|
121
|
-
return matches.length > 0
|
|
122
|
-
? (matches[matches.length - 1].v as string)
|
|
123
|
-
: undefined;
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
// Gather related entity links
|
|
127
|
-
const links = ctx.store.getLinksByAttribute('relatedTo');
|
|
128
|
-
const related = links.filter((l) => l.e1 === entityId).map((l) => l.e2);
|
|
129
|
-
|
|
130
|
-
const bareId = entityId.replace(/^decision:/, '');
|
|
131
|
-
|
|
132
|
-
const alternativesRaw = get('alternatives');
|
|
133
|
-
let alternatives: string[] | undefined;
|
|
134
|
-
if (alternativesRaw) {
|
|
135
|
-
try {
|
|
136
|
-
alternatives = JSON.parse(alternativesRaw);
|
|
137
|
-
} catch {
|
|
138
|
-
alternatives = [alternativesRaw];
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
const confidenceRaw = get('confidence');
|
|
143
|
-
const confidence =
|
|
144
|
-
confidenceRaw !== undefined ? parseFloat(confidenceRaw) : undefined;
|
|
145
|
-
|
|
146
|
-
return {
|
|
147
|
-
id: bareId,
|
|
148
|
-
toolName: get('toolName') ?? '',
|
|
149
|
-
outputSummary: get('outputSummary'),
|
|
150
|
-
context: get('context'),
|
|
151
|
-
rationale: get('rationale'),
|
|
152
|
-
alternatives,
|
|
153
|
-
confidence,
|
|
154
|
-
createdAt: get('createdAt'),
|
|
155
|
-
createdBy: get('createdBy'),
|
|
156
|
-
relatedEntities: related,
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* Query decisions with optional filters.
|
|
162
|
-
*/
|
|
163
|
-
export function queryDecisions(
|
|
164
|
-
ctx: EngineContext,
|
|
165
|
-
filter?: DecisionFilter,
|
|
166
|
-
): Decision[] {
|
|
167
|
-
const decisionFacts = ctx.store
|
|
168
|
-
.getFactsByAttribute('type')
|
|
169
|
-
.filter((f) => f.v === 'Decision');
|
|
170
|
-
|
|
171
|
-
let decisions = decisionFacts.map((f) => buildDecision(ctx, f.e));
|
|
172
|
-
|
|
173
|
-
if (filter?.toolPattern) {
|
|
174
|
-
const pattern = filter.toolPattern;
|
|
175
|
-
const regex = pattern.includes('*')
|
|
176
|
-
? new RegExp(
|
|
177
|
-
`^${pattern.replace(/[.+^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '.*')}$`,
|
|
178
|
-
)
|
|
179
|
-
: null;
|
|
180
|
-
decisions = decisions.filter((d) =>
|
|
181
|
-
regex ? regex.test(d.toolName) : d.toolName === pattern,
|
|
182
|
-
);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
if (filter?.agentId) {
|
|
186
|
-
decisions = decisions.filter((d) => d.createdBy === filter.agentId);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
if (filter?.since) {
|
|
190
|
-
const since = new Date(filter.since).getTime();
|
|
191
|
-
decisions = decisions.filter(
|
|
192
|
-
(d) => d.createdAt && new Date(d.createdAt).getTime() >= since,
|
|
193
|
-
);
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
if (filter?.until) {
|
|
197
|
-
const until = new Date(filter.until).getTime();
|
|
198
|
-
decisions = decisions.filter(
|
|
199
|
-
(d) => d.createdAt && new Date(d.createdAt).getTime() <= until,
|
|
200
|
-
);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
if (filter?.entityId) {
|
|
204
|
-
decisions = decisions.filter((d) =>
|
|
205
|
-
d.relatedEntities.includes(filter.entityId!),
|
|
206
|
-
);
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
// Sort by createdAt descending (newest first)
|
|
210
|
-
decisions.sort((a, b) => {
|
|
211
|
-
if (!a.createdAt || !b.createdAt) return 0;
|
|
212
|
-
return new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime();
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
if (filter?.limit && filter.limit > 0) {
|
|
216
|
-
decisions = decisions.slice(0, filter.limit);
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
return decisions;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
/**
|
|
223
|
-
* Get all decisions that affected a given entity (the decision chain).
|
|
224
|
-
*/
|
|
225
|
-
export function getDecisionChain(
|
|
226
|
-
ctx: EngineContext,
|
|
227
|
-
entityId: string,
|
|
228
|
-
): Decision[] {
|
|
229
|
-
// Find all decision entities linked to this entity
|
|
230
|
-
const allLinks = ctx.store.getLinksByAttribute('relatedTo');
|
|
231
|
-
const decisionEids = new Set(
|
|
232
|
-
allLinks
|
|
233
|
-
.filter((l) => l.e2 === entityId)
|
|
234
|
-
.map((l) => l.e1)
|
|
235
|
-
.filter((e) => e.startsWith('decision:')),
|
|
236
|
-
);
|
|
237
|
-
|
|
238
|
-
const decisions = Array.from(decisionEids).map((eid) =>
|
|
239
|
-
buildDecision(ctx, eid),
|
|
240
|
-
);
|
|
241
|
-
|
|
242
|
-
// Sort chronologically
|
|
243
|
-
decisions.sort((a, b) => {
|
|
244
|
-
if (!a.createdAt || !b.createdAt) return 0;
|
|
245
|
-
return new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime();
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
return decisions;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
/**
|
|
252
|
-
* Get a single decision by ID.
|
|
253
|
-
*/
|
|
254
|
-
export function getDecision(ctx: EngineContext, id: string): Decision | null {
|
|
255
|
-
const eid = decisionEntityId(id);
|
|
256
|
-
const typeFact = ctx.store
|
|
257
|
-
.getFactsByEntity(eid)
|
|
258
|
-
.find((f) => f.a === 'type' && f.v === 'Decision');
|
|
259
|
-
if (!typeFact) return null;
|
|
260
|
-
return buildDecision(ctx, eid);
|
|
261
|
-
}
|
package/src/decisions/types.ts
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Decision Trace Types
|
|
3
|
-
*
|
|
4
|
-
* Types for auto-captured agent decision traces. Decisions are first-class
|
|
5
|
-
* entities in the EAV store, emitted automatically from MCP tool calls
|
|
6
|
-
* and enrichable via pre/post hooks.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
// ---------------------------------------------------------------------------
|
|
10
|
-
// Decision Entity
|
|
11
|
-
// ---------------------------------------------------------------------------
|
|
12
|
-
|
|
13
|
-
export interface Decision {
|
|
14
|
-
id: string;
|
|
15
|
-
toolName: string;
|
|
16
|
-
input?: Record<string, unknown>;
|
|
17
|
-
outputSummary?: string;
|
|
18
|
-
context?: string;
|
|
19
|
-
rationale?: string;
|
|
20
|
-
alternatives?: string[];
|
|
21
|
-
confidence?: number;
|
|
22
|
-
createdAt?: string;
|
|
23
|
-
createdBy?: string;
|
|
24
|
-
/** IDs of related entities (issues, files, milestones) affected by this decision */
|
|
25
|
-
relatedEntities: string[];
|
|
26
|
-
custom?: Record<string, unknown>;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// ---------------------------------------------------------------------------
|
|
30
|
-
// Decision Input (for recording)
|
|
31
|
-
// ---------------------------------------------------------------------------
|
|
32
|
-
|
|
33
|
-
export interface DecisionInput {
|
|
34
|
-
toolName: string;
|
|
35
|
-
input?: Record<string, unknown>;
|
|
36
|
-
outputSummary?: string;
|
|
37
|
-
context?: string;
|
|
38
|
-
rationale?: string;
|
|
39
|
-
alternatives?: string[];
|
|
40
|
-
confidence?: number;
|
|
41
|
-
/** Entity IDs this decision relates to (e.g. "issue:TRL-5") */
|
|
42
|
-
relatedEntities?: string[];
|
|
43
|
-
custom?: Record<string, unknown>;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// ---------------------------------------------------------------------------
|
|
47
|
-
// Decision Filters (for querying)
|
|
48
|
-
// ---------------------------------------------------------------------------
|
|
49
|
-
|
|
50
|
-
export interface DecisionFilter {
|
|
51
|
-
/** Filter by MCP tool name (glob-like, e.g. "trellis_issue_*") */
|
|
52
|
-
toolPattern?: string;
|
|
53
|
-
/** Filter by agent ID */
|
|
54
|
-
agentId?: string;
|
|
55
|
-
/** Only decisions after this ISO timestamp */
|
|
56
|
-
since?: string;
|
|
57
|
-
/** Only decisions before this ISO timestamp */
|
|
58
|
-
until?: string;
|
|
59
|
-
/** Only decisions referencing this entity */
|
|
60
|
-
entityId?: string;
|
|
61
|
-
/** Max results */
|
|
62
|
-
limit?: number;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// ---------------------------------------------------------------------------
|
|
66
|
-
// Hook Types
|
|
67
|
-
// ---------------------------------------------------------------------------
|
|
68
|
-
|
|
69
|
-
export interface DecisionContext {
|
|
70
|
-
prompt?: string;
|
|
71
|
-
conversationId?: string;
|
|
72
|
-
agentModel?: string;
|
|
73
|
-
custom?: Record<string, unknown>;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export interface DecisionEnrichment {
|
|
77
|
-
rationale?: string;
|
|
78
|
-
alternatives?: string[];
|
|
79
|
-
confidence?: number;
|
|
80
|
-
relatedEntities?: string[];
|
|
81
|
-
custom?: Record<string, unknown>;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export interface DecisionPreHook {
|
|
85
|
-
name: string;
|
|
86
|
-
/** Which tools to intercept — string (glob) or RegExp */
|
|
87
|
-
toolPattern: string | RegExp;
|
|
88
|
-
handler: (
|
|
89
|
-
toolName: string,
|
|
90
|
-
input: Record<string, unknown>,
|
|
91
|
-
) => Promise<DecisionContext>;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
export interface DecisionPostHook {
|
|
95
|
-
name: string;
|
|
96
|
-
toolPattern: string | RegExp;
|
|
97
|
-
handler: (
|
|
98
|
-
toolName: string,
|
|
99
|
-
input: Record<string, unknown>,
|
|
100
|
-
output: unknown,
|
|
101
|
-
preContext: DecisionContext,
|
|
102
|
-
) => Promise<DecisionEnrichment>;
|
|
103
|
-
}
|