@xiaolei.shawn/mcp-server 0.2.0

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/tools.js ADDED
@@ -0,0 +1,783 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import * as z from "zod";
3
+ import { buildSessionLog, createEvent, createSession, endActiveSession, getActiveSession, ensureActiveSession, initializeSessionLog, persistEvent, persistNormalizedSnapshot, setActiveIntent, } from "./store.js";
4
+ const actor = { type: "agent" };
5
+ const AUTO_GOAL = process.env.AL_AUTO_GOAL ?? "Agent task execution";
6
+ const AUTO_PROMPT = process.env.AL_AUTO_USER_PROMPT ?? "Auto-instrumented run";
7
+ const sessionStartSchema = z
8
+ .object({
9
+ goal: z.string().min(1),
10
+ user_prompt: z.string().min(1).optional(),
11
+ repo: z.string().min(1).optional(),
12
+ branch: z.string().min(1).optional(),
13
+ })
14
+ .strict();
15
+ const intentSchema = z
16
+ .object({
17
+ title: z.string().min(1),
18
+ description: z.string().min(1).optional(),
19
+ priority: z.number().optional(),
20
+ })
21
+ .strict();
22
+ const activitySchema = z
23
+ .object({
24
+ category: z.enum(["file", "tool", "search", "execution"]),
25
+ action: z.string().min(1),
26
+ target: z.string().optional(),
27
+ details: z.record(z.unknown()).optional(),
28
+ })
29
+ .strict();
30
+ const decisionSchema = z
31
+ .object({
32
+ summary: z.string().min(1),
33
+ rationale: z.string().optional(),
34
+ options: z.array(z.string()).optional(),
35
+ chosen_option: z.string().optional(),
36
+ reversibility: z.enum(["easy", "medium", "hard"]).optional(),
37
+ })
38
+ .strict();
39
+ const assumptionSchema = z
40
+ .object({
41
+ statement: z.string().min(1),
42
+ validated: z.union([z.boolean(), z.literal("unknown")]).optional(),
43
+ risk: z.enum(["low", "medium", "high"]).optional(),
44
+ })
45
+ .strict();
46
+ const verificationSchema = z
47
+ .object({
48
+ type: z.enum(["test", "lint", "typecheck", "manual"]),
49
+ result: z.enum(["pass", "fail", "unknown"]),
50
+ details: z.string().optional(),
51
+ })
52
+ .strict();
53
+ const sessionEndSchema = z
54
+ .object({
55
+ outcome: z.enum(["completed", "partial", "failed", "aborted"]),
56
+ summary: z.string().optional(),
57
+ })
58
+ .strict();
59
+ const gatewayBeginSchema = z
60
+ .object({
61
+ goal: z.string().min(1),
62
+ user_prompt: z.string().min(1).optional(),
63
+ repo: z.string().min(1).optional(),
64
+ branch: z.string().min(1).optional(),
65
+ intent_title: z.string().min(1).optional(),
66
+ intent_description: z.string().min(1).optional(),
67
+ intent_priority: z.number().optional(),
68
+ })
69
+ .strict();
70
+ const gatewayActSchema = z
71
+ .object({
72
+ op: z.enum([
73
+ "file",
74
+ "tool",
75
+ "search",
76
+ "execution",
77
+ "intent",
78
+ "decision",
79
+ "assumption",
80
+ "verification",
81
+ ]),
82
+ action: z.string().min(1).optional(),
83
+ target: z.string().min(1).optional(),
84
+ details: z.record(z.unknown()).optional(),
85
+ usage: z
86
+ .object({
87
+ model: z.string().min(1).optional(),
88
+ prompt_tokens: z.number().int().nonnegative().optional(),
89
+ completion_tokens: z.number().int().nonnegative().optional(),
90
+ total_tokens: z.number().int().nonnegative().optional(),
91
+ estimated_cost_usd: z.number().nonnegative().optional(),
92
+ })
93
+ .strict()
94
+ .optional(),
95
+ intent: intentSchema.optional(),
96
+ decision: decisionSchema.optional(),
97
+ assumption: assumptionSchema.optional(),
98
+ verification: verificationSchema.optional(),
99
+ visibility: z.enum(["raw", "review", "debug"]).optional(),
100
+ })
101
+ .strict();
102
+ const gatewayEndSchema = sessionEndSchema;
103
+ export const GATEWAY_RULES = {
104
+ file: {
105
+ maps_to_tool: "record_activity",
106
+ emits_kind: "file_op",
107
+ required_fields: ["action"],
108
+ default_visibility: "raw",
109
+ },
110
+ tool: {
111
+ maps_to_tool: "record_activity",
112
+ emits_kind: "tool_call",
113
+ required_fields: ["action"],
114
+ default_visibility: "raw",
115
+ },
116
+ search: {
117
+ maps_to_tool: "record_activity",
118
+ emits_kind: "tool_call",
119
+ required_fields: ["action"],
120
+ default_visibility: "raw",
121
+ },
122
+ execution: {
123
+ maps_to_tool: "record_activity",
124
+ emits_kind: "tool_call",
125
+ required_fields: ["action"],
126
+ default_visibility: "raw",
127
+ },
128
+ intent: {
129
+ maps_to_tool: "record_intent",
130
+ emits_kind: "intent",
131
+ required_fields: ["intent.title"],
132
+ default_visibility: "review",
133
+ },
134
+ decision: {
135
+ maps_to_tool: "record_decision",
136
+ emits_kind: "decision",
137
+ required_fields: ["decision.summary"],
138
+ default_visibility: "review",
139
+ },
140
+ assumption: {
141
+ maps_to_tool: "record_assumption",
142
+ emits_kind: "assumption",
143
+ required_fields: ["assumption.statement"],
144
+ default_visibility: "review",
145
+ },
146
+ verification: {
147
+ maps_to_tool: "record_verification",
148
+ emits_kind: "verification",
149
+ required_fields: ["verification.type", "verification.result"],
150
+ default_visibility: "review",
151
+ },
152
+ };
153
+ function textContent(value) {
154
+ const text = typeof value === "string" ? value : JSON.stringify(value, null, 2);
155
+ return { content: [{ type: "text", text }] };
156
+ }
157
+ function errorContent(error) {
158
+ const message = error instanceof Error ? error.message : String(error);
159
+ return {
160
+ content: [{ type: "text", text: `Error: ${message}` }],
161
+ isError: true,
162
+ };
163
+ }
164
+ async function appendCurrentSessionEvent(input) {
165
+ const state = ensureActiveSession();
166
+ const event = createEvent(state, {
167
+ session_id: state.session_id,
168
+ kind: input.kind,
169
+ actor,
170
+ scope: input.scope,
171
+ payload: input.payload,
172
+ visibility: input.visibility,
173
+ });
174
+ await persistEvent(event);
175
+ return event;
176
+ }
177
+ async function ensureGatewaySession() {
178
+ const active = getActiveSession();
179
+ if (active && !active.ended_at)
180
+ return active;
181
+ const state = createSession({
182
+ goal: AUTO_GOAL,
183
+ user_prompt: AUTO_PROMPT,
184
+ repo: process.env.AL_AUTO_REPO,
185
+ branch: process.env.AL_AUTO_BRANCH,
186
+ });
187
+ initializeSessionLog(state);
188
+ const event = createEvent(state, {
189
+ session_id: state.session_id,
190
+ kind: "session_start",
191
+ actor,
192
+ payload: {
193
+ goal: state.goal,
194
+ user_prompt: state.user_prompt,
195
+ repo: state.repo,
196
+ branch: state.branch,
197
+ auto_created: true,
198
+ },
199
+ visibility: "review",
200
+ });
201
+ await persistEvent(event);
202
+ return state;
203
+ }
204
+ export async function handleRecordSessionStart(raw) {
205
+ try {
206
+ const args = sessionStartSchema.parse(raw);
207
+ const state = createSession(args);
208
+ initializeSessionLog(state);
209
+ const event = createEvent(state, {
210
+ session_id: state.session_id,
211
+ kind: "session_start",
212
+ actor,
213
+ payload: {
214
+ goal: args.goal,
215
+ user_prompt: args.user_prompt,
216
+ repo: args.repo,
217
+ branch: args.branch,
218
+ },
219
+ visibility: "review",
220
+ });
221
+ await persistEvent(event);
222
+ return textContent({
223
+ session_id: state.session_id,
224
+ event_id: event.id,
225
+ seq: event.seq,
226
+ ts: event.ts,
227
+ });
228
+ }
229
+ catch (err) {
230
+ return errorContent(err);
231
+ }
232
+ }
233
+ export async function handleRecordIntent(raw) {
234
+ try {
235
+ const args = intentSchema.parse(raw);
236
+ const intentId = `intent_${Date.now()}_${randomUUID().slice(0, 8)}`;
237
+ setActiveIntent(intentId);
238
+ const event = await appendCurrentSessionEvent({
239
+ kind: "intent",
240
+ payload: {
241
+ intent_id: intentId,
242
+ title: args.title,
243
+ description: args.description,
244
+ priority: args.priority,
245
+ },
246
+ scope: { intent_id: intentId },
247
+ visibility: "review",
248
+ });
249
+ return textContent({
250
+ intent_id: intentId,
251
+ event_id: event.id,
252
+ seq: event.seq,
253
+ ts: event.ts,
254
+ });
255
+ }
256
+ catch (err) {
257
+ return errorContent(err);
258
+ }
259
+ }
260
+ export async function handleRecordActivity(raw) {
261
+ try {
262
+ const args = activitySchema.parse(raw);
263
+ const state = ensureActiveSession();
264
+ const kind = args.category === "file" ? "file_op" : "tool_call";
265
+ const scope = {
266
+ intent_id: state.active_intent_id,
267
+ file: args.category === "file" ? args.target : undefined,
268
+ module: args.details && typeof args.details.module === "string"
269
+ ? args.details.module
270
+ : undefined,
271
+ };
272
+ const event = await appendCurrentSessionEvent({
273
+ kind,
274
+ payload: {
275
+ category: args.category,
276
+ action: args.action,
277
+ target: args.target,
278
+ details: args.details ?? {},
279
+ },
280
+ scope,
281
+ visibility: "raw",
282
+ });
283
+ return textContent({
284
+ event_id: event.id,
285
+ kind: event.kind,
286
+ seq: event.seq,
287
+ ts: event.ts,
288
+ });
289
+ }
290
+ catch (err) {
291
+ return errorContent(err);
292
+ }
293
+ }
294
+ export async function handleRecordDecision(raw) {
295
+ try {
296
+ const args = decisionSchema.parse(raw);
297
+ const state = ensureActiveSession();
298
+ const event = await appendCurrentSessionEvent({
299
+ kind: "decision",
300
+ payload: {
301
+ summary: args.summary,
302
+ rationale: args.rationale,
303
+ options: args.options,
304
+ chosen_option: args.chosen_option,
305
+ reversibility: args.reversibility,
306
+ },
307
+ scope: { intent_id: state.active_intent_id },
308
+ visibility: "review",
309
+ });
310
+ return textContent({
311
+ event_id: event.id,
312
+ seq: event.seq,
313
+ ts: event.ts,
314
+ });
315
+ }
316
+ catch (err) {
317
+ return errorContent(err);
318
+ }
319
+ }
320
+ export async function handleRecordAssumption(raw) {
321
+ try {
322
+ const args = assumptionSchema.parse(raw);
323
+ const state = ensureActiveSession();
324
+ const event = await appendCurrentSessionEvent({
325
+ kind: "assumption",
326
+ payload: {
327
+ statement: args.statement,
328
+ validated: args.validated ?? "unknown",
329
+ risk: args.risk,
330
+ },
331
+ scope: { intent_id: state.active_intent_id },
332
+ visibility: "review",
333
+ });
334
+ return textContent({
335
+ event_id: event.id,
336
+ seq: event.seq,
337
+ ts: event.ts,
338
+ });
339
+ }
340
+ catch (err) {
341
+ return errorContent(err);
342
+ }
343
+ }
344
+ export async function handleRecordVerification(raw) {
345
+ try {
346
+ const args = verificationSchema.parse(raw);
347
+ const state = ensureActiveSession();
348
+ const event = await appendCurrentSessionEvent({
349
+ kind: "verification",
350
+ payload: {
351
+ type: args.type,
352
+ result: args.result,
353
+ details: args.details,
354
+ },
355
+ scope: { intent_id: state.active_intent_id },
356
+ visibility: "review",
357
+ });
358
+ return textContent({
359
+ event_id: event.id,
360
+ seq: event.seq,
361
+ ts: event.ts,
362
+ });
363
+ }
364
+ catch (err) {
365
+ return errorContent(err);
366
+ }
367
+ }
368
+ export async function handleRecordSessionEnd(raw) {
369
+ try {
370
+ const args = sessionEndSchema.parse(raw);
371
+ const state = ensureActiveSession();
372
+ const event = createEvent(state, {
373
+ session_id: state.session_id,
374
+ kind: "session_end",
375
+ actor,
376
+ payload: {
377
+ outcome: args.outcome,
378
+ summary: args.summary,
379
+ },
380
+ visibility: "review",
381
+ });
382
+ await persistEvent(event);
383
+ const ended = await endActiveSession(event.ts);
384
+ const normalized = await persistNormalizedSnapshot(ended);
385
+ const snapshot = buildSessionLog(ended, [event]);
386
+ return textContent({
387
+ session_id: ended.session_id,
388
+ ended_at: ended.ended_at,
389
+ final_event_id: event.id,
390
+ seq: event.seq,
391
+ outcome: args.outcome,
392
+ note: "Events are persisted as JSONL per session in AL_SESSIONS_DIR.",
393
+ session_log_preview: snapshot,
394
+ normalized_snapshot: normalized,
395
+ });
396
+ }
397
+ catch (err) {
398
+ return errorContent(err);
399
+ }
400
+ }
401
+ function createIntentId() {
402
+ return `intent_${Date.now()}_${randomUUID().slice(0, 8)}`;
403
+ }
404
+ async function appendIntentEvent(input) {
405
+ const intentId = createIntentId();
406
+ setActiveIntent(intentId);
407
+ const event = await appendCurrentSessionEvent({
408
+ kind: "intent",
409
+ payload: {
410
+ intent_id: intentId,
411
+ title: input.title,
412
+ description: input.description,
413
+ priority: input.priority,
414
+ },
415
+ scope: { intent_id: intentId },
416
+ visibility: "review",
417
+ });
418
+ return { event, intent_id: intentId };
419
+ }
420
+ export async function handleGatewayBeginRun(raw) {
421
+ try {
422
+ const args = gatewayBeginSchema.parse(raw);
423
+ let active = getActiveSession();
424
+ let sessionStartEvent = null;
425
+ let reusedSession = false;
426
+ if (!active || active.ended_at) {
427
+ active = createSession({
428
+ goal: args.goal,
429
+ user_prompt: args.user_prompt,
430
+ repo: args.repo,
431
+ branch: args.branch,
432
+ });
433
+ initializeSessionLog(active);
434
+ sessionStartEvent = createEvent(active, {
435
+ session_id: active.session_id,
436
+ kind: "session_start",
437
+ actor,
438
+ payload: {
439
+ goal: args.goal,
440
+ user_prompt: args.user_prompt,
441
+ repo: args.repo,
442
+ branch: args.branch,
443
+ },
444
+ visibility: "review",
445
+ });
446
+ await persistEvent(sessionStartEvent);
447
+ }
448
+ else {
449
+ reusedSession = true;
450
+ }
451
+ let intent = null;
452
+ if (args.intent_title) {
453
+ intent = await appendIntentEvent({
454
+ title: args.intent_title,
455
+ description: args.intent_description,
456
+ priority: args.intent_priority,
457
+ });
458
+ }
459
+ return textContent({
460
+ session_id: active.session_id,
461
+ reused_session: reusedSession,
462
+ start_event_id: sessionStartEvent?.id ?? null,
463
+ start_seq: sessionStartEvent?.seq ?? null,
464
+ intent_id: intent?.intent_id ?? active.active_intent_id ?? null,
465
+ intent_event_id: intent?.event.id ?? null,
466
+ rule_hint: "Use gateway_act for all subsequent operations.",
467
+ });
468
+ }
469
+ catch (err) {
470
+ return errorContent(err);
471
+ }
472
+ }
473
+ export async function handleGatewayAct(raw) {
474
+ try {
475
+ const args = gatewayActSchema.parse(raw);
476
+ const state = await ensureGatewaySession();
477
+ const rule = GATEWAY_RULES[args.op];
478
+ const visibility = args.visibility ?? rule.default_visibility;
479
+ const usagePayload = args.usage
480
+ ? {
481
+ model: args.usage.model,
482
+ prompt_tokens: args.usage.prompt_tokens,
483
+ completion_tokens: args.usage.completion_tokens,
484
+ total_tokens: args.usage.total_tokens,
485
+ estimated_cost_usd: args.usage.estimated_cost_usd,
486
+ }
487
+ : undefined;
488
+ if (args.op === "intent") {
489
+ if (!args.intent)
490
+ throw new Error("op=intent requires `intent` payload.");
491
+ const intent = await appendIntentEvent(args.intent);
492
+ return textContent({
493
+ mapped_tool: rule.maps_to_tool,
494
+ event_id: intent.event.id,
495
+ kind: intent.event.kind,
496
+ seq: intent.event.seq,
497
+ ts: intent.event.ts,
498
+ intent_id: intent.intent_id,
499
+ });
500
+ }
501
+ if (args.op === "decision") {
502
+ if (!args.decision)
503
+ throw new Error("op=decision requires `decision` payload.");
504
+ const event = await appendCurrentSessionEvent({
505
+ kind: "decision",
506
+ payload: {
507
+ summary: args.decision.summary,
508
+ rationale: args.decision.rationale,
509
+ options: args.decision.options,
510
+ chosen_option: args.decision.chosen_option,
511
+ reversibility: args.decision.reversibility,
512
+ usage: usagePayload,
513
+ },
514
+ scope: { intent_id: state.active_intent_id },
515
+ visibility,
516
+ });
517
+ return textContent({
518
+ mapped_tool: rule.maps_to_tool,
519
+ event_id: event.id,
520
+ kind: event.kind,
521
+ seq: event.seq,
522
+ ts: event.ts,
523
+ });
524
+ }
525
+ if (args.op === "assumption") {
526
+ if (!args.assumption)
527
+ throw new Error("op=assumption requires `assumption` payload.");
528
+ const event = await appendCurrentSessionEvent({
529
+ kind: "assumption",
530
+ payload: {
531
+ statement: args.assumption.statement,
532
+ validated: args.assumption.validated ?? "unknown",
533
+ risk: args.assumption.risk,
534
+ usage: usagePayload,
535
+ },
536
+ scope: { intent_id: state.active_intent_id },
537
+ visibility,
538
+ });
539
+ return textContent({
540
+ mapped_tool: rule.maps_to_tool,
541
+ event_id: event.id,
542
+ kind: event.kind,
543
+ seq: event.seq,
544
+ ts: event.ts,
545
+ });
546
+ }
547
+ if (args.op === "verification") {
548
+ if (!args.verification)
549
+ throw new Error("op=verification requires `verification` payload.");
550
+ const event = await appendCurrentSessionEvent({
551
+ kind: "verification",
552
+ payload: {
553
+ type: args.verification.type,
554
+ result: args.verification.result,
555
+ details: args.verification.details,
556
+ usage: usagePayload,
557
+ },
558
+ scope: { intent_id: state.active_intent_id },
559
+ visibility,
560
+ });
561
+ return textContent({
562
+ mapped_tool: rule.maps_to_tool,
563
+ event_id: event.id,
564
+ kind: event.kind,
565
+ seq: event.seq,
566
+ ts: event.ts,
567
+ });
568
+ }
569
+ if (!args.action) {
570
+ throw new Error(`op=${args.op} requires 'action'.`);
571
+ }
572
+ if (!state.active_intent_id) {
573
+ const intent = await appendIntentEvent({
574
+ title: `Auto intent: ${args.op} ${args.action}`.trim(),
575
+ description: "Created automatically by gateway_act",
576
+ });
577
+ setActiveIntent(intent.intent_id);
578
+ }
579
+ const kind = args.op === "file" ? "file_op" : "tool_call";
580
+ const scope = {
581
+ intent_id: state.active_intent_id,
582
+ file: args.op === "file" ? args.target : undefined,
583
+ module: args.details && typeof args.details.module === "string"
584
+ ? args.details.module
585
+ : undefined,
586
+ };
587
+ const event = await appendCurrentSessionEvent({
588
+ kind,
589
+ payload: {
590
+ category: args.op,
591
+ action: args.action,
592
+ target: args.target,
593
+ details: args.details ?? {},
594
+ usage: usagePayload,
595
+ },
596
+ scope,
597
+ visibility,
598
+ });
599
+ let verificationEvent = null;
600
+ if (args.verification) {
601
+ verificationEvent = await appendCurrentSessionEvent({
602
+ kind: "verification",
603
+ payload: {
604
+ type: args.verification.type,
605
+ result: args.verification.result,
606
+ details: args.verification.details,
607
+ usage: usagePayload,
608
+ },
609
+ scope: { intent_id: state.active_intent_id },
610
+ visibility: "review",
611
+ });
612
+ }
613
+ return textContent({
614
+ mapped_tool: rule.maps_to_tool,
615
+ event_id: event.id,
616
+ kind: event.kind,
617
+ seq: event.seq,
618
+ ts: event.ts,
619
+ verification_event_id: verificationEvent?.id ?? null,
620
+ usage: usagePayload ?? null,
621
+ });
622
+ }
623
+ catch (err) {
624
+ return errorContent(err);
625
+ }
626
+ }
627
+ export async function handleGatewayEndRun(raw) {
628
+ try {
629
+ const active = getActiveSession();
630
+ if (!active || active.ended_at) {
631
+ return textContent({
632
+ ended: false,
633
+ reason: "No active session to close.",
634
+ });
635
+ }
636
+ return handleRecordSessionEnd(gatewayEndSchema.parse(raw));
637
+ }
638
+ catch (err) {
639
+ return errorContent(err);
640
+ }
641
+ }
642
+ export const toolSchemas = {
643
+ record_session_start: { inputSchema: sessionStartSchema.shape },
644
+ record_intent: { inputSchema: intentSchema.shape },
645
+ record_activity: { inputSchema: activitySchema.shape },
646
+ record_decision: { inputSchema: decisionSchema.shape },
647
+ record_assumption: { inputSchema: assumptionSchema.shape },
648
+ record_verification: { inputSchema: verificationSchema.shape },
649
+ record_session_end: { inputSchema: sessionEndSchema.shape },
650
+ gateway_begin_run: { inputSchema: gatewayBeginSchema.shape },
651
+ gateway_act: { inputSchema: gatewayActSchema.shape },
652
+ gateway_end_run: { inputSchema: gatewayEndSchema.shape },
653
+ };
654
+ export const EVENT_EXAMPLES = {
655
+ record_session_start: {
656
+ id: "sess_1739620000000_abcd1234:1:a1b2c3d4",
657
+ session_id: "sess_1739620000000_abcd1234",
658
+ seq: 1,
659
+ ts: "2026-02-15T20:00:00.000Z",
660
+ kind: "session_start",
661
+ actor: { type: "agent" },
662
+ payload: {
663
+ goal: "Add robust audit logging",
664
+ user_prompt: "Refactor tools to canonical event model",
665
+ repo: "AL/mcp-server",
666
+ branch: "codex/refactor-audit-tools",
667
+ },
668
+ visibility: "review",
669
+ schema_version: 1,
670
+ },
671
+ record_intent: {
672
+ id: "sess_1739620000000_abcd1234:2:e5f6a7b8",
673
+ session_id: "sess_1739620000000_abcd1234",
674
+ seq: 2,
675
+ ts: "2026-02-15T20:00:10.000Z",
676
+ kind: "intent",
677
+ actor: { type: "agent" },
678
+ scope: { intent_id: "intent_1739620010000_1122aabb" },
679
+ payload: {
680
+ intent_id: "intent_1739620010000_1122aabb",
681
+ title: "Replace old MCP tools",
682
+ description: "Converge to 7 semantic tools",
683
+ priority: 1,
684
+ },
685
+ visibility: "review",
686
+ schema_version: 1,
687
+ },
688
+ record_activity: {
689
+ id: "sess_1739620000000_abcd1234:3:c9d0e1f2",
690
+ session_id: "sess_1739620000000_abcd1234",
691
+ seq: 3,
692
+ ts: "2026-02-15T20:00:20.000Z",
693
+ kind: "file_op",
694
+ actor: { type: "agent" },
695
+ scope: {
696
+ intent_id: "intent_1739620010000_1122aabb",
697
+ file: "src/tools.ts",
698
+ module: "tools",
699
+ },
700
+ payload: {
701
+ category: "file",
702
+ action: "edit",
703
+ target: "src/tools.ts",
704
+ details: { lines_changed: 120, module: "tools" },
705
+ },
706
+ visibility: "raw",
707
+ schema_version: 1,
708
+ },
709
+ record_decision: {
710
+ id: "sess_1739620000000_abcd1234:4:3344ccdd",
711
+ session_id: "sess_1739620000000_abcd1234",
712
+ seq: 4,
713
+ ts: "2026-02-15T20:00:30.000Z",
714
+ kind: "decision",
715
+ actor: { type: "agent" },
716
+ scope: { intent_id: "intent_1739620010000_1122aabb" },
717
+ payload: {
718
+ summary: "Use JSONL for append-only persistence",
719
+ rationale: "Reduces corruption risk and preserves ordering",
720
+ options: ["single JSON rewrite", "JSONL append-only"],
721
+ chosen_option: "JSONL append-only",
722
+ reversibility: "easy",
723
+ },
724
+ visibility: "review",
725
+ schema_version: 1,
726
+ },
727
+ record_assumption: {
728
+ id: "sess_1739620000000_abcd1234:5:99aabbcc",
729
+ session_id: "sess_1739620000000_abcd1234",
730
+ seq: 5,
731
+ ts: "2026-02-15T20:00:40.000Z",
732
+ kind: "assumption",
733
+ actor: { type: "agent" },
734
+ scope: { intent_id: "intent_1739620010000_1122aabb" },
735
+ payload: {
736
+ statement: "Single active session is sufficient for one agent run",
737
+ validated: "unknown",
738
+ risk: "medium",
739
+ },
740
+ visibility: "review",
741
+ schema_version: 1,
742
+ },
743
+ record_verification: {
744
+ id: "sess_1739620000000_abcd1234:6:77dd8899",
745
+ session_id: "sess_1739620000000_abcd1234",
746
+ seq: 6,
747
+ ts: "2026-02-15T20:00:50.000Z",
748
+ kind: "verification",
749
+ actor: { type: "agent" },
750
+ scope: { intent_id: "intent_1739620010000_1122aabb" },
751
+ payload: {
752
+ type: "test",
753
+ result: "pass",
754
+ details: "npm run build",
755
+ },
756
+ visibility: "review",
757
+ schema_version: 1,
758
+ },
759
+ record_session_end: {
760
+ id: "sess_1739620000000_abcd1234:7:44ee66ff",
761
+ session_id: "sess_1739620000000_abcd1234",
762
+ seq: 7,
763
+ ts: "2026-02-15T20:01:00.000Z",
764
+ kind: "session_end",
765
+ actor: { type: "agent" },
766
+ payload: {
767
+ outcome: "completed",
768
+ summary: "Tool model refactor finished",
769
+ },
770
+ visibility: "review",
771
+ schema_version: 1,
772
+ },
773
+ };
774
+ export const AGENT_INSTRUCTIONS = [
775
+ "Preferred low-friction path: call gateway_begin_run once, gateway_act for every operation, then gateway_end_run once.",
776
+ "Call record_session_start once before any other tool.",
777
+ "Call record_intent whenever objective shifts; use one intent per cohesive chunk.",
778
+ "Use record_activity for every meaningful file/tool/search/execution step.",
779
+ "Use record_decision for irreversible or high-impact choices.",
780
+ "Use record_assumption for uncertain premises that affect implementation.",
781
+ "Use record_verification for tests/lint/typecheck/manual checks with explicit result.",
782
+ "Call record_session_end exactly once to close the session.",
783
+ ];