driftseal 1.3.2 → 2.0.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/README.md +223 -322
- package/README.zh-CN.md +199 -287
- package/bin/driftseal-mcp.js +156 -62
- package/bin/driftseal.js +1971 -352
- package/index.js +3 -0
- package/package.json +4 -3
- package/skills/use-driftseal/SKILL.md +19 -13
package/bin/driftseal-mcp.js
CHANGED
|
@@ -79,14 +79,25 @@ 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
|
|
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
|
-
|
|
96
|
+
outcome: z.string(),
|
|
97
|
+
extensions: z.array(extensionRecord),
|
|
88
98
|
acceptance: z.array(z.string()),
|
|
89
99
|
verify: z.string().nullable(),
|
|
100
|
+
contractHash: z.string().regex(/^[a-f0-9]{64}$/),
|
|
90
101
|
verification: verificationRecord.nullable(),
|
|
91
102
|
decisions: z.array(z.string()),
|
|
92
103
|
status: z.enum(END_STATUSES).or(z.literal('in_progress')),
|
|
@@ -99,6 +110,10 @@ function registerTools(server, api, z) {
|
|
|
99
110
|
reclaimed: z.boolean(),
|
|
100
111
|
reclaimReason: z.string().nullable(),
|
|
101
112
|
reclaimedAt: z.string().nullable(),
|
|
113
|
+
imported: z.object({
|
|
114
|
+
sourceIds: z.array(z.string()),
|
|
115
|
+
sourceFingerprint: z.string().regex(/^[a-f0-9]{64}$/),
|
|
116
|
+
}).nullable(),
|
|
102
117
|
readOnly: z.boolean().optional(),
|
|
103
118
|
});
|
|
104
119
|
const decisionRecord = z.object({
|
|
@@ -111,7 +126,7 @@ function registerTools(server, api, z) {
|
|
|
111
126
|
const absorbResult = z.object({
|
|
112
127
|
mappings: z.array(
|
|
113
128
|
z.object({
|
|
114
|
-
kind: z.enum(['
|
|
129
|
+
kind: z.enum(['outcome', 'decision']),
|
|
115
130
|
from: z.string(),
|
|
116
131
|
to: z.string(),
|
|
117
132
|
})
|
|
@@ -131,27 +146,27 @@ function registerTools(server, api, z) {
|
|
|
131
146
|
server.registerTool(
|
|
132
147
|
'driftseal_status',
|
|
133
148
|
{
|
|
134
|
-
title: 'Get current DriftSeal
|
|
149
|
+
title: 'Get current DriftSeal outcome',
|
|
135
150
|
description:
|
|
136
|
-
'Inspect the one
|
|
151
|
+
'Inspect the one outcome currently in progress before repository work or after context loss. Returns null when no outcome is open.',
|
|
137
152
|
inputSchema: {},
|
|
138
153
|
outputSchema: {
|
|
139
154
|
root: z.string(),
|
|
140
|
-
|
|
155
|
+
outcome: outcomeRecord.nullable(),
|
|
141
156
|
readOnly: z.boolean().optional(),
|
|
142
157
|
},
|
|
143
158
|
annotations: readOnly,
|
|
144
159
|
},
|
|
145
160
|
async () =>
|
|
146
161
|
guarded(() => {
|
|
147
|
-
const
|
|
162
|
+
const outcome = api.status();
|
|
148
163
|
const readOnly = api.readOnly;
|
|
149
|
-
const snapshot =
|
|
164
|
+
const snapshot = outcome && readOnly ? { ...outcome, readOnly: true } : outcome;
|
|
150
165
|
const summary = snapshot
|
|
151
|
-
? `
|
|
152
|
-
: 'No DriftSeal
|
|
166
|
+
? `Outcome ${snapshot.id} is ${snapshot.status}.`
|
|
167
|
+
: 'No DriftSeal outcome is in progress.';
|
|
153
168
|
return success(
|
|
154
|
-
{ root: api.root,
|
|
169
|
+
{ root: api.root, outcome: snapshot, ...(readOnly ? { readOnly: true } : {}) },
|
|
155
170
|
readOnly ? `${summary} ${READ_ONLY_SUFFIX}` : summary
|
|
156
171
|
);
|
|
157
172
|
})
|
|
@@ -160,11 +175,11 @@ function registerTools(server, api, z) {
|
|
|
160
175
|
server.registerTool(
|
|
161
176
|
'driftseal_begin',
|
|
162
177
|
{
|
|
163
|
-
title: 'Begin a DriftSeal
|
|
178
|
+
title: 'Begin a DriftSeal outcome',
|
|
164
179
|
description:
|
|
165
|
-
'Open one
|
|
180
|
+
'Open one coherent delivery outcome before making durable project changes. Fails if another outcome is already open.',
|
|
166
181
|
inputSchema: {
|
|
167
|
-
|
|
182
|
+
outcome: nonEmpty.describe('Coherent delivery outcome this work will accomplish.'),
|
|
168
183
|
acceptance: z
|
|
169
184
|
.array(nonEmpty)
|
|
170
185
|
.default([])
|
|
@@ -175,13 +190,35 @@ function registerTools(server, api, z) {
|
|
|
175
190
|
.default([])
|
|
176
191
|
.describe('Existing decision IDs this round may change or explicitly confirm.'),
|
|
177
192
|
},
|
|
178
|
-
outputSchema: { root: z.string(),
|
|
193
|
+
outputSchema: { root: z.string(), outcome: outcomeRecord },
|
|
194
|
+
annotations: localWrite,
|
|
195
|
+
},
|
|
196
|
+
async (input) =>
|
|
197
|
+
guarded(() => {
|
|
198
|
+
const outcome = api.begin(input);
|
|
199
|
+
return success({ root: api.root, outcome }, `Opened DriftSeal outcome ${outcome.id}.`);
|
|
200
|
+
})
|
|
201
|
+
);
|
|
202
|
+
|
|
203
|
+
server.registerTool(
|
|
204
|
+
'driftseal_extend',
|
|
205
|
+
{
|
|
206
|
+
title: 'Extend the current DriftSeal outcome',
|
|
207
|
+
description:
|
|
208
|
+
'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.',
|
|
209
|
+
inputSchema: {
|
|
210
|
+
extension: nonEmpty,
|
|
211
|
+
acceptance: z.array(nonEmpty).default([]),
|
|
212
|
+
verify: nonEmpty.optional(),
|
|
213
|
+
decisions: z.array(decisionId).default([]),
|
|
214
|
+
},
|
|
215
|
+
outputSchema: { root: z.string(), outcome: outcomeRecord },
|
|
179
216
|
annotations: localWrite,
|
|
180
217
|
},
|
|
181
218
|
async (input) =>
|
|
182
219
|
guarded(() => {
|
|
183
|
-
const
|
|
184
|
-
return success({ root: api.root,
|
|
220
|
+
const outcome = api.extend(input);
|
|
221
|
+
return success({ root: api.root, outcome }, `Extended DriftSeal outcome ${outcome.id}.`);
|
|
185
222
|
})
|
|
186
223
|
);
|
|
187
224
|
|
|
@@ -190,18 +227,18 @@ function registerTools(server, api, z) {
|
|
|
190
227
|
{
|
|
191
228
|
title: 'Run the declared DriftSeal verification',
|
|
192
229
|
description:
|
|
193
|
-
'Execute the current acceptance-bound
|
|
230
|
+
'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
231
|
inputSchema: {
|
|
195
232
|
allowTrackedCommand: z
|
|
196
233
|
.boolean()
|
|
197
234
|
.default(false)
|
|
198
235
|
.describe(
|
|
199
|
-
'Explicitly allow a command
|
|
236
|
+
'Explicitly allow a command without matching local outcome provenance after inspection.'
|
|
200
237
|
),
|
|
201
238
|
},
|
|
202
239
|
outputSchema: {
|
|
203
240
|
root: z.string(),
|
|
204
|
-
|
|
241
|
+
outcome: outcomeRecord,
|
|
205
242
|
verification: verificationRecord,
|
|
206
243
|
exitCode: z.number().int().nonnegative(),
|
|
207
244
|
},
|
|
@@ -212,7 +249,7 @@ function registerTools(server, api, z) {
|
|
|
212
249
|
const result = api.verify({ allowTrackedCommand: input.allowTrackedCommand });
|
|
213
250
|
return success(
|
|
214
251
|
{ root: api.root, ...result },
|
|
215
|
-
`Machine verification ${result.verification.passed ? 'passed' : 'failed'} for
|
|
252
|
+
`Machine verification ${result.verification.passed ? 'passed' : 'failed'} for outcome ${result.outcome.id}.`
|
|
216
253
|
);
|
|
217
254
|
})
|
|
218
255
|
);
|
|
@@ -220,49 +257,49 @@ function registerTools(server, api, z) {
|
|
|
220
257
|
server.registerTool(
|
|
221
258
|
'driftseal_end',
|
|
222
259
|
{
|
|
223
|
-
title: 'Close a DriftSeal
|
|
260
|
+
title: 'Close a DriftSeal outcome',
|
|
224
261
|
description:
|
|
225
|
-
'Close the current
|
|
262
|
+
'Close the current outcome honestly. Reconcile linked decisions before final verification; completed acceptance-bound outcomes require fresh contract- and workspace-bound evidence.',
|
|
226
263
|
inputSchema: {
|
|
227
|
-
id: z.string().optional().describe('
|
|
264
|
+
id: z.string().optional().describe('Outcome ID; omit to close the current open outcome.'),
|
|
228
265
|
status: closedStatus.default('completed'),
|
|
229
266
|
note: nonEmpty.optional().describe('What actually happened in the round.'),
|
|
230
267
|
verifyResult: nonEmpty.optional().describe('Concise, honest result of the declared verification.'),
|
|
231
268
|
},
|
|
232
|
-
outputSchema: { root: z.string(),
|
|
269
|
+
outputSchema: { root: z.string(), outcome: outcomeRecord },
|
|
233
270
|
annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: false },
|
|
234
271
|
},
|
|
235
272
|
async (input) =>
|
|
236
273
|
guarded(() => {
|
|
237
|
-
const
|
|
238
|
-
return success({ root: api.root,
|
|
274
|
+
const outcome = api.end(input);
|
|
275
|
+
return success({ root: api.root, outcome }, `Closed DriftSeal outcome ${outcome.id} as ${outcome.status}.`);
|
|
239
276
|
})
|
|
240
277
|
);
|
|
241
278
|
|
|
242
279
|
server.registerTool(
|
|
243
280
|
'driftseal_log',
|
|
244
281
|
{
|
|
245
|
-
title: 'List DriftSeal
|
|
282
|
+
title: 'List DriftSeal outcome history',
|
|
246
283
|
description:
|
|
247
|
-
'Review recent or complete DriftSeal
|
|
284
|
+
'Review recent or complete DriftSeal outcome history. Reclaimed records are hidden unless includeReclaimed is set.',
|
|
248
285
|
inputSchema: {
|
|
249
286
|
last: z.number().int().positive().max(100).optional(),
|
|
250
287
|
includeReclaimed: z.boolean().default(false),
|
|
251
288
|
},
|
|
252
289
|
outputSchema: {
|
|
253
290
|
root: z.string(),
|
|
254
|
-
|
|
291
|
+
outcomes: z.array(outcomeRecord),
|
|
255
292
|
readOnly: z.boolean().optional(),
|
|
256
293
|
},
|
|
257
294
|
annotations: readOnly,
|
|
258
295
|
},
|
|
259
296
|
async (input) =>
|
|
260
297
|
guarded(() => {
|
|
261
|
-
const
|
|
298
|
+
const outcomes = api.log({ last: input.last, all: input.includeReclaimed });
|
|
262
299
|
const readOnly = api.readOnly;
|
|
263
|
-
const summary = `Found ${
|
|
300
|
+
const summary = `Found ${outcomes.length} DriftSeal outcome records.`;
|
|
264
301
|
return success(
|
|
265
|
-
{ root: api.root,
|
|
302
|
+
{ root: api.root, outcomes, ...(readOnly ? { readOnly: true } : {}) },
|
|
266
303
|
readOnly ? `${summary} ${READ_ONLY_SUFFIX}` : summary
|
|
267
304
|
);
|
|
268
305
|
})
|
|
@@ -273,7 +310,7 @@ function registerTools(server, api, z) {
|
|
|
273
310
|
{
|
|
274
311
|
title: 'Absorb another DriftSeal lineage',
|
|
275
312
|
description:
|
|
276
|
-
'Repair the fixed repository after a merge collision or absorb another worktree\'s
|
|
313
|
+
'Repair the fixed repository after a merge collision or absorb another worktree\'s outcome and MADR logs, remapping colliding IDs.',
|
|
277
314
|
inputSchema: {
|
|
278
315
|
otherLog: z
|
|
279
316
|
.string()
|
|
@@ -286,7 +323,7 @@ function registerTools(server, api, z) {
|
|
|
286
323
|
abandon: z
|
|
287
324
|
.enum(['ours', 'theirs'])
|
|
288
325
|
.optional()
|
|
289
|
-
.describe('Side whose open
|
|
326
|
+
.describe('Side whose open outcome to abandon when both lineages have one in progress.'),
|
|
290
327
|
dryRun: z.boolean().default(false),
|
|
291
328
|
},
|
|
292
329
|
outputSchema: { root: z.string(), result: absorbResult },
|
|
@@ -306,14 +343,14 @@ function registerTools(server, api, z) {
|
|
|
306
343
|
server.registerTool(
|
|
307
344
|
'driftseal_reclaim',
|
|
308
345
|
{
|
|
309
|
-
title: 'Reclaim DriftSeal
|
|
346
|
+
title: 'Reclaim DriftSeal outcome records',
|
|
310
347
|
description:
|
|
311
|
-
'Hide meaningless closed
|
|
348
|
+
'Hide meaningless closed outcome records behind append-only markers. Never deletes log lines.',
|
|
312
349
|
inputSchema: {
|
|
313
350
|
ids: z
|
|
314
351
|
.array(z.string())
|
|
315
352
|
.default([])
|
|
316
|
-
.describe('
|
|
353
|
+
.describe('Outcome IDs to reclaim; omit for batch mode by age.'),
|
|
317
354
|
reason: nonEmpty.describe('Why these records are meaningless (required, kept in the log).'),
|
|
318
355
|
olderThan: z
|
|
319
356
|
.number()
|
|
@@ -327,12 +364,12 @@ function registerTools(server, api, z) {
|
|
|
327
364
|
.describe('Allow reclaiming partial/completed or decision-linked records by explicit id.'),
|
|
328
365
|
dryRun: z.boolean().default(false),
|
|
329
366
|
},
|
|
330
|
-
outputSchema: { root: z.string(),
|
|
367
|
+
outputSchema: { root: z.string(), outcomes: z.array(outcomeRecord) },
|
|
331
368
|
annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: false },
|
|
332
369
|
},
|
|
333
370
|
async (input) =>
|
|
334
371
|
guarded(() => {
|
|
335
|
-
const
|
|
372
|
+
const outcomes = api.reclaim({
|
|
336
373
|
ids: input.ids,
|
|
337
374
|
reason: input.reason,
|
|
338
375
|
olderThan: input.olderThan,
|
|
@@ -340,10 +377,10 @@ function registerTools(server, api, z) {
|
|
|
340
377
|
dryRun: input.dryRun,
|
|
341
378
|
});
|
|
342
379
|
return success(
|
|
343
|
-
{ root: api.root,
|
|
380
|
+
{ root: api.root, outcomes },
|
|
344
381
|
input.dryRun
|
|
345
|
-
? `${
|
|
346
|
-
: `Reclaimed ${
|
|
382
|
+
? `${outcomes.length} DriftSeal outcome records match.`
|
|
383
|
+
: `Reclaimed ${outcomes.length} DriftSeal outcome records.`
|
|
347
384
|
);
|
|
348
385
|
})
|
|
349
386
|
);
|
|
@@ -351,19 +388,19 @@ function registerTools(server, api, z) {
|
|
|
351
388
|
server.registerTool(
|
|
352
389
|
'driftseal_unreclaim',
|
|
353
390
|
{
|
|
354
|
-
title: 'Restore a reclaimed DriftSeal
|
|
355
|
-
description: 'Restore one reclaimed
|
|
391
|
+
title: 'Restore a reclaimed DriftSeal outcome record',
|
|
392
|
+
description: 'Restore one reclaimed outcome record to the visible log by appending an unreclaim marker.',
|
|
356
393
|
inputSchema: {
|
|
357
394
|
id: z.string(),
|
|
358
395
|
reason: nonEmpty.describe('Why this record is being restored (required, kept in the log).'),
|
|
359
396
|
},
|
|
360
|
-
outputSchema: { root: z.string(),
|
|
397
|
+
outputSchema: { root: z.string(), outcome: outcomeRecord },
|
|
361
398
|
annotations: localWrite,
|
|
362
399
|
},
|
|
363
400
|
async (input) =>
|
|
364
401
|
guarded(() => {
|
|
365
|
-
const
|
|
366
|
-
return success({ root: api.root,
|
|
402
|
+
const outcome = api.unreclaim(input);
|
|
403
|
+
return success({ root: api.root, outcome }, `Restored DriftSeal outcome ${outcome.id}.`);
|
|
367
404
|
})
|
|
368
405
|
);
|
|
369
406
|
|
|
@@ -408,7 +445,7 @@ function registerTools(server, api, z) {
|
|
|
408
445
|
{
|
|
409
446
|
title: 'Add a DriftSeal decision',
|
|
410
447
|
description:
|
|
411
|
-
'Create a MADR record only for durable rationale, rejected paths, deferred choices, or costly-to-reverse decisions that Git and the
|
|
448
|
+
'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
449
|
inputSchema: {
|
|
413
450
|
title: nonEmpty,
|
|
414
451
|
context: nonEmpty,
|
|
@@ -433,7 +470,7 @@ function registerTools(server, api, z) {
|
|
|
433
470
|
{
|
|
434
471
|
title: 'Reconcile a DriftSeal decision',
|
|
435
472
|
description:
|
|
436
|
-
'Reconcile one decision linked to the current open
|
|
473
|
+
'Reconcile one decision linked to the current open outcome, updating or explicitly confirming its status with a history note.',
|
|
437
474
|
inputSchema: {
|
|
438
475
|
id: decisionId,
|
|
439
476
|
status: decisionStatus.optional(),
|
|
@@ -448,6 +485,63 @@ function registerTools(server, api, z) {
|
|
|
448
485
|
return success({ root: api.root, decision }, `Reconciled DriftSeal decision ${decision.id}.`);
|
|
449
486
|
})
|
|
450
487
|
);
|
|
488
|
+
|
|
489
|
+
const migrationPlan = z.object({
|
|
490
|
+
format: z.literal('driftseal-v1-to-v2-plan'),
|
|
491
|
+
sourceFingerprint: z.string().regex(/^[a-f0-9]{64}$/),
|
|
492
|
+
groups: z.array(z.object({
|
|
493
|
+
outcome: nonEmpty,
|
|
494
|
+
summary: nonEmpty,
|
|
495
|
+
sourceIds: z.array(z.string()).min(1),
|
|
496
|
+
})),
|
|
497
|
+
excluded: z.array(z.object({ sourceId: z.string(), reason: nonEmpty })).default([]),
|
|
498
|
+
});
|
|
499
|
+
const migrationSources = {
|
|
500
|
+
sourceLog: nonEmpty.optional().describe('Path to the v1 events.jsonl source.'),
|
|
501
|
+
sourceDecisions: nonEmpty.optional().describe('Path to the v1 MADR directory.'),
|
|
502
|
+
};
|
|
503
|
+
server.registerTool(
|
|
504
|
+
'driftseal_migration_inspect',
|
|
505
|
+
{
|
|
506
|
+
title: 'Inspect a DriftSeal v1 repository for v2 migration',
|
|
507
|
+
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.',
|
|
508
|
+
inputSchema: migrationSources,
|
|
509
|
+
outputSchema: { root: z.string(), inspection: z.unknown() },
|
|
510
|
+
annotations: readOnly,
|
|
511
|
+
},
|
|
512
|
+
async (locations) => guarded(() => {
|
|
513
|
+
const inspection = api.migrationInspect(locations);
|
|
514
|
+
return success({ root: api.root, inspection }, `Found ${inspection.records.length} closed v1 intent records.`);
|
|
515
|
+
})
|
|
516
|
+
);
|
|
517
|
+
server.registerTool(
|
|
518
|
+
'driftseal_migration_apply',
|
|
519
|
+
{
|
|
520
|
+
title: 'Stage a validated DriftSeal v1-to-v2 migration',
|
|
521
|
+
description: 'Validate a model-generated ordered grouping plan, create .seal side-by-side, copy MADRs byte-for-byte, and never delete v1 data.',
|
|
522
|
+
inputSchema: { plan: migrationPlan, ...migrationSources },
|
|
523
|
+
outputSchema: { root: z.string(), result: z.unknown() },
|
|
524
|
+
annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: false },
|
|
525
|
+
},
|
|
526
|
+
async ({ plan, ...locations }) => guarded(() => {
|
|
527
|
+
const result = api.migrationApply({ plan, ...locations });
|
|
528
|
+
return success({ root: api.root, result }, 'Staged DriftSeal v2 without deleting v1 data.');
|
|
529
|
+
})
|
|
530
|
+
);
|
|
531
|
+
server.registerTool(
|
|
532
|
+
'driftseal_migration_check',
|
|
533
|
+
{
|
|
534
|
+
title: 'Check a staged DriftSeal v1-to-v2 migration',
|
|
535
|
+
description: 'Validate the staged outcome log and manifest-backed MADRs, then report whether v1 still awaits manual removal.',
|
|
536
|
+
inputSchema: migrationSources,
|
|
537
|
+
outputSchema: { root: z.string(), result: z.unknown() },
|
|
538
|
+
annotations: readOnly,
|
|
539
|
+
},
|
|
540
|
+
async (locations) => guarded(() => {
|
|
541
|
+
const result = api.migrationCheck(locations);
|
|
542
|
+
return success({ root: api.root, result }, result.complete ? 'Migration complete.' : 'Migration valid; v1 remains for user review.');
|
|
543
|
+
})
|
|
544
|
+
);
|
|
451
545
|
}
|
|
452
546
|
|
|
453
547
|
function registerResources(server, api) {
|
|
@@ -464,22 +558,22 @@ function registerResources(server, api) {
|
|
|
464
558
|
};
|
|
465
559
|
|
|
466
560
|
registerJson(
|
|
467
|
-
'current-
|
|
468
|
-
'driftseal://
|
|
469
|
-
'Current DriftSeal
|
|
470
|
-
'The
|
|
471
|
-
() => ({ root: api.root,
|
|
561
|
+
'current-outcome',
|
|
562
|
+
'driftseal://outcome/current',
|
|
563
|
+
'Current DriftSeal outcome',
|
|
564
|
+
'The delivery outcome currently in progress for the fixed repository.',
|
|
565
|
+
() => ({ root: api.root, outcome: api.status() })
|
|
472
566
|
);
|
|
473
567
|
registerJson(
|
|
474
|
-
'recent-
|
|
475
|
-
'driftseal://
|
|
476
|
-
'Recent DriftSeal
|
|
477
|
-
'The ten most recent
|
|
478
|
-
() => ({ root: api.root,
|
|
568
|
+
'recent-outcomes',
|
|
569
|
+
'driftseal://outcomes/recent',
|
|
570
|
+
'Recent DriftSeal outcomes',
|
|
571
|
+
'The ten most recent outcome records for the fixed repository.',
|
|
572
|
+
() => ({ root: api.root, outcomes: api.log({ last: 10 }) })
|
|
479
573
|
);
|
|
480
574
|
registerJson(
|
|
481
575
|
'decision-catalog',
|
|
482
|
-
'driftseal://
|
|
576
|
+
'driftseal://madr',
|
|
483
577
|
'DriftSeal decision catalog',
|
|
484
578
|
'All MADR decision summaries for the fixed repository.',
|
|
485
579
|
() => ({ root: api.root, decisions: api.decisionList() })
|
|
@@ -498,7 +592,7 @@ async function createServer({ root }) {
|
|
|
498
592
|
{ name: SERVER_NAME, version: SERVER_VERSION },
|
|
499
593
|
{
|
|
500
594
|
instructions:
|
|
501
|
-
'Use driftseal_status before
|
|
595
|
+
'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.',
|
|
502
596
|
}
|
|
503
597
|
);
|
|
504
598
|
registerTools(server, api, z);
|