dsh-doublecheck 0.9.30 → 0.9.31
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/CHANGELOG.md +7 -0
- package/README.en.md +577 -0
- package/README.es.md +577 -0
- package/README.hi.md +577 -0
- package/README.md +343 -267
- package/README.pt.md +577 -0
- package/lib/domain/report.d.ts +6 -0
- package/lib/domain/report.js +1 -1
- package/lib/events.d.ts +2 -0
- package/lib/grill/index.js +84 -26
- package/lib/guard/command.js +1 -0
- package/package.json +1 -1
- package/README-es.md +0 -496
- package/README-hi.md +0 -496
- package/README-pt.md +0 -496
- package/README-zh.md +0 -496
package/lib/grill/index.js
CHANGED
|
@@ -348,6 +348,7 @@ export function apply(ctx, config) {
|
|
|
348
348
|
],
|
|
349
349
|
required: true,
|
|
350
350
|
},
|
|
351
|
+
verificationNote: { oneOf: [{ type: 'string' }, { type: 'null' }], required: true },
|
|
351
352
|
path: { oneOf: [{ type: 'string' }, { type: 'null' }], required: true },
|
|
352
353
|
written: { type: 'boolean', required: true },
|
|
353
354
|
},
|
|
@@ -365,13 +366,14 @@ export function apply(ctx, config) {
|
|
|
365
366
|
? { spec: null, testRuns: { failed: 0, passed: 0 }, timeline: [], edits: 0, review: null }
|
|
366
367
|
: foldReportFacts(sessionEvents(session), reportDetection);
|
|
367
368
|
const verify = args.verify ?? config.reportVerify;
|
|
368
|
-
const
|
|
369
|
+
const attempt = verify
|
|
369
370
|
? await runVerifyWorkflow(ctx, config, facts.spec, exec)
|
|
370
|
-
: null;
|
|
371
|
+
: { verification: null, note: null };
|
|
371
372
|
const report = {
|
|
372
373
|
...facts,
|
|
373
|
-
verdict: deriveReportVerdict(facts, verification),
|
|
374
|
-
verification,
|
|
374
|
+
verdict: deriveReportVerdict(facts, attempt.verification),
|
|
375
|
+
verification: attempt.verification,
|
|
376
|
+
verificationNote: attempt.note,
|
|
375
377
|
path: null,
|
|
376
378
|
written: false,
|
|
377
379
|
};
|
|
@@ -379,7 +381,7 @@ export function apply(ctx, config) {
|
|
|
379
381
|
report.path = outcome.path;
|
|
380
382
|
report.written = outcome.written;
|
|
381
383
|
if (session !== undefined) {
|
|
382
|
-
ctx.emit('doublecheck/report', { session, verdict: report.verdict, verification, path: report.path, written: report.written });
|
|
384
|
+
ctx.emit('doublecheck/report', { session, verdict: report.verdict, verification: report.verification, verificationNote: report.verificationNote, path: report.path, written: report.written });
|
|
383
385
|
}
|
|
384
386
|
return report;
|
|
385
387
|
},
|
|
@@ -394,19 +396,65 @@ export function apply(ctx, config) {
|
|
|
394
396
|
}));
|
|
395
397
|
}
|
|
396
398
|
/**
|
|
397
|
-
*
|
|
398
|
-
*
|
|
399
|
-
*
|
|
400
|
-
*
|
|
401
|
-
*
|
|
399
|
+
* Resolve the workflow engine for this call.
|
|
400
|
+
*
|
|
401
|
+
* A profile-level bundle row lives in the Host realm, but the web profile
|
|
402
|
+
* mounts the engine inside the calling preset's isolated `delegation` group,
|
|
403
|
+
* so `ctx.get('workflowEngine')` from the plugin context returns undefined
|
|
404
|
+
* even though the service is registered. `agentPresets.serviceFor()` is the
|
|
405
|
+
* host's explicit cross-realm accessor (it inspects the agent's retained
|
|
406
|
+
* composition), so it is tried first; the plain lookup stays as the fallback
|
|
407
|
+
* for profiles that mount the engine on the host plane.
|
|
408
|
+
* @param ctx - the plugin context (Host/profile realm).
|
|
409
|
+
* @param agent - the calling agent, when the tool call has one.
|
|
410
|
+
* @returns the engine, or a human-readable reason it is unreachable.
|
|
411
|
+
*/
|
|
412
|
+
function resolveWorkflowEngine(ctx, agent) {
|
|
413
|
+
const presets = ctx.get('agentPresets');
|
|
414
|
+
if (agent?.ctx !== undefined && typeof presets?.serviceFor === 'function') {
|
|
415
|
+
try {
|
|
416
|
+
const scoped = presets.serviceFor(agent, 'workflowEngine');
|
|
417
|
+
if (scoped !== undefined)
|
|
418
|
+
return { engine: scoped };
|
|
419
|
+
}
|
|
420
|
+
catch (error) {
|
|
421
|
+
ctx.logger.debug(`dsh-doublecheck: preset workflowEngine lookup failed: ${String(error)}`);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
const host = ctx.get('workflowEngine');
|
|
425
|
+
if (host !== undefined)
|
|
426
|
+
return { engine: host };
|
|
427
|
+
return {
|
|
428
|
+
why: presets === undefined
|
|
429
|
+
? 'the agent-preset registry is not mounted and the host plane has no workflowEngine'
|
|
430
|
+
: typeof presets.serviceFor !== 'function'
|
|
431
|
+
? 'the mounted agentPresets service has no serviceFor() and the host plane has no workflowEngine'
|
|
432
|
+
: 'the calling agent preset does not mount a workflow engine (standard/cordis enable workflow-ptc; ptc/minimal do not) and the host plane has none',
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Run the per-dimension verification workflow through the workflow seam.
|
|
437
|
+
*
|
|
438
|
+
* Every way this can fail — no spec, no agent, an engine that is unreachable
|
|
439
|
+
* from this realm, a rejected start, an early stop, a malformed value, a
|
|
440
|
+
* rejected result — settles as `verification: null` plus a note that the
|
|
441
|
+
* report renders. A missing seam must not fail the report call itself, but it
|
|
442
|
+
* must not look like "the checks all passed and there was nothing to say"
|
|
443
|
+
* either.
|
|
444
|
+
* @returns the settled checks, or null verification with the reason.
|
|
402
445
|
*/
|
|
403
446
|
async function runVerifyWorkflow(ctx, config, spec, exec) {
|
|
404
|
-
if (spec === null
|
|
405
|
-
return null;
|
|
406
|
-
|
|
447
|
+
if (spec === null) {
|
|
448
|
+
return { verification: null, note: 'no committed spec is on record; record one with doublecheck_spec before verification' };
|
|
449
|
+
}
|
|
450
|
+
if (exec.agent === undefined) {
|
|
451
|
+
return { verification: null, note: 'the call has no owning agent, so no agent preset can supply a workflow engine' };
|
|
452
|
+
}
|
|
453
|
+
const { engine, why } = resolveWorkflowEngine(ctx, exec.agent);
|
|
407
454
|
if (engine === undefined) {
|
|
408
|
-
|
|
409
|
-
|
|
455
|
+
const note = `verification did not run: ${why}`;
|
|
456
|
+
ctx.logger.warn(`dsh-doublecheck: ${note}`);
|
|
457
|
+
return { verification: null, note };
|
|
410
458
|
}
|
|
411
459
|
let run;
|
|
412
460
|
try {
|
|
@@ -423,16 +471,20 @@ async function runVerifyWorkflow(ctx, config, spec, exec) {
|
|
|
423
471
|
catch (error) {
|
|
424
472
|
// Invalid script/meta or an absent verify provider: verification did not
|
|
425
473
|
// run, and the report states so instead of failing the report itself.
|
|
426
|
-
|
|
427
|
-
|
|
474
|
+
const note = `verification did not run: the workflow engine rejected the verify run: ${String(error)}`;
|
|
475
|
+
ctx.logger.warn(`dsh-doublecheck: ${note}`);
|
|
476
|
+
return { verification: null, note };
|
|
428
477
|
}
|
|
429
478
|
try {
|
|
430
479
|
const result = await run.result;
|
|
431
|
-
if (result.stopReason !== 'completed')
|
|
432
|
-
|
|
480
|
+
if (result.stopReason !== 'completed') {
|
|
481
|
+
const detail = result.error === undefined ? '' : `: ${result.error}`;
|
|
482
|
+
return { verification: null, note: `verification did not run: the verify workflow stopped with "${result.stopReason}" before completing${detail}` };
|
|
483
|
+
}
|
|
433
484
|
const value = result.value;
|
|
434
|
-
if (value === null || value === undefined || !Array.isArray(value.checks))
|
|
435
|
-
return null;
|
|
485
|
+
if (value === null || value === undefined || !Array.isArray(value.checks)) {
|
|
486
|
+
return { verification: null, note: 'verification did not run: the verify workflow completed without a structured checks array' };
|
|
487
|
+
}
|
|
436
488
|
const checks = [];
|
|
437
489
|
for (const check of value.checks) {
|
|
438
490
|
if (!VERIFY_DIMENSIONS.includes(check.dimension))
|
|
@@ -443,17 +495,23 @@ async function runVerifyWorkflow(ctx, config, spec, exec) {
|
|
|
443
495
|
// judged here so a checker that silently dropped a dimension cannot
|
|
444
496
|
// upgrade the delivery.
|
|
445
497
|
const complete = VERIFY_DIMENSIONS.every(dimension => checks.some(check => check.dimension === dimension));
|
|
446
|
-
return { checks, complete };
|
|
498
|
+
return { verification: { checks, complete }, note: null };
|
|
447
499
|
}
|
|
448
500
|
catch (error) {
|
|
449
501
|
// A broken workflow engine must not fail the report call itself: the
|
|
450
502
|
// delivery settles as unverified and the markdown says verification did
|
|
451
|
-
// not run.
|
|
452
|
-
|
|
453
|
-
|
|
503
|
+
// not run, with the reason.
|
|
504
|
+
const note = `verification did not run: the verify workflow failed: ${String(error)}`;
|
|
505
|
+
ctx.logger.warn(`dsh-doublecheck: ${note}`);
|
|
506
|
+
return { verification: null, note };
|
|
454
507
|
}
|
|
455
508
|
finally {
|
|
456
|
-
|
|
509
|
+
try {
|
|
510
|
+
await run.dispose();
|
|
511
|
+
}
|
|
512
|
+
catch (error) {
|
|
513
|
+
ctx.logger.warn(`dsh-doublecheck: verify run disposal failed: ${String(error)}`);
|
|
514
|
+
}
|
|
457
515
|
}
|
|
458
516
|
}
|
|
459
517
|
/** Write the report markdown through the filesystem seam, when one exists. */
|
package/lib/guard/command.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-doublecheck",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.31",
|
|
4
4
|
"description": "Delivery quality gate for DeepSeek Harness: grill the requirements, test the implementation, prove the delivery, and gate the handoff with a deliverable/rework decision.",
|
|
5
5
|
"packageManager": "pnpm@11.7.0",
|
|
6
6
|
"repository": {
|