driftseal 1.4.0 → 2.1.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.
@@ -79,14 +79,26 @@ function registerTools(server, api, z) {
79
79
  stdoutBytes: z.number().int().nonnegative(),
80
80
  stderrBytes: z.number().int().nonnegative(),
81
81
  workspace: z.string().regex(/^[a-f0-9]{64}$/).nullable(),
82
+ contractHash: z.string().regex(/^[a-f0-9]{64}$/).nullable(),
82
83
  head: z.string().nullable(),
83
84
  ranAt: z.string(),
84
85
  });
85
- const intentRecord = z.object({
86
+ const extensionRecord = z.object({
87
+ extension: z.string(),
88
+ acceptance: z.array(z.string()),
89
+ verify: z.string().nullable(),
90
+ decisions: z.array(z.string()),
91
+ extendedAt: z.string(),
92
+ head: z.string().nullable(),
93
+ });
94
+ const outcomeRecord = z.object({
86
95
  id: z.string(),
87
- intent: z.string(),
96
+ outcome: z.string(),
97
+ lane: z.string().optional(),
98
+ extensions: z.array(extensionRecord),
88
99
  acceptance: z.array(z.string()),
89
100
  verify: z.string().nullable(),
101
+ contractHash: z.string().regex(/^[a-f0-9]{64}$/),
90
102
  verification: verificationRecord.nullable(),
91
103
  decisions: z.array(z.string()),
92
104
  status: z.enum(END_STATUSES).or(z.literal('in_progress')),
@@ -99,6 +111,10 @@ function registerTools(server, api, z) {
99
111
  reclaimed: z.boolean(),
100
112
  reclaimReason: z.string().nullable(),
101
113
  reclaimedAt: z.string().nullable(),
114
+ imported: z.object({
115
+ sourceIds: z.array(z.string()),
116
+ sourceFingerprint: z.string().regex(/^[a-f0-9]{64}$/),
117
+ }).nullable(),
102
118
  readOnly: z.boolean().optional(),
103
119
  });
104
120
  const decisionRecord = z.object({
@@ -111,7 +127,7 @@ function registerTools(server, api, z) {
111
127
  const absorbResult = z.object({
112
128
  mappings: z.array(
113
129
  z.object({
114
- kind: z.enum(['intent', 'decision']),
130
+ kind: z.enum(['outcome', 'decision']),
115
131
  from: z.string(),
116
132
  to: z.string(),
117
133
  })
@@ -131,27 +147,27 @@ function registerTools(server, api, z) {
131
147
  server.registerTool(
132
148
  'driftseal_status',
133
149
  {
134
- title: 'Get current DriftSeal intent',
150
+ title: 'Get current DriftSeal outcome',
135
151
  description:
136
- 'Inspect the one intent currently in progress before repository work or after context loss. Returns null when no intent is open.',
152
+ 'Inspect the one outcome currently in progress before repository work or after context loss. Returns null when no outcome is open.',
137
153
  inputSchema: {},
138
154
  outputSchema: {
139
155
  root: z.string(),
140
- intent: intentRecord.nullable(),
156
+ outcome: outcomeRecord.nullable(),
141
157
  readOnly: z.boolean().optional(),
142
158
  },
143
159
  annotations: readOnly,
144
160
  },
145
161
  async () =>
146
162
  guarded(() => {
147
- const intent = api.status();
163
+ const outcome = api.status();
148
164
  const readOnly = api.readOnly;
149
- const snapshot = intent && readOnly ? { ...intent, readOnly: true } : intent;
165
+ const snapshot = outcome && readOnly ? { ...outcome, readOnly: true } : outcome;
150
166
  const summary = snapshot
151
- ? `Intent ${snapshot.id} is ${snapshot.status}.`
152
- : 'No DriftSeal intent is in progress.';
167
+ ? `Outcome ${snapshot.id} is ${snapshot.status}.`
168
+ : 'No DriftSeal outcome is in progress.';
153
169
  return success(
154
- { root: api.root, intent: snapshot, ...(readOnly ? { readOnly: true } : {}) },
170
+ { root: api.root, outcome: snapshot, ...(readOnly ? { readOnly: true } : {}) },
155
171
  readOnly ? `${summary} ${READ_ONLY_SUFFIX}` : summary
156
172
  );
157
173
  })
@@ -160,11 +176,11 @@ function registerTools(server, api, z) {
160
176
  server.registerTool(
161
177
  'driftseal_begin',
162
178
  {
163
- title: 'Begin a DriftSeal intent',
179
+ title: 'Begin a DriftSeal outcome',
164
180
  description:
165
- 'Open one focused work-round intent before making repository changes. Fails if another intent is already open; close it explicitly first.',
181
+ 'Open one coherent delivery outcome before making durable project changes. Fails if another outcome is already open.',
166
182
  inputSchema: {
167
- intent: nonEmpty.describe('Outcome this work round will accomplish.'),
183
+ outcome: nonEmpty.describe('Coherent delivery outcome this work will accomplish.'),
168
184
  acceptance: z
169
185
  .array(nonEmpty)
170
186
  .default([])
@@ -175,13 +191,35 @@ function registerTools(server, api, z) {
175
191
  .default([])
176
192
  .describe('Existing decision IDs this round may change or explicitly confirm.'),
177
193
  },
178
- outputSchema: { root: z.string(), intent: intentRecord },
194
+ outputSchema: { root: z.string(), outcome: outcomeRecord },
195
+ annotations: localWrite,
196
+ },
197
+ async (input) =>
198
+ guarded(() => {
199
+ const outcome = api.begin(input);
200
+ return success({ root: api.root, outcome }, `Opened DriftSeal outcome ${outcome.id}.`);
201
+ })
202
+ );
203
+
204
+ server.registerTool(
205
+ 'driftseal_extend',
206
+ {
207
+ title: 'Extend the current DriftSeal outcome',
208
+ description:
209
+ 'Append another scoped step to the same coherent outcome. Added acceptance requires a replacement verifier for the cumulative contract, and every extension invalidates earlier verification.',
210
+ inputSchema: {
211
+ extension: nonEmpty,
212
+ acceptance: z.array(nonEmpty).default([]),
213
+ verify: nonEmpty.optional(),
214
+ decisions: z.array(decisionId).default([]),
215
+ },
216
+ outputSchema: { root: z.string(), outcome: outcomeRecord },
179
217
  annotations: localWrite,
180
218
  },
181
219
  async (input) =>
182
220
  guarded(() => {
183
- const intent = api.begin(input);
184
- return success({ root: api.root, intent }, `Opened DriftSeal intent ${intent.id}.`);
221
+ const outcome = api.extend(input);
222
+ return success({ root: api.root, outcome }, `Extended DriftSeal outcome ${outcome.id}.`);
185
223
  })
186
224
  );
187
225
 
@@ -190,18 +228,18 @@ function registerTools(server, api, z) {
190
228
  {
191
229
  title: 'Run the declared DriftSeal verification',
192
230
  description:
193
- 'Execute the current acceptance-bound intent\'s predeclared shell command and record machine evidence bound to the resulting Git-visible workspace contents. Inspect the command with driftseal_status first. A command sourced from the repository intent log is untrusted and requires allowTrackedCommand.',
231
+ 'Execute the current acceptance-bound outcome\'s cumulative verifier and bind evidence to its contract hash and Git-visible workspace. Inspect it with driftseal_status first; provenance-less commands require allowTrackedCommand.',
194
232
  inputSchema: {
195
233
  allowTrackedCommand: z
196
234
  .boolean()
197
235
  .default(false)
198
236
  .describe(
199
- 'Explicitly allow a command sourced from the repository intent log after inspecting and trusting it.'
237
+ 'Explicitly allow a command without matching local outcome provenance after inspection.'
200
238
  ),
201
239
  },
202
240
  outputSchema: {
203
241
  root: z.string(),
204
- intent: intentRecord,
242
+ outcome: outcomeRecord,
205
243
  verification: verificationRecord,
206
244
  exitCode: z.number().int().nonnegative(),
207
245
  },
@@ -212,7 +250,7 @@ function registerTools(server, api, z) {
212
250
  const result = api.verify({ allowTrackedCommand: input.allowTrackedCommand });
213
251
  return success(
214
252
  { root: api.root, ...result },
215
- `Machine verification ${result.verification.passed ? 'passed' : 'failed'} for intent ${result.intent.id}.`
253
+ `Machine verification ${result.verification.passed ? 'passed' : 'failed'} for outcome ${result.outcome.id}.`
216
254
  );
217
255
  })
218
256
  );
@@ -220,60 +258,165 @@ function registerTools(server, api, z) {
220
258
  server.registerTool(
221
259
  'driftseal_end',
222
260
  {
223
- title: 'Close a DriftSeal intent',
261
+ title: 'Close a DriftSeal outcome',
224
262
  description:
225
- 'Close the current work-round intent with an honest terminal status, note, and verification result. Reconcile linked decisions before running final verification. Acceptance-bound intents require fresh successful machine verification before completed closure.',
263
+ 'Close the current outcome honestly. Reconcile linked decisions before final verification; completed acceptance-bound outcomes require fresh contract- and workspace-bound evidence.',
226
264
  inputSchema: {
227
- id: z.string().optional().describe('Intent ID; omit to close the current open intent.'),
265
+ id: z.string().optional().describe('Outcome ID; omit to close the current open outcome.'),
228
266
  status: closedStatus.default('completed'),
229
267
  note: nonEmpty.optional().describe('What actually happened in the round.'),
230
268
  verifyResult: nonEmpty.optional().describe('Concise, honest result of the declared verification.'),
231
269
  },
232
- outputSchema: { root: z.string(), intent: intentRecord },
270
+ outputSchema: { root: z.string(), outcome: outcomeRecord },
233
271
  annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: false },
234
272
  },
235
273
  async (input) =>
236
274
  guarded(() => {
237
- const intent = api.end(input);
238
- return success({ root: api.root, intent }, `Closed DriftSeal intent ${intent.id} as ${intent.status}.`);
275
+ const outcome = api.end(input);
276
+ return success({ root: api.root, outcome }, `Closed DriftSeal outcome ${outcome.id} as ${outcome.status}.`);
239
277
  })
240
278
  );
241
279
 
242
280
  server.registerTool(
243
281
  'driftseal_log',
244
282
  {
245
- title: 'List DriftSeal intent history',
283
+ title: 'List DriftSeal outcome history',
246
284
  description:
247
- 'Review recent or complete DriftSeal intent history to re-anchor work and understand prior outcomes. Reclaimed records are hidden unless includeReclaimed is set.',
285
+ 'Review recent or complete DriftSeal outcome history. Defaults to the current lane. Reclaimed records are hidden unless includeReclaimed is set.',
248
286
  inputSchema: {
249
287
  last: z.number().int().positive().max(100).optional(),
250
288
  includeReclaimed: z.boolean().default(false),
289
+ allLanes: z
290
+ .boolean()
291
+ .default(false)
292
+ .describe('Show outcomes from every lane instead of the current lane.'),
251
293
  },
252
294
  outputSchema: {
253
295
  root: z.string(),
254
- intents: z.array(intentRecord),
296
+ outcomes: z.array(outcomeRecord),
255
297
  readOnly: z.boolean().optional(),
256
298
  },
257
299
  annotations: readOnly,
258
300
  },
259
301
  async (input) =>
260
302
  guarded(() => {
261
- const intents = api.log({ last: input.last, all: input.includeReclaimed });
303
+ const outcomes = api.log({
304
+ last: input.last,
305
+ all: input.includeReclaimed,
306
+ allLanes: input.allLanes,
307
+ });
262
308
  const readOnly = api.readOnly;
263
- const summary = `Found ${intents.length} DriftSeal intent records.`;
309
+ const summary = `Found ${outcomes.length} DriftSeal outcome records.`;
264
310
  return success(
265
- { root: api.root, intents, ...(readOnly ? { readOnly: true } : {}) },
311
+ { root: api.root, outcomes, ...(readOnly ? { readOnly: true } : {}) },
266
312
  readOnly ? `${summary} ${READ_ONLY_SUFFIX}` : summary
267
313
  );
268
314
  })
269
315
  );
270
316
 
317
+ const laneRecord = z.object({
318
+ name: z.string(),
319
+ description: z.string().nullable(),
320
+ addedAt: z.string().nullable(),
321
+ inferred: z.boolean().optional(),
322
+ visible: z.number().int().nonnegative(),
323
+ count: z.number().int().nonnegative(),
324
+ current: z.boolean().optional(),
325
+ });
326
+
327
+ server.registerTool(
328
+ 'driftseal_lane',
329
+ {
330
+ title: 'Show DriftSeal lanes',
331
+ description:
332
+ 'List named outcome lanes and the current lane. Re-anchoring and log history follow the current lane.',
333
+ inputSchema: {},
334
+ outputSchema: {
335
+ root: z.string(),
336
+ current: z.string(),
337
+ missingCurrentLane: z.string().nullable().optional(),
338
+ lanes: z.array(laneRecord),
339
+ total: z.number().int().nonnegative(),
340
+ readOnly: z.boolean().optional(),
341
+ },
342
+ annotations: readOnly,
343
+ },
344
+ async () =>
345
+ guarded(() => {
346
+ const snapshot = api.lane();
347
+ const readOnly = api.readOnly;
348
+ return success(
349
+ { root: api.root, ...snapshot, ...(readOnly ? { readOnly: true } : {}) },
350
+ `Current DriftSeal lane is ${snapshot.current}.`
351
+ );
352
+ })
353
+ );
354
+
355
+ server.registerTool(
356
+ 'driftseal_lane_add',
357
+ {
358
+ title: 'Add a DriftSeal lane',
359
+ description:
360
+ 'Create a named lane for a long-lived capability. The default lane main always exists.',
361
+ inputSchema: {
362
+ name: nonEmpty.describe('Lane name: a lowercase letter, then letters, digits, or hyphens.'),
363
+ description: nonEmpty.optional(),
364
+ },
365
+ outputSchema: { root: z.string(), name: z.string(), description: z.string().nullable() },
366
+ annotations: localWrite,
367
+ },
368
+ async (input) =>
369
+ guarded(() => {
370
+ const lane = api.laneAdd({ name: input.name, description: input.description });
371
+ return success({ root: api.root, ...lane }, `Added DriftSeal lane ${lane.name}.`);
372
+ })
373
+ );
374
+
375
+ server.registerTool(
376
+ 'driftseal_lane_switch',
377
+ {
378
+ title: 'Switch the current DriftSeal lane',
379
+ description:
380
+ 'Move this worktree onto an existing lane. Refused while an outcome is open.',
381
+ inputSchema: { name: nonEmpty },
382
+ outputSchema: { root: z.string(), current: z.string() },
383
+ annotations: localWrite,
384
+ },
385
+ async (input) =>
386
+ guarded(() => {
387
+ const result = api.laneSwitch({ name: input.name });
388
+ return success({ root: api.root, ...result }, `Switched to DriftSeal lane ${result.current}.`);
389
+ })
390
+ );
391
+
392
+ server.registerTool(
393
+ 'driftseal_lane_assign',
394
+ {
395
+ title: 'Assign a closed outcome to a lane',
396
+ description: 'Move a closed outcome onto an existing lane with an append-only assign event.',
397
+ inputSchema: {
398
+ id: nonEmpty.describe('Closed outcome id.'),
399
+ lane: nonEmpty,
400
+ },
401
+ outputSchema: { root: z.string(), outcome: outcomeRecord },
402
+ annotations: localWrite,
403
+ },
404
+ async (input) =>
405
+ guarded(() => {
406
+ const outcome = api.laneAssign({ id: input.id, lane: input.lane });
407
+ return success(
408
+ { root: api.root, outcome },
409
+ `Assigned outcome ${outcome.id} to lane ${outcome.lane}.`
410
+ );
411
+ })
412
+ );
413
+
271
414
  server.registerTool(
272
415
  'driftseal_absorb',
273
416
  {
274
417
  title: 'Absorb another DriftSeal lineage',
275
418
  description:
276
- 'Repair the fixed repository after a merge collision or absorb another worktree\'s intent and decision logs, remapping colliding IDs. Omit otherLog to repair the current repository. This rewrites only the fixed repository; incoming paths are read-only sources.',
419
+ 'Repair the fixed repository after a merge collision or absorb another worktree\'s outcome and MADR logs, remapping colliding IDs.',
277
420
  inputSchema: {
278
421
  otherLog: z
279
422
  .string()
@@ -286,7 +429,7 @@ function registerTools(server, api, z) {
286
429
  abandon: z
287
430
  .enum(['ours', 'theirs'])
288
431
  .optional()
289
- .describe('Side whose open intent to abandon when both lineages have one in progress.'),
432
+ .describe('Side whose open outcome to abandon when both lineages have one in progress.'),
290
433
  dryRun: z.boolean().default(false),
291
434
  },
292
435
  outputSchema: { root: z.string(), result: absorbResult },
@@ -306,14 +449,14 @@ function registerTools(server, api, z) {
306
449
  server.registerTool(
307
450
  'driftseal_reclaim',
308
451
  {
309
- title: 'Reclaim DriftSeal intent records',
452
+ title: 'Reclaim DriftSeal outcome records',
310
453
  description:
311
- 'Hide meaningless closed intent records (for example harness- or sandbox-caused failures) by appending reclaim markers. Never deletes log lines. Without ids, reclaims failed/abandoned, decision-unlinked records older than olderThan days.',
454
+ 'Hide meaningless closed outcome records behind append-only markers. Never deletes log lines.',
312
455
  inputSchema: {
313
456
  ids: z
314
457
  .array(z.string())
315
458
  .default([])
316
- .describe('Intent IDs to reclaim; omit for batch mode by age.'),
459
+ .describe('Outcome IDs to reclaim; omit for batch mode by age.'),
317
460
  reason: nonEmpty.describe('Why these records are meaningless (required, kept in the log).'),
318
461
  olderThan: z
319
462
  .number()
@@ -327,12 +470,12 @@ function registerTools(server, api, z) {
327
470
  .describe('Allow reclaiming partial/completed or decision-linked records by explicit id.'),
328
471
  dryRun: z.boolean().default(false),
329
472
  },
330
- outputSchema: { root: z.string(), intents: z.array(intentRecord) },
473
+ outputSchema: { root: z.string(), outcomes: z.array(outcomeRecord) },
331
474
  annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: false },
332
475
  },
333
476
  async (input) =>
334
477
  guarded(() => {
335
- const intents = api.reclaim({
478
+ const outcomes = api.reclaim({
336
479
  ids: input.ids,
337
480
  reason: input.reason,
338
481
  olderThan: input.olderThan,
@@ -340,10 +483,10 @@ function registerTools(server, api, z) {
340
483
  dryRun: input.dryRun,
341
484
  });
342
485
  return success(
343
- { root: api.root, intents },
486
+ { root: api.root, outcomes },
344
487
  input.dryRun
345
- ? `${intents.length} DriftSeal intent records match.`
346
- : `Reclaimed ${intents.length} DriftSeal intent records.`
488
+ ? `${outcomes.length} DriftSeal outcome records match.`
489
+ : `Reclaimed ${outcomes.length} DriftSeal outcome records.`
347
490
  );
348
491
  })
349
492
  );
@@ -351,19 +494,19 @@ function registerTools(server, api, z) {
351
494
  server.registerTool(
352
495
  'driftseal_unreclaim',
353
496
  {
354
- title: 'Restore a reclaimed DriftSeal intent record',
355
- description: 'Restore one reclaimed intent record to the visible log by appending an unreclaim marker.',
497
+ title: 'Restore a reclaimed DriftSeal outcome record',
498
+ description: 'Restore one reclaimed outcome record to the visible log by appending an unreclaim marker.',
356
499
  inputSchema: {
357
500
  id: z.string(),
358
501
  reason: nonEmpty.describe('Why this record is being restored (required, kept in the log).'),
359
502
  },
360
- outputSchema: { root: z.string(), intent: intentRecord },
503
+ outputSchema: { root: z.string(), outcome: outcomeRecord },
361
504
  annotations: localWrite,
362
505
  },
363
506
  async (input) =>
364
507
  guarded(() => {
365
- const intent = api.unreclaim(input);
366
- return success({ root: api.root, intent }, `Restored DriftSeal intent ${intent.id}.`);
508
+ const outcome = api.unreclaim(input);
509
+ return success({ root: api.root, outcome }, `Restored DriftSeal outcome ${outcome.id}.`);
367
510
  })
368
511
  );
369
512
 
@@ -408,7 +551,7 @@ function registerTools(server, api, z) {
408
551
  {
409
552
  title: 'Add a DriftSeal decision',
410
553
  description:
411
- 'Create a MADR record only for durable rationale, rejected paths, deferred choices, or costly-to-reverse decisions that Git and the intent log cannot recover.',
554
+ 'Create a MADR record only for durable rationale, rejected paths, deferred choices, or costly-to-reverse decisions that Git and the outcome log cannot recover.',
412
555
  inputSchema: {
413
556
  title: nonEmpty,
414
557
  context: nonEmpty,
@@ -433,7 +576,7 @@ function registerTools(server, api, z) {
433
576
  {
434
577
  title: 'Reconcile a DriftSeal decision',
435
578
  description:
436
- 'Reconcile one decision linked to the current open intent, updating or explicitly confirming its status with a history note.',
579
+ 'Reconcile one decision linked to the current open outcome, updating or explicitly confirming its status with a history note.',
437
580
  inputSchema: {
438
581
  id: decisionId,
439
582
  status: decisionStatus.optional(),
@@ -448,6 +591,63 @@ function registerTools(server, api, z) {
448
591
  return success({ root: api.root, decision }, `Reconciled DriftSeal decision ${decision.id}.`);
449
592
  })
450
593
  );
594
+
595
+ const migrationPlan = z.object({
596
+ format: z.literal('driftseal-v1-to-v2-plan'),
597
+ sourceFingerprint: z.string().regex(/^[a-f0-9]{64}$/),
598
+ groups: z.array(z.object({
599
+ outcome: nonEmpty,
600
+ summary: nonEmpty,
601
+ sourceIds: z.array(z.string()).min(1),
602
+ })),
603
+ excluded: z.array(z.object({ sourceId: z.string(), reason: nonEmpty })).default([]),
604
+ });
605
+ const migrationSources = {
606
+ sourceLog: nonEmpty.optional().describe('Path to the v1 events.jsonl source.'),
607
+ sourceDecisions: nonEmpty.optional().describe('Path to the v1 MADR directory.'),
608
+ };
609
+ server.registerTool(
610
+ 'driftseal_migration_inspect',
611
+ {
612
+ title: 'Inspect a DriftSeal v1 repository for v2 migration',
613
+ description: 'Read and normalize custom or repository-default v1 logs for model-assisted grouping. The v2 destination is the fixed repository .seal root. Makes no changes.',
614
+ inputSchema: migrationSources,
615
+ outputSchema: { root: z.string(), inspection: z.unknown() },
616
+ annotations: readOnly,
617
+ },
618
+ async (locations) => guarded(() => {
619
+ const inspection = api.migrationInspect(locations);
620
+ return success({ root: api.root, inspection }, `Found ${inspection.records.length} closed v1 intent records.`);
621
+ })
622
+ );
623
+ server.registerTool(
624
+ 'driftseal_migration_apply',
625
+ {
626
+ title: 'Stage a validated DriftSeal v1-to-v2 migration',
627
+ description: 'Validate a model-generated ordered grouping plan, create .seal side-by-side, copy MADRs byte-for-byte, and never delete v1 data.',
628
+ inputSchema: { plan: migrationPlan, ...migrationSources },
629
+ outputSchema: { root: z.string(), result: z.unknown() },
630
+ annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: false },
631
+ },
632
+ async ({ plan, ...locations }) => guarded(() => {
633
+ const result = api.migrationApply({ plan, ...locations });
634
+ return success({ root: api.root, result }, 'Staged DriftSeal v2 without deleting v1 data.');
635
+ })
636
+ );
637
+ server.registerTool(
638
+ 'driftseal_migration_check',
639
+ {
640
+ title: 'Check a staged DriftSeal v1-to-v2 migration',
641
+ description: 'Validate the staged outcome log and manifest-backed MADRs, then report whether v1 still awaits manual removal.',
642
+ inputSchema: migrationSources,
643
+ outputSchema: { root: z.string(), result: z.unknown() },
644
+ annotations: readOnly,
645
+ },
646
+ async (locations) => guarded(() => {
647
+ const result = api.migrationCheck(locations);
648
+ return success({ root: api.root, result }, result.complete ? 'Migration complete.' : 'Migration valid; v1 remains for user review.');
649
+ })
650
+ );
451
651
  }
452
652
 
453
653
  function registerResources(server, api) {
@@ -464,22 +664,29 @@ function registerResources(server, api) {
464
664
  };
465
665
 
466
666
  registerJson(
467
- 'current-intent',
468
- 'driftseal://intent/current',
469
- 'Current DriftSeal intent',
470
- 'The work-round intent currently in progress for the fixed repository.',
471
- () => ({ root: api.root, intent: api.status() })
667
+ 'current-outcome',
668
+ 'driftseal://outcome/current',
669
+ 'Current DriftSeal outcome',
670
+ 'The delivery outcome currently in progress for the fixed repository.',
671
+ () => ({ root: api.root, outcome: api.status() })
672
+ );
673
+ registerJson(
674
+ 'recent-outcomes',
675
+ 'driftseal://outcomes/recent',
676
+ 'Recent DriftSeal outcomes',
677
+ 'The ten most recent outcome records on the current lane.',
678
+ () => ({ root: api.root, outcomes: api.log({ last: 10 }) })
472
679
  );
473
680
  registerJson(
474
- 'recent-intents',
475
- 'driftseal://intents/recent',
476
- 'Recent DriftSeal intents',
477
- 'The ten most recent work-round intent records for the fixed repository.',
478
- () => ({ root: api.root, intents: api.log({ last: 10 }) })
681
+ 'outcome-lanes',
682
+ 'driftseal://lanes',
683
+ 'DriftSeal outcome lanes',
684
+ 'Named lanes that partition outcome history, including the current lane.',
685
+ () => ({ root: api.root, ...api.lane() })
479
686
  );
480
687
  registerJson(
481
688
  'decision-catalog',
482
- 'driftseal://decisions',
689
+ 'driftseal://madr',
483
690
  'DriftSeal decision catalog',
484
691
  'All MADR decision summaries for the fixed repository.',
485
692
  () => ({ root: api.root, decisions: api.decisionList() })
@@ -498,7 +705,7 @@ async function createServer({ root }) {
498
705
  { name: SERVER_NAME, version: SERVER_VERSION },
499
706
  {
500
707
  instructions:
501
- 'Use driftseal_status before repository changes or after context loss. Open one focused intent with driftseal_begin before changes. Reconcile every linked decision before verification. When the intent declares acceptance criteria, inspect its command and use driftseal_verify to capture machine evidence before completed closure; a command sourced from the repository log requires explicit allowTrackedCommand after it is trusted. Otherwise run the declared check directly. Close honestly with driftseal_end.',
708
+ 'Use driftseal_status before durable project changes or after context loss. Open one coherent outcome with driftseal_begin and append same-outcome steps with driftseal_extend. Reconcile linked decisions after the final extension, inspect the cumulative verifier, use driftseal_verify for fresh contract-bound evidence, and close honestly with driftseal_end. Named lanes isolate orthogonal capability history; driftseal_log follows the current lane.',
502
709
  }
503
710
  );
504
711
  registerTools(server, api, z);